Skip to content Skip to sidebar Skip to footer

How To Share A Renderscript Allocation With Opengl In Android

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

Solution 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.

Solution 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;

publicclassHelloComputeextendsActivity {
    private Bitmap mBitmapIn;

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

    @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mBitmapIn = loadBitmap(R.drawable.data);
        intx= mBitmapIn.getWidth();
        inty= mBitmapIn.getHeight();

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

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

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

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

        TextureViewmTextureView= (TextureView) findViewById(R.id.displayout);
        mTextureView.setSurfaceTextureListener(
          newTextureView.SurfaceTextureListener() {
            @OverridepublicvoidonSurfaceTextureAvailable(SurfaceTexture s, 
                    int w, int h) {
                if(s != null) mSurfaceAllocation.setSurface(newSurface(s));
                mScript.forEach_root(mCanvasAllocation, mSurfaceAllocation);
                mSurfaceAllocation.ioSend();
            }

            @OverridepublicvoidonSurfaceTextureUpdated(SurfaceTexture s) {
            }

            @OverridepublicvoidonSurfaceTextureSizeChanged(SurfaceTexture s, 
                    int w, int h) {
                if(s != null) mSurfaceAllocation.setSurface(newSurface(s));
            }

            @OverridepublicbooleanonSurfaceTextureDestroyed(SurfaceTexture s) {
                mSurfaceAllocation.setSurface(null);
                returntrue;
            }
        });

        try {
            Surfacesurface= mCanvasAllocation.getSurface();
            Canvascanvas= surface.lockCanvas(newRect(0,0,100,100));
            canvas.drawBitmap(mBitmapIn, 0, 0, newPaint());
            surface.unlockCanvasAndPost(canvas);
            mCanvasAllocation.ioReceive();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (OutOfResourcesException e) {
            e.printStackTrace();
        }
    }

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

Post a Comment for "How To Share A Renderscript Allocation With Opengl In Android"