| Index: cc/output/gl_renderer.cc
|
| diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
|
| index 3f642d05eb79df68ba8235dea8c759b5e2b72749..4c8c62d14634eea89c8182fee991eefd2d097135 100644
|
| --- a/cc/output/gl_renderer.cc
|
| +++ b/cc/output/gl_renderer.cc
|
| @@ -49,6 +49,7 @@
|
| #include "gpu/GLES2/gl2extchromium.h"
|
| #include "gpu/command_buffer/client/context_support.h"
|
| #include "gpu/command_buffer/client/gles2_interface.h"
|
| +#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
|
| #include "gpu/command_buffer/common/gpu_memory_allocation.h"
|
| #include "media/base/media_switches.h"
|
| #include "skia/ext/texture_handle.h"
|
| @@ -2935,30 +2936,7 @@ void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
|
| }
|
|
|
| void GLRenderer::SwapBuffersComplete() {
|
| - if (settings_->release_overlay_resources_after_gpu_query) {
|
| - // Once a resource has been swap-ACKed, send a query to the GPU process to
|
| - // ask if the resource is no longer being consumed by the system compositor.
|
| - // The response will come with the next swap-ACK.
|
| - if (!swapping_overlay_resources_.empty()) {
|
| - for (OverlayResourceLock& lock : swapping_overlay_resources_.front()) {
|
| - unsigned texture = lock->texture_id();
|
| - if (swapped_and_acked_overlay_resources_.find(texture) ==
|
| - swapped_and_acked_overlay_resources_.end()) {
|
| - swapped_and_acked_overlay_resources_[texture] = std::move(lock);
|
| - }
|
| - }
|
| - swapping_overlay_resources_.pop_front();
|
| - }
|
| -
|
| - if (!swapped_and_acked_overlay_resources_.empty()) {
|
| - std::vector<unsigned> textures;
|
| - textures.reserve(swapped_and_acked_overlay_resources_.size());
|
| - for (auto& pair : swapped_and_acked_overlay_resources_) {
|
| - textures.push_back(pair.first);
|
| - }
|
| - gl_->ScheduleCALayerInUseQueryCHROMIUM(textures.size(), textures.data());
|
| - }
|
| - } else if (swapping_overlay_resources_.size() > 1) {
|
| + if (swapping_overlay_resources_.size() > 1) {
|
| // If a query is not needed to release the overlay buffers, we can assume
|
| // that once a swap buffer has completed we can remove the oldest buffers
|
| // from the queue.
|
| @@ -2970,10 +2948,45 @@ void GLRenderer::DidReceiveTextureInUseResponses(
|
| const gpu::TextureInUseResponses& responses) {
|
| DCHECK(settings_->release_overlay_resources_after_gpu_query);
|
| for (const gpu::TextureInUseResponse& response : responses) {
|
| - if (!response.in_use) {
|
| - swapped_and_acked_overlay_resources_.erase(response.texture);
|
| + auto found = ca_layer_resources_.find(response.texture);
|
| + DCHECK(found != ca_layer_resources_.end());
|
| + CALayerResourceLock& ca_layer_resource_lock = found->second;
|
| + DCHECK(ca_layer_resource_lock.outstanding_ack_count > 0);
|
| +
|
| + ca_layer_resource_lock.outstanding_ack_count -= 1;
|
| + ca_layer_resource_lock.in_use_valid = response.in_use_valid;
|
| +
|
| + // Requesting the GpuMemoryBuffer handle is expensive. We should do it only
|
| + // only once per resource.
|
| + if (!response.gpu_memory_buffer_handle.is_null()) {
|
| + DCHECK(!ca_layer_resource_lock.gpu_memory_buffer);
|
| + // The size and format for this resource do not matter.
|
| + gfx::Size dummy_size(256, 256);
|
| + gfx::BufferFormat dummy_format = gfx::BufferFormat::RGBA_8888;
|
| + DCHECK(response.gpu_memory_buffer_handle.type ==
|
| + gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER);
|
| + ca_layer_resource_lock.gpu_memory_buffer =
|
| + resource_provider_->gpu_memory_buffer_manager()
|
| + ->CreateGpuMemoryBufferFromHandle(
|
| + response.gpu_memory_buffer_handle, dummy_size, dummy_format);
|
| + }
|
| + }
|
| +
|
| + // Clear locks on resources that are no longer in use.
|
| + auto iter = ca_layer_resources_.begin();
|
| + while (iter != ca_layer_resources_.end()) {
|
| + auto iter_old = iter++;
|
| + CALayerResourceLock& ca_layer_resource_lock = iter_old->second;
|
| + if (ca_layer_resource_lock.outstanding_ack_count == 0) {
|
| + if (!ca_layer_resource_lock.in_use_valid ||
|
| + !ca_layer_resource_lock.gpu_memory_buffer ||
|
| + !ca_layer_resource_lock.gpu_memory_buffer
|
| + ->IsInUseByMacOSWindowServer()) {
|
| + ca_layer_resources_.erase(iter_old);
|
| + }
|
| }
|
| }
|
| +
|
| color_lut_cache_.Swap();
|
| }
|
|
|
| @@ -3774,56 +3787,79 @@ void GLRenderer::ScheduleCALayers(DrawingFrame* frame) {
|
| overlay_resource_pool_->CheckBusyResources();
|
| }
|
|
|
| + std::vector<unsigned> textures_and_handle_requests_for_in_use_query;
|
| scoped_refptr<CALayerOverlaySharedState> shared_state;
|
| size_t copied_render_pass_count = 0;
|
| for (const CALayerOverlay& ca_layer_overlay : frame->ca_layer_overlay_list) {
|
| + std::unique_ptr<ResourceProvider::ScopedReadLockGL> lock;
|
| if (ca_layer_overlay.rpdq) {
|
| - ScheduleRenderPassDrawQuad(&ca_layer_overlay, frame);
|
| + lock = ScheduleRenderPassDrawQuad(&ca_layer_overlay, frame);
|
| shared_state = nullptr;
|
| ++copied_render_pass_count;
|
| - continue;
|
| - }
|
| -
|
| - ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id;
|
| - unsigned texture_id = 0;
|
| - if (contents_resource_id) {
|
| - pending_overlay_resources_.push_back(
|
| - base::MakeUnique<ResourceProvider::ScopedReadLockGL>(
|
| - resource_provider_, contents_resource_id));
|
| - texture_id = pending_overlay_resources_.back()->texture_id();
|
| + } else {
|
| + ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id;
|
| + unsigned texture_id = 0;
|
| + if (contents_resource_id) {
|
| + lock = base::MakeUnique<ResourceProvider::ScopedReadLockGL>(
|
| + resource_provider_, contents_resource_id);
|
| + texture_id = lock->texture_id();
|
| + }
|
| + GLfloat contents_rect[4] = {
|
| + ca_layer_overlay.contents_rect.x(),
|
| + ca_layer_overlay.contents_rect.y(),
|
| + ca_layer_overlay.contents_rect.width(),
|
| + ca_layer_overlay.contents_rect.height(),
|
| + };
|
| + GLfloat bounds_rect[4] = {
|
| + ca_layer_overlay.bounds_rect.x(), ca_layer_overlay.bounds_rect.y(),
|
| + ca_layer_overlay.bounds_rect.width(),
|
| + ca_layer_overlay.bounds_rect.height(),
|
| + };
|
| + GLboolean is_clipped = ca_layer_overlay.shared_state->is_clipped;
|
| + GLfloat clip_rect[4] = {
|
| + ca_layer_overlay.shared_state->clip_rect.x(),
|
| + ca_layer_overlay.shared_state->clip_rect.y(),
|
| + ca_layer_overlay.shared_state->clip_rect.width(),
|
| + ca_layer_overlay.shared_state->clip_rect.height()};
|
| + GLint sorting_context_id =
|
| + ca_layer_overlay.shared_state->sorting_context_id;
|
| + GLfloat transform[16];
|
| + ca_layer_overlay.shared_state->transform.asColMajorf(transform);
|
| + unsigned filter = ca_layer_overlay.filter;
|
| +
|
| + if (ca_layer_overlay.shared_state != shared_state) {
|
| + shared_state = ca_layer_overlay.shared_state;
|
| + gl_->ScheduleCALayerSharedStateCHROMIUM(
|
| + ca_layer_overlay.shared_state->opacity, is_clipped, clip_rect,
|
| + sorting_context_id, transform);
|
| + }
|
| + gl_->ScheduleCALayerCHROMIUM(
|
| + texture_id, contents_rect, ca_layer_overlay.background_color,
|
| + ca_layer_overlay.edge_aa_mask, bounds_rect, filter);
|
| }
|
| - GLfloat contents_rect[4] = {
|
| - ca_layer_overlay.contents_rect.x(), ca_layer_overlay.contents_rect.y(),
|
| - ca_layer_overlay.contents_rect.width(),
|
| - ca_layer_overlay.contents_rect.height(),
|
| - };
|
| - GLfloat bounds_rect[4] = {
|
| - ca_layer_overlay.bounds_rect.x(), ca_layer_overlay.bounds_rect.y(),
|
| - ca_layer_overlay.bounds_rect.width(),
|
| - ca_layer_overlay.bounds_rect.height(),
|
| - };
|
| - GLboolean is_clipped = ca_layer_overlay.shared_state->is_clipped;
|
| - GLfloat clip_rect[4] = {ca_layer_overlay.shared_state->clip_rect.x(),
|
| - ca_layer_overlay.shared_state->clip_rect.y(),
|
| - ca_layer_overlay.shared_state->clip_rect.width(),
|
| - ca_layer_overlay.shared_state->clip_rect.height()};
|
| - GLint sorting_context_id =
|
| - ca_layer_overlay.shared_state->sorting_context_id;
|
| - GLfloat transform[16];
|
| - ca_layer_overlay.shared_state->transform.asColMajorf(transform);
|
| - unsigned filter = ca_layer_overlay.filter;
|
| -
|
| - if (ca_layer_overlay.shared_state != shared_state) {
|
| - shared_state = ca_layer_overlay.shared_state;
|
| - gl_->ScheduleCALayerSharedStateCHROMIUM(
|
| - ca_layer_overlay.shared_state->opacity, is_clipped, clip_rect,
|
| - sorting_context_id, transform);
|
| + if (lock) {
|
| + unsigned texture = lock->texture_id();
|
| + CALayerResourceLock& ca_layer_resource_lock =
|
| + ca_layer_resources_[texture];
|
| +
|
| + textures_and_handle_requests_for_in_use_query.push_back(texture);
|
| + textures_and_handle_requests_for_in_use_query.push_back(
|
| + !ca_layer_resource_lock.gpu_memory_buffer &&
|
| + !ca_layer_resource_lock.outstanding_ack_count);
|
| +
|
| + ca_layer_resource_lock.outstanding_ack_count += 1;
|
| + if (!ca_layer_resource_lock.lock)
|
| + ca_layer_resource_lock.lock = std::move(lock);
|
| }
|
| - gl_->ScheduleCALayerCHROMIUM(
|
| - texture_id, contents_rect, ca_layer_overlay.background_color,
|
| - ca_layer_overlay.edge_aa_mask, bounds_rect, filter);
|
| }
|
|
|
| + // Schedule a query to open the GpuMemoryBuffers for all resources.
|
| + // TODO: add the need_gmb_for_in_use_query argument to avoid creating extra
|
| + // mach ports when it's unnecessary.
|
| + gl_->ScheduleCALayerInUseQueryCHROMIUM(
|
| + textures_and_handle_requests_for_in_use_query.size() / 2,
|
| + textures_and_handle_requests_for_in_use_query.data());
|
| +
|
| // Take the number of copied render passes in this frame, and use 3 times that
|
| // amount as the cache limit.
|
| if (overlay_resource_pool_) {
|
| @@ -3996,9 +4032,9 @@ void GLRenderer::CopyRenderPassDrawQuadToOverlayResource(
|
| gl_->DeleteFramebuffers(1, &temp_fbo);
|
| }
|
|
|
| -void GLRenderer::ScheduleRenderPassDrawQuad(
|
| - const CALayerOverlay* ca_layer_overlay,
|
| - DrawingFrame* external_frame) {
|
| +std::unique_ptr<ResourceProvider::ScopedReadLockGL>
|
| +GLRenderer::ScheduleRenderPassDrawQuad(const CALayerOverlay* ca_layer_overlay,
|
| + DrawingFrame* external_frame) {
|
| DCHECK(ca_layer_overlay->rpdq);
|
|
|
| if (!overlay_resource_pool_) {
|
| @@ -4012,12 +4048,11 @@ void GLRenderer::ScheduleRenderPassDrawQuad(
|
| CopyRenderPassDrawQuadToOverlayResource(ca_layer_overlay, &resource,
|
| external_frame, &new_bounds);
|
| if (!resource || !resource->id())
|
| - return;
|
| + return nullptr;
|
|
|
| - pending_overlay_resources_.push_back(
|
| + std::unique_ptr<ResourceProvider::ScopedReadLockGL> lock =
|
| base::MakeUnique<ResourceProvider::ScopedReadLockGL>(resource_provider_,
|
| - resource->id()));
|
| - unsigned texture_id = pending_overlay_resources_.back()->texture_id();
|
| + resource->id());
|
|
|
| // Once a resource is released, it is marked as "busy". It will be
|
| // available for reuse after the ScopedReadLockGL is destroyed.
|
| @@ -4047,8 +4082,14 @@ void GLRenderer::ScheduleRenderPassDrawQuad(
|
| gl_->ScheduleCALayerSharedStateCHROMIUM(alpha, is_clipped, clip_rect,
|
| sorting_context_id, gl_transform);
|
| gl_->ScheduleCALayerCHROMIUM(
|
| - texture_id, contents_rect, ca_layer_overlay->background_color,
|
| + lock->texture_id(), contents_rect, ca_layer_overlay->background_color,
|
| ca_layer_overlay->edge_aa_mask, bounds_rect, filter);
|
| + return lock;
|
| }
|
|
|
| +GLRenderer::CALayerResourceLock::CALayerResourceLock() = default;
|
| +GLRenderer::CALayerResourceLock::~CALayerResourceLock() = default;
|
| +GLRenderer::CALayerResourceLock::CALayerResourceLock(
|
| + CALayerResourceLock&& ca_layer_resource) = default;
|
| +
|
| } // namespace cc
|
|
|