| Index: cc/output/gl_renderer.cc
|
| diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
|
| index 733b89298135f048eb001ef2a4de70e073e987d4..87738ad671b6966bab52e70951fc2bf27c0f328b 100644
|
| --- a/cc/output/gl_renderer.cc
|
| +++ b/cc/output/gl_renderer.cc
|
| @@ -15,6 +15,7 @@
|
| #include <string>
|
| #include <vector>
|
|
|
| +#include "base/callback_helpers.h"
|
| #include "base/feature_list.h"
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| @@ -153,6 +154,30 @@ const float kAntiAliasingEpsilon = 1.0f / 1024.0f;
|
| // Block or crash if the number of pending sync queries reach this high as
|
| // something is seriously wrong on the service side if this happens.
|
| const size_t kMaxPendingSyncQueries = 16;
|
| +
|
| +void ReadbackSwappedOverlayTexturesDone(
|
| + gpu::gles2::GLES2Interface* gl,
|
| + std::vector<GLuint> buffers,
|
| + GLuint query,
|
| + std::vector<SkBitmap>* bitmaps,
|
| + const base::Callback<void(bool)>& callback) {
|
| + TRACE_EVENT0("cc", "ReadbackSwappedOverlayTexturesDone");
|
| +
|
| + DCHECK_EQ(buffers.size(), bitmaps->size());
|
| + for (size_t i = 0; i < buffers.size(); ++i) {
|
| + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, buffers[i]);
|
| + uint8_t* data = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
|
| + GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
|
| + if (data)
|
| + memcpy(bitmaps->at(i).getPixels(), data, bitmaps->at(i).getSize());
|
| + gl->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
|
| + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
|
| + }
|
| + gl->DeleteBuffers(buffers.size(), &buffers[0]);
|
| + gl->DeleteQueriesEXT(1, &query);
|
| + callback.Run(true);
|
| +}
|
| +
|
| } // anonymous namespace
|
|
|
| // Parameters needed to draw a RenderPassDrawQuad.
|
| @@ -2756,22 +2781,85 @@ void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
|
| swap_buffer_rect_ = gfx::Rect();
|
| }
|
|
|
| +void GLRenderer::ReadbackSwappedOverlayTextures(
|
| + std::vector<SkBitmap>* bitmaps,
|
| + const base::Callback<void(bool)>& callback) {
|
| + TRACE_EVENT0("cc", "GLRenderer::RequestSwappedOverlayTextureSnapshot");
|
| +
|
| + if (swapped_and_acked_overlay_resources_.empty()) {
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + std::vector<GLuint> buffers(swapped_and_acked_overlay_resources_.size());
|
| + gl_->GenBuffers(buffers.size(), &buffers[0]);
|
| +
|
| + GLuint fbo = 0;
|
| + gl_->GenFramebuffers(1, &fbo);
|
| + gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
| +
|
| + GLuint query = 0;
|
| + gl_->GenQueriesEXT(1, &query);
|
| + gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, query);
|
| +
|
| + DCHECK_EQ(bitmaps->size(), 0u);
|
| + for (auto& entry : swapped_and_acked_overlay_resources_) {
|
| + const OverlayResourceLock& overlay_resource = entry.second;
|
| + gfx::Size size = overlay_resource->size();
|
| + bitmaps->resize(bitmaps->size() + 1);
|
| + bitmaps->back().allocN32Pixels(size.width(), size.height());
|
| + std::unique_ptr<ScopedResource> texture =
|
| + ScopedResource::Create(resource_provider_);
|
| + texture->Allocate(size, ResourceProvider::TEXTURE_HINT_DEFAULT, RGBA_8888,
|
| + gfx::ColorSpace());
|
| + ResourceProvider::ScopedWriteLockGL write_lock(resource_provider_,
|
| + texture->id(), false);
|
| + gl_->CopyTextureCHROMIUM(overlay_resource->texture_id(), 0, GL_TEXTURE_2D,
|
| + write_lock.texture_id(), 0, GL_RGBA,
|
| + GL_UNSIGNED_BYTE, false, false, false);
|
| + gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
| + write_lock.target(), write_lock.texture_id(), 0);
|
| + DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
|
| + GL_FRAMEBUFFER_COMPLETE);
|
| + gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
|
| + buffers[bitmaps->size() - 1]);
|
| + gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
|
| + bitmaps->back().getSize(), nullptr, GL_STREAM_READ);
|
| + gl_->ReadPixels(0, 0, size.width(), size.height(), GL_RGBA,
|
| + GL_UNSIGNED_BYTE, nullptr);
|
| + gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
|
| + }
|
| +
|
| + gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
|
| + gl_->DeleteFramebuffers(1, &fbo);
|
| +
|
| + context_support_->SignalQuery(
|
| + query, base::Bind(&ReadbackSwappedOverlayTexturesDone, gl_,
|
| + std::move(buffers), query, bitmaps, callback));
|
| +}
|
| +
|
| void GLRenderer::SwapBuffersComplete() {
|
| + // If a query is not needed to release the overlay buffers, we can assume
|
| + // that once a swap buffer has completed we can release the previously
|
| + // swapped buffers.
|
| + if (!settings_->release_overlay_resources_after_gpu_query)
|
| + swapped_and_acked_overlay_resources_.clear();
|
| +
|
| + 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 (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());
|
| @@ -2780,11 +2868,6 @@ void GLRenderer::SwapBuffersComplete() {
|
| }
|
| gl_->ScheduleCALayerInUseQueryCHROMIUM(textures.size(), textures.data());
|
| }
|
| - } else 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.
|
| - swapping_overlay_resources_.pop_front();
|
| }
|
| }
|
|
|
|
|