How to share a Renderscript allocation with OpenGL in Android

拟墨画扇 提交于 2019-12-03 01:38:08

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.

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