Chromium Code Reviews| 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 CompressedFormat(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 |
| 75 } // namespace | 113 } // namespace |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 98 DCHECK_EQ(0u, egl_texture_id_); | 136 DCHECK_EQ(0u, egl_texture_id_); |
| 99 #endif | 137 #endif |
| 100 } | 138 } |
| 101 | 139 |
| 102 // static | 140 // static |
| 103 bool GLImageMemory::StrideInBytes(size_t width, | 141 bool GLImageMemory::StrideInBytes(size_t width, |
| 104 gfx::GpuMemoryBuffer::Format format, | 142 gfx::GpuMemoryBuffer::Format format, |
| 105 size_t* stride_in_bytes) { | 143 size_t* stride_in_bytes) { |
| 106 base::CheckedNumeric<size_t> s = width; | 144 base::CheckedNumeric<size_t> s = width; |
| 107 switch (format) { | 145 switch (format) { |
| 146 case gfx::GpuMemoryBuffer::ATCIA: | |
| 147 case gfx::GpuMemoryBuffer::DXT5: | |
| 148 *stride_in_bytes = width; | |
| 149 return true; | |
| 150 case gfx::GpuMemoryBuffer::ATC: | |
| 151 case gfx::GpuMemoryBuffer::DXT1: | |
| 152 case gfx::GpuMemoryBuffer::ETC1: | |
| 153 DCHECK_EQ(width % 2, 0U); | |
| 154 s /= 2; | |
| 155 if (!s.IsValid()) | |
| 156 return false; | |
| 157 | |
| 158 *stride_in_bytes = s.ValueOrDie(); | |
| 159 return true; | |
| 108 case gfx::GpuMemoryBuffer::RGBA_8888: | 160 case gfx::GpuMemoryBuffer::RGBA_8888: |
| 109 case gfx::GpuMemoryBuffer::BGRA_8888: | 161 case gfx::GpuMemoryBuffer::BGRA_8888: |
| 110 s *= 4; | 162 s *= 4; |
| 111 if (!s.IsValid()) | 163 if (!s.IsValid()) |
| 112 return false; | 164 return false; |
| 113 | 165 |
| 114 *stride_in_bytes = s.ValueOrDie(); | 166 *stride_in_bytes = s.ValueOrDie(); |
| 115 return true; | 167 return true; |
| 116 case gfx::GpuMemoryBuffer::RGBX_8888: | 168 case gfx::GpuMemoryBuffer::RGBX_8888: |
| 117 NOTREACHED(); | 169 NOTREACHED(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 } | 232 } |
| 181 | 233 |
| 182 bool GLImageMemory::CopyTexImage(unsigned target) { | 234 bool GLImageMemory::CopyTexImage(unsigned target) { |
| 183 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage"); | 235 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage"); |
| 184 | 236 |
| 185 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target. | 237 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target. |
| 186 if (target == GL_TEXTURE_EXTERNAL_OES) | 238 if (target == GL_TEXTURE_EXTERNAL_OES) |
| 187 return false; | 239 return false; |
| 188 | 240 |
| 189 DCHECK(memory_); | 241 DCHECK(memory_); |
| 190 glTexSubImage2D(target, 0, // level | 242 if (CompressedFormat(format_)) { |
| 191 0, // x | 243 glCompressedTexSubImage2D(target, |
|
reveman
2015/02/11 13:58:40
Should we avoid calling CompressedTexSubImage2D if
christiank
2015/02/12 08:41:52
Yes, that's the idea. The code assumes that we onl
reveman
2015/02/12 12:51:28
What's preventing a malicious renderer from being
christiank
2015/02/12 13:54:42
I guess that's possible. One could argue that a ma
reveman
2015/02/12 14:18:00
Yes, that could be a problem. In general, we shoul
christiank
2015/02/13 10:08:36
I have now added some checks to GpuCommandBufferSt
| |
| 192 0, // y | 244 0, // level |
| 193 size_.width(), size_.height(), DataFormat(format_), | 245 0, // x-offset |
| 194 DataType(format_), memory_); | 246 0, // y-offset |
| 247 size_.width(), size_.height(), | |
| 248 DataFormat(format_), MemoryBytes(format_), | |
| 249 memory_); | |
| 250 } else { | |
| 251 glTexSubImage2D(target, 0, // level | |
| 252 0, // x | |
| 253 0, // y | |
| 254 size_.width(), size_.height(), DataFormat(format_), | |
| 255 DataType(format_), memory_); | |
| 256 } | |
| 195 | 257 |
| 196 return true; | 258 return true; |
| 197 } | 259 } |
| 198 | 260 |
| 199 void GLImageMemory::WillUseTexImage() { | 261 void GLImageMemory::WillUseTexImage() { |
| 200 DCHECK(!in_use_); | 262 DCHECK(!in_use_); |
| 201 in_use_ = true; | 263 in_use_ = true; |
| 202 | 264 |
| 203 if (!need_do_bind_tex_image_) | 265 if (!need_do_bind_tex_image_) |
| 204 return; | 266 return; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 233 if (egl_image_ == EGL_NO_IMAGE_KHR) { | 295 if (egl_image_ == EGL_NO_IMAGE_KHR) { |
| 234 DCHECK_EQ(0u, egl_texture_id_); | 296 DCHECK_EQ(0u, egl_texture_id_); |
| 235 glGenTextures(1, &egl_texture_id_); | 297 glGenTextures(1, &egl_texture_id_); |
| 236 | 298 |
| 237 { | 299 { |
| 238 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | 300 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); |
| 239 | 301 |
| 240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 303 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); | 304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 243 glTexImage2D(GL_TEXTURE_2D, | 305 if (CompressedFormat(format_)) { |
| 244 0, // mip level | 306 glCompressedTexImage2D(GL_TEXTURE_2D, |
| 245 TextureFormat(format_), | 307 0, // mip level |
| 246 size_.width(), | 308 TextureFormat(format_), size_.width(), |
| 247 size_.height(), | 309 size_.height(), |
| 248 0, // border | 310 0, // border |
| 249 DataFormat(format_), | 311 MemoryBytes(format_), memory_); |
| 250 DataType(format_), | 312 } else { |
| 251 memory_); | 313 glTexImage2D(GL_TEXTURE_2D, |
| 314 0, // mip level | |
| 315 TextureFormat(format_), | |
| 316 size_.width(), | |
| 317 size_.height(), | |
| 318 0, // border | |
| 319 DataFormat(format_), | |
| 320 DataType(format_), | |
| 321 memory_); | |
| 322 } | |
| 252 } | 323 } |
| 253 | 324 |
| 254 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | 325 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; |
| 255 // Need to pass current EGL rendering context to eglCreateImageKHR for | 326 // Need to pass current EGL rendering context to eglCreateImageKHR for |
| 256 // target type EGL_GL_TEXTURE_2D_KHR. | 327 // target type EGL_GL_TEXTURE_2D_KHR. |
| 257 egl_image_ = | 328 egl_image_ = |
| 258 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | 329 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), |
| 259 eglGetCurrentContext(), | 330 eglGetCurrentContext(), |
| 260 EGL_GL_TEXTURE_2D_KHR, | 331 EGL_GL_TEXTURE_2D_KHR, |
| 261 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), | 332 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), |
| 262 attrs); | 333 attrs); |
| 263 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) | 334 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) |
| 264 << "Error creating EGLImage: " << eglGetError(); | 335 << "Error creating EGLImage: " << eglGetError(); |
| 265 } else { | 336 } else { |
| 266 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | 337 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); |
| 267 | 338 |
| 268 glTexSubImage2D(GL_TEXTURE_2D, | 339 if (CompressedFormat(format_)) { |
| 269 0, // mip level | 340 glCompressedTexSubImage2D(GL_TEXTURE_2D, |
| 270 0, // x-offset | 341 0, // mip level |
| 271 0, // y-offset | 342 0, // x-offset |
| 272 size_.width(), | 343 0, // y-offset |
| 273 size_.height(), | 344 size_.width(), size_.height(), |
| 274 DataFormat(format_), | 345 DataFormat(format_), MemoryBytes(format_), |
| 275 DataType(format_), | 346 memory_); |
| 276 memory_); | 347 } else { |
| 348 glTexSubImage2D(GL_TEXTURE_2D, | |
| 349 0, // mip level | |
| 350 0, // x-offset | |
| 351 0, // y-offset | |
| 352 size_.width(), | |
| 353 size_.height(), | |
| 354 DataFormat(format_), | |
| 355 DataType(format_), | |
| 356 memory_); | |
| 357 } | |
| 277 } | 358 } |
| 278 | 359 |
| 279 glEGLImageTargetTexture2DOES(target, egl_image_); | 360 glEGLImageTargetTexture2DOES(target, egl_image_); |
| 280 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 361 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 281 return; | 362 return; |
| 282 } | 363 } |
| 283 #endif | 364 #endif |
| 284 | 365 |
| 285 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); | 366 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); |
| 286 glTexImage2D(target, | 367 if (CompressedFormat(format_)) { |
| 287 0, // mip level | 368 glCompressedTexImage2D(target, |
| 288 TextureFormat(format_), | 369 0, // mip level |
| 289 size_.width(), | 370 TextureFormat(format_), size_.width(), |
| 290 size_.height(), | 371 size_.height(), |
| 291 0, // border | 372 0, // border |
| 292 DataFormat(format_), | 373 MemoryBytes(format_), memory_); |
| 293 DataType(format_), | 374 } else { |
| 294 memory_); | 375 glTexImage2D(target, |
| 376 0, // mip level | |
| 377 TextureFormat(format_), | |
| 378 size_.width(), | |
| 379 size_.height(), | |
| 380 0, // border | |
| 381 DataFormat(format_), | |
| 382 DataType(format_), | |
| 383 memory_); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 size_t GLImageMemory::MemoryBytes(gfx::GpuMemoryBuffer::Format format) { | |
|
reveman
2015/02/11 13:58:40
Please move this to anonymous namespace, rename it
christiank
2015/02/12 08:41:52
Sounds good, fixed.
| |
| 388 size_t stride_in_bytes = 0; | |
| 389 bool valid_stride = StrideInBytes(size_.width(), format, &stride_in_bytes); | |
| 390 DCHECK(valid_stride); | |
| 391 return stride_in_bytes * size_.height(); | |
| 295 } | 392 } |
| 296 | 393 |
| 297 } // namespace gfx | 394 } // namespace gfx |
| OLD | NEW |