如何使用android OpenGL在线程之间进行通信

时间:2016-09-14 18:28:41

标签: java android multithreading opengl-es

假设我得到一个像素缓冲区流,我想用OpelnGL显示它们;为此,我使用GLES20.glTexImage2D。现在我想在每次获得新缓冲区时更新图像。我如何从MainActivity或其他不了解OpenGL线程的类中做到这一点?

这是我的loadTexture方法

private int loadTexture ()
    {
        int[] textureId = new int[1];
        buffer.clear(); // buffer is a public static variable
        buffer.put(data); // data has been created for the test
        buffer.position(0);

        GLES20.glGenTextures(1, textureId, 0);
        GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureId[0] );

        GLES20.glTexImage2D ( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 512, 512, 0,
                GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, buffer );

        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        return textureId[0];
    }

即使我将OpenGL线程添加到onDrawFrame方法

public void onDrawFrame(GL10 glUnused)
    {
        GLES20.glViewport(0, 0, mWidth, mHeight);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glUseProgram(mProgramObject);
        ...

        // Bind the base map
        GLES20.glActiveTexture ( GLES20.GL_TEXTURE0 );
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBaseMapTexId);

        // Set the base map sampler to texture unit to 0
        GLES20.glUniform1i(mBaseMapLoc, 0);

        // Bind the light map
        GLES20.glActiveTexture ( GLES20.GL_TEXTURE1 );
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mLightMapTexId);

        // Set the light map sampler to texture unit 1
        GLES20.glUniform1i(mLightMapLoc, 1);

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mIndices);

        // For test purpose, I try to update the data in the buffer
        byte[] data = new byte[512*512*3];
        for ( int y = 0; y < 512; y++ )
            for ( int x = 0; x < 512; x++ )
            {
                int pixel = 200;
                data[(y * 512 + x) * 3 + 0] = (byte)((pixel >> 0) & 0xFF);
                data[(y * 512 + x) * 3 + 1] = (byte)((pixel >> 0) & 0xFF);
                data[(y * 512 + x) * 3 + 2] = (byte)((pixel >> 0) & 0xFF);
            }
        buffer.clear();
        buffer.put(data);
        buffer.position(0);          
    } 

但图片未更新。即使我试图添加到后一种方法的末尾,这也不起作用

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBaseMapTexId);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 512, 512, 0,
                    GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, buffer);

1 个答案:

答案 0 :(得分:0)

  

如何从MainActivity或其他不了解OpenGL线程的类中做到这一点?

首先 - 让我们更正一些术语。没有&#34; OpenGL线程&#34 ;;如果你使用那个术语,它会很快变得非常混乱。

您拥有的是特定平台(例如iOS上的EAGL,Android上的EGL)渲染层的渲染上下文。每个渲染上下文可以在任何时间点在一个线程中激活,但是可以移动线程(例如,通过调用eglMakeCurrent用于EGL平台层),这就是思考一个&#34; OpenGL线程& #34;在概念上是一个坏主意。

将上下文绑定到线程将删除任何现有上下文的绑定,并从其他线程解除绑定新上下文。除了在线程之间移动线程之外,还可以将多个不同的渲染上下文绑定到并行运行的多个不同线程,这对于这个问题非常重要。

您想要的数据共享是通过在同一个共享组中拥有多个呈现上下文来实现的(例如,如果您正在使用EGL,请参阅share_context参数到eglCreateContext),绑定到不同的线程。您可以在一个上下文中创建纹理,上传数据,然后另一个上下文可以绑定它并使用它。同步(例如,因此另一个线程知道何时使用该纹理绑定是安全的)必须通过应用程序级同步协议来完成 - 它不是由API提供的。

多个上下文之间的状态同步规则有点复杂(总的来说它通常是懒惰的,只有在上下文重新绑定资源时才会同步),所以我强烈建议阅读附录C OpenGL ES 2.0规范(或后来的ES版本中的等效版本 - 它没有改变)。