Update {virtual,override,final} for crypto/ to follow C++11 style.
[chromium-blink-merge.git] / ui / gl / gl_image_memory.cc
blob0a67e000665b6a5806a0f935f61e02faaf540a15
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 glTexSubImage2D(target, 0, // level
183 0, // x
184 0, // y
185 size_.width(), size_.height(), DataFormat(format_),
186 DataType(format_), memory_);
188 return true;
191 void GLImageMemory::WillUseTexImage() {
192 DCHECK(!in_use_);
193 in_use_ = true;
195 if (!need_do_bind_tex_image_)
196 return;
198 DCHECK(target_);
199 DoBindTexImage(target_);
202 void GLImageMemory::DidUseTexImage() {
203 DCHECK(in_use_);
204 in_use_ = false;
207 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
208 int z_order,
209 OverlayTransform transform,
210 const Rect& bounds_rect,
211 const RectF& crop_rect) {
212 return false;
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;
221 DCHECK(memory_);
222 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
223 defined(USE_OZONE)
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,
236 0, // mip level
237 TextureFormat(format_),
238 size_.width(),
239 size_.height(),
240 0, // border
241 DataFormat(format_),
242 DataType(format_),
243 memory_);
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.
249 egl_image_ =
250 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
251 eglGetCurrentContext(),
252 EGL_GL_TEXTURE_2D_KHR,
253 reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
254 attrs);
255 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
256 << "Error creating EGLImage: " << eglGetError();
257 } else {
258 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
260 glTexSubImage2D(GL_TEXTURE_2D,
261 0, // mip level
262 0, // x-offset
263 0, // y-offset
264 size_.width(),
265 size_.height(),
266 DataFormat(format_),
267 DataType(format_),
268 memory_);
271 glEGLImageTargetTexture2DOES(target, egl_image_);
272 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
273 return;
275 #endif
277 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
278 glTexImage2D(target,
279 0, // mip level
280 TextureFormat(format_),
281 size_.width(),
282 size_.height(),
283 0, // border
284 DataFormat(format_),
285 DataType(format_),
286 memory_);
289 } // namespace gfx