Linked Questions

Popular Questions

How do I get glMapBufferRange() to run in background

Asked by At

I'm writing an android application to capture screen data, and make an MP4 out of it. The first step in this is to use some openGL calls to read out the pixels from the screen.

private void screenScrape() {

    Log.d(TAG, "In screenScrape");

    //read pixels from frame buffer into PBO (GL_PIXEL_PACK_BUFFER)
    mySurface.queueEvent(new Runnable() {
        public void run() {

            Log.d(TAG, "In Screen Scrape 1");

            //generate and bind buffer ID
            GLES30.glGenBuffers(1, pboIds);
            checkGlError("Gen Buffers");

            GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pboIds.get(0));
            checkGlError("Bind Buffers");

            //creates and initializes data store for PBO.  Any pre-existing data store is deleted
            GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER, (mWidth * mHeight * 4), null, GLES30.GL_STATIC_READ);
            checkGlError("Buffer Data");

            glReadPixelsPBO(0, 0, mWidth, mHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, 0);
            checkGlError("Read Pixels");

    //map PBO data into client address space
    mySurface.queueEvent(new Runnable() {
        public void run() {
            Log.d(TAG, "In Screen Scrape 2");

            //read pixels from PBO into a byte buffer for processing.  Unmap buffer for use in next pass
            mapBuffer = ((ByteBuffer) GLES30.glMapBufferRange(GLES30.GL_PIXEL_PACK_BUFFER, 0, 4 * mWidth * mHeight, GLES30.GL_MAP_READ_BIT)).order(ByteOrder.nativeOrder());
            checkGlError("Map Buffer");

            checkGlError("Unmap Buffer");

            //openGL calls return pixels in a flipped format.  Flip buffer so image presented right side up
            for (int i = 0; i < mWidth; ++i) {
                for (int j = 0; j < mHeight; ++j) {
                    for (int k = 0; k < 4; ++k) {
                        flippedBuffer.put((i + j * mWidth) * 4 + k, mapBuffer.get((i + (mHeight - 1 - j) * mWidth) * 4 + k));

            isByteBufferEmpty(mapBuffer, "MAP BUFFER");
            Log.d(TAG, "Flipped Buffer Position: " + flippedBuffer.position() + "Remaining: " + flippedBuffer.remaining() + " Limit: " + flippedBuffer.limit());

mySurface is a GLMapsurface that I initialize from an input parameter.

e.g. GLMapSurface mySurface = inputSurface where inputSurface is a passed parameter.

Now my issue is that the call to glMapBufferRange blocks the UI. How can I get this call to run in a background thread so it doesn't block the UI?

I've attempted creating a new GLMapSurface object and queuing up events to that, but they never get executed.

Related Questions