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

Unified Diff: content/browser/compositor/buffer_queue.cc

Issue 1905863002: Revert of Introduce components/display_compositor (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/compositor/buffer_queue.h ('k') | content/browser/compositor/buffer_queue_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/compositor/buffer_queue.cc
diff --git a/content/browser/compositor/buffer_queue.cc b/content/browser/compositor/buffer_queue.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c1a0340ef827cd7ac492bba48800b0d329653401
--- /dev/null
+++ b/content/browser/compositor/buffer_queue.cc
@@ -0,0 +1,265 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/compositor/buffer_queue.h"
+
+#include "base/containers/adapters.h"
+#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
+#include "cc/output/context_provider.h"
+#include "content/browser/compositor/gl_helper.h"
+#include "gpu/GLES2/gl2extchromium.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_buffer_support.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/skia_util.h"
+
+namespace content {
+
+BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider,
+ unsigned int texture_target,
+ unsigned int internalformat,
+ GLHelper* gl_helper,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ int surface_id)
+ : context_provider_(context_provider),
+ fbo_(0),
+ allocated_count_(0),
+ texture_target_(texture_target),
+ internal_format_(internalformat),
+ gl_helper_(gl_helper),
+ gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
+ surface_id_(surface_id) {}
+
+BufferQueue::~BufferQueue() {
+ FreeAllSurfaces();
+
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ if (fbo_)
+ gl->DeleteFramebuffers(1, &fbo_);
+}
+
+void BufferQueue::Initialize() {
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->GenFramebuffers(1, &fbo_);
+}
+
+void BufferQueue::BindFramebuffer() {
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+
+ if (!current_surface_)
+ current_surface_ = GetNextSurface();
+
+ if (current_surface_) {
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ texture_target_, current_surface_->texture, 0);
+ }
+}
+
+void BufferQueue::CopyBufferDamage(int texture,
+ int source_texture,
+ const gfx::Rect& new_damage,
+ const gfx::Rect& old_damage) {
+ gl_helper_->CopySubBufferDamage(
+ texture_target_, texture, source_texture,
+ SkRegion(gfx::RectToSkIRect(new_damage)),
+ SkRegion(gfx::RectToSkIRect(old_damage)));
+}
+
+void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
+ if (displayed_surface_)
+ displayed_surface_->damage.Union(damage);
+ for (auto& surface : available_surfaces_)
+ surface->damage.Union(damage);
+ for (auto& surface : in_flight_surfaces_) {
+ if (surface)
+ surface->damage.Union(damage);
+ }
+}
+
+void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
+ if (current_surface_) {
+ if (damage != gfx::Rect(size_)) {
+ // Copy damage from the most recently swapped buffer. In the event that
+ // the buffer was destroyed and failed to recreate, pick from the most
+ // recently available buffer.
+ unsigned int texture_id = 0;
+ for (auto& surface : base::Reversed(in_flight_surfaces_)) {
+ if (surface) {
+ texture_id = surface->texture;
+ break;
+ }
+ }
+ if (!texture_id && displayed_surface_)
+ texture_id = displayed_surface_->texture;
+
+ if (texture_id) {
+ CopyBufferDamage(current_surface_->texture, texture_id, damage,
+ current_surface_->damage);
+ }
+ }
+ current_surface_->damage = gfx::Rect();
+ }
+ UpdateBufferDamage(damage);
+ in_flight_surfaces_.push_back(std::move(current_surface_));
+ // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
+ // paths), so ensure we restore it here.
+ context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+}
+
+void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
+ if (size == size_)
+ return;
+ // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
+ // is cause for concern or if it is benign.
+ // http://crbug.com/524624
+#if !defined(OS_MACOSX)
+ DCHECK(!current_surface_);
+#endif
+ size_ = size;
+
+ // TODO: add stencil buffer when needed.
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ texture_target_, 0, 0);
+
+ FreeAllSurfaces();
+}
+
+void BufferQueue::RecreateBuffers() {
+ // We need to recreate the buffers, for whatever reason the old ones are not
+ // presentable on the device anymore.
+ // Unused buffers can be freed directly, they will be re-allocated as needed.
+ // Any in flight, current or displayed surface must be replaced.
+ available_surfaces_.clear();
+
+ // Recreate all in-flight surfaces and put the recreated copies in the queue.
+ for (auto& surface : in_flight_surfaces_)
+ surface = RecreateBuffer(std::move(surface));
+
+ current_surface_ = RecreateBuffer(std::move(current_surface_));
+ displayed_surface_ = RecreateBuffer(std::move(displayed_surface_));
+
+ if (current_surface_) {
+ // If we have a texture bound, we will need to re-bind it.
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ texture_target_, current_surface_->texture, 0);
+ }
+}
+
+std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
+ std::unique_ptr<AllocatedSurface> surface) {
+ if (!surface)
+ return nullptr;
+
+ std::unique_ptr<AllocatedSurface> new_surface(GetNextSurface());
+ if (!new_surface)
+ return nullptr;
+
+ new_surface->damage = surface->damage;
+
+ // Copy the entire texture.
+ CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
+ gfx::Rect(size_));
+ return new_surface;
+}
+
+void BufferQueue::PageFlipComplete() {
+ DCHECK(!in_flight_surfaces_.empty());
+ if (displayed_surface_)
+ available_surfaces_.push_back(std::move(displayed_surface_));
+ displayed_surface_ = std::move(in_flight_surfaces_.front());
+ in_flight_surfaces_.pop_front();
+}
+
+void BufferQueue::FreeAllSurfaces() {
+ displayed_surface_.reset();
+ current_surface_.reset();
+ // This is intentionally not emptied since the swap buffers acks are still
+ // expected to arrive.
+ for (auto& surface : in_flight_surfaces_)
+ surface = nullptr;
+ available_surfaces_.clear();
+}
+
+void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) {
+ if (!surface->texture)
+ return;
+
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindTexture(texture_target_, surface->texture);
+ gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
+ gl->DeleteTextures(1, &surface->texture);
+ gl->DestroyImageCHROMIUM(surface->image);
+ surface->buffer.reset();
+ allocated_count_--;
+}
+
+std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
+ if (!available_surfaces_.empty()) {
+ std::unique_ptr<AllocatedSurface> surface =
+ std::move(available_surfaces_.back());
+ available_surfaces_.pop_back();
+ return surface;
+ }
+
+ unsigned int texture = 0;
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->GenTextures(1, &texture);
+ if (!texture)
+ return nullptr;
+
+ // We don't want to allow anything more than triple buffering.
+ DCHECK_LT(allocated_count_, 4U);
+
+ std::unique_ptr<gfx::GpuMemoryBuffer> buffer(
+ gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
+ size_, gpu::DefaultBufferFormatForImageFormat(internal_format_),
+ gfx::BufferUsage::SCANOUT, surface_id_));
+ if (!buffer.get()) {
+ gl->DeleteTextures(1, &texture);
+ DLOG(ERROR) << "Failed to allocate GPU memory buffer";
+ return nullptr;
+ }
+
+ unsigned int id = gl->CreateImageCHROMIUM(
+ buffer->AsClientBuffer(), size_.width(), size_.height(),
+ internal_format_);
+ if (!id) {
+ LOG(ERROR) << "Failed to allocate backing image surface";
+ gl->DeleteTextures(1, &texture);
+ return nullptr;
+ }
+
+ allocated_count_++;
+ gl->BindTexture(texture_target_, texture);
+ gl->BindTexImage2DCHROMIUM(texture_target_, id);
+ return base::WrapUnique(new AllocatedSurface(this, std::move(buffer), texture,
+ id, gfx::Rect(size_)));
+}
+
+BufferQueue::AllocatedSurface::AllocatedSurface(
+ BufferQueue* buffer_queue,
+ std::unique_ptr<gfx::GpuMemoryBuffer> buffer,
+ unsigned int texture,
+ unsigned int image,
+ const gfx::Rect& rect)
+ : buffer_queue(buffer_queue),
+ buffer(buffer.release()),
+ texture(texture),
+ image(image),
+ damage(rect) {}
+
+BufferQueue::AllocatedSurface::~AllocatedSurface() {
+ buffer_queue->FreeSurfaceResources(this);
+}
+
+} // namespace content
« no previous file with comments | « content/browser/compositor/buffer_queue.h ('k') | content/browser/compositor/buffer_queue_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698