问题
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:
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 textureRepeat 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