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 |