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)
184 TextureFormat(format_),
195 void GLImageMemory::WillUseTexImage() {
199 if (!need_do_bind_tex_image_)
203 DoBindTexImage(target_);
206 void GLImageMemory::DidUseTexImage() {
211 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
213 OverlayTransform transform,
214 const Rect& bounds_rect,
215 const RectF& crop_rect) {
219 void GLImageMemory::DoBindTexImage(unsigned target) {
220 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
222 DCHECK(need_do_bind_tex_image_);
223 need_do_bind_tex_image_ = false;
226 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
228 if (target == GL_TEXTURE_EXTERNAL_OES) {
229 if (egl_image_ == EGL_NO_IMAGE_KHR) {
230 DCHECK_EQ(0u, egl_texture_id_);
231 glGenTextures(1, &egl_texture_id_);
234 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
239 glTexImage2D(GL_TEXTURE_2D,
241 TextureFormat(format_),
250 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
251 // Need to pass current EGL rendering context to eglCreateImageKHR for
252 // target type EGL_GL_TEXTURE_2D_KHR.
254 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
255 eglGetCurrentContext(),
256 EGL_GL_TEXTURE_2D_KHR,
257 reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
259 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
260 << "Error creating EGLImage: " << eglGetError();
262 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
264 glTexSubImage2D(GL_TEXTURE_2D,
275 glEGLImageTargetTexture2DOES(target, egl_image_);
276 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
281 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
284 TextureFormat(format_),