• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GLImageAndroidNativeBuffer(gfx::Size size)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 
~GLImageAndroidNativeBuffer()20 GLImageAndroidNativeBuffer::~GLImageAndroidNativeBuffer() { Destroy(); }
21 
Initialize(gfx::GpuMemoryBufferHandle buffer)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 
Destroy()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 
BindTexImage(unsigned target)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 
WillUseTexImage()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 
DidUseTexImage()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 
SetReleaseAfterUse()114 void GLImageAndroidNativeBuffer::SetReleaseAfterUse() {
115   release_after_use_ = true;
116 }
117 
118 }  // namespace gfx
119