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