Fix search results being clipped in app list.
[chromium-blink-merge.git] / ui / gl / gl_image_memory.cc
blob908ce7eb774736d12530b948b1fdb977c26756c0
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) || \
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_R8:
23 case GL_RGBA:
24 case GL_BGRA_EXT:
25 return true;
26 default:
27 return false;
31 bool ValidFormat(gfx::GpuMemoryBuffer::Format format) {
32 switch (format) {
33 case gfx::GpuMemoryBuffer::ATC:
34 case gfx::GpuMemoryBuffer::ATCIA:
35 case gfx::GpuMemoryBuffer::DXT1:
36 case gfx::GpuMemoryBuffer::DXT5:
37 case gfx::GpuMemoryBuffer::ETC1:
38 case gfx::GpuMemoryBuffer::R_8:
39 case gfx::GpuMemoryBuffer::RGBA_8888:
40 case gfx::GpuMemoryBuffer::BGRA_8888:
41 return true;
42 case gfx::GpuMemoryBuffer::RGBX_8888:
43 case gfx::GpuMemoryBuffer::YUV_420:
44 return false;
47 NOTREACHED();
48 return false;
51 bool IsCompressedFormat(gfx::GpuMemoryBuffer::Format format) {
52 switch (format) {
53 case gfx::GpuMemoryBuffer::ATC:
54 case gfx::GpuMemoryBuffer::ATCIA:
55 case gfx::GpuMemoryBuffer::DXT1:
56 case gfx::GpuMemoryBuffer::DXT5:
57 case gfx::GpuMemoryBuffer::ETC1:
58 case gfx::GpuMemoryBuffer::YUV_420:
59 return true;
60 case gfx::GpuMemoryBuffer::R_8:
61 case gfx::GpuMemoryBuffer::RGBA_8888:
62 case gfx::GpuMemoryBuffer::BGRA_8888:
63 case gfx::GpuMemoryBuffer::RGBX_8888:
64 return false;
67 NOTREACHED();
68 return false;
71 GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) {
72 switch (format) {
73 case gfx::GpuMemoryBuffer::ATC:
74 return GL_ATC_RGB_AMD;
75 case gfx::GpuMemoryBuffer::ATCIA:
76 return GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD;
77 case gfx::GpuMemoryBuffer::DXT1:
78 return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
79 case gfx::GpuMemoryBuffer::DXT5:
80 return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
81 case gfx::GpuMemoryBuffer::ETC1:
82 return GL_ETC1_RGB8_OES;
83 case gfx::GpuMemoryBuffer::R_8:
84 return GL_RED;
85 case gfx::GpuMemoryBuffer::RGBA_8888:
86 return GL_RGBA;
87 case gfx::GpuMemoryBuffer::BGRA_8888:
88 return GL_BGRA_EXT;
89 case gfx::GpuMemoryBuffer::RGBX_8888:
90 case gfx::GpuMemoryBuffer::YUV_420:
91 NOTREACHED();
92 return 0;
95 NOTREACHED();
96 return 0;
99 GLenum DataFormat(gfx::GpuMemoryBuffer::Format format) {
100 return TextureFormat(format);
103 GLenum DataType(gfx::GpuMemoryBuffer::Format format) {
104 switch (format) {
105 case gfx::GpuMemoryBuffer::RGBA_8888:
106 case gfx::GpuMemoryBuffer::BGRA_8888:
107 case gfx::GpuMemoryBuffer::R_8:
108 return GL_UNSIGNED_BYTE;
109 case gfx::GpuMemoryBuffer::ATC:
110 case gfx::GpuMemoryBuffer::ATCIA:
111 case gfx::GpuMemoryBuffer::DXT1:
112 case gfx::GpuMemoryBuffer::DXT5:
113 case gfx::GpuMemoryBuffer::ETC1:
114 case gfx::GpuMemoryBuffer::RGBX_8888:
115 case gfx::GpuMemoryBuffer::YUV_420:
116 NOTREACHED();
117 return 0;
120 NOTREACHED();
121 return 0;
124 GLsizei SizeInBytes(const gfx::Size& size,
125 gfx::GpuMemoryBuffer::Format format) {
126 size_t stride_in_bytes = 0;
127 bool valid_stride = GLImageMemory::StrideInBytes(
128 size.width(), format, &stride_in_bytes);
129 DCHECK(valid_stride);
130 return static_cast<GLsizei>(stride_in_bytes * size.height());
133 } // namespace
135 GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat)
136 : size_(size),
137 internalformat_(internalformat),
138 memory_(NULL),
139 format_(gfx::GpuMemoryBuffer::RGBA_8888),
140 in_use_(false),
141 target_(0),
142 need_do_bind_tex_image_(false)
143 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
144 defined(USE_OZONE)
146 egl_texture_id_(0u),
147 egl_image_(EGL_NO_IMAGE_KHR)
148 #endif
152 GLImageMemory::~GLImageMemory() {
153 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
154 defined(USE_OZONE)
155 DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
156 DCHECK_EQ(0u, egl_texture_id_);
157 #endif
160 // static
161 bool GLImageMemory::StrideInBytes(size_t width,
162 gfx::GpuMemoryBuffer::Format format,
163 size_t* stride_in_bytes) {
164 base::CheckedNumeric<size_t> checked_stride = width;
165 switch (format) {
166 case gfx::GpuMemoryBuffer::ATCIA:
167 case gfx::GpuMemoryBuffer::DXT5:
168 *stride_in_bytes = width;
169 return true;
170 case gfx::GpuMemoryBuffer::ATC:
171 case gfx::GpuMemoryBuffer::DXT1:
172 case gfx::GpuMemoryBuffer::ETC1:
173 DCHECK_EQ(width % 2, 0u);
174 *stride_in_bytes = width / 2;
175 return true;
176 case gfx::GpuMemoryBuffer::R_8:
177 checked_stride += 3;
178 if (!checked_stride.IsValid())
179 return false;
180 *stride_in_bytes = checked_stride.ValueOrDie() & ~0x3;
181 return true;
182 case gfx::GpuMemoryBuffer::RGBA_8888:
183 case gfx::GpuMemoryBuffer::BGRA_8888:
184 checked_stride *= 4;
185 if (!checked_stride.IsValid())
186 return false;
187 *stride_in_bytes = checked_stride.ValueOrDie();
188 return true;
189 case gfx::GpuMemoryBuffer::RGBX_8888:
190 case gfx::GpuMemoryBuffer::YUV_420:
191 NOTREACHED();
192 return false;
195 NOTREACHED();
196 return false;
199 bool GLImageMemory::Initialize(const unsigned char* memory,
200 gfx::GpuMemoryBuffer::Format format) {
201 if (!ValidInternalFormat(internalformat_)) {
202 LOG(ERROR) << "Invalid internalformat: " << internalformat_;
203 return false;
206 if (!ValidFormat(format)) {
207 LOG(ERROR) << "Invalid format: " << format;
208 return false;
211 DCHECK(memory);
212 DCHECK(!memory_);
213 DCHECK_IMPLIES(IsCompressedFormat(format), size_.width() % 4 == 0);
214 DCHECK_IMPLIES(IsCompressedFormat(format), size_.height() % 4 == 0);
215 memory_ = memory;
216 format_ = format;
217 return true;
220 void GLImageMemory::Destroy(bool have_context) {
221 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
222 defined(USE_OZONE)
223 if (egl_image_ != EGL_NO_IMAGE_KHR) {
224 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
225 egl_image_ = EGL_NO_IMAGE_KHR;
228 if (egl_texture_id_) {
229 if (have_context)
230 glDeleteTextures(1, &egl_texture_id_);
231 egl_texture_id_ = 0u;
233 #endif
234 memory_ = NULL;
237 gfx::Size GLImageMemory::GetSize() {
238 return size_;
241 bool GLImageMemory::BindTexImage(unsigned target) {
242 if (target_ && target_ != target) {
243 LOG(ERROR) << "GLImage can only be bound to one target";
244 return false;
246 target_ = target;
248 // Defer DoBindTexImage if not currently in use.
249 if (!in_use_) {
250 need_do_bind_tex_image_ = true;
251 return true;
254 DoBindTexImage(target);
255 return true;
258 bool GLImageMemory::CopyTexImage(unsigned target) {
259 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage");
261 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target.
262 if (target == GL_TEXTURE_EXTERNAL_OES)
263 return false;
265 DCHECK(memory_);
266 if (IsCompressedFormat(format_)) {
267 glCompressedTexSubImage2D(target,
268 0, // level
269 0, // x-offset
270 0, // y-offset
271 size_.width(), size_.height(),
272 DataFormat(format_), SizeInBytes(size_, format_),
273 memory_);
274 } else {
275 glTexSubImage2D(target, 0, // level
276 0, // x
277 0, // y
278 size_.width(), size_.height(), DataFormat(format_),
279 DataType(format_), memory_);
282 return true;
285 void GLImageMemory::WillUseTexImage() {
286 DCHECK(!in_use_);
287 in_use_ = true;
289 if (!need_do_bind_tex_image_)
290 return;
292 DCHECK(target_);
293 DoBindTexImage(target_);
296 void GLImageMemory::DidUseTexImage() {
297 DCHECK(in_use_);
298 in_use_ = false;
301 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
302 int z_order,
303 OverlayTransform transform,
304 const Rect& bounds_rect,
305 const RectF& crop_rect) {
306 return false;
309 void GLImageMemory::DoBindTexImage(unsigned target) {
310 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
312 DCHECK(need_do_bind_tex_image_);
313 need_do_bind_tex_image_ = false;
315 DCHECK(memory_);
316 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
317 defined(USE_OZONE)
318 if (target == GL_TEXTURE_EXTERNAL_OES) {
319 if (egl_image_ == EGL_NO_IMAGE_KHR) {
320 DCHECK_EQ(0u, egl_texture_id_);
321 glGenTextures(1, &egl_texture_id_);
324 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
329 if (IsCompressedFormat(format_)) {
330 glCompressedTexImage2D(GL_TEXTURE_2D,
331 0, // mip level
332 TextureFormat(format_), size_.width(),
333 size_.height(),
334 0, // border
335 SizeInBytes(size_, format_), memory_);
336 } else {
337 glTexImage2D(GL_TEXTURE_2D,
338 0, // mip level
339 TextureFormat(format_),
340 size_.width(),
341 size_.height(),
342 0, // border
343 DataFormat(format_),
344 DataType(format_),
345 memory_);
349 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
350 // Need to pass current EGL rendering context to eglCreateImageKHR for
351 // target type EGL_GL_TEXTURE_2D_KHR.
352 egl_image_ =
353 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
354 eglGetCurrentContext(),
355 EGL_GL_TEXTURE_2D_KHR,
356 reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
357 attrs);
358 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
359 << "Error creating EGLImage: " << eglGetError();
360 } else {
361 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
363 if (IsCompressedFormat(format_)) {
364 glCompressedTexSubImage2D(GL_TEXTURE_2D,
365 0, // mip level
366 0, // x-offset
367 0, // y-offset
368 size_.width(), size_.height(),
369 DataFormat(format_),
370 SizeInBytes(size_, format_), memory_);
371 } else {
372 glTexSubImage2D(GL_TEXTURE_2D,
373 0, // mip level
374 0, // x-offset
375 0, // y-offset
376 size_.width(),
377 size_.height(),
378 DataFormat(format_),
379 DataType(format_),
380 memory_);
384 glEGLImageTargetTexture2DOES(target, egl_image_);
385 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
386 return;
388 #endif
390 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
391 if (IsCompressedFormat(format_)) {
392 glCompressedTexImage2D(target,
393 0, // mip level
394 TextureFormat(format_), size_.width(),
395 size_.height(),
396 0, // border
397 SizeInBytes(size_, format_), memory_);
398 } else {
399 glTexImage2D(target,
400 0, // mip level
401 TextureFormat(format_),
402 size_.width(),
403 size_.height(),
404 0, // border
405 DataFormat(format_),
406 DataType(format_),
407 memory_);
411 } // namespace gfx