GLSurfaceview 详细工作流程

本文深入探讨了GLSurfaceView的工作流程,包括Renderer实例化、EGL环境创建、GL纹理对象生成、SurfaceTexture与Surface交互机制,以及如何通过SurfaceTexture更新纹理并绘制到屏幕上的详细过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • GLSurfaceview 详细工作流程
    在这里插入图片描述
  1. 编写GLSurfaceView.Renderer的实例,调setRenderer()将之设成GLSurfaceView的Renderer。

  2. GLSurfaceView中的GLThread启动,创建EGL环境后回调Renderer中onSurfaceCreated()

  3. 通过GLES创建GL的外部纹理。外部纹理说明它的真正内容是放在ion分配出来的系统物理内存中,而不是GPU中,GPU中只是维护了其元数据。

    int[] textures = new int[1];
    GLES20.glGenTextures(1, textures, 0);
    mTextureID = textures[0];
    GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
    

    第一个参数是什么类型的纹理,在此是GLES11Ext.GL_BLEND_EQUATION_RGB_OES,也可以是常用的2D纹理如GLES20.GL_TEXTURE_2D等;第二个参数texture,在程序第一次使用这个参数时,这个函数会创建一个新的对象,并把这个对象分配给它,之后这个texture就成了一个活动的纹理对象。如果texture=0 则OpenGL就停止使用纹理对象,并返回到初始的默认纹理。

  4. 根据前面创建的GL纹理对象创建SurfaceTexture。SurfaceTexture的参数为GLES接口函数glGenTexture()得到的纹理对象id,在初始化函数SurfaceTexture_init()中,先创建GLConsumer和相应的BufferQueue,再将它们的指针通过JNI放到SurfaceTexture的Java层对象成员中。

    mSurface = new SurfaceTexture(mTextureID);
    
  5. 设置监听,
    由于直接的Listener在Java层,而触发者在Native层,因此需要从Native层回调到Java层。这里通过JNISurfaceTextureContext当了跳板JNISurfaceTextureContext的onFrameAvailable()起到了Native和Java的桥接作用:通知renderer新的数据到来。

    mSurface.setOnFrameAvailableListener(this);
    
  6. 创建供外部生产者使用的Surface类。Surface的构造函数之一带有参数SurfaceTexture。
    它实际上是把SurfaceTexture中创建的BufferQueue的Producer接口实现类拿出来后创建了相应的Surface类。
    这样,Surface为BufferQueue的Producer端,SurfaceTexture中的GLConsumer为BufferQueue的Consumer端。当通过Surface绘制时,SurfaceTexture可以通过updateTexImage()来将绘制结果绑定到GL的纹理中

    Surface surface = new Surface(mSurface);
    
  7. 将SurfaceTexture传给MediaPlayer
    因为这里MediaPlayer是生产者,SurfaceTexture是消费者。后者要接收前者输出的Video frame。这样,就通过Observer pattern建立起了一条通知链:MediaPlayer -> SurfaceTexture -> VideDumpRenderer。

    mMediaPlayer.setSurface(surface);
    
  8. 在onFrameAvailable()回调函数中,将updateSurface标志设为true,表示有新的图像到来,需要更新Surface了。
    在这不能马上更新纹理
    因为当前可能不在渲染线程。SurfaceTexture对象可以在任意线程被创建(回调也会在该线程被调用),但updateTexImage()只能在含有纹理对象的GL Context所在线程中被调用。因此一般情况下回调中不能直接调用updateTexImage()。
    与此同时,GLSurfaceView中的GLThread也在运行,它会调用到VideoDumpRenderer的绘制函数onDrawFrame()。通过SurfaceTexture的updateTexImage()将内容流中的新图像转成GL中的纹理,再进行坐标转换。绑定刚生成的纹理,画到屏幕上。

    if (updateSurface)
    {mSurface.updateTexImage();
    mSurface.getTransformMatrix(mSTMatrix);
    updateSurface = false;
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值