OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "gpu/command_buffer/service/texture_manager.h" | 5 #include "gpu/command_buffer/service/texture_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 } | 308 } |
309 | 309 |
310 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint. | 310 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint. |
311 GLuint ToGLuint(const void* ptr) { | 311 GLuint ToGLuint(const void* ptr) { |
312 return static_cast<GLuint>(reinterpret_cast<size_t>(ptr)); | 312 return static_cast<GLuint>(reinterpret_cast<size_t>(ptr)); |
313 } | 313 } |
314 | 314 |
315 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = | 315 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = |
316 LAZY_INSTANCE_INITIALIZER; | 316 LAZY_INSTANCE_INITIALIZER; |
317 | 317 |
| 318 class ScopedResetPixelUnpackBuffer{ |
| 319 public: |
| 320 explicit ScopedResetPixelUnpackBuffer(ContextState* state) |
| 321 : buffer_(nullptr) { |
| 322 buffer_ = state->bound_pixel_unpack_buffer.get(); |
| 323 if (buffer_) { |
| 324 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); |
| 325 } |
| 326 } |
| 327 |
| 328 ~ScopedResetPixelUnpackBuffer() { |
| 329 if (buffer_) { |
| 330 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer_->service_id()); |
| 331 } |
| 332 } |
| 333 |
| 334 private: |
| 335 Buffer* buffer_; |
| 336 }; |
| 337 |
318 } // namespace anonymous | 338 } // namespace anonymous |
319 | 339 |
320 TextureManager::DestructionObserver::DestructionObserver() {} | 340 TextureManager::DestructionObserver::DestructionObserver() {} |
321 | 341 |
322 TextureManager::DestructionObserver::~DestructionObserver() {} | 342 TextureManager::DestructionObserver::~DestructionObserver() {} |
323 | 343 |
324 TextureManager::~TextureManager() { | 344 TextureManager::~TextureManager() { |
325 for (unsigned int i = 0; i < destruction_observers_.size(); i++) | 345 for (unsigned int i = 0; i < destruction_observers_.size(); i++) |
326 destruction_observers_[i]->OnTextureManagerDestroying(this); | 346 destruction_observers_[i]->OnTextureManagerDestroying(this); |
327 | 347 |
(...skipping 2067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2395 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, | 2415 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, |
2396 "out of memory"); | 2416 "out of memory"); |
2397 return false; | 2417 return false; |
2398 } | 2418 } |
2399 | 2419 |
2400 // Write the TextureReference since this is valid. | 2420 // Write the TextureReference since this is valid. |
2401 *texture_ref = local_texture_ref; | 2421 *texture_ref = local_texture_ref; |
2402 return true; | 2422 return true; |
2403 } | 2423 } |
2404 | 2424 |
| 2425 void TextureManager::DoCubeMapWorkaround( |
| 2426 DecoderTextureState* texture_state, |
| 2427 ContextState* state, |
| 2428 DecoderFramebufferState* framebuffer_state, |
| 2429 TextureRef* texture_ref, |
| 2430 const char* function_name, |
| 2431 const DoTexImageArguments& args) { |
| 2432 // This workaround code does not work with an unpack buffer bound. |
| 2433 ScopedResetPixelUnpackBuffer scoped_reset_pbo(state); |
| 2434 |
| 2435 std::vector<GLenum> undefined_faces; |
| 2436 Texture* texture = texture_ref->texture(); |
| 2437 if (texture_state->force_cube_complete) { |
| 2438 int width = 0; |
| 2439 int height = 0; |
| 2440 for (unsigned i = 0; i < 6; i++) { |
| 2441 GLenum target = static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); |
| 2442 bool defined = texture->GetLevelSize( |
| 2443 target, args.level, &width, &height, nullptr); |
| 2444 if (!defined && target != args.target) |
| 2445 undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); |
| 2446 } |
| 2447 } else { |
| 2448 DCHECK(args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X); |
| 2449 int width = 0; |
| 2450 int height = 0; |
| 2451 if (!texture->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X, args.level, |
| 2452 &width, &height, nullptr)) { |
| 2453 undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X); |
| 2454 } |
| 2455 } |
| 2456 if (!memory_type_tracker_->EnsureGPUMemoryAvailable( |
| 2457 (undefined_faces.size() + 1) * args.pixels_size)) { |
| 2458 ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY, |
| 2459 function_name, "out of memory"); |
| 2460 return; |
| 2461 } |
| 2462 DoTexImageArguments new_args = args; |
| 2463 std::unique_ptr<char[]> zero(new char[args.pixels_size]); |
| 2464 memset(zero.get(), 0, args.pixels_size); |
| 2465 for (GLenum face : undefined_faces) { |
| 2466 new_args.target = face; |
| 2467 new_args.pixels = zero.get(); |
| 2468 DoTexImage(texture_state, state, framebuffer_state, |
| 2469 function_name, texture_ref, new_args); |
| 2470 texture->MarkLevelAsInternalWorkaround(face, args.level); |
| 2471 } |
| 2472 } |
| 2473 |
2405 void TextureManager::ValidateAndDoTexImage( | 2474 void TextureManager::ValidateAndDoTexImage( |
2406 DecoderTextureState* texture_state, | 2475 DecoderTextureState* texture_state, |
2407 ContextState* state, | 2476 ContextState* state, |
2408 DecoderFramebufferState* framebuffer_state, | 2477 DecoderFramebufferState* framebuffer_state, |
2409 const char* function_name, | 2478 const char* function_name, |
2410 const DoTexImageArguments& args) { | 2479 const DoTexImageArguments& args) { |
2411 TextureRef* texture_ref; | 2480 TextureRef* texture_ref; |
2412 if (!ValidateTexImage(state, function_name, args, &texture_ref)) { | 2481 if (!ValidateTexImage(state, function_name, args, &texture_ref)) { |
2413 return; | 2482 return; |
2414 } | 2483 } |
2415 | 2484 |
2416 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); | 2485 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); |
2417 | 2486 |
2418 // ValidateTexImage is passed already. | 2487 // ValidateTexImage is passed already. |
2419 Texture* texture = texture_ref->texture(); | 2488 Texture* texture = texture_ref->texture(); |
2420 bool need_cube_map_workaround = | 2489 bool need_cube_map_workaround = |
2421 !feature_info_->IsES3Enabled() && | 2490 !feature_info_->IsES3Enabled() && |
2422 texture->target() == GL_TEXTURE_CUBE_MAP && | 2491 texture->target() == GL_TEXTURE_CUBE_MAP && |
2423 (texture_state->force_cube_complete || | 2492 (texture_state->force_cube_complete || |
2424 (texture_state->force_cube_map_positive_x_allocation && | 2493 (texture_state->force_cube_map_positive_x_allocation && |
2425 args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X)); | 2494 args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X)); |
2426 if (need_cube_map_workaround && !buffer) { | 2495 if (need_cube_map_workaround && !buffer) { |
2427 // TODO(zmo): The following code does not work with an unpack buffer bound. | 2496 DoCubeMapWorkaround(texture_state, state, framebuffer_state, |
2428 std::vector<GLenum> undefined_faces; | 2497 texture_ref, function_name, args); |
2429 if (texture_state->force_cube_complete) { | |
2430 int width = 0; | |
2431 int height = 0; | |
2432 for (unsigned i = 0; i < 6; i++) { | |
2433 GLenum target = static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); | |
2434 bool defined = texture->GetLevelSize( | |
2435 target, args.level, &width, &height, nullptr); | |
2436 if (!defined && target != args.target) | |
2437 undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); | |
2438 } | |
2439 } else { | |
2440 DCHECK(texture_state->force_cube_map_positive_x_allocation && | |
2441 args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X); | |
2442 int width = 0; | |
2443 int height = 0; | |
2444 if (!texture->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X, args.level, | |
2445 &width, &height, nullptr)) { | |
2446 undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X); | |
2447 } | |
2448 } | |
2449 if (!memory_type_tracker_->EnsureGPUMemoryAvailable( | |
2450 (undefined_faces.size() + 1) * args.pixels_size)) { | |
2451 ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY, | |
2452 function_name, "out of memory"); | |
2453 return; | |
2454 } | |
2455 DoTexImageArguments new_args = args; | |
2456 std::unique_ptr<char[]> zero(new char[args.pixels_size]); | |
2457 memset(zero.get(), 0, args.pixels_size); | |
2458 for (GLenum face : undefined_faces) { | |
2459 new_args.target = face; | |
2460 new_args.pixels = zero.get(); | |
2461 DoTexImage(texture_state, state, framebuffer_state, | |
2462 function_name, texture_ref, new_args); | |
2463 texture->MarkLevelAsInternalWorkaround(face, args.level); | |
2464 } | |
2465 } | 2498 } |
2466 | 2499 |
2467 if (texture_state->unpack_overlapping_rows_separately_unpack_buffer && | 2500 if (texture_state->unpack_overlapping_rows_separately_unpack_buffer && |
2468 buffer) { | 2501 buffer) { |
2469 ContextState::Dimension dimension = | 2502 ContextState::Dimension dimension = |
2470 (args.command_type == DoTexImageArguments::kTexImage3D) | 2503 (args.command_type == DoTexImageArguments::kTexImage3D) |
2471 ? ContextState::k3D | 2504 ? ContextState::k3D |
2472 : ContextState::k2D; | 2505 : ContextState::k2D; |
2473 const PixelStoreParams unpack_params(state->GetUnpackParams(dimension)); | 2506 const PixelStoreParams unpack_params(state->GetUnpackParams(dimension)); |
2474 if (unpack_params.row_length != 0 && | 2507 if (unpack_params.row_length != 0 && |
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3428 uint32_t TextureManager::GetServiceIdGeneration() const { | 3461 uint32_t TextureManager::GetServiceIdGeneration() const { |
3429 return current_service_id_generation_; | 3462 return current_service_id_generation_; |
3430 } | 3463 } |
3431 | 3464 |
3432 void TextureManager::IncrementServiceIdGeneration() { | 3465 void TextureManager::IncrementServiceIdGeneration() { |
3433 current_service_id_generation_++; | 3466 current_service_id_generation_++; |
3434 } | 3467 } |
3435 | 3468 |
3436 } // namespace gles2 | 3469 } // namespace gles2 |
3437 } // namespace gpu | 3470 } // namespace gpu |
OLD | NEW |