EGL texture 0-copy

来自百问网嵌入式Linux wiki

<securetransclude src="ProtectedTemplate:ReviewsComments" params="PCO (W803) : the article name is not so nice"></securetransclude>{{#set:Has reviews comments=true}} <securetransclude src="ProtectedTemplate:ReviewsComments" params="PCO (W803) : avoid "br""></securetransclude>{{#set:Has reviews comments=true}} <securetransclude src="ProtectedTemplate:ReviewsComments" params="PCO (W803) : bad titles, please use 2x'"`UNIQ--nowiki-00000000-QINU`"'"></securetransclude>{{#set:Has reviews comments=true}}


This article explain how to use the EGL texture 0-copy in a 3D application.

What is texture 0-copy?

The texture 0-copy consists in using specific OpenGLES interfaces to avoid to copy the texture from the EGL application environment to the GPU execution environment.
The OpenGLES interfaces to be used (instead of the standard glTexImage2D interface) are:

  • eglCreateImageKHR (create a reference on the image texture)
  • eglDestroyImageKHR (destroy the reference of the image texture)
  • glEGLImageTargetTexture2DOES (upload the texture)

<securetransclude src="ProtectedTemplate:ReviewsComments" params="PCO (W803) : It could be nice to add web links to these extension documentation"></securetransclude>{{#set:Has reviews comments=true}} The texture 0-copy procedure assumes that the texture buffer could be shared (e.g.: using DMABUF) and that the application will lock the texture until the OpenGLES draw procedure is completed.

The texture 0-copy is very useful when the texture to apply on a 3D object is refreshed with a high rate (e.g: video texture).

Example of implementation

<securetransclude src="ProtectedTemplate:ReviewsComments" params="PCO (W803) : please use the code template instead"></securetransclude>{{#set:Has reviews comments=true}} In this example we consider that the GPU natively support NV12 pixel format.

      EGLint eglImgAttrs[30];
      EGLImageKHR image;
      GLenum target;

      if (meta) {
        switch (meta->format) {
        case GST_VIDEO_FORMAT_NV12:
          format = DRM_FORMAT_NV12;
          n_planes = 2;
          target = GL_TEXTURE_EXTERNAL_OES;
          break;
        case GST_VIDEO_FORMAT_RGB16:
          format = DRM_FORMAT_RGB565;
        case GST_VIDEO_FORMAT_BGRx:
          format = DRM_FORMAT_XRGB8888;
          n_planes = 1;
          target = GL_TEXTURE_2D;
          break;
        default:
          fprintf(stdout, "%s: buffer format (0x%x) not supported for texture\n", __func__, meta->format);
          return;
        }
      } else {
        fprintf(stdout, "%s: no meta data found\n", __func__);
        return;
      }

      eglImgAttrs[atti++] = EGL_WIDTH;
      eglImgAttrs[atti++] = meta->width;
      eglImgAttrs[atti++] = EGL_HEIGHT;
      eglImgAttrs[atti++] = meta->height;
      eglImgAttrs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
      eglImgAttrs[atti++] = format;

      if (n_planes > 0) {
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
        eglImgAttrs[atti++] = fd_mem;
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
        eglImgAttrs[atti++] = meta->offset[0];
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
        eglImgAttrs[atti++] = meta->stride[0];
      }

      if (n_planes > 1) {
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
        eglImgAttrs[atti++] = fd_mem;
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
        eglImgAttrs[atti++] = meta->offset[1];
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
        eglImgAttrs[atti++] = meta->stride[1];
      }

      if (n_planes > 2) {
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
        eglImgAttrs[atti++] = fd_mem;
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
        eglImgAttrs[atti++] = meta->offset[2];
        eglImgAttrs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
        eglImgAttrs[atti++] = meta->stride[2];
      }

      eglImgAttrs[atti++] = EGL_NONE;

      image = eglCreateImageKHR(display,
                EGL_NO_CONTEXT,
                EGL_LINUX_DMA_BUF_EXT,
                NULL,
                eglImgAttrs);

      /* Updating the related input texture. */
      glActiveTexture(GL_TEXTURE0);
      glBindTexture(target, input_textures_handle[stream_index]);
      glEGLImageTargetTexture2DOES(target, image);
 
      eglDestroyImageKHR(display, image);