Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: gpu/command_buffer/service/texture_manager.cc

Issue 1963683002: Fix unpacking overlapping unpack buffer rows on NVIDIA GL (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Slight refactoring and change Linux expectations Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | gpu/config/gpu_driver_bug_list_json.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 2376 matching lines...) Expand 10 before | Expand all | Expand 10 after
2387 memset(zero.get(), 0, args.pixels_size); 2387 memset(zero.get(), 0, args.pixels_size);
2388 for (GLenum face : undefined_faces) { 2388 for (GLenum face : undefined_faces) {
2389 new_args.target = face; 2389 new_args.target = face;
2390 new_args.pixels = zero.get(); 2390 new_args.pixels = zero.get();
2391 DoTexImage(texture_state, state, framebuffer_state, 2391 DoTexImage(texture_state, state, framebuffer_state,
2392 function_name, texture_ref, new_args); 2392 function_name, texture_ref, new_args);
2393 texture->MarkLevelAsInternalWorkaround(face, args.level); 2393 texture->MarkLevelAsInternalWorkaround(face, args.level);
2394 } 2394 }
2395 } 2395 }
2396 2396
2397 if (texture_state->unpack_overlapping_rows_separately_unpack_buffer &&
2398 buffer) {
2399 ContextState::Dimension dimension =
2400 (args.command_type == DoTexImageArguments::kTexImage3D)
2401 ? ContextState::k3D
2402 : ContextState::k2D;
2403 const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
2404 if (unpack_params.row_length != 0 &&
2405 unpack_params.row_length < args.width) {
2406 // The rows overlap in unpack memory. Upload the texture row by row to
2407 // work around driver bug.
2408
2409 ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
2410 function_name, texture_ref, args);
2411
2412 DoTexSubImageArguments sub_args = {
2413 args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
2414 args.format, args.type, args.pixels, args.pixels_size, args.padding,
2415 args.command_type == DoTexImageArguments::kTexImage3D
2416 ? DoTexSubImageArguments::kTexSubImage3D
2417 : DoTexSubImageArguments::kTexSubImage2D};
2418 DoTexSubImageRowByRowWorkaround(texture_state, state, sub_args,
2419 unpack_params);
2420
2421 SetLevelCleared(texture_ref, args.target, args.level, true);
2422 return;
2423 }
2424 }
2425
2397 if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) { 2426 if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
2398 uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); 2427 uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
2399 if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) { 2428 if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
2400 // In ValidateTexImage(), we already made sure buffer size is no less 2429 // In ValidateTexImage(), we already made sure buffer size is no less
2401 // than offset + pixels_size. 2430 // than offset + pixels_size.
2402 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 2431 ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
2403 state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr); 2432 function_name, texture_ref, args);
2404 DoTexImageArguments new_args = args;
2405 new_args.pixels = nullptr;
2406 // pixels_size might be incorrect, but it's not used in this case.
2407 DoTexImage(texture_state, state, framebuffer_state, function_name,
2408 texture_ref, new_args);
2409 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
2410 state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
2411 2433
2412 DoTexSubImageArguments sub_args = { 2434 DoTexSubImageArguments sub_args = {
2413 args.target, args.level, 0, 0, 0, args.width, args.height, args.depth, 2435 args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
2414 args.format, args.type, args.pixels, args.pixels_size, args.padding, 2436 args.format, args.type, args.pixels, args.pixels_size, args.padding,
2415 args.command_type == DoTexImageArguments::kTexImage3D ? 2437 args.command_type == DoTexImageArguments::kTexImage3D ?
2416 DoTexSubImageArguments::kTexSubImage3D : 2438 DoTexSubImageArguments::kTexSubImage3D :
2417 DoTexSubImageArguments::kTexSubImage2D}; 2439 DoTexSubImageArguments::kTexSubImage2D};
2418 DoTexSubImageWithAlignmentWorkaround(texture_state, state, sub_args); 2440 DoTexSubImageWithAlignmentWorkaround(texture_state, state, sub_args);
2419 2441
2420 SetLevelCleared(texture_ref, args.target, args.level, true); 2442 SetLevelCleared(texture_ref, args.target, args.level, true);
2421 return; 2443 return;
2422 } 2444 }
2423 } 2445 }
2424 DoTexImage(texture_state, state, framebuffer_state, 2446 DoTexImage(texture_state, state, framebuffer_state,
2425 function_name, texture_ref, args); 2447 function_name, texture_ref, args);
2426 } 2448 }
2427 2449
2450 void TextureManager::ReserveTexImageToBeFilled(
2451 DecoderTextureState* texture_state,
2452 ContextState* state,
2453 DecoderFramebufferState* framebuffer_state,
2454 const char* function_name,
2455 TextureRef* texture_ref,
2456 const DoTexImageArguments& args) {
2457 Buffer* buffer = state->bound_pixel_unpack_buffer.get();
2458 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
2459 state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr);
2460 DoTexImageArguments new_args = args;
2461 new_args.pixels = nullptr;
2462 // pixels_size might be incorrect, but it's not used in this case.
2463 DoTexImage(texture_state, state, framebuffer_state, function_name,
2464 texture_ref, new_args);
2465 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
2466 state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
2467 }
2468
2428 bool TextureManager::ValidateTexSubImage(ContextState* state, 2469 bool TextureManager::ValidateTexSubImage(ContextState* state,
2429 const char* function_name, 2470 const char* function_name,
2430 const DoTexSubImageArguments& args, 2471 const DoTexSubImageArguments& args,
2431 TextureRef** texture_ref) { 2472 TextureRef** texture_ref) {
2432 ErrorState* error_state = state->GetErrorState(); 2473 ErrorState* error_state = state->GetErrorState();
2433 const Validators* validators = feature_info_->validators(); 2474 const Validators* validators = feature_info_->validators();
2434 2475
2435 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && 2476 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D &&
2436 !validators->texture_target.IsValid(args.target)) || 2477 !validators->texture_target.IsValid(args.target)) ||
2437 (args.command_type == DoTexSubImageArguments::kTexSubImage3D && 2478 (args.command_type == DoTexSubImageArguments::kTexSubImage3D &&
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2565 return; 2606 return;
2566 } 2607 }
2567 } 2608 }
2568 full_image = false; 2609 full_image = false;
2569 } else { 2610 } else {
2570 SetLevelCleared(texture_ref, args.target, args.level, true); 2611 SetLevelCleared(texture_ref, args.target, args.level, true);
2571 full_image = true; 2612 full_image = true;
2572 } 2613 }
2573 2614
2574 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); 2615 Buffer* buffer = state->bound_pixel_unpack_buffer.get();
2616
2617 if (texture_state->unpack_overlapping_rows_separately_unpack_buffer &&
2618 buffer) {
2619 ContextState::Dimension dimension =
2620 (args.command_type == DoTexSubImageArguments::kTexSubImage3D)
2621 ? ContextState::k3D
2622 : ContextState::k2D;
2623 const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
2624 if (unpack_params.row_length != 0 &&
2625 unpack_params.row_length < args.width) {
2626 // The rows overlap in unpack memory. Upload the texture row by row to
2627 // work around driver bug.
2628 DoTexSubImageRowByRowWorkaround(texture_state, state, args,
2629 unpack_params);
2630 return;
2631 }
2632 }
2633
2575 if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) { 2634 if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
2576 uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); 2635 uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
2577 if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) { 2636 if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
2578 DoTexSubImageWithAlignmentWorkaround(texture_state, state, args); 2637 DoTexSubImageWithAlignmentWorkaround(texture_state, state, args);
2579 return; 2638 return;
2580 } 2639 }
2581 } 2640 }
2582 2641
2583 if (full_image && !texture_state->texsubimage_faster_than_teximage && 2642 if (full_image && !texture_state->texsubimage_faster_than_teximage &&
2584 !texture->IsImmutable() && !texture->HasImages()) { 2643 !texture->IsImmutable() && !texture->HasImages()) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2712 args.format, args.type, 2771 args.format, args.type,
2713 params, 2772 params,
2714 &size, 2773 &size,
2715 nullptr, nullptr, nullptr, nullptr); 2774 nullptr, nullptr, nullptr, nullptr);
2716 offset += size; 2775 offset += size;
2717 } 2776 }
2718 } 2777 }
2719 DCHECK_EQ(ToGLuint(args.pixels) + args.pixels_size, offset); 2778 DCHECK_EQ(ToGLuint(args.pixels) + args.pixels_size, offset);
2720 } 2779 }
2721 2780
2781 void TextureManager::DoTexSubImageRowByRowWorkaround(
2782 DecoderTextureState* texture_state,
2783 ContextState* state,
2784 const DoTexSubImageArguments& args,
2785 const PixelStoreParams& unpack_params) {
2786 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2787 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2788 DCHECK_EQ(0, state->unpack_skip_pixels);
2789 DCHECK_EQ(0, state->unpack_skip_rows);
2790 DCHECK_EQ(0, state->unpack_skip_images);
2791
2792 GLenum format = AdjustTexFormat(args.format);
2793
2794 GLsizei row_bytes = unpack_params.row_length *
2795 GLES2Util::ComputeImageGroupSize(format, args.type);
2796 GLsizei alignment_diff = row_bytes % unpack_params.alignment;
2797 if (alignment_diff != 0) {
2798 row_bytes += unpack_params.alignment - alignment_diff;
2799 }
2800 DCHECK_EQ(0, row_bytes % unpack_params.alignment);
2801 if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
2802 GLsizei image_height = args.height;
2803 if (unpack_params.image_height != 0) {
2804 image_height = unpack_params.image_height;
2805 }
2806 GLsizei image_bytes = row_bytes * image_height;
2807 for (GLsizei image = 0; image < args.depth; ++image) {
2808 GLsizei image_byte_offset = image * image_bytes;
2809 for (GLsizei row = 0; row < args.height; ++row) {
2810 GLsizei byte_offset = image_byte_offset + row * row_bytes;
2811 const GLubyte* row_pixels =
2812 reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset;
2813 glTexSubImage3D(args.target, args.level, args.xoffset,
2814 row + args.yoffset, image + args.zoffset, args.width, 1,
2815 1, format, args.type, row_pixels);
2816 }
2817 }
2818 } else {
2819 for (GLsizei row = 0; row < args.height; ++row) {
2820 GLsizei byte_offset = row * row_bytes;
2821 const GLubyte* row_pixels =
2822 reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset;
2823 glTexSubImage2D(args.target, args.level, args.xoffset, row + args.yoffset,
2824 args.width, 1, format, args.type, row_pixels);
2825 }
2826 }
2827
2828 // Restore unpack state
2829 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_params.alignment);
2830 glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_params.row_length);
2831 }
2832
2722 GLenum TextureManager::AdjustTexInternalFormat(GLenum format) const { 2833 GLenum TextureManager::AdjustTexInternalFormat(GLenum format) const {
2723 if (feature_info_->gl_version_info().is_desktop_core_profile) { 2834 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2724 const Texture::CompatibilitySwizzle* swizzle = 2835 const Texture::CompatibilitySwizzle* swizzle =
2725 GetCompatibilitySwizzle(format); 2836 GetCompatibilitySwizzle(format);
2726 if (swizzle) 2837 if (swizzle)
2727 return swizzle->dest_format; 2838 return swizzle->dest_format;
2728 } 2839 }
2729 return format; 2840 return format;
2730 } 2841 }
2731 2842
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
3198 uint32_t TextureManager::GetServiceIdGeneration() const { 3309 uint32_t TextureManager::GetServiceIdGeneration() const {
3199 return current_service_id_generation_; 3310 return current_service_id_generation_;
3200 } 3311 }
3201 3312
3202 void TextureManager::IncrementServiceIdGeneration() { 3313 void TextureManager::IncrementServiceIdGeneration() {
3203 current_service_id_generation_++; 3314 current_service_id_generation_++;
3204 } 3315 }
3205 3316
3206 } // namespace gles2 3317 } // namespace gles2
3207 } // namespace gpu 3318 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | gpu/config/gpu_driver_bug_list_json.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698