| 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 "cc/raster/one_copy_tile_task_worker_pool.h" | 5 #include "cc/raster/one_copy_tile_task_worker_pool.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 105 |
| 106 OneCopyTileTaskWorkerPool::StagingBuffer::~StagingBuffer() { | 106 OneCopyTileTaskWorkerPool::StagingBuffer::~StagingBuffer() { |
| 107 DCHECK_EQ(texture_id, 0u); | 107 DCHECK_EQ(texture_id, 0u); |
| 108 DCHECK_EQ(image_id, 0u); | 108 DCHECK_EQ(image_id, 0u); |
| 109 DCHECK_EQ(query_id, 0u); | 109 DCHECK_EQ(query_id, 0u); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void OneCopyTileTaskWorkerPool::StagingBuffer::DestroyGLResources( | 112 void OneCopyTileTaskWorkerPool::StagingBuffer::DestroyGLResources( |
| 113 gpu::gles2::GLES2Interface* gl) { | 113 gpu::gles2::GLES2Interface* gl) { |
| 114 if (query_id) { | 114 if (query_id) { |
| 115 gl->DeleteQueriesEXT(1, &query_id); | 115 if (gl) |
| 116 gl->DeleteQueriesEXT(1, &query_id); |
| 116 query_id = 0; | 117 query_id = 0; |
| 117 } | 118 } |
| 118 if (image_id) { | 119 if (image_id) { |
| 119 gl->DestroyImageCHROMIUM(image_id); | 120 if (gl) |
| 121 gl->DestroyImageCHROMIUM(image_id); |
| 120 image_id = 0; | 122 image_id = 0; |
| 121 } | 123 } |
| 122 if (texture_id) { | 124 if (texture_id) { |
| 123 gl->DeleteTextures(1, &texture_id); | 125 if (gl) |
| 126 gl->DeleteTextures(1, &texture_id); |
| 124 texture_id = 0; | 127 texture_id = 0; |
| 125 } | 128 } |
| 126 } | 129 } |
| 127 | 130 |
| 128 void OneCopyTileTaskWorkerPool::StagingBuffer::OnMemoryDump( | 131 void OneCopyTileTaskWorkerPool::StagingBuffer::OnMemoryDump( |
| 129 base::trace_event::ProcessMemoryDump* pmd, | 132 base::trace_event::ProcessMemoryDump* pmd, |
| 130 ResourceFormat format, | 133 ResourceFormat format, |
| 131 bool in_free_list) const { | 134 bool in_free_list) const { |
| 132 if (!gpu_memory_buffer) | 135 if (!gpu_memory_buffer) |
| 133 return; | 136 return; |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 } | 420 } |
| 418 | 421 |
| 419 ContextProvider* context_provider = | 422 ContextProvider* context_provider = |
| 420 resource_provider_->output_surface()->worker_context_provider(); | 423 resource_provider_->output_surface()->worker_context_provider(); |
| 421 DCHECK(context_provider); | 424 DCHECK(context_provider); |
| 422 | 425 |
| 423 { | 426 { |
| 424 ContextProvider::ScopedContextLock scoped_context(context_provider); | 427 ContextProvider::ScopedContextLock scoped_context(context_provider); |
| 425 | 428 |
| 426 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); | 429 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); |
| 427 DCHECK(gl); | 430 if (gl) { |
| 431 unsigned image_target = resource_provider_->GetImageTextureTarget( |
| 432 resource_provider_->memory_efficient_texture_format()); |
| 428 | 433 |
| 429 unsigned image_target = resource_provider_->GetImageTextureTarget( | 434 // Create and bind staging texture. |
| 430 resource_provider_->memory_efficient_texture_format()); | 435 if (!staging_buffer->texture_id) { |
| 436 gl->GenTextures(1, &staging_buffer->texture_id); |
| 437 gl->BindTexture(image_target, staging_buffer->texture_id); |
| 438 gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 439 gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 440 gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 441 gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 442 } else { |
| 443 gl->BindTexture(image_target, staging_buffer->texture_id); |
| 444 } |
| 431 | 445 |
| 432 // Create and bind staging texture. | 446 // Create and bind image. |
| 433 if (!staging_buffer->texture_id) { | 447 if (!staging_buffer->image_id) { |
| 434 gl->GenTextures(1, &staging_buffer->texture_id); | 448 if (staging_buffer->gpu_memory_buffer) { |
| 435 gl->BindTexture(image_target, staging_buffer->texture_id); | 449 staging_buffer->image_id = gl->CreateImageCHROMIUM( |
| 436 gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 450 staging_buffer->gpu_memory_buffer->AsClientBuffer(), |
| 437 gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 451 staging_buffer->size.width(), staging_buffer->size.height(), |
| 438 gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 452 GLInternalFormat( |
| 439 gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 453 resource_provider_->memory_efficient_texture_format())); |
| 440 } else { | 454 gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id); |
| 441 gl->BindTexture(image_target, staging_buffer->texture_id); | 455 } |
| 442 } | 456 } else { |
| 443 | 457 gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id); |
| 444 // Create and bind image. | |
| 445 if (!staging_buffer->image_id) { | |
| 446 if (staging_buffer->gpu_memory_buffer) { | |
| 447 staging_buffer->image_id = gl->CreateImageCHROMIUM( | |
| 448 staging_buffer->gpu_memory_buffer->AsClientBuffer(), | |
| 449 staging_buffer->size.width(), staging_buffer->size.height(), | |
| 450 GLInternalFormat( | |
| 451 resource_provider_->memory_efficient_texture_format())); | |
| 452 gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id); | 458 gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id); |
| 453 } | 459 } |
| 454 } else { | |
| 455 gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id); | |
| 456 gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id); | |
| 457 } | |
| 458 | 460 |
| 459 // Unbind staging texture. | 461 // Unbind staging texture. |
| 460 gl->BindTexture(image_target, 0); | 462 gl->BindTexture(image_target, 0); |
| 461 | 463 |
| 462 if (resource_provider_->use_sync_query()) { | 464 if (resource_provider_->use_sync_query()) { |
| 463 if (!staging_buffer->query_id) | 465 if (!staging_buffer->query_id) |
| 464 gl->GenQueriesEXT(1, &staging_buffer->query_id); | 466 gl->GenQueriesEXT(1, &staging_buffer->query_id); |
| 465 | 467 |
| 466 #if defined(OS_CHROMEOS) | 468 #if defined(OS_CHROMEOS) |
| 467 // TODO(reveman): This avoids a performance problem on some ChromeOS | 469 // TODO(reveman): This avoids a performance problem on some ChromeOS |
| 468 // devices. This needs to be removed to support native GpuMemoryBuffer | 470 // devices. This needs to be removed to support native GpuMemoryBuffer |
| 469 // implementations. crbug.com/436314 | 471 // implementations. crbug.com/436314 |
| 470 gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id); | 472 gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, |
| 473 staging_buffer->query_id); |
| 471 #else | 474 #else |
| 472 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, | 475 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, |
| 473 staging_buffer->query_id); | 476 staging_buffer->query_id); |
| 474 #endif | 477 #endif |
| 478 } |
| 479 |
| 480 int bytes_per_row = |
| 481 (BitsPerPixel(resource_provider_->memory_efficient_texture_format()) * |
| 482 resource->size().width()) / |
| 483 8; |
| 484 int chunk_size_in_rows = |
| 485 std::max(1, max_bytes_per_copy_operation_ / bytes_per_row); |
| 486 // Align chunk size to 4. Required to support compressed texture formats. |
| 487 chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4); |
| 488 int y = 0; |
| 489 int height = resource->size().height(); |
| 490 while (y < height) { |
| 491 // Copy at most |chunk_size_in_rows|. |
| 492 int rows_to_copy = std::min(chunk_size_in_rows, height - y); |
| 493 DCHECK_GT(rows_to_copy, 0); |
| 494 |
| 495 gl->CopySubTextureCHROMIUM(GL_TEXTURE_2D, staging_buffer->texture_id, |
| 496 resource_lock->texture_id(), 0, y, 0, y, |
| 497 resource->size().width(), rows_to_copy, |
| 498 false, false, false); |
| 499 y += rows_to_copy; |
| 500 |
| 501 // Increment |bytes_scheduled_since_last_flush_| by the amount of memory |
| 502 // used for this copy operation. |
| 503 bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row; |
| 504 |
| 505 if (bytes_scheduled_since_last_flush_ >= |
| 506 max_bytes_per_copy_operation_) { |
| 507 gl->ShallowFlushCHROMIUM(); |
| 508 bytes_scheduled_since_last_flush_ = 0; |
| 509 } |
| 510 } |
| 511 |
| 512 if (resource_provider_->use_sync_query()) { |
| 513 #if defined(OS_CHROMEOS) |
| 514 gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); |
| 515 #else |
| 516 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); |
| 517 #endif |
| 518 } |
| 519 |
| 520 // Barrier to sync worker context output to cc context. |
| 521 gl->OrderingBarrierCHROMIUM(); |
| 475 } | 522 } |
| 476 | |
| 477 int bytes_per_row = | |
| 478 (BitsPerPixel(resource_provider_->memory_efficient_texture_format()) * | |
| 479 resource->size().width()) / | |
| 480 8; | |
| 481 int chunk_size_in_rows = | |
| 482 std::max(1, max_bytes_per_copy_operation_ / bytes_per_row); | |
| 483 // Align chunk size to 4. Required to support compressed texture formats. | |
| 484 chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4); | |
| 485 int y = 0; | |
| 486 int height = resource->size().height(); | |
| 487 while (y < height) { | |
| 488 // Copy at most |chunk_size_in_rows|. | |
| 489 int rows_to_copy = std::min(chunk_size_in_rows, height - y); | |
| 490 DCHECK_GT(rows_to_copy, 0); | |
| 491 | |
| 492 gl->CopySubTextureCHROMIUM(GL_TEXTURE_2D, staging_buffer->texture_id, | |
| 493 resource_lock->texture_id(), 0, y, 0, y, | |
| 494 resource->size().width(), rows_to_copy, false, | |
| 495 false, false); | |
| 496 y += rows_to_copy; | |
| 497 | |
| 498 // Increment |bytes_scheduled_since_last_flush_| by the amount of memory | |
| 499 // used for this copy operation. | |
| 500 bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row; | |
| 501 | |
| 502 if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) { | |
| 503 gl->ShallowFlushCHROMIUM(); | |
| 504 bytes_scheduled_since_last_flush_ = 0; | |
| 505 } | |
| 506 } | |
| 507 | |
| 508 if (resource_provider_->use_sync_query()) { | |
| 509 #if defined(OS_CHROMEOS) | |
| 510 gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); | |
| 511 #else | |
| 512 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); | |
| 513 #endif | |
| 514 } | |
| 515 | |
| 516 // Barrier to sync worker context output to cc context. | |
| 517 gl->OrderingBarrierCHROMIUM(); | |
| 518 } | 523 } |
| 519 | 524 |
| 520 staging_buffer->last_usage = base::TimeTicks::Now(); | 525 staging_buffer->last_usage = base::TimeTicks::Now(); |
| 521 busy_buffers_.push_back(staging_buffer.Pass()); | 526 busy_buffers_.push_back(staging_buffer.Pass()); |
| 522 | 527 |
| 523 ScheduleReduceMemoryUsage(); | 528 ScheduleReduceMemoryUsage(); |
| 524 } | 529 } |
| 525 | 530 |
| 526 bool OneCopyTileTaskWorkerPool::OnMemoryDump( | 531 bool OneCopyTileTaskWorkerPool::OnMemoryDump( |
| 527 const base::trace_event::MemoryDumpArgs& args, | 532 const base::trace_event::MemoryDumpArgs& args, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 | 596 |
| 592 scoped_ptr<StagingBuffer> staging_buffer; | 597 scoped_ptr<StagingBuffer> staging_buffer; |
| 593 | 598 |
| 594 ContextProvider* context_provider = | 599 ContextProvider* context_provider = |
| 595 resource_provider_->output_surface()->worker_context_provider(); | 600 resource_provider_->output_surface()->worker_context_provider(); |
| 596 DCHECK(context_provider); | 601 DCHECK(context_provider); |
| 597 | 602 |
| 598 ContextProvider::ScopedContextLock scoped_context(context_provider); | 603 ContextProvider::ScopedContextLock scoped_context(context_provider); |
| 599 | 604 |
| 600 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); | 605 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); |
| 601 DCHECK(gl); | 606 if (gl) { |
| 607 // Check if any busy buffers have become available. |
| 608 if (resource_provider_->use_sync_query()) { |
| 609 while (!busy_buffers_.empty()) { |
| 610 if (!CheckForQueryResult(gl, busy_buffers_.front()->query_id)) |
| 611 break; |
| 602 | 612 |
| 603 // Check if any busy buffers have become available. | |
| 604 if (resource_provider_->use_sync_query()) { | |
| 605 while (!busy_buffers_.empty()) { | |
| 606 if (!CheckForQueryResult(gl, busy_buffers_.front()->query_id)) | |
| 607 break; | |
| 608 | |
| 609 MarkStagingBufferAsFree(busy_buffers_.front()); | |
| 610 free_buffers_.push_back(busy_buffers_.take_front()); | |
| 611 } | |
| 612 } | |
| 613 | |
| 614 // Wait for memory usage of non-free buffers to become less than the limit. | |
| 615 while ( | |
| 616 (staging_buffer_usage_in_bytes_ - free_staging_buffer_usage_in_bytes_) >= | |
| 617 max_staging_buffer_usage_in_bytes_) { | |
| 618 // Stop when there are no more busy buffers to wait for. | |
| 619 if (busy_buffers_.empty()) | |
| 620 break; | |
| 621 | |
| 622 if (resource_provider_->use_sync_query()) { | |
| 623 WaitForQueryResult(gl, busy_buffers_.front()->query_id); | |
| 624 MarkStagingBufferAsFree(busy_buffers_.front()); | |
| 625 free_buffers_.push_back(busy_buffers_.take_front()); | |
| 626 } else { | |
| 627 // Fall-back to glFinish if CHROMIUM_sync_query is not available. | |
| 628 gl->Finish(); | |
| 629 while (!busy_buffers_.empty()) { | |
| 630 MarkStagingBufferAsFree(busy_buffers_.front()); | 613 MarkStagingBufferAsFree(busy_buffers_.front()); |
| 631 free_buffers_.push_back(busy_buffers_.take_front()); | 614 free_buffers_.push_back(busy_buffers_.take_front()); |
| 632 } | 615 } |
| 633 } | 616 } |
| 617 |
| 618 // Wait for memory usage of non-free buffers to become less than the limit. |
| 619 while ((staging_buffer_usage_in_bytes_ - |
| 620 free_staging_buffer_usage_in_bytes_) >= |
| 621 max_staging_buffer_usage_in_bytes_) { |
| 622 // Stop when there are no more busy buffers to wait for. |
| 623 if (busy_buffers_.empty()) |
| 624 break; |
| 625 |
| 626 if (resource_provider_->use_sync_query()) { |
| 627 WaitForQueryResult(gl, busy_buffers_.front()->query_id); |
| 628 MarkStagingBufferAsFree(busy_buffers_.front()); |
| 629 free_buffers_.push_back(busy_buffers_.take_front()); |
| 630 } else { |
| 631 // Fall-back to glFinish if CHROMIUM_sync_query is not available. |
| 632 gl->Finish(); |
| 633 while (!busy_buffers_.empty()) { |
| 634 MarkStagingBufferAsFree(busy_buffers_.front()); |
| 635 free_buffers_.push_back(busy_buffers_.take_front()); |
| 636 } |
| 637 } |
| 638 } |
| 634 } | 639 } |
| 635 | 640 |
| 636 // Find a staging buffer that allows us to perform partial raster when | 641 // Find a staging buffer that allows us to perform partial raster when |
| 637 // using persistent GpuMemoryBuffers. | 642 // using persistent GpuMemoryBuffers. |
| 638 if (use_persistent_gpu_memory_buffers_ && previous_content_id) { | 643 if (use_persistent_gpu_memory_buffers_ && previous_content_id) { |
| 639 StagingBufferDeque::iterator it = | 644 StagingBufferDeque::iterator it = |
| 640 std::find_if(free_buffers_.begin(), free_buffers_.end(), | 645 std::find_if(free_buffers_.begin(), free_buffers_.end(), |
| 641 [previous_content_id](const StagingBuffer* buffer) { | 646 [previous_content_id](const StagingBuffer* buffer) { |
| 642 return buffer->content_id == previous_content_id; | 647 return buffer->content_id == previous_content_id; |
| 643 }); | 648 }); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 lock_.AssertAcquired(); | 743 lock_.AssertAcquired(); |
| 739 | 744 |
| 740 ContextProvider* context_provider = | 745 ContextProvider* context_provider = |
| 741 resource_provider_->output_surface()->worker_context_provider(); | 746 resource_provider_->output_surface()->worker_context_provider(); |
| 742 DCHECK(context_provider); | 747 DCHECK(context_provider); |
| 743 | 748 |
| 744 { | 749 { |
| 745 ContextProvider::ScopedContextLock scoped_context(context_provider); | 750 ContextProvider::ScopedContextLock scoped_context(context_provider); |
| 746 | 751 |
| 747 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); | 752 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); |
| 748 DCHECK(gl); | |
| 749 | 753 |
| 750 // Note: Front buffer is guaranteed to be LRU so we can stop releasing | 754 // Note: Front buffer is guaranteed to be LRU so we can stop releasing |
| 751 // buffers as soon as we find a buffer that has been used since |time|. | 755 // buffers as soon as we find a buffer that has been used since |time|. |
| 752 while (!free_buffers_.empty()) { | 756 while (!free_buffers_.empty()) { |
| 753 if (free_buffers_.front()->last_usage > time) | 757 if (free_buffers_.front()->last_usage > time) |
| 754 return; | 758 return; |
| 755 | 759 |
| 756 free_buffers_.front()->DestroyGLResources(gl); | 760 free_buffers_.front()->DestroyGLResources(gl); |
| 757 MarkStagingBufferAsBusy(free_buffers_.front()); | 761 MarkStagingBufferAsBusy(free_buffers_.front()); |
| 758 RemoveStagingBuffer(free_buffers_.front()); | 762 RemoveStagingBuffer(free_buffers_.front()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 | 811 |
| 808 staging_state->SetInteger("staging_buffer_count", | 812 staging_state->SetInteger("staging_buffer_count", |
| 809 static_cast<int>(buffers_.size())); | 813 static_cast<int>(buffers_.size())); |
| 810 staging_state->SetInteger("busy_count", | 814 staging_state->SetInteger("busy_count", |
| 811 static_cast<int>(busy_buffers_.size())); | 815 static_cast<int>(busy_buffers_.size())); |
| 812 staging_state->SetInteger("free_count", | 816 staging_state->SetInteger("free_count", |
| 813 static_cast<int>(free_buffers_.size())); | 817 static_cast<int>(free_buffers_.size())); |
| 814 } | 818 } |
| 815 | 819 |
| 816 } // namespace cc | 820 } // namespace cc |
| OLD | NEW |