How to share a Renderscript allocation with OpenGL in Android

孤街浪徒 提交于 2019-12-20 10:48:25

问题


I have a Renderscript which processes an image that is given in output to an Allocation. I want to use this Allocation as a texture in my OpenGL program but I don't know how to get a texture ID from the Allocation.

On the other hand, I know I could use a graphic Renderscript, but since it has been deprecated, I guess there must be some other way to achieve the same result.


回答1:


Specify USAGE_IO_OUTPUT when you create the Allocation. Assuming you are generating the texture data in a script you would also add USAGE_SCRIPT. You can then call

Allocation.setSurface(theGLSurface)

to link the allocation to a texture. Each time you want to update the texture with the contents of the script you need to call.

Allocation.ioSend()

This will move the data without making extra copies.




回答2:


You have phrased the question in terms of transforming an Allocation into a texture, but it's easier to think of creating a texture then granting the Allocation ownership of that texture. This way, you would know the texture ID before passing it to the Allocation. Beware: the Allocation has the power to radically change properties of the texture.

Step by step:

  1. Create a GL texture

  2. Create a SurfaceTexture using its ID

  3. Create an Allocation with usage Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT

  4. Pass the SurfaceTexture to the Allocation with setSurface()

  5. Put data in the Allocation

  6. Call ioSend() on the Allocation to update the texture

  7. Repeat steps 5 and 6 as often as you want to update the texture

I am very far from a GL expert, so step 2 is frankly conjecture. Below is an adaptation of the HelloCompute sample in which I replace displayout with a TextureView, which is a View that handily creates a texture and a SurfaceTexture for me. From then on I follow the steps above.

package com.example.android.rs.hellocompute;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.Type;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.TextureView;
import android.widget.ImageView;

public class HelloCompute extends Activity {
    private Bitmap mBitmapIn;

    private RenderScript mRS;
    private ScriptC_mono mScript;
    private Allocation mSurfaceAllocation;
    private Allocation mCanvasAllocation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mBitmapIn = loadBitmap(R.drawable.data);
        int x = mBitmapIn.getWidth();
        int y = mBitmapIn.getHeight();

        ImageView in = (ImageView) findViewById(R.id.displayin);
        in.setImageBitmap(mBitmapIn);

        mRS = RenderScript.create(this);
        mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono);

        mCanvasAllocation = Allocation.createTyped(mRS, 
                new Type.Builder(mRS, Element.RGBA_8888(mRS))
                    .setX(x).setY(y).create(), 
                Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);

        mSurfaceAllocation = Allocation.createTyped(mRS, 
                new Type.Builder(mRS, Element.RGBA_8888(mRS))
                    .setX(x).setY(y).create(), 
                Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);

        TextureView mTextureView = (TextureView) findViewById(R.id.displayout);
        mTextureView.setSurfaceTextureListener(
          new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture s, 
                    int w, int h) {
                if(s != null) mSurfaceAllocation.setSurface(new Surface(s));
                mScript.forEach_root(mCanvasAllocation, mSurfaceAllocation);
                mSurfaceAllocation.ioSend();
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture s) {
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture s, 
                    int w, int h) {
                if(s != null) mSurfaceAllocation.setSurface(new Surface(s));
            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture s) {
                mSurfaceAllocation.setSurface(null);
                return true;
            }
        });

        try {
            Surface surface = mCanvasAllocation.getSurface();
            Canvas canvas = surface.lockCanvas(new Rect(0,0,100,100));
            canvas.drawBitmap(mBitmapIn, 0, 0, new Paint());
            surface.unlockCanvasAndPost(canvas);
            mCanvasAllocation.ioReceive();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (OutOfResourcesException e) {
            e.printStackTrace();
        }
    }

    private Bitmap loadBitmap(int resource) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeResource(getResources(), resource, options);
    }
}


来源:https://stackoverflow.com/questions/15274505/how-to-share-a-renderscript-allocation-with-opengl-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!