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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 } | 136 } |
| 137 | 137 |
| 138 GLsizei SizeInBytes(const Size& size, BufferFormat format) { | 138 GLsizei SizeInBytes(const Size& size, BufferFormat format) { |
| 139 size_t stride_in_bytes = 0; | 139 size_t stride_in_bytes = 0; |
| 140 bool valid_stride = GLImageMemory::StrideInBytes( | 140 bool valid_stride = GLImageMemory::StrideInBytes( |
| 141 size.width(), format, &stride_in_bytes); | 141 size.width(), format, &stride_in_bytes); |
| 142 DCHECK(valid_stride); | 142 DCHECK(valid_stride); |
| 143 return static_cast<GLsizei>(stride_in_bytes * size.height()); | 143 return static_cast<GLsizei>(stride_in_bytes * size.height()); |
| 144 } | 144 } |
| 145 | 145 |
| 146 bool GetTextureBindingForTarget(GLenum target, GLenum* binding) { | |
| 147 switch (target) { | |
| 148 case GL_TEXTURE_2D: | |
| 149 *binding = GL_TEXTURE_BINDING_2D; | |
| 150 return true; | |
| 151 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | |
| 152 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | |
| 153 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | |
| 154 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | |
| 155 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | |
| 156 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | |
| 157 *binding = GL_TEXTURE_BINDING_CUBE_MAP; | |
| 158 return true; | |
| 159 case GL_TEXTURE_RECTANGLE_ARB: | |
| 160 *binding = GL_TEXTURE_BINDING_RECTANGLE_ARB; | |
| 161 return true; | |
| 162 case GL_TEXTURE_EXTERNAL_OES: | |
| 163 *binding = GL_TEXTURE_BINDING_EXTERNAL_OES; | |
| 164 return true; | |
| 165 } | |
| 166 | |
| 167 return false; | |
| 168 } | |
| 169 | |
| 146 } // namespace | 170 } // namespace |
| 147 | 171 |
| 148 GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) | 172 GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) |
| 149 : size_(size), | 173 : size_(size), |
| 150 internalformat_(internalformat), | 174 internalformat_(internalformat), |
| 151 memory_(NULL), | 175 memory_(NULL), |
| 152 format_(BufferFormat::RGBA_8888), | 176 format_(BufferFormat::RGBA_8888), |
| 153 in_use_(false), | 177 in_use_(false), |
| 154 target_(0), | 178 target_(0), |
| 155 need_do_bind_tex_image_(false) | 179 need_do_bind_tex_image_(false), |
| 180 texture_id_(0u), | |
| 181 need_to_free_texture_id_(false) | |
| 156 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | 182 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ |
| 157 defined(USE_OZONE) | 183 defined(USE_OZONE) |
| 158 , | 184 , |
| 159 egl_texture_id_(0u), | |
| 160 egl_image_(EGL_NO_IMAGE_KHR) | 185 egl_image_(EGL_NO_IMAGE_KHR) |
| 161 #endif | 186 #endif |
| 162 { | 187 { |
| 163 } | 188 } |
| 164 | 189 |
| 165 GLImageMemory::~GLImageMemory() { | 190 GLImageMemory::~GLImageMemory() { |
| 166 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | 191 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ |
| 167 defined(USE_OZONE) | 192 defined(USE_OZONE) |
| 168 DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); | 193 DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); |
| 169 DCHECK_EQ(0u, egl_texture_id_); | 194 DCHECK_IMPLIES(need_to_free_texture_id_, texture_id_ == 0u); |
| 170 #endif | 195 #endif |
| 171 } | 196 } |
| 172 | 197 |
| 173 // static | 198 // static |
| 174 bool GLImageMemory::StrideInBytes(size_t width, | 199 bool GLImageMemory::StrideInBytes(size_t width, |
| 175 BufferFormat format, | 200 BufferFormat format, |
| 176 size_t* stride_in_bytes) { | 201 size_t* stride_in_bytes) { |
| 177 base::CheckedNumeric<size_t> checked_stride = width; | 202 base::CheckedNumeric<size_t> checked_stride = width; |
| 178 switch (format) { | 203 switch (format) { |
| 179 case BufferFormat::ATCIA: | 204 case BufferFormat::ATCIA: |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 } | 263 } |
| 239 | 264 |
| 240 void GLImageMemory::Destroy(bool have_context) { | 265 void GLImageMemory::Destroy(bool have_context) { |
| 241 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | 266 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ |
| 242 defined(USE_OZONE) | 267 defined(USE_OZONE) |
| 243 if (egl_image_ != EGL_NO_IMAGE_KHR) { | 268 if (egl_image_ != EGL_NO_IMAGE_KHR) { |
| 244 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); | 269 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); |
| 245 egl_image_ = EGL_NO_IMAGE_KHR; | 270 egl_image_ = EGL_NO_IMAGE_KHR; |
| 246 } | 271 } |
| 247 | 272 |
| 248 if (egl_texture_id_) { | 273 if (texture_id_ && need_to_free_texture_id_) { |
| 249 if (have_context) | 274 if (have_context) |
| 250 glDeleteTextures(1, &egl_texture_id_); | 275 glDeleteTextures(1, &texture_id_); |
| 251 egl_texture_id_ = 0u; | 276 texture_id_ = 0u; |
| 252 } | 277 } |
| 253 #endif | 278 #endif |
| 254 memory_ = NULL; | 279 memory_ = NULL; |
| 255 } | 280 } |
| 256 | 281 |
| 257 Size GLImageMemory::GetSize() { | 282 Size GLImageMemory::GetSize() { |
| 258 return size_; | 283 return size_; |
| 259 } | 284 } |
| 260 | 285 |
| 261 unsigned GLImageMemory::GetInternalFormat() { | 286 unsigned GLImageMemory::GetInternalFormat() { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage"); | 370 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage"); |
| 346 | 371 |
| 347 DCHECK(need_do_bind_tex_image_); | 372 DCHECK(need_do_bind_tex_image_); |
| 348 need_do_bind_tex_image_ = false; | 373 need_do_bind_tex_image_ = false; |
| 349 | 374 |
| 350 DCHECK(memory_); | 375 DCHECK(memory_); |
| 351 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | 376 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ |
| 352 defined(USE_OZONE) | 377 defined(USE_OZONE) |
| 353 if (target == GL_TEXTURE_EXTERNAL_OES) { | 378 if (target == GL_TEXTURE_EXTERNAL_OES) { |
| 354 if (egl_image_ == EGL_NO_IMAGE_KHR) { | 379 if (egl_image_ == EGL_NO_IMAGE_KHR) { |
| 355 DCHECK_EQ(0u, egl_texture_id_); | 380 DCHECK_EQ(0u, texture_id_); |
| 356 glGenTextures(1, &egl_texture_id_); | 381 glGenTextures(1, &texture_id_); |
| 382 need_to_free_texture_id_ = true; | |
| 357 | 383 |
| 358 { | 384 { |
| 359 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | 385 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_); |
| 360 | 386 |
| 361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 387 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 388 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 364 if (IsCompressedFormat(format_)) { | 390 if (IsCompressedFormat(format_)) { |
| 365 glCompressedTexImage2D(GL_TEXTURE_2D, | 391 glCompressedTexImage2D(GL_TEXTURE_2D, |
| 366 0, // mip level | 392 0, // mip level |
| 367 TextureFormat(format_), size_.width(), | 393 TextureFormat(format_), size_.width(), |
| 368 size_.height(), | 394 size_.height(), |
| 369 0, // border | 395 0, // border |
| 370 SizeInBytes(size_, format_), memory_); | 396 SizeInBytes(size_, format_), memory_); |
| 371 } else { | 397 } else { |
| 372 glTexImage2D(GL_TEXTURE_2D, | 398 glTexImage2D(GL_TEXTURE_2D, |
| 373 0, // mip level | 399 0, // mip level |
| 374 TextureFormat(format_), | 400 TextureFormat(format_), |
| 375 size_.width(), | 401 size_.width(), |
| 376 size_.height(), | 402 size_.height(), |
| 377 0, // border | 403 0, // border |
| 378 DataFormat(format_), | 404 DataFormat(format_), |
| 379 DataType(format_), | 405 DataType(format_), |
| 380 memory_); | 406 memory_); |
| 381 } | 407 } |
| 382 } | 408 } |
| 383 | 409 |
| 384 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | 410 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; |
| 385 // Need to pass current EGL rendering context to eglCreateImageKHR for | 411 // Need to pass current EGL rendering context to eglCreateImageKHR for |
| 386 // target type EGL_GL_TEXTURE_2D_KHR. | 412 // target type EGL_GL_TEXTURE_2D_KHR. |
| 387 egl_image_ = | 413 egl_image_ = eglCreateImageKHR( |
| 388 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | 414 GLSurfaceEGL::GetHardwareDisplay(), eglGetCurrentContext(), |
| 389 eglGetCurrentContext(), | 415 EGL_GL_TEXTURE_2D_KHR, reinterpret_cast<EGLClientBuffer>(texture_id_), |
| 390 EGL_GL_TEXTURE_2D_KHR, | 416 attrs); |
| 391 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), | |
| 392 attrs); | |
| 393 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) | 417 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) |
| 394 << "Error creating EGLImage: " << eglGetError(); | 418 << "Error creating EGLImage: " << eglGetError(); |
| 395 } else { | 419 } else { |
| 396 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | 420 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_); |
| 397 | 421 |
| 398 if (IsCompressedFormat(format_)) { | 422 if (IsCompressedFormat(format_)) { |
| 399 glCompressedTexSubImage2D(GL_TEXTURE_2D, | 423 glCompressedTexSubImage2D(GL_TEXTURE_2D, |
| 400 0, // mip level | 424 0, // mip level |
| 401 0, // x-offset | 425 0, // x-offset |
| 402 0, // y-offset | 426 0, // y-offset |
| 403 size_.width(), size_.height(), | 427 size_.width(), size_.height(), |
| 404 DataFormat(format_), | 428 DataFormat(format_), |
| 405 SizeInBytes(size_, format_), memory_); | 429 SizeInBytes(size_, format_), memory_); |
| 406 } else { | 430 } else { |
| 407 glTexSubImage2D(GL_TEXTURE_2D, | 431 glTexSubImage2D(GL_TEXTURE_2D, |
| 408 0, // mip level | 432 0, // mip level |
| 409 0, // x-offset | 433 0, // x-offset |
| 410 0, // y-offset | 434 0, // y-offset |
| 411 size_.width(), | 435 size_.width(), |
| 412 size_.height(), | 436 size_.height(), |
| 413 DataFormat(format_), | 437 DataFormat(format_), |
| 414 DataType(format_), | 438 DataType(format_), |
| 415 memory_); | 439 memory_); |
| 416 } | 440 } |
| 417 } | 441 } |
| 418 | 442 |
| 419 glEGLImageTargetTexture2DOES(target, egl_image_); | 443 glEGLImageTargetTexture2DOES(target, egl_image_); |
| 420 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 444 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 421 return; | 445 return; |
| 422 } | 446 } |
| 423 #endif | 447 #endif |
| 424 | 448 |
| 449 // Make sure the same image is only ever bound to one texture. | |
|
reveman
2015/08/31 17:38:48
I don't think any of this is needed as we will alw
ericrk
2015/08/31 18:31:14
sgtm - added a comment and used the original logic
| |
| 450 GLenum binding; | |
| 451 if (!GetTextureBindingForTarget(target, &binding)) { | |
| 452 LOG(ERROR) << "Trying to bind image to an invalid target"; | |
| 453 return; | |
| 454 } | |
| 455 | |
| 456 GLuint texture_id; | |
| 457 glGetIntegerv(binding, reinterpret_cast<GLint*>(&texture_id)); | |
| 458 if (!texture_id) { | |
| 459 LOG(ERROR) << "Trying to bind image without no texture bound"; | |
| 460 return; | |
| 461 } | |
| 462 | |
| 463 if (texture_id_ && texture_id_ != texture_id) { | |
| 464 LOG(ERROR) << "Image can only be bound to one texture ID"; | |
| 465 return; | |
| 466 } | |
| 467 | |
| 468 texture_id_ = texture_id; | |
| 469 | |
| 425 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); | 470 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); |
| 426 if (IsCompressedFormat(format_)) { | 471 if (IsCompressedFormat(format_)) { |
| 427 glCompressedTexImage2D(target, | 472 glCompressedTexImage2D(target, |
| 428 0, // mip level | 473 0, // mip level |
| 429 TextureFormat(format_), size_.width(), | 474 TextureFormat(format_), size_.width(), |
| 430 size_.height(), | 475 size_.height(), |
| 431 0, // border | 476 0, // border |
| 432 SizeInBytes(size_, format_), memory_); | 477 SizeInBytes(size_, format_), memory_); |
| 433 } else { | 478 } else { |
| 434 glTexImage2D(target, | 479 glTexImage2D(target, |
| 435 0, // mip level | 480 0, // mip level |
| 436 TextureFormat(format_), | 481 TextureFormat(format_), |
| 437 size_.width(), | 482 size_.width(), |
| 438 size_.height(), | 483 size_.height(), |
| 439 0, // border | 484 0, // border |
| 440 DataFormat(format_), | 485 DataFormat(format_), |
| 441 DataType(format_), | 486 DataType(format_), |
| 442 memory_); | 487 memory_); |
| 443 } | 488 } |
| 444 } | 489 } |
| 445 | 490 |
| 446 void GLImageMemory::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, | 491 void GLImageMemory::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
| 447 uint64_t process_tracing_id, | 492 uint64_t process_tracing_id, |
| 448 const std::string& dump_name) { | 493 const std::string& dump_name) { |
| 449 // Log size 0 if |ref_counted_memory_| has been released. | 494 size_t size_in_bytes = texture_id_ ? SizeInBytes(size_, format_) : 0; |
| 450 size_t size_in_bytes = memory_ ? SizeInBytes(size_, format_) : 0; | |
| 451 | 495 |
| 452 base::trace_event::MemoryAllocatorDump* dump = | 496 base::trace_event::MemoryAllocatorDump* dump = |
| 453 pmd->CreateAllocatorDump(dump_name); | 497 pmd->CreateAllocatorDump(dump_name + "/texture_memory"); |
| 454 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | 498 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
| 455 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 499 base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 456 static_cast<uint64_t>(size_in_bytes)); | 500 static_cast<uint64_t>(size_in_bytes)); |
| 501 | |
| 502 // No need for a global shared edge here. This object in the GPU process is | |
| 503 // the sole owner of this texture id. | |
| 457 } | 504 } |
| 458 | 505 |
| 459 } // namespace gfx | 506 } // namespace gfx |
| OLD | NEW |