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.
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:
Create a GL texture
Create a SurfaceTexture using its ID
Create an Allocation with usage Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT
Pass the SurfaceTexture to the Allocation with setSurface()
Put data in the Allocation
Call ioSend()
on the Allocation to update the texture
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); } }