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.
5 #include "ui/gl/gl_image_memory.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "ui/gl/gl_bindings.h"
10 #include "ui/gl/scoped_binders.h"
12 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
14 #include "ui/gl/gl_surface_egl.h"
20 bool ValidFormat(unsigned internalformat
) {
21 switch (internalformat
) {
30 GLenum
TextureFormat(unsigned internalformat
) {
31 switch (internalformat
) {
42 GLenum
DataFormat(unsigned internalformat
) {
43 return TextureFormat(internalformat
);
46 GLenum
DataType(unsigned internalformat
) {
47 switch (internalformat
) {
50 return GL_UNSIGNED_BYTE
;
57 int BytesPerPixel(unsigned internalformat
) {
58 switch (internalformat
) {
70 GLImageMemory::GLImageMemory(const gfx::Size
& size
, unsigned internalformat
)
73 internalformat_(internalformat
),
76 need_do_bind_tex_image_(false)
77 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
81 egl_image_(EGL_NO_IMAGE_KHR
)
86 GLImageMemory::~GLImageMemory() {
87 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
89 DCHECK_EQ(EGL_NO_IMAGE_KHR
, egl_image_
);
90 DCHECK_EQ(0u, egl_texture_id_
);
94 bool GLImageMemory::Initialize(const unsigned char* memory
) {
95 if (!ValidFormat(internalformat_
)) {
96 DVLOG(0) << "Invalid format: " << internalformat_
;
106 void GLImageMemory::Destroy(bool have_context
) {
107 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
109 if (egl_image_
!= EGL_NO_IMAGE_KHR
) {
110 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_
);
111 egl_image_
= EGL_NO_IMAGE_KHR
;
114 if (egl_texture_id_
) {
116 glDeleteTextures(1, &egl_texture_id_
);
117 egl_texture_id_
= 0u;
123 gfx::Size
GLImageMemory::GetSize() {
127 bool GLImageMemory::BindTexImage(unsigned target
) {
128 if (target_
&& target_
!= target
) {
129 LOG(ERROR
) << "GLImage can only be bound to one target";
134 // Defer DoBindTexImage if not currently in use.
136 need_do_bind_tex_image_
= true;
140 DoBindTexImage(target
);
144 bool GLImageMemory::CopyTexImage(unsigned target
) {
145 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage");
147 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target.
148 if (target
== GL_TEXTURE_EXTERNAL_OES
)
154 TextureFormat(internalformat_
),
158 DataFormat(internalformat_
),
159 DataType(internalformat_
),
165 void GLImageMemory::WillUseTexImage() {
169 if (!need_do_bind_tex_image_
)
173 DoBindTexImage(target_
);
176 void GLImageMemory::DidUseTexImage() {
181 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
183 OverlayTransform transform
,
184 const Rect
& bounds_rect
,
185 const RectF
& crop_rect
) {
189 bool GLImageMemory::HasValidFormat() const {
190 return ValidFormat(internalformat_
);
193 size_t GLImageMemory::Bytes() const {
194 return size_
.GetArea() * BytesPerPixel(internalformat_
);
197 void GLImageMemory::DoBindTexImage(unsigned target
) {
198 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
200 DCHECK(need_do_bind_tex_image_
);
201 need_do_bind_tex_image_
= false;
204 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
206 if (target
== GL_TEXTURE_EXTERNAL_OES
) {
207 if (egl_image_
== EGL_NO_IMAGE_KHR
) {
208 DCHECK_EQ(0u, egl_texture_id_
);
209 glGenTextures(1, &egl_texture_id_
);
212 ScopedTextureBinder
texture_binder(GL_TEXTURE_2D
, egl_texture_id_
);
214 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
215 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
216 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
217 glTexImage2D(GL_TEXTURE_2D
,
219 TextureFormat(internalformat_
),
223 DataFormat(internalformat_
),
224 DataType(internalformat_
),
228 EGLint attrs
[] = {EGL_IMAGE_PRESERVED_KHR
, EGL_TRUE
, EGL_NONE
};
229 // Need to pass current EGL rendering context to eglCreateImageKHR for
230 // target type EGL_GL_TEXTURE_2D_KHR.
232 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
233 eglGetCurrentContext(),
234 EGL_GL_TEXTURE_2D_KHR
,
235 reinterpret_cast<EGLClientBuffer
>(egl_texture_id_
),
237 DCHECK_NE(EGL_NO_IMAGE_KHR
, egl_image_
)
238 << "Error creating EGLImage: " << eglGetError();
240 ScopedTextureBinder
texture_binder(GL_TEXTURE_2D
, egl_texture_id_
);
242 glTexSubImage2D(GL_TEXTURE_2D
,
248 DataFormat(internalformat_
),
249 DataType(internalformat_
),
253 glEGLImageTargetTexture2DOES(target
, egl_image_
);
254 DCHECK_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
259 DCHECK_NE(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
), target
);
262 TextureFormat(internalformat_
),
266 DataFormat(internalformat_
),
267 DataType(internalformat_
),