1
votes

I am using PBO to take screenshot. However, the result image is all black. It works perfectly fine without PBO. Is there any thing that I need to take care before doing this ?

I even tried by rendering to a FBO and then use GLES30.glReadBuffer(GLES30.GL_COLOR_ATTACHMENT0), no hope

public void SetupPBO(){ 
    GLES30.glGenBuffers(1, pbuffers, 0);        
    GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbuffers[0]);
    int size = (int)this.mScreenHeight *  (int)this.mScreenWidth * 4;
    GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER, size, null, GLES30.GL_DYNAMIC_READ);
    checkGlError("glReadBuffer");
    GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);
}

private void Render(float[] m) {
    .......//Normal render logic
    exportBitmap();
}

 private void exportBitmap() {
    int screenshotSize = (int)this.mScreenWidth * (int)this.mScreenHeight;
    ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
    bb.order(ByteOrder.nativeOrder());

    // set the target framebuffer to read
    GLES30.glReadBuffer(GLES30.GL_FRONT);
    checkGlError("glReadBuffer");
    GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbuffers[0]);
    GLES30.glReadPixels(0, 0, (int)mScreenWidth, (int)mScreenHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);  //<------ not working ?????

    int pixelsBuffer[] = new int[screenshotSize];
    bb.asIntBuffer().get(pixelsBuffer);
    bb = null;

    for (int i = 0; i < screenshotSize; ++i) {
        // The alpha and green channels' positions are preserved while the
        // red and blue are swapped
        pixelsBuffer[i] = ((pixelsBuffer[i] & 0xff00ff00))
                    | ((pixelsBuffer[i] & 0x000000ff) << 16)
                    | ((pixelsBuffer[i] & 0x00ff0000) >> 16);
    }

    Bitmap bitmap = Bitmap.createBitmap((int)mScreenWidth, (int)mScreenHeight, Bitmap.Config.ARGB_8888);
    bitmap.setPixels(pixelsBuffer, screenshotSize - (int)mScreenWidth, -(int)mScreenWidth, 0, 0, (int)mScreenWidth, (int)mScreenHeight);
    SaveBitmap(bitmap);
}
1

1 Answers

1
votes
GLES30.glReadPixels(0, 0, (int)mScreenWidth, (int)mScreenHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);

bb is interpret as an offset in your PBO. Thus you're writing out of buffer (On some drivers this code cause crash). You should pass 0 instead of bb. To retrive the data from PBO use glMapBuffer.