OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/gl_image_memory.h" | 5 #include "ui/gl/gl_image_memory.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/trace_event/trace_event.h" | 8 #include "base/trace_event/trace_event.h" |
9 #include "ui/gl/gl_bindings.h" | 9 #include "ui/gl/gl_bindings.h" |
10 #include "ui/gl/scoped_binders.h" | 10 #include "ui/gl/scoped_binders.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 switch (internalformat) { | 21 switch (internalformat) { |
22 case GL_RGBA: | 22 case GL_RGBA: |
23 return true; | 23 return true; |
24 default: | 24 default: |
25 return false; | 25 return false; |
26 } | 26 } |
27 } | 27 } |
28 | 28 |
29 bool ValidFormat(gfx::GpuMemoryBuffer::Format format) { | 29 bool ValidFormat(gfx::GpuMemoryBuffer::Format format) { |
30 switch (format) { | 30 switch (format) { |
| 31 case gfx::GpuMemoryBuffer::ATC: |
| 32 case gfx::GpuMemoryBuffer::ATCIA: |
| 33 case gfx::GpuMemoryBuffer::DXT1: |
| 34 case gfx::GpuMemoryBuffer::DXT5: |
| 35 case gfx::GpuMemoryBuffer::ETC1: |
31 case gfx::GpuMemoryBuffer::RGBA_8888: | 36 case gfx::GpuMemoryBuffer::RGBA_8888: |
32 case gfx::GpuMemoryBuffer::BGRA_8888: | 37 case gfx::GpuMemoryBuffer::BGRA_8888: |
33 return true; | 38 return true; |
34 case gfx::GpuMemoryBuffer::RGBX_8888: | 39 case gfx::GpuMemoryBuffer::RGBX_8888: |
35 return false; | 40 return false; |
36 } | 41 } |
37 | 42 |
38 NOTREACHED(); | 43 NOTREACHED(); |
39 return false; | 44 return false; |
40 } | 45 } |
41 | 46 |
| 47 bool IsCompressedFormat(gfx::GpuMemoryBuffer::Format format) { |
| 48 switch (format) { |
| 49 case gfx::GpuMemoryBuffer::ATC: |
| 50 case gfx::GpuMemoryBuffer::ATCIA: |
| 51 case gfx::GpuMemoryBuffer::DXT1: |
| 52 case gfx::GpuMemoryBuffer::DXT5: |
| 53 case gfx::GpuMemoryBuffer::ETC1: |
| 54 return true; |
| 55 case gfx::GpuMemoryBuffer::RGBA_8888: |
| 56 case gfx::GpuMemoryBuffer::BGRA_8888: |
| 57 case gfx::GpuMemoryBuffer::RGBX_8888: |
| 58 return false; |
| 59 } |
| 60 |
| 61 NOTREACHED(); |
| 62 return false; |
| 63 } |
| 64 |
42 GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) { | 65 GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) { |
43 switch (format) { | 66 switch (format) { |
| 67 case gfx::GpuMemoryBuffer::ATC: |
| 68 return GL_ATC_RGB_AMD; |
| 69 case gfx::GpuMemoryBuffer::ATCIA: |
| 70 return GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD; |
| 71 case gfx::GpuMemoryBuffer::DXT1: |
| 72 return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; |
| 73 case gfx::GpuMemoryBuffer::DXT5: |
| 74 return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; |
| 75 case gfx::GpuMemoryBuffer::ETC1: |
| 76 return GL_ETC1_RGB8_OES; |
44 case gfx::GpuMemoryBuffer::RGBA_8888: | 77 case gfx::GpuMemoryBuffer::RGBA_8888: |
45 return GL_RGBA; | 78 return GL_RGBA; |
46 case gfx::GpuMemoryBuffer::BGRA_8888: | 79 case gfx::GpuMemoryBuffer::BGRA_8888: |
47 return GL_BGRA_EXT; | 80 return GL_BGRA_EXT; |
48 case gfx::GpuMemoryBuffer::RGBX_8888: | 81 case gfx::GpuMemoryBuffer::RGBX_8888: |
49 NOTREACHED(); | 82 NOTREACHED(); |
50 return 0; | 83 return 0; |
51 } | 84 } |
52 | 85 |
53 NOTREACHED(); | 86 NOTREACHED(); |
54 return 0; | 87 return 0; |
55 } | 88 } |
56 | 89 |
57 GLenum DataFormat(gfx::GpuMemoryBuffer::Format format) { | 90 GLenum DataFormat(gfx::GpuMemoryBuffer::Format format) { |
58 return TextureFormat(format); | 91 return TextureFormat(format); |
59 } | 92 } |
60 | 93 |
61 GLenum DataType(gfx::GpuMemoryBuffer::Format format) { | 94 GLenum DataType(gfx::GpuMemoryBuffer::Format format) { |
62 switch (format) { | 95 switch (format) { |
63 case gfx::GpuMemoryBuffer::RGBA_8888: | 96 case gfx::GpuMemoryBuffer::RGBA_8888: |
64 case gfx::GpuMemoryBuffer::BGRA_8888: | 97 case gfx::GpuMemoryBuffer::BGRA_8888: |
65 return GL_UNSIGNED_BYTE; | 98 return GL_UNSIGNED_BYTE; |
| 99 case gfx::GpuMemoryBuffer::ATC: |
| 100 case gfx::GpuMemoryBuffer::ATCIA: |
| 101 case gfx::GpuMemoryBuffer::DXT1: |
| 102 case gfx::GpuMemoryBuffer::DXT5: |
| 103 case gfx::GpuMemoryBuffer::ETC1: |
66 case gfx::GpuMemoryBuffer::RGBX_8888: | 104 case gfx::GpuMemoryBuffer::RGBX_8888: |
67 NOTREACHED(); | 105 NOTREACHED(); |
68 return 0; | 106 return 0; |
69 } | 107 } |
70 | 108 |
71 NOTREACHED(); | 109 NOTREACHED(); |
72 return 0; | 110 return 0; |
73 } | 111 } |
74 | 112 |
| 113 GLsizei SizeInBytes(const gfx::Size& size, |
| 114 gfx::GpuMemoryBuffer::Format format) { |
| 115 size_t stride_in_bytes = 0; |
| 116 bool valid_stride = GLImageMemory::StrideInBytes( |
| 117 size.width(), format, &stride_in_bytes); |
| 118 DCHECK(valid_stride); |
| 119 return static_cast<GLsizei>(stride_in_bytes * size.height()); |
| 120 } |
| 121 |
75 } // namespace | 122 } // namespace |
76 | 123 |
77 GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat) | 124 GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat) |
78 : size_(size), | 125 : size_(size), |
79 internalformat_(internalformat), | 126 internalformat_(internalformat), |
80 memory_(NULL), | 127 memory_(NULL), |
81 format_(gfx::GpuMemoryBuffer::RGBA_8888), | 128 format_(gfx::GpuMemoryBuffer::RGBA_8888), |
82 in_use_(false), | 129 in_use_(false), |
83 target_(0), | 130 target_(0), |
84 need_do_bind_tex_image_(false) | 131 need_do_bind_tex_image_(false) |
(...skipping 13 matching lines...) Expand all Loading... |
98 DCHECK_EQ(0u, egl_texture_id_); | 145 DCHECK_EQ(0u, egl_texture_id_); |
99 #endif | 146 #endif |
100 } | 147 } |
101 | 148 |
102 // static | 149 // static |
103 bool GLImageMemory::StrideInBytes(size_t width, | 150 bool GLImageMemory::StrideInBytes(size_t width, |
104 gfx::GpuMemoryBuffer::Format format, | 151 gfx::GpuMemoryBuffer::Format format, |
105 size_t* stride_in_bytes) { | 152 size_t* stride_in_bytes) { |
106 base::CheckedNumeric<size_t> s = width; | 153 base::CheckedNumeric<size_t> s = width; |
107 switch (format) { | 154 switch (format) { |
| 155 case gfx::GpuMemoryBuffer::ATCIA: |
| 156 case gfx::GpuMemoryBuffer::DXT5: |
| 157 *stride_in_bytes = width; |
| 158 return true; |
| 159 case gfx::GpuMemoryBuffer::ATC: |
| 160 case gfx::GpuMemoryBuffer::DXT1: |
| 161 case gfx::GpuMemoryBuffer::ETC1: |
| 162 DCHECK_EQ(width % 2, 0U); |
| 163 s /= 2; |
| 164 if (!s.IsValid()) |
| 165 return false; |
| 166 |
| 167 *stride_in_bytes = s.ValueOrDie(); |
| 168 return true; |
108 case gfx::GpuMemoryBuffer::RGBA_8888: | 169 case gfx::GpuMemoryBuffer::RGBA_8888: |
109 case gfx::GpuMemoryBuffer::BGRA_8888: | 170 case gfx::GpuMemoryBuffer::BGRA_8888: |
110 s *= 4; | 171 s *= 4; |
111 if (!s.IsValid()) | 172 if (!s.IsValid()) |
112 return false; | 173 return false; |
113 | 174 |
114 *stride_in_bytes = s.ValueOrDie(); | 175 *stride_in_bytes = s.ValueOrDie(); |
115 return true; | 176 return true; |
116 case gfx::GpuMemoryBuffer::RGBX_8888: | 177 case gfx::GpuMemoryBuffer::RGBX_8888: |
117 NOTREACHED(); | 178 NOTREACHED(); |
118 return false; | 179 return false; |
119 } | 180 } |
120 | 181 |
121 NOTREACHED(); | 182 NOTREACHED(); |
122 return false; | 183 return false; |
123 } | 184 } |
124 | 185 |
| 186 // static |
| 187 bool GLImageMemory::ValidSize(const gfx::Size& size, |
| 188 gfx::GpuMemoryBuffer::Format format) { |
| 189 switch (format) { |
| 190 case gfx::GpuMemoryBuffer::ATC: |
| 191 case gfx::GpuMemoryBuffer::ATCIA: |
| 192 case gfx::GpuMemoryBuffer::DXT1: |
| 193 case gfx::GpuMemoryBuffer::DXT5: |
| 194 case gfx::GpuMemoryBuffer::ETC1: |
| 195 // Compressed images must have a width and height that's evenly divisible |
| 196 // by the block size. |
| 197 return size.width() % 4 == 0 && size.height() % 4 == 0; |
| 198 case gfx::GpuMemoryBuffer::RGBA_8888: |
| 199 case gfx::GpuMemoryBuffer::BGRA_8888: |
| 200 return true; |
| 201 case gfx::GpuMemoryBuffer::RGBX_8888: |
| 202 NOTREACHED(); |
| 203 return false; |
| 204 } |
| 205 |
| 206 NOTREACHED(); |
| 207 return false; |
| 208 } |
| 209 |
125 bool GLImageMemory::Initialize(const unsigned char* memory, | 210 bool GLImageMemory::Initialize(const unsigned char* memory, |
126 gfx::GpuMemoryBuffer::Format format) { | 211 gfx::GpuMemoryBuffer::Format format) { |
127 if (!ValidInternalFormat(internalformat_)) { | 212 if (!ValidInternalFormat(internalformat_)) { |
128 LOG(ERROR) << "Invalid internalformat: " << internalformat_; | 213 LOG(ERROR) << "Invalid internalformat: " << internalformat_; |
129 return false; | 214 return false; |
130 } | 215 } |
131 | 216 |
132 if (!ValidFormat(format)) { | 217 if (!ValidFormat(format)) { |
133 LOG(ERROR) << "Invalid format: " << format; | 218 LOG(ERROR) << "Invalid format: " << format; |
134 return false; | 219 return false; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 265 } |
181 | 266 |
182 bool GLImageMemory::CopyTexImage(unsigned target) { | 267 bool GLImageMemory::CopyTexImage(unsigned target) { |
183 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage"); | 268 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage"); |
184 | 269 |
185 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target. | 270 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target. |
186 if (target == GL_TEXTURE_EXTERNAL_OES) | 271 if (target == GL_TEXTURE_EXTERNAL_OES) |
187 return false; | 272 return false; |
188 | 273 |
189 DCHECK(memory_); | 274 DCHECK(memory_); |
190 glTexSubImage2D(target, 0, // level | 275 if (IsCompressedFormat(format_)) { |
191 0, // x | 276 glCompressedTexSubImage2D(target, |
192 0, // y | 277 0, // level |
193 size_.width(), size_.height(), DataFormat(format_), | 278 0, // x-offset |
194 DataType(format_), memory_); | 279 0, // y-offset |
| 280 size_.width(), size_.height(), |
| 281 DataFormat(format_), SizeInBytes(size_, format_), |
| 282 memory_); |
| 283 } else { |
| 284 glTexSubImage2D(target, 0, // level |
| 285 0, // x |
| 286 0, // y |
| 287 size_.width(), size_.height(), DataFormat(format_), |
| 288 DataType(format_), memory_); |
| 289 } |
195 | 290 |
196 return true; | 291 return true; |
197 } | 292 } |
198 | 293 |
199 void GLImageMemory::WillUseTexImage() { | 294 void GLImageMemory::WillUseTexImage() { |
200 DCHECK(!in_use_); | 295 DCHECK(!in_use_); |
201 in_use_ = true; | 296 in_use_ = true; |
202 | 297 |
203 if (!need_do_bind_tex_image_) | 298 if (!need_do_bind_tex_image_) |
204 return; | 299 return; |
(...skipping 28 matching lines...) Expand all Loading... |
233 if (egl_image_ == EGL_NO_IMAGE_KHR) { | 328 if (egl_image_ == EGL_NO_IMAGE_KHR) { |
234 DCHECK_EQ(0u, egl_texture_id_); | 329 DCHECK_EQ(0u, egl_texture_id_); |
235 glGenTextures(1, &egl_texture_id_); | 330 glGenTextures(1, &egl_texture_id_); |
236 | 331 |
237 { | 332 { |
238 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | 333 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); |
239 | 334 |
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 336 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); | 337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
243 glTexImage2D(GL_TEXTURE_2D, | 338 if (IsCompressedFormat(format_)) { |
244 0, // mip level | 339 glCompressedTexImage2D(GL_TEXTURE_2D, |
245 TextureFormat(format_), | 340 0, // mip level |
246 size_.width(), | 341 TextureFormat(format_), size_.width(), |
247 size_.height(), | 342 size_.height(), |
248 0, // border | 343 0, // border |
249 DataFormat(format_), | 344 SizeInBytes(size_, format_), memory_); |
250 DataType(format_), | 345 } else { |
251 memory_); | 346 glTexImage2D(GL_TEXTURE_2D, |
| 347 0, // mip level |
| 348 TextureFormat(format_), |
| 349 size_.width(), |
| 350 size_.height(), |
| 351 0, // border |
| 352 DataFormat(format_), |
| 353 DataType(format_), |
| 354 memory_); |
| 355 } |
252 } | 356 } |
253 | 357 |
254 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | 358 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; |
255 // Need to pass current EGL rendering context to eglCreateImageKHR for | 359 // Need to pass current EGL rendering context to eglCreateImageKHR for |
256 // target type EGL_GL_TEXTURE_2D_KHR. | 360 // target type EGL_GL_TEXTURE_2D_KHR. |
257 egl_image_ = | 361 egl_image_ = |
258 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | 362 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), |
259 eglGetCurrentContext(), | 363 eglGetCurrentContext(), |
260 EGL_GL_TEXTURE_2D_KHR, | 364 EGL_GL_TEXTURE_2D_KHR, |
261 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), | 365 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), |
262 attrs); | 366 attrs); |
263 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) | 367 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) |
264 << "Error creating EGLImage: " << eglGetError(); | 368 << "Error creating EGLImage: " << eglGetError(); |
265 } else { | 369 } else { |
266 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | 370 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); |
267 | 371 |
268 glTexSubImage2D(GL_TEXTURE_2D, | 372 if (IsCompressedFormat(format_)) { |
269 0, // mip level | 373 glCompressedTexSubImage2D(GL_TEXTURE_2D, |
270 0, // x-offset | 374 0, // mip level |
271 0, // y-offset | 375 0, // x-offset |
272 size_.width(), | 376 0, // y-offset |
273 size_.height(), | 377 size_.width(), size_.height(), |
274 DataFormat(format_), | 378 DataFormat(format_), |
275 DataType(format_), | 379 SizeInBytes(size_, format_), |
276 memory_); | 380 memory_); |
| 381 } else { |
| 382 glTexSubImage2D(GL_TEXTURE_2D, |
| 383 0, // mip level |
| 384 0, // x-offset |
| 385 0, // y-offset |
| 386 size_.width(), |
| 387 size_.height(), |
| 388 DataFormat(format_), |
| 389 DataType(format_), |
| 390 memory_); |
| 391 } |
277 } | 392 } |
278 | 393 |
279 glEGLImageTargetTexture2DOES(target, egl_image_); | 394 glEGLImageTargetTexture2DOES(target, egl_image_); |
280 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 395 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
281 return; | 396 return; |
282 } | 397 } |
283 #endif | 398 #endif |
284 | 399 |
285 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); | 400 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); |
286 glTexImage2D(target, | 401 if (IsCompressedFormat(format_)) { |
287 0, // mip level | 402 glCompressedTexImage2D(target, |
288 TextureFormat(format_), | 403 0, // mip level |
289 size_.width(), | 404 TextureFormat(format_), size_.width(), |
290 size_.height(), | 405 size_.height(), |
291 0, // border | 406 0, // border |
292 DataFormat(format_), | 407 SizeInBytes(size_, format_), memory_); |
293 DataType(format_), | 408 } else { |
294 memory_); | 409 glTexImage2D(target, |
| 410 0, // mip level |
| 411 TextureFormat(format_), |
| 412 size_.width(), |
| 413 size_.height(), |
| 414 0, // border |
| 415 DataFormat(format_), |
| 416 DataType(format_), |
| 417 memory_); |
| 418 } |
295 } | 419 } |
296 | 420 |
297 } // namespace gfx | 421 } // namespace gfx |
OLD | NEW |