1 // Copyright (c) 2013 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_egl.h"
6
7 #include "ui/gl/gl_bindings.h"
8 #include "ui/gl/gl_surface_egl.h"
9
10 namespace gfx {
11
GLImageEGL(gfx::Size size)12 GLImageEGL::GLImageEGL(gfx::Size size)
13 : egl_image_(EGL_NO_IMAGE_KHR),
14 size_(size),
15 release_after_use_(false),
16 in_use_(false),
17 target_(0) {
18 }
19
~GLImageEGL()20 GLImageEGL::~GLImageEGL() {
21 Destroy();
22 }
23
Initialize(gfx::GpuMemoryBufferHandle buffer)24 bool GLImageEGL::Initialize(gfx::GpuMemoryBufferHandle buffer) {
25 DCHECK(buffer.native_buffer);
26 EGLint attrs[] = {
27 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
28 EGL_NONE,
29 };
30 egl_image_ = eglCreateImageKHR(
31 GLSurfaceEGL::GetHardwareDisplay(),
32 EGL_NO_CONTEXT,
33 EGL_NATIVE_BUFFER_ANDROID,
34 buffer.native_buffer,
35 attrs);
36
37 if (egl_image_ == EGL_NO_IMAGE_KHR) {
38 EGLint error = eglGetError();
39 LOG(ERROR) << "Error creating EGLImage: " << error;
40 return false;
41 }
42
43 return true;
44 }
45
Destroy()46 void GLImageEGL::Destroy() {
47 if (egl_image_ == EGL_NO_IMAGE_KHR)
48 return;
49
50 EGLBoolean success = eglDestroyImageKHR(
51 GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
52
53 if (success == EGL_FALSE) {
54 EGLint error = eglGetError();
55 LOG(ERROR) << "Error destroying EGLImage: " << error;
56 }
57
58 egl_image_ = EGL_NO_IMAGE_KHR;
59 }
60
GetSize()61 gfx::Size GLImageEGL::GetSize() {
62 return size_;
63 }
64
BindTexImage(unsigned target)65 bool GLImageEGL::BindTexImage(unsigned target) {
66 if (egl_image_ == EGL_NO_IMAGE_KHR) {
67 LOG(ERROR) << "NULL EGLImage in BindTexImage";
68 return false;
69 }
70
71 if (target == GL_TEXTURE_RECTANGLE_ARB) {
72 LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target";
73 return false;
74 }
75
76 if (target_ && target_ != target) {
77 LOG(ERROR) << "EGLImage can only be bound to one target";
78 return false;
79 }
80 target_ = target;
81
82 // Defer ImageTargetTexture2D if not currently in use.
83 if (!in_use_)
84 return true;
85
86 glEGLImageTargetTexture2DOES(target_, egl_image_);
87 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
88 return true;
89 }
90
ReleaseTexImage(unsigned target)91 void GLImageEGL::ReleaseTexImage(unsigned target) {
92 // Nothing to do here as image is released after each use or there is no need
93 // to release image.
94 }
95
WillUseTexImage()96 void GLImageEGL::WillUseTexImage() {
97 DCHECK(egl_image_);
98 DCHECK(!in_use_);
99 in_use_ = true;
100 glEGLImageTargetTexture2DOES(target_, egl_image_);
101 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
102 }
103
DidUseTexImage()104 void GLImageEGL::DidUseTexImage() {
105 DCHECK(in_use_);
106 in_use_ = false;
107
108 if (!release_after_use_)
109 return;
110
111 char zero[4] = { 0, };
112 glTexImage2D(target_,
113 0,
114 GL_RGBA,
115 1,
116 1,
117 0,
118 GL_RGBA,
119 GL_UNSIGNED_BYTE,
120 &zero);
121 }
122
SetReleaseAfterUse()123 void GLImageEGL::SetReleaseAfterUse() {
124 release_after_use_ = true;
125 }
126
127 } // namespace gfx
128