Roll src/third_party/WebKit 6f84130:7353389 (svn 184386:184391)
[chromium-blink-merge.git] / ui / gl / gl_image_memory.cc
bloba752940615fd9a6b7cb10bc6f2772468fbd63050
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) || \
13 defined(USE_OZONE)
14 #include "ui/gl/gl_surface_egl.h"
15 #endif
17 namespace gfx {
18 namespace {
20 bool ValidInternalFormat(unsigned internalformat) {
21 switch (internalformat) {
22 case GL_RGBA:
23 return true;
24 default:
25 return false;
29 bool ValidFormat(gfx::GpuMemoryBuffer::Format format) {
30 switch (format) {
31 case gfx::GpuMemoryBuffer::RGBA_8888:
32 case gfx::GpuMemoryBuffer::BGRA_8888:
33 return true;
34 case gfx::GpuMemoryBuffer::RGBX_8888:
35 return false;
38 NOTREACHED();
39 return false;
42 GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) {
43 switch (format) {
44 case gfx::GpuMemoryBuffer::RGBA_8888:
45 return GL_RGBA;
46 case gfx::GpuMemoryBuffer::BGRA_8888:
47 return GL_BGRA_EXT;
48 case gfx::GpuMemoryBuffer::RGBX_8888:
49 NOTREACHED();
50 return 0;
53 NOTREACHED();
54 return 0;
57 GLenum DataFormat(gfx::GpuMemoryBuffer::Format format) {
58 return TextureFormat(format);
61 GLenum DataType(gfx::GpuMemoryBuffer::Format format) {
62 switch (format) {
63 case gfx::GpuMemoryBuffer::RGBA_8888:
64 case gfx::GpuMemoryBuffer::BGRA_8888:
65 return GL_UNSIGNED_BYTE;
66 case gfx::GpuMemoryBuffer::RGBX_8888:
67 NOTREACHED();
68 return 0;
71 NOTREACHED();
72 return 0;
75 } // namespace
77 GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat)
78 : size_(size),
79 internalformat_(internalformat),
80 memory_(NULL),
81 format_(gfx::GpuMemoryBuffer::RGBA_8888),
82 in_use_(false),
83 target_(0),
84 need_do_bind_tex_image_(false)
85 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
86 defined(USE_OZONE)
88 egl_texture_id_(0u),
89 egl_image_(EGL_NO_IMAGE_KHR)
90 #endif
94 GLImageMemory::~GLImageMemory() {
95 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
96 defined(USE_OZONE)
97 DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
98 DCHECK_EQ(0u, egl_texture_id_);
99 #endif
102 // static
103 size_t GLImageMemory::BytesPerPixel(gfx::GpuMemoryBuffer::Format format) {
104 switch (format) {
105 case gfx::GpuMemoryBuffer::RGBA_8888:
106 case gfx::GpuMemoryBuffer::BGRA_8888:
107 return 4;
108 case gfx::GpuMemoryBuffer::RGBX_8888:
109 NOTREACHED();
110 return 0;
113 NOTREACHED();
114 return 0;
117 bool GLImageMemory::Initialize(const unsigned char* memory,
118 gfx::GpuMemoryBuffer::Format format) {
119 if (!ValidInternalFormat(internalformat_)) {
120 LOG(ERROR) << "Invalid internalformat: " << internalformat_;
121 return false;
124 if (!ValidFormat(format)) {
125 LOG(ERROR) << "Invalid format: " << format;
126 return false;
129 DCHECK(memory);
130 DCHECK(!memory_);
131 memory_ = memory;
132 format_ = format;
133 return true;
136 void GLImageMemory::Destroy(bool have_context) {
137 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
138 defined(USE_OZONE)
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_) {
145 if (have_context)
146 glDeleteTextures(1, &egl_texture_id_);
147 egl_texture_id_ = 0u;
149 #endif
150 memory_ = NULL;
153 gfx::Size GLImageMemory::GetSize() {
154 return size_;
157 bool GLImageMemory::BindTexImage(unsigned target) {
158 if (target_ && target_ != target) {
159 LOG(ERROR) << "GLImage can only be bound to one target";
160 return false;
162 target_ = target;
164 // Defer DoBindTexImage if not currently in use.
165 if (!in_use_) {
166 need_do_bind_tex_image_ = true;
167 return true;
170 DoBindTexImage(target);
171 return true;
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)
179 return false;
181 DCHECK(memory_);
182 glTexImage2D(target,
183 0, // mip level
184 TextureFormat(format_),
185 size_.width(),
186 size_.height(),
187 0, // border
188 DataFormat(format_),
189 DataType(format_),
190 memory_);
192 return true;
195 void GLImageMemory::WillUseTexImage() {
196 DCHECK(!in_use_);
197 in_use_ = true;
199 if (!need_do_bind_tex_image_)
200 return;
202 DCHECK(target_);
203 DoBindTexImage(target_);
206 void GLImageMemory::DidUseTexImage() {
207 DCHECK(in_use_);
208 in_use_ = false;
211 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
212 int z_order,
213 OverlayTransform transform,
214 const Rect& bounds_rect,
215 const RectF& crop_rect) {
216 return false;
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;
225 DCHECK(memory_);
226 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
227 defined(USE_OZONE)
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,
240 0, // mip level
241 TextureFormat(format_),
242 size_.width(),
243 size_.height(),
244 0, // border
245 DataFormat(format_),
246 DataType(format_),
247 memory_);
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.
253 egl_image_ =
254 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
255 eglGetCurrentContext(),
256 EGL_GL_TEXTURE_2D_KHR,
257 reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
258 attrs);
259 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
260 << "Error creating EGLImage: " << eglGetError();
261 } else {
262 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
264 glTexSubImage2D(GL_TEXTURE_2D,
265 0, // mip level
266 0, // x-offset
267 0, // y-offset
268 size_.width(),
269 size_.height(),
270 DataFormat(format_),
271 DataType(format_),
272 memory_);
275 glEGLImageTargetTexture2DOES(target, egl_image_);
276 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
277 return;
279 #endif
281 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
282 glTexImage2D(target,
283 0, // mip level
284 TextureFormat(format_),
285 size_.width(),
286 size_.height(),
287 0, // border
288 DataFormat(format_),
289 DataType(format_),
290 memory_);
293 } // namespace gfx