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/logging.h"
8 #include "base/trace_event/trace_event.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 bool GLImageMemory::StrideInBytes(size_t width
,
104 gfx::GpuMemoryBuffer::Format format
,
105 size_t* stride_in_bytes
) {
106 base::CheckedNumeric
<size_t> s
= width
;
108 case gfx::GpuMemoryBuffer::RGBA_8888
:
109 case gfx::GpuMemoryBuffer::BGRA_8888
:
114 *stride_in_bytes
= s
.ValueOrDie();
116 case gfx::GpuMemoryBuffer::RGBX_8888
:
125 bool GLImageMemory::Initialize(const unsigned char* memory
,
126 gfx::GpuMemoryBuffer::Format format
) {
127 if (!ValidInternalFormat(internalformat_
)) {
128 LOG(ERROR
) << "Invalid internalformat: " << internalformat_
;
132 if (!ValidFormat(format
)) {
133 LOG(ERROR
) << "Invalid format: " << format
;
144 void GLImageMemory::Destroy(bool have_context
) {
145 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
147 if (egl_image_
!= EGL_NO_IMAGE_KHR
) {
148 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_
);
149 egl_image_
= EGL_NO_IMAGE_KHR
;
152 if (egl_texture_id_
) {
154 glDeleteTextures(1, &egl_texture_id_
);
155 egl_texture_id_
= 0u;
161 gfx::Size
GLImageMemory::GetSize() {
165 bool GLImageMemory::BindTexImage(unsigned target
) {
166 if (target_
&& target_
!= target
) {
167 LOG(ERROR
) << "GLImage can only be bound to one target";
172 // Defer DoBindTexImage if not currently in use.
174 need_do_bind_tex_image_
= true;
178 DoBindTexImage(target
);
182 bool GLImageMemory::CopyTexImage(unsigned target
) {
183 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage");
185 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target.
186 if (target
== GL_TEXTURE_EXTERNAL_OES
)
190 glTexSubImage2D(target
, 0, // level
193 size_
.width(), size_
.height(), DataFormat(format_
),
194 DataType(format_
), memory_
);
199 void GLImageMemory::WillUseTexImage() {
203 if (!need_do_bind_tex_image_
)
207 DoBindTexImage(target_
);
210 void GLImageMemory::DidUseTexImage() {
215 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
217 OverlayTransform transform
,
218 const Rect
& bounds_rect
,
219 const RectF
& crop_rect
) {
223 void GLImageMemory::DoBindTexImage(unsigned target
) {
224 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
226 DCHECK(need_do_bind_tex_image_
);
227 need_do_bind_tex_image_
= false;
230 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
232 if (target
== GL_TEXTURE_EXTERNAL_OES
) {
233 if (egl_image_
== EGL_NO_IMAGE_KHR
) {
234 DCHECK_EQ(0u, egl_texture_id_
);
235 glGenTextures(1, &egl_texture_id_
);
238 ScopedTextureBinder
texture_binder(GL_TEXTURE_2D
, egl_texture_id_
);
240 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
241 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
242 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
243 glTexImage2D(GL_TEXTURE_2D
,
245 TextureFormat(format_
),
254 EGLint attrs
[] = {EGL_IMAGE_PRESERVED_KHR
, EGL_TRUE
, EGL_NONE
};
255 // Need to pass current EGL rendering context to eglCreateImageKHR for
256 // target type EGL_GL_TEXTURE_2D_KHR.
258 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
259 eglGetCurrentContext(),
260 EGL_GL_TEXTURE_2D_KHR
,
261 reinterpret_cast<EGLClientBuffer
>(egl_texture_id_
),
263 DCHECK_NE(EGL_NO_IMAGE_KHR
, egl_image_
)
264 << "Error creating EGLImage: " << eglGetError();
266 ScopedTextureBinder
texture_binder(GL_TEXTURE_2D
, egl_texture_id_
);
268 glTexSubImage2D(GL_TEXTURE_2D
,
279 glEGLImageTargetTexture2DOES(target
, egl_image_
);
280 DCHECK_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
285 DCHECK_NE(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
), target
);
288 TextureFormat(format_
),