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 ValidInternalFormat(unsigned internalformat
) {
21 switch (internalformat
) {
29 bool ValidFormat(gfx::GpuMemoryBuffer::Format format
) {
31 case gfx::GpuMemoryBuffer::RGBA_8888
:
32 case gfx::GpuMemoryBuffer::BGRA_8888
:
34 case gfx::GpuMemoryBuffer::RGBX_8888
:
42 GLenum
TextureFormat(gfx::GpuMemoryBuffer::Format format
) {
44 case gfx::GpuMemoryBuffer::RGBA_8888
:
46 case gfx::GpuMemoryBuffer::BGRA_8888
:
48 case gfx::GpuMemoryBuffer::RGBX_8888
:
57 GLenum
DataFormat(gfx::GpuMemoryBuffer::Format format
) {
58 return TextureFormat(format
);
61 GLenum
DataType(gfx::GpuMemoryBuffer::Format format
) {
63 case gfx::GpuMemoryBuffer::RGBA_8888
:
64 case gfx::GpuMemoryBuffer::BGRA_8888
:
65 return GL_UNSIGNED_BYTE
;
66 case gfx::GpuMemoryBuffer::RGBX_8888
:
77 GLImageMemory::GLImageMemory(const gfx::Size
& size
, unsigned internalformat
)
79 internalformat_(internalformat
),
81 format_(gfx::GpuMemoryBuffer::RGBA_8888
),
84 need_do_bind_tex_image_(false)
85 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
89 egl_image_(EGL_NO_IMAGE_KHR
)
94 GLImageMemory::~GLImageMemory() {
95 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
97 DCHECK_EQ(EGL_NO_IMAGE_KHR
, egl_image_
);
98 DCHECK_EQ(0u, egl_texture_id_
);
103 size_t GLImageMemory::BytesPerPixel(gfx::GpuMemoryBuffer::Format format
) {
105 case gfx::GpuMemoryBuffer::RGBA_8888
:
106 case gfx::GpuMemoryBuffer::BGRA_8888
:
108 case gfx::GpuMemoryBuffer::RGBX_8888
:
117 bool GLImageMemory::Initialize(const unsigned char* memory
,
118 gfx::GpuMemoryBuffer::Format format
) {
119 if (!ValidInternalFormat(internalformat_
)) {
120 LOG(ERROR
) << "Invalid internalformat: " << internalformat_
;
124 if (!ValidFormat(format
)) {
125 LOG(ERROR
) << "Invalid format: " << format
;
136 void GLImageMemory::Destroy(bool have_context
) {
137 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
139 if (egl_image_
!= EGL_NO_IMAGE_KHR
) {
140 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_
);
141 egl_image_
= EGL_NO_IMAGE_KHR
;
144 if (egl_texture_id_
) {
146 glDeleteTextures(1, &egl_texture_id_
);
147 egl_texture_id_
= 0u;
153 gfx::Size
GLImageMemory::GetSize() {
157 bool GLImageMemory::BindTexImage(unsigned target
) {
158 if (target_
&& target_
!= target
) {
159 LOG(ERROR
) << "GLImage can only be bound to one target";
164 // Defer DoBindTexImage if not currently in use.
166 need_do_bind_tex_image_
= true;
170 DoBindTexImage(target
);
174 bool GLImageMemory::CopyTexImage(unsigned target
) {
175 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage");
177 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target.
178 if (target
== GL_TEXTURE_EXTERNAL_OES
)
182 glTexSubImage2D(target
, 0, // level
185 size_
.width(), size_
.height(), DataFormat(format_
),
186 DataType(format_
), memory_
);
191 void GLImageMemory::WillUseTexImage() {
195 if (!need_do_bind_tex_image_
)
199 DoBindTexImage(target_
);
202 void GLImageMemory::DidUseTexImage() {
207 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
209 OverlayTransform transform
,
210 const Rect
& bounds_rect
,
211 const RectF
& crop_rect
) {
215 void GLImageMemory::DoBindTexImage(unsigned target
) {
216 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
218 DCHECK(need_do_bind_tex_image_
);
219 need_do_bind_tex_image_
= false;
222 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
224 if (target
== GL_TEXTURE_EXTERNAL_OES
) {
225 if (egl_image_
== EGL_NO_IMAGE_KHR
) {
226 DCHECK_EQ(0u, egl_texture_id_
);
227 glGenTextures(1, &egl_texture_id_
);
230 ScopedTextureBinder
texture_binder(GL_TEXTURE_2D
, egl_texture_id_
);
232 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
233 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
234 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
235 glTexImage2D(GL_TEXTURE_2D
,
237 TextureFormat(format_
),
246 EGLint attrs
[] = {EGL_IMAGE_PRESERVED_KHR
, EGL_TRUE
, EGL_NONE
};
247 // Need to pass current EGL rendering context to eglCreateImageKHR for
248 // target type EGL_GL_TEXTURE_2D_KHR.
250 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
251 eglGetCurrentContext(),
252 EGL_GL_TEXTURE_2D_KHR
,
253 reinterpret_cast<EGLClientBuffer
>(egl_texture_id_
),
255 DCHECK_NE(EGL_NO_IMAGE_KHR
, egl_image_
)
256 << "Error creating EGLImage: " << eglGetError();
258 ScopedTextureBinder
texture_binder(GL_TEXTURE_2D
, egl_texture_id_
);
260 glTexSubImage2D(GL_TEXTURE_2D
,
271 glEGLImageTargetTexture2DOES(target
, egl_image_
);
272 DCHECK_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
277 DCHECK_NE(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
), target
);
280 TextureFormat(format_
),