Home | History | Annotate | Download | only in gl
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/gl/gl_image_android_native_buffer.h"
      6 
      7 #include "ui/gl/gl_surface_egl.h"
      8 #include "ui/gl/scoped_binders.h"
      9 
     10 namespace gfx {
     11 
     12 GLImageAndroidNativeBuffer::GLImageAndroidNativeBuffer(gfx::Size size)
     13     : GLImageEGL(size),
     14       release_after_use_(false),
     15       in_use_(false),
     16       target_(0),
     17       egl_image_for_unbind_(EGL_NO_IMAGE_KHR),
     18       texture_id_for_unbind_(0) {}
     19 
     20 GLImageAndroidNativeBuffer::~GLImageAndroidNativeBuffer() { Destroy(); }
     21 
     22 bool GLImageAndroidNativeBuffer::Initialize(gfx::GpuMemoryBufferHandle buffer) {
     23   DCHECK(buffer.native_buffer);
     24 
     25   EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
     26   return GLImageEGL::Initialize(
     27       EGL_NATIVE_BUFFER_ANDROID, buffer.native_buffer, attrs);
     28 }
     29 
     30 void GLImageAndroidNativeBuffer::Destroy() {
     31   if (egl_image_for_unbind_ != EGL_NO_IMAGE_KHR) {
     32     eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
     33                        egl_image_for_unbind_);
     34     egl_image_for_unbind_ = EGL_NO_IMAGE_KHR;
     35   }
     36   if (texture_id_for_unbind_) {
     37     glDeleteTextures(1, &texture_id_for_unbind_);
     38     texture_id_for_unbind_ = 0;
     39   }
     40 
     41   GLImageEGL::Destroy();
     42 }
     43 
     44 bool GLImageAndroidNativeBuffer::BindTexImage(unsigned target) {
     45   DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
     46 
     47   if (target == GL_TEXTURE_RECTANGLE_ARB) {
     48     LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target";
     49     return false;
     50   }
     51 
     52   if (target_ && target_ != target) {
     53     LOG(ERROR) << "EGLImage can only be bound to one target";
     54     return false;
     55   }
     56   target_ = target;
     57 
     58   // Defer ImageTargetTexture2D if not currently in use.
     59   if (!in_use_)
     60     return true;
     61 
     62   glEGLImageTargetTexture2DOES(target_, egl_image_);
     63   DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
     64   return true;
     65 }
     66 
     67 void GLImageAndroidNativeBuffer::WillUseTexImage() {
     68   DCHECK(egl_image_);
     69   DCHECK(!in_use_);
     70   in_use_ = true;
     71   glEGLImageTargetTexture2DOES(target_, egl_image_);
     72   DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
     73 }
     74 
     75 void GLImageAndroidNativeBuffer::DidUseTexImage() {
     76   DCHECK(in_use_);
     77   in_use_ = false;
     78 
     79   if (!release_after_use_)
     80     return;
     81 
     82   if (egl_image_for_unbind_ == EGL_NO_IMAGE_KHR) {
     83     DCHECK_EQ(0u, texture_id_for_unbind_);
     84     glGenTextures(1, &texture_id_for_unbind_);
     85 
     86     {
     87       ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_for_unbind_);
     88       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     89       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     90       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     91 
     92       char zero[4] = {0, };
     93       glTexImage2D(
     94           GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero);
     95     }
     96 
     97     EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
     98     // Need to pass current EGL rendering context to eglCreateImageKHR for
     99     // target type EGL_GL_TEXTURE_2D_KHR.
    100     egl_image_for_unbind_ = eglCreateImageKHR(
    101         GLSurfaceEGL::GetHardwareDisplay(),
    102         eglGetCurrentContext(),
    103         EGL_GL_TEXTURE_2D_KHR,
    104         reinterpret_cast<EGLClientBuffer>(texture_id_for_unbind_),
    105         attrs);
    106     DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_for_unbind_)
    107         << "Error creating EGLImage: " << eglGetError();
    108   }
    109 
    110   glEGLImageTargetTexture2DOES(target_, egl_image_for_unbind_);
    111   DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
    112 }
    113 
    114 void GLImageAndroidNativeBuffer::SetReleaseAfterUse() {
    115   release_after_use_ = true;
    116 }
    117 
    118 }  // namespace gfx
    119