Commit 592eb864 authored by oshima's avatar oshima Committed by Commit bot

Draw the offscreen texture to reflector's surface without extra copy

This CL also refactor Reflector/BrowserCompositorOutputSurface as follows.

* BrowserCompositorOutputSurface ('s subclass) is responsible for creating Texture mailbox for mirroring
 - when reflector is set
 - or texture size is changed
* OutputSurface notifies reflector when mailbox is updated.

BUG=365662

Review URL: https://codereview.chromium.org/1123763003

Cr-Commit-Position: refs/heads/master@{#330042}
parent 8f9b2d98
......@@ -78,6 +78,16 @@ void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) {
overlay_candidate_validator_->SetSoftwareMirrorMode(reflector != nullptr);
}
reflector_ = reflector;
OnReflectorChanged();
}
void BrowserCompositorOutputSurface::OnReflectorChanged() {
}
base::Closure
BrowserCompositorOutputSurface::CreateCompositionStartedCallback() {
return base::Closure();
}
cc::OverlayCandidateValidator*
......
......@@ -39,6 +39,13 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
void SetReflector(ReflectorImpl* reflector);
// Called when |reflector_| was updated.
virtual void OnReflectorChanged();
// Returns a callback that will be called when all mirroring
// compositors have started composition.
virtual base::Closure CreateCompositionStartedCallback();
#if defined(OS_MACOSX)
virtual void OnSurfaceDisplayed() = 0;
virtual void SetSurfaceSuspendedForRecycle(bool suspended) = 0;
......
......@@ -8,11 +8,10 @@
#include "cc/output/output_surface_client.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/reflector_texture.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
namespace content {
......@@ -60,6 +59,15 @@ bool GpuBrowserCompositorOutputSurface::BindToClient(
return true;
}
void GpuBrowserCompositorOutputSurface::OnReflectorChanged() {
if (!reflector_) {
reflector_texture_.reset();
} else {
reflector_texture_.reset(new ReflectorTexture(context_provider()));
reflector_->OnSourceTextureMailboxUpdated(reflector_texture_->mailbox());
}
}
void GpuBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
DCHECK(frame->gl_frame_data);
......@@ -68,10 +76,14 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers(
if (reflector_) {
if (frame->gl_frame_data->sub_buffer_rect ==
gfx::Rect(frame->gl_frame_data->size))
gfx::Rect(frame->gl_frame_data->size)) {
reflector_texture_->CopyTextureFullImage(SurfaceSize());
reflector_->OnSourceSwapBuffers();
else
reflector_->OnSourcePostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
} else {
const gfx::Rect& rect = frame->gl_frame_data->sub_buffer_rect;
reflector_texture_->CopyTextureSubImage(rect);
reflector_->OnSourcePostSubBuffer(rect);
}
}
if (frame->gl_frame_data->sub_buffer_rect ==
......
......@@ -15,6 +15,7 @@ class CompositorVSyncManager;
namespace content {
class CommandBufferProxyImpl;
class BrowserCompositorOverlayCandidateValidator;
class ReflectorTexture;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// cc::OutputSurface that also handles vsync parameter updates
......@@ -31,6 +32,9 @@ class GpuBrowserCompositorOutputSurface
~GpuBrowserCompositorOutputSurface() override;
protected:
// BrowserCompositorOutputSurface:
void OnReflectorChanged() override;
// cc::OutputSurface implementation.
void SwapBuffers(cc::CompositorFrame* frame) override;
bool BindToClient(cc::OutputSurfaceClient* client) override;
......@@ -62,6 +66,8 @@ class GpuBrowserCompositorOutputSurface
base::TimeDelta interval)>
update_vsync_parameters_callback_;
scoped_ptr<ReflectorTexture> reflector_texture_;
DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
};
......
......@@ -12,6 +12,7 @@
#include "cc/resources/resource_provider.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/reflector_texture.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/context_support.h"
......@@ -37,7 +38,6 @@ OffscreenBrowserCompositorOutputSurface::
overlay_candidate_validator.Pass()),
fbo_(0),
is_backbuffer_discarded_(false),
backing_texture_id_(0),
weak_ptr_factory_(this) {
capabilities_.max_frames_pending = 1;
capabilities_.uses_default_gl_framebuffer = false;
......@@ -51,12 +51,12 @@ OffscreenBrowserCompositorOutputSurface::
void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
is_backbuffer_discarded_ = false;
if (!backing_texture_id_) {
if (!reflector_texture_.get()) {
reflector_texture_.reset(new ReflectorTexture(context_provider()));
GLES2Interface* gl = context_provider_->ContextGL();
cc::ResourceFormat format = cc::RGBA_8888;
gl->GenTextures(1, &backing_texture_id_);
gl->BindTexture(GL_TEXTURE_2D, backing_texture_id_);
gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id());
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
......@@ -64,6 +64,15 @@ void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format),
surface_size_.width(), surface_size_.height(), 0,
GLDataFormat(format), GLDataType(format), nullptr);
if (!fbo_)
gl->GenFramebuffers(1, &fbo_);
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, reflector_texture_->texture_id(),
0);
reflector_->OnSourceTextureMailboxUpdated(
reflector_texture_->mailbox());
}
}
......@@ -72,9 +81,10 @@ void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() {
GLES2Interface* gl = context_provider_->ContextGL();
if (backing_texture_id_) {
gl->DeleteTextures(1, &backing_texture_id_);
backing_texture_id_ = 0;
if (reflector_texture_) {
reflector_texture_.reset();
if (reflector_)
reflector_->OnSourceTextureMailboxUpdated(nullptr);
}
if (fbo_) {
......@@ -96,23 +106,18 @@ void OffscreenBrowserCompositorOutputSurface::Reshape(const gfx::Size& size,
}
void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() {
bool need_to_bind = !!reflector_texture_.get();
EnsureBackbuffer();
DCHECK(backing_texture_id_);
GLES2Interface* gl = context_provider_->ContextGL();
DCHECK(reflector_texture_.get());
if (!fbo_)
gl->GenFramebuffers(1, &fbo_);
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
backing_texture_id_, 0);
if (need_to_bind) {
GLES2Interface* gl = context_provider_->ContextGL();
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
}
}
void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
// TODO(oshima): Pass the texture to the reflector so that the
// reflector can simply use and draw it on their surface instead of
// copying the texture.
if (reflector_) {
if (frame->gl_frame_data->sub_buffer_rect ==
gfx::Rect(frame->gl_frame_data->size))
......@@ -122,13 +127,17 @@ void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
}
client_->DidSwapBuffers();
}
void OffscreenBrowserCompositorOutputSurface::OnReflectorChanged() {
if (reflector_)
EnsureBackbuffer();
}
// TODO(oshima): sync with the reflector's SwapBuffersComplete.
uint32_t sync_point =
context_provider_->ContextGL()->InsertSyncPointCHROMIUM();
context_provider_->ContextSupport()->SignalSyncPoint(
sync_point, base::Bind(&OutputSurface::OnSwapBuffersComplete,
weak_ptr_factory_.GetWeakPtr()));
base::Closure
OffscreenBrowserCompositorOutputSurface::CreateCompositionStartedCallback() {
return base::Bind(&OutputSurface::OnSwapBuffersComplete,
weak_ptr_factory_.GetWeakPtr());
}
#if defined(OS_MACOSX)
......
......@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_COMPOSITOR_OFFSCREEN_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#include "base/cancelable_callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
......@@ -15,6 +16,7 @@ class CompositorVSyncManager;
namespace content {
class CommandBufferProxyImpl;
class ReflectorTexture;
class OffscreenBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
......@@ -35,6 +37,9 @@ class OffscreenBrowserCompositorOutputSurface
void BindFramebuffer() override;
void SwapBuffers(cc::CompositorFrame* frame) override;
// BrowserCompositorOutputSurface
void OnReflectorChanged() override;
base::Closure CreateCompositionStartedCallback() override;
#if defined(OS_MACOSX)
void OnSurfaceDisplayed() override {};
void SetSurfaceSuspendedForRecycle(bool suspended) override {};
......@@ -43,7 +48,7 @@ class OffscreenBrowserCompositorOutputSurface
uint32 fbo_;
bool is_backbuffer_discarded_;
uint32 backing_texture_id_;
scoped_ptr<ReflectorTexture> reflector_texture_;
base::WeakPtrFactory<OffscreenBrowserCompositorOutputSurface>
weak_ptr_factory_;
......
......@@ -8,7 +8,7 @@
#include "base/location.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/common/gpu/client/gl_helper.h"
//#include "content/common/gpu/client/gl_helper.h"
#include "ui/compositor/layer.h"
namespace content {
......@@ -23,11 +23,11 @@ struct ReflectorImpl::LayerData {
ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor,
ui::Layer* mirroring_layer)
: mirrored_compositor_(mirrored_compositor),
mirrored_compositor_gl_helper_texture_id_(0),
flip_texture_(false),
composition_count_(0),
output_surface_(nullptr) {
if (mirroring_layer)
mirroring_layers_.push_back(new LayerData(mirroring_layer));
AddMirroringLayer(mirroring_layer);
}
ReflectorImpl::~ReflectorImpl() {
......@@ -46,10 +46,6 @@ void ReflectorImpl::DetachFromOutputSurface() {
DCHECK(mailbox_.get());
mailbox_ = nullptr;
output_surface_ = nullptr;
mirrored_compositor_gl_helper_->DeleteTexture(
mirrored_compositor_gl_helper_texture_id_);
mirrored_compositor_gl_helper_texture_id_ = 0;
mirrored_compositor_gl_helper_ = nullptr;
for (LayerData* layer_data : mirroring_layers_)
layer_data->layer->SetShowSolidColorContent();
}
......@@ -63,34 +59,13 @@ void ReflectorImpl::OnSourceSurfaceReady(
if (output_surface_)
DetachFromOutputSurface();
// Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we
// don't have to manage the lifetime of the GLHelper relative to the lifetime
// of the mailbox.
GLHelper* shared_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
mailbox_ = new OwnedMailbox(shared_helper);
for (LayerData* layer_data : mirroring_layers_)
layer_data->needs_set_mailbox = true;
output_surface_ = output_surface;
// Create a GLHelper attached to the mirrored compositor's output surface for
// copying the output of the mirrored compositor.
mirrored_compositor_gl_helper_.reset(
new GLHelper(output_surface->context_provider()->ContextGL(),
output_surface->context_provider()->ContextSupport()));
// Create a texture id in the name space of the new GLHelper to update the
// mailbox being held by the |mirroring_layer_|.
mirrored_compositor_gl_helper_texture_id_ =
mirrored_compositor_gl_helper_->ConsumeMailboxToTexture(
mailbox_->mailbox(), mailbox_->sync_point());
composition_started_callback_ =
output_surface_->CreateCompositionStartedCallback();
flip_texture_ = !output_surface->capabilities().flipped_output_surface;
// The texture doesn't have the data. Request full redraw on mirrored
// compositor so that the full content will be copied to mirroring compositor.
// This full redraw should land us in OnSourceSwapBuffers() to resize the
// texture appropriately.
mirrored_compositor_->ScheduleFullRedraw();
output_surface_ = output_surface;
output_surface_->SetReflector(this);
}
......@@ -100,58 +75,87 @@ void ReflectorImpl::OnMirroringCompositorResized() {
}
void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) {
DCHECK(layer->GetCompositor());
DCHECK(mirroring_layers_.end() == FindLayerData(layer));
LayerData* layer_data = new LayerData(layer);
if (mailbox_)
layer_data->needs_set_mailbox = true;
mirroring_layers_.push_back(layer_data);
mirrored_compositor_->ScheduleFullRedraw();
layer->GetCompositor()->AddObserver(this);
}
void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) {
DCHECK(layer->GetCompositor());
ScopedVector<LayerData>::iterator iter = FindLayerData(layer);
DCHECK(iter != mirroring_layers_.end());
(*iter)->layer->SetShowSolidColorContent();
mirroring_layers_.erase(iter);
layer->GetCompositor()->RemoveObserver(this);
composition_count_--;
if (composition_count_ == 0 && !composition_started_callback_.is_null())
composition_started_callback_.Run();
if (mirroring_layers_.empty() && output_surface_)
DetachFromOutputSurface();
}
void ReflectorImpl::OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) {
if (composition_count_ > 0 && --composition_count_ == 0 &&
!composition_started_callback_.is_null()) {
composition_started_callback_.Run();
}
}
void ReflectorImpl::OnSourceTextureMailboxUpdated(
scoped_refptr<OwnedMailbox> mailbox) {
mailbox_ = mailbox;
if (mailbox_.get()) {
for (LayerData* layer_data : mirroring_layers_)
layer_data->needs_set_mailbox = true;
// The texture doesn't have the data. Request full redraw on mirrored
// compositor so that the full content will be copied to mirroring
// compositor. This full redraw should land us in OnSourceSwapBuffers() to
// resize the texture appropriately.
mirrored_compositor_->ScheduleFullRedraw();
}
}
void ReflectorImpl::OnSourceSwapBuffers() {
if (mirroring_layers_.empty())
if (mirroring_layers_.empty()) {
if (!composition_started_callback_.is_null())
composition_started_callback_.Run();
return;
}
// Should be attached to the source output surface already.
DCHECK(mailbox_.get());
gfx::Size size = output_surface_->SurfaceSize();
mirrored_compositor_gl_helper_->CopyTextureFullImage(
mirrored_compositor_gl_helper_texture_id_, size);
// Insert a barrier to make the copy show up in the mirroring compositor's
// mailbox. Since the the compositor contexts and the ImageTransportFactory's
// GLHelper are all on the same GPU channel, this is sufficient instead of
// plumbing through a sync point.
mirrored_compositor_gl_helper_->InsertOrderingBarrier();
// Request full redraw on mirroring compositor.
for (LayerData* layer_data : mirroring_layers_)
UpdateTexture(layer_data, size, layer_data->layer->bounds());
composition_count_ = mirroring_layers_.size();
}
void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) {
if (mirroring_layers_.empty())
if (mirroring_layers_.empty()) {
if (!composition_started_callback_.is_null())
composition_started_callback_.Run();
return;
}
// Should be attached to the source output surface already.
DCHECK(mailbox_.get());
gfx::Size size = output_surface_->SurfaceSize();
mirrored_compositor_gl_helper_->CopyTextureSubImage(
mirrored_compositor_gl_helper_texture_id_, rect);
// Insert a barrier to make the copy show up in the mirroring compositor's
// mailbox. Since the the compositor contexts and the ImageTransportFactory's
// GLHelper are all on the same GPU channel, this is sufficient instead of
// plumbing through a sync point.
mirrored_compositor_gl_helper_->InsertOrderingBarrier();
int y = rect.y();
// Flip the coordinates to compositor's one.
......@@ -162,6 +166,7 @@ void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) {
// Request redraw of the dirty portion in mirroring compositor.
for (LayerData* layer_data : mirroring_layers_)
UpdateTexture(layer_data, size, mirroring_rect);
composition_count_ = mirroring_layers_.size();
}
static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
......
......@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_COMPOSITOR_REFLECTOR_IMPL_H_
#define CONTENT_BROWSER_COMPOSITOR_REFLECTOR_IMPL_H_
#include "base/callback.h"
#include "base/id_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
......@@ -13,6 +14,7 @@
#include "content/browser/compositor/image_transport_factory.h"
#include "content/common/content_export.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/reflector.h"
#include "ui/gfx/geometry/size.h"
......@@ -34,7 +36,8 @@ class BrowserCompositorOutputSurface;
// to the texture, then draw it onto the mirroring compositor.
class CONTENT_EXPORT ReflectorImpl
: public base::SupportsWeakPtr<ReflectorImpl>,
public ui::Reflector {
public ui::Reflector,
public ui::CompositorObserver {
public:
ReflectorImpl(ui::Compositor* mirrored_compositor,
ui::Layer* mirroring_layer);
......@@ -46,11 +49,20 @@ class CONTENT_EXPORT ReflectorImpl
void DetachFromOutputSurface();
// ui::Reflector implementation.
// ui::Reflector:
void OnMirroringCompositorResized() override;
void AddMirroringLayer(ui::Layer* layer) override;
void RemoveMirroringLayer(ui::Layer* layer) override;
// ui::CompositorObserver:
void OnCompositingDidCommit(ui::Compositor* compositor) override {}
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override;
void OnCompositingEnded(ui::Compositor* compositor) override {}
void OnCompositingAborted(ui::Compositor* compositor) override {}
void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
// Called in |BrowserCompositorOutputSurface::SwapBuffers| to copy
// the full screen image to the |mailbox_| texture.
void OnSourceSwapBuffers();
......@@ -62,6 +74,10 @@ class CONTENT_EXPORT ReflectorImpl
// Called when the source surface is bound and available.
void OnSourceSurfaceReady(BrowserCompositorOutputSurface* surface);
// Called when the mailbox which has the source surface's texture
// is updated.
void OnSourceTextureMailboxUpdated(scoped_refptr<OwnedMailbox> mailbox);
private:
struct LayerData;
......@@ -73,11 +89,12 @@ class CONTENT_EXPORT ReflectorImpl
ui::Compositor* mirrored_compositor_;
ScopedVector<LayerData> mirroring_layers_;
scoped_refptr<OwnedMailbox> mailbox_;
scoped_ptr<GLHelper> mirrored_compositor_gl_helper_;
int mirrored_compositor_gl_helper_texture_id_;
bool flip_texture_;
int composition_count_;
BrowserCompositorOutputSurface* output_surface_;
base::Closure composition_started_callback_;
};
} // namespace content
......
......@@ -11,6 +11,7 @@
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/reflector_texture.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
......@@ -80,6 +81,15 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
void SwapBuffers(cc::CompositorFrame* frame) override {}
void OnReflectorChanged() override {
if (!reflector_) {
reflector_texture_.reset();
} else {
reflector_texture_.reset(new ReflectorTexture(context_provider()));
reflector_->OnSourceTextureMailboxUpdated(reflector_texture_->mailbox());
}
}
#if defined(OS_MACOSX)
void OnSurfaceDisplayed() override {}
void SetSurfaceSuspendedForRecycle(bool suspended) override {}
......@@ -89,6 +99,9 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
#endif
gfx::Size SurfaceSize() const override { return gfx::Size(256, 256); }
private:
scoped_ptr<ReflectorTexture> reflector_texture_;
};
const gfx::Rect kSubRect(0, 0, 64, 64);
......@@ -118,7 +131,10 @@ class ReflectorImplTest : public testing::Test {
compositor_->vsync_manager())).Pass();
CHECK(output_surface_->BindToClient(&output_surface_client_));
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
compositor_->SetRootLayer(root_layer_.get());
mirroring_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
compositor_->root_layer()->Add(mirroring_layer_.get());
gfx::Size size = output_surface_->SurfaceSize();
mirroring_layer_->SetBounds(gfx::Rect(size.width(), size.height()));
}
......@@ -130,6 +146,8 @@ class ReflectorImplTest : public testing::Test {
}
void TearDown() override {
if (reflector_)
reflector_->RemoveMirroringLayer(mirroring_layer_.get());
cc::TextureMailbox mailbox;
scoped_ptr<cc::SingleReleaseCallback> release;
if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release, false)) {
......@@ -149,6 +167,7 @@ class ReflectorImplTest : public testing::Test {
scoped_ptr<base::MessageLoop> message_loop_;
scoped_refptr<base::MessageLoopProxy> proxy_;
scoped_ptr<ui::Compositor> compositor_;
scoped_ptr<ui::Layer> root_layer_;
scoped_ptr<ui::Layer> mirroring_layer_;
scoped_ptr<ReflectorImpl> reflector_;
scoped_ptr<TestOutputSurface> output_surface_;
......
// Copyright 2015 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/reflector_texture.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gl_helper.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
namespace content {
ReflectorTexture::ReflectorTexture(cc::ContextProvider* context_provider)
: texture_id_(0) {
GLHelper* shared_helper =
ImageTransportFactory::GetInstance()->GetGLHelper();
mailbox_ = new OwnedMailbox(shared_helper);
gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
gl_helper_.reset(new GLHelper(gl, context_provider->ContextSupport()));
texture_id_ = gl_helper_->ConsumeMailboxToTexture(
mailbox_->mailbox(), mailbox_->sync_point());
}
ReflectorTexture::~ReflectorTexture() {
gl_helper_->DeleteTexture(texture_id_);
}
void ReflectorTexture::CopyTextureFullImage(const gfx::Size& size) {
gl_helper_->CopyTextureFullImage(texture_id_, size);
// Insert a barrier to make the copy show up in the mirroring compositor's
// mailbox. Since the the compositor contexts and the
// ImageTransportFactory's
// GLHelper are all on the same GPU channel, this is sufficient instead of
// plumbing through a sync point.
gl_helper_->InsertOrderingBarrier();
}
void ReflectorTexture::CopyTextureSubImage(const gfx::Rect& rect) {
gl_helper_->CopyTextureSubImage(texture_id_, rect);
// Insert a barrier for the same reason above.
gl_helper_->InsertOrderingBarrier();
}
} // namespace content
// Copyright 2015 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.
#ifndef CONTENT_BROWSER_COMPOSITOR_REFLECTOR_TEXTURE_H_
#define CONTENT_BROWSER_COMPOSITOR_REFLECTOR_TEXTURE_H_
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/common/content_export.h"
namespace cc {
class ContextProvider;
}
namespace gfx {
class Rect;
class Size;
}
namespace content {
class GLHelper;
// Create and manages texture mailbox to be used by Reflector.
class CONTENT_EXPORT ReflectorTexture {
public:
explicit ReflectorTexture(cc::ContextProvider* provider);
~ReflectorTexture();
void CopyTextureFullImage(const gfx::Size& size);
void CopyTextureSubImage(const gfx::Rect& size);
uint32 texture_id() const { return texture_id_; }
scoped_refptr<OwnedMailbox> mailbox() { return mailbox_; }
private:
scoped_refptr<OwnedMailbox> mailbox_;
scoped_ptr<GLHelper> gl_helper_;
uint32 texture_id_;
DISALLOW_COPY_AND_ASSIGN(ReflectorTexture);
};
} // namespace content
#endif
......@@ -1589,6 +1589,8 @@
'browser/compositor/owned_mailbox.h',
'browser/compositor/reflector_impl.cc',
'browser/compositor/reflector_impl.h',
'browser/compositor/reflector_texture.cc',
'browser/compositor/reflector_texture.h',
'browser/compositor/resize_lock.cc',
'browser/compositor/resize_lock.h',
'browser/compositor/software_browser_compositor_output_surface.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment