Search code examples
androidallocationrenderscript

rsForEach called with null out allocation


I am new to renderscript and was trying out few things. This is an example which I am trying out. Everything seems to work well.

public class RsYuv implements TextureView.SurfaceTextureListener
{
     private int mHeight;
     private int mWidth;
     private RenderScript mRS;
     private Allocation mAllocationOut;
     private Allocation mAllocationIn;
     private ScriptIntrinsicYuvToRGB mYuv;
     private boolean mHaveSurface;
     private Surface mSurface;

    RsYuv(RenderScript rs) {
        mRS = rs;
        mYuv = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(mRS));
    }


     public void reset(int mWidth, int mHeight) {
        Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
        tb.setX(mWidth);
        tb.setY(mHeight);
        Type t = tb.create();
        mAllocationOut = Allocation.createTyped(mRS, t, Allocation.USAGE_SCRIPT |
                                                        Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SHARED);

        tb = new Type.Builder(mRS, Element.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV));
        tb.setX(mWidth);
        tb.setY(mHeight);
        tb.setYuvFormat(android.graphics.ImageFormat.NV21);
        mAllocationIn = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
        mYuv.setInput(mAllocationIn);

        setupSurface();
    }

    void execute(byte[] yuv) {
         mAllocationIn.copyFrom(yuv);
        if (mHaveSurface) {
            mYuv.forEach(mAllocationOut);
            mAllocationOut.ioSend();
        }
    }

    void setupSurface() {
        if (mAllocationOut != null) {

            mAllocationOut.setSurface(mSurface);
        }
        if (mSurface != null) {
            mHaveSurface = true;
        } else {
            mHaveSurface = false;
        }
    }
}

This seems to work well. But when I introduce another allocation, it always gives me

non fatal RS error, rsForEach called with null out allocations.

Here's how I am initializing another allocation after declaring it.

public void reset(int mWidth, mHeight) {
    // after initializing mAllocationOut

     mAllocationOut1 = Allocation.createTyped(mRS, mAllocationOut.getType(), Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SHARED);

    // further code
}

void execute(data[] yuv) {
     if (mHaveSurface) {
        mYuv.forEach(mAllocationOut);
        mYuv.forEach(mAllocationOut1); // Here it gives the error
        mAllocationOut.ioSend();
     }
}

What could be the problem? I want to make a copy of mAllocationOut. I tried using copyFrom but it results in a crash each time without giving much detailed error. Any help is appreciated.


Solution

  • the comment above that warning says "possible for this to occur with IO_INPUT/IO_INPUT with no bound surface," so I'm guessing that's what you're seeing. did you ever call mAllocationOut1.setSurface? Creating an Allocation with IO_OUTPUT does not create any backing store; the backing store comes from whatever Surface is associated with it. This would explain the warning and the crash with copyTo. (I'll look and see if we need to add more error checks somewhere to make this more obvious going forward)