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) { ...@@ -78,6 +78,16 @@ void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) {
overlay_candidate_validator_->SetSoftwareMirrorMode(reflector != nullptr); overlay_candidate_validator_->SetSoftwareMirrorMode(reflector != nullptr);
} }
reflector_ = reflector; reflector_ = reflector;
OnReflectorChanged();
}
void BrowserCompositorOutputSurface::OnReflectorChanged() {
}
base::Closure
BrowserCompositorOutputSurface::CreateCompositionStartedCallback() {
return base::Closure();
} }
cc::OverlayCandidateValidator* cc::OverlayCandidateValidator*
......
...@@ -39,6 +39,13 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface ...@@ -39,6 +39,13 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
void SetReflector(ReflectorImpl* reflector); 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) #if defined(OS_MACOSX)
virtual void OnSurfaceDisplayed() = 0; virtual void OnSurfaceDisplayed() = 0;
virtual void SetSurfaceSuspendedForRecycle(bool suspended) = 0; virtual void SetSurfaceSuspendedForRecycle(bool suspended) = 0;
......
...@@ -8,11 +8,10 @@ ...@@ -8,11 +8,10 @@
#include "cc/output/output_surface_client.h" #include "cc/output/output_surface_client.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h" #include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.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/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.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/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
namespace content { namespace content {
...@@ -60,6 +59,15 @@ bool GpuBrowserCompositorOutputSurface::BindToClient( ...@@ -60,6 +59,15 @@ bool GpuBrowserCompositorOutputSurface::BindToClient(
return true; 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( void GpuBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) { cc::CompositorFrame* frame) {
DCHECK(frame->gl_frame_data); DCHECK(frame->gl_frame_data);
...@@ -68,10 +76,14 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers( ...@@ -68,10 +76,14 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers(
if (reflector_) { if (reflector_) {
if (frame->gl_frame_data->sub_buffer_rect == 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(); reflector_->OnSourceSwapBuffers();
else } else {
reflector_->OnSourcePostSubBuffer(frame->gl_frame_data->sub_buffer_rect); 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 == if (frame->gl_frame_data->sub_buffer_rect ==
......
...@@ -15,6 +15,7 @@ class CompositorVSyncManager; ...@@ -15,6 +15,7 @@ class CompositorVSyncManager;
namespace content { namespace content {
class CommandBufferProxyImpl; class CommandBufferProxyImpl;
class BrowserCompositorOverlayCandidateValidator; class BrowserCompositorOverlayCandidateValidator;
class ReflectorTexture;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a // Adapts a WebGraphicsContext3DCommandBufferImpl into a
// cc::OutputSurface that also handles vsync parameter updates // cc::OutputSurface that also handles vsync parameter updates
...@@ -31,6 +32,9 @@ class GpuBrowserCompositorOutputSurface ...@@ -31,6 +32,9 @@ class GpuBrowserCompositorOutputSurface
~GpuBrowserCompositorOutputSurface() override; ~GpuBrowserCompositorOutputSurface() override;
protected: protected:
// BrowserCompositorOutputSurface:
void OnReflectorChanged() override;
// cc::OutputSurface implementation. // cc::OutputSurface implementation.
void SwapBuffers(cc::CompositorFrame* frame) override; void SwapBuffers(cc::CompositorFrame* frame) override;
bool BindToClient(cc::OutputSurfaceClient* client) override; bool BindToClient(cc::OutputSurfaceClient* client) override;
...@@ -62,6 +66,8 @@ class GpuBrowserCompositorOutputSurface ...@@ -62,6 +66,8 @@ class GpuBrowserCompositorOutputSurface
base::TimeDelta interval)> base::TimeDelta interval)>
update_vsync_parameters_callback_; update_vsync_parameters_callback_;
scoped_ptr<ReflectorTexture> reflector_texture_;
DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface); DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "cc/resources/resource_provider.h" #include "cc/resources/resource_provider.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h" #include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.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/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/context_support.h"
...@@ -37,7 +38,6 @@ OffscreenBrowserCompositorOutputSurface:: ...@@ -37,7 +38,6 @@ OffscreenBrowserCompositorOutputSurface::
overlay_candidate_validator.Pass()), overlay_candidate_validator.Pass()),
fbo_(0), fbo_(0),
is_backbuffer_discarded_(false), is_backbuffer_discarded_(false),
backing_texture_id_(0),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
capabilities_.max_frames_pending = 1; capabilities_.max_frames_pending = 1;
capabilities_.uses_default_gl_framebuffer = false; capabilities_.uses_default_gl_framebuffer = false;
...@@ -51,12 +51,12 @@ OffscreenBrowserCompositorOutputSurface:: ...@@ -51,12 +51,12 @@ OffscreenBrowserCompositorOutputSurface::
void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() { void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
is_backbuffer_discarded_ = false; is_backbuffer_discarded_ = false;
if (!backing_texture_id_) { if (!reflector_texture_.get()) {
reflector_texture_.reset(new ReflectorTexture(context_provider()));
GLES2Interface* gl = context_provider_->ContextGL(); GLES2Interface* gl = context_provider_->ContextGL();
cc::ResourceFormat format = cc::RGBA_8888; cc::ResourceFormat format = cc::RGBA_8888;
gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id());
gl->GenTextures(1, &backing_texture_id_);
gl->BindTexture(GL_TEXTURE_2D, backing_texture_id_);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 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_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
...@@ -64,6 +64,15 @@ void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() { ...@@ -64,6 +64,15 @@ void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format),
surface_size_.width(), surface_size_.height(), 0, surface_size_.width(), surface_size_.height(), 0,
GLDataFormat(format), GLDataType(format), nullptr); 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() { ...@@ -72,9 +81,10 @@ void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() {
GLES2Interface* gl = context_provider_->ContextGL(); GLES2Interface* gl = context_provider_->ContextGL();
if (backing_texture_id_) { if (reflector_texture_) {
gl->DeleteTextures(1, &backing_texture_id_); reflector_texture_.reset();
backing_texture_id_ = 0; if (reflector_)
reflector_->OnSourceTextureMailboxUpdated(nullptr);
} }
if (fbo_) { if (fbo_) {
...@@ -96,23 +106,18 @@ void OffscreenBrowserCompositorOutputSurface::Reshape(const gfx::Size& size, ...@@ -96,23 +106,18 @@ void OffscreenBrowserCompositorOutputSurface::Reshape(const gfx::Size& size,
} }
void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() { void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() {
bool need_to_bind = !!reflector_texture_.get();
EnsureBackbuffer(); EnsureBackbuffer();
DCHECK(backing_texture_id_); DCHECK(reflector_texture_.get());
GLES2Interface* gl = context_provider_->ContextGL();
if (!fbo_) if (need_to_bind) {
gl->GenFramebuffers(1, &fbo_); GLES2Interface* gl = context_provider_->ContextGL();
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, }
backing_texture_id_, 0);
} }
void OffscreenBrowserCompositorOutputSurface::SwapBuffers( void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) { 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 (reflector_) {
if (frame->gl_frame_data->sub_buffer_rect == if (frame->gl_frame_data->sub_buffer_rect ==
gfx::Rect(frame->gl_frame_data->size)) gfx::Rect(frame->gl_frame_data->size))
...@@ -122,13 +127,17 @@ void OffscreenBrowserCompositorOutputSurface::SwapBuffers( ...@@ -122,13 +127,17 @@ void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
} }
client_->DidSwapBuffers(); client_->DidSwapBuffers();
}
void OffscreenBrowserCompositorOutputSurface::OnReflectorChanged() {
if (reflector_)
EnsureBackbuffer();
}
// TODO(oshima): sync with the reflector's SwapBuffersComplete. base::Closure
uint32_t sync_point = OffscreenBrowserCompositorOutputSurface::CreateCompositionStartedCallback() {
context_provider_->ContextGL()->InsertSyncPointCHROMIUM(); return base::Bind(&OutputSurface::OnSwapBuffersComplete,
context_provider_->ContextSupport()->SignalSyncPoint( weak_ptr_factory_.GetWeakPtr());
sync_point, base::Bind(&OutputSurface::OnSwapBuffersComplete,
weak_ptr_factory_.GetWeakPtr()));
} }
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_COMPOSITOR_OFFSCREEN_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_ #define CONTENT_BROWSER_COMPOSITOR_OFFSCREEN_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#include "base/cancelable_callback.h" #include "base/cancelable_callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "content/browser/compositor/browser_compositor_output_surface.h" #include "content/browser/compositor/browser_compositor_output_surface.h"
...@@ -15,6 +16,7 @@ class CompositorVSyncManager; ...@@ -15,6 +16,7 @@ class CompositorVSyncManager;
namespace content { namespace content {
class CommandBufferProxyImpl; class CommandBufferProxyImpl;
class ReflectorTexture;
class OffscreenBrowserCompositorOutputSurface class OffscreenBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface { : public BrowserCompositorOutputSurface {
...@@ -35,6 +37,9 @@ class OffscreenBrowserCompositorOutputSurface ...@@ -35,6 +37,9 @@ class OffscreenBrowserCompositorOutputSurface
void BindFramebuffer() override; void BindFramebuffer() override;
void SwapBuffers(cc::CompositorFrame* frame) override; void SwapBuffers(cc::CompositorFrame* frame) override;
// BrowserCompositorOutputSurface
void OnReflectorChanged() override;
base::Closure CreateCompositionStartedCallback() override;
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
void OnSurfaceDisplayed() override {}; void OnSurfaceDisplayed() override {};
void SetSurfaceSuspendedForRecycle(bool suspended) override {}; void SetSurfaceSuspendedForRecycle(bool suspended) override {};
...@@ -43,7 +48,7 @@ class OffscreenBrowserCompositorOutputSurface ...@@ -43,7 +48,7 @@ class OffscreenBrowserCompositorOutputSurface
uint32 fbo_; uint32 fbo_;
bool is_backbuffer_discarded_; bool is_backbuffer_discarded_;
uint32 backing_texture_id_; scoped_ptr<ReflectorTexture> reflector_texture_;
base::WeakPtrFactory<OffscreenBrowserCompositorOutputSurface> base::WeakPtrFactory<OffscreenBrowserCompositorOutputSurface>
weak_ptr_factory_; weak_ptr_factory_;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "base/location.h" #include "base/location.h"
#include "content/browser/compositor/browser_compositor_output_surface.h" #include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/owned_mailbox.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" #include "ui/compositor/layer.h"
namespace content { namespace content {
...@@ -23,11 +23,11 @@ struct ReflectorImpl::LayerData { ...@@ -23,11 +23,11 @@ struct ReflectorImpl::LayerData {
ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor, ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor,
ui::Layer* mirroring_layer) ui::Layer* mirroring_layer)
: mirrored_compositor_(mirrored_compositor), : mirrored_compositor_(mirrored_compositor),
mirrored_compositor_gl_helper_texture_id_(0),
flip_texture_(false), flip_texture_(false),
composition_count_(0),
output_surface_(nullptr) { output_surface_(nullptr) {
if (mirroring_layer) if (mirroring_layer)
mirroring_layers_.push_back(new LayerData(mirroring_layer)); AddMirroringLayer(mirroring_layer);
} }
ReflectorImpl::~ReflectorImpl() { ReflectorImpl::~ReflectorImpl() {
...@@ -46,10 +46,6 @@ void ReflectorImpl::DetachFromOutputSurface() { ...@@ -46,10 +46,6 @@ void ReflectorImpl::DetachFromOutputSurface() {
DCHECK(mailbox_.get()); DCHECK(mailbox_.get());
mailbox_ = nullptr; mailbox_ = nullptr;
output_surface_ = 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_) for (LayerData* layer_data : mirroring_layers_)
layer_data->layer->SetShowSolidColorContent(); layer_data->layer->SetShowSolidColorContent();
} }
...@@ -63,34 +59,13 @@ void ReflectorImpl::OnSourceSurfaceReady( ...@@ -63,34 +59,13 @@ void ReflectorImpl::OnSourceSurfaceReady(
if (output_surface_) if (output_surface_)
DetachFromOutputSurface(); DetachFromOutputSurface();
// Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we output_surface_ = output_surface;
// 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;
// Create a GLHelper attached to the mirrored compositor's output surface for composition_started_callback_ =
// copying the output of the mirrored compositor. output_surface_->CreateCompositionStartedCallback();
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());
flip_texture_ = !output_surface->capabilities().flipped_output_surface; 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); output_surface_->SetReflector(this);
} }
...@@ -100,58 +75,87 @@ void ReflectorImpl::OnMirroringCompositorResized() { ...@@ -100,58 +75,87 @@ void ReflectorImpl::OnMirroringCompositorResized() {
} }
void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) { void ReflectorImpl::AddMirroringLayer(ui::Layer* layer) {
DCHECK(layer->GetCompositor());
DCHECK(mirroring_layers_.end() == FindLayerData(layer)); DCHECK(mirroring_layers_.end() == FindLayerData(layer));
LayerData* layer_data = new LayerData(layer); LayerData* layer_data = new LayerData(layer);
if (mailbox_) if (mailbox_)
layer_data->needs_set_mailbox = true; layer_data->needs_set_mailbox = true;
mirroring_layers_.push_back(layer_data); mirroring_layers_.push_back(layer_data);
mirrored_compositor_->ScheduleFullRedraw(); mirrored_compositor_->ScheduleFullRedraw();
layer->GetCompositor()->AddObserver(this);
} }
void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) { void ReflectorImpl::RemoveMirroringLayer(ui::Layer* layer) {
DCHECK(layer->GetCompositor());
ScopedVector<LayerData>::iterator iter = FindLayerData(layer); ScopedVector<LayerData>::iterator iter = FindLayerData(layer);
DCHECK(iter != mirroring_layers_.end()); DCHECK(iter != mirroring_layers_.end());
(*iter)->layer->SetShowSolidColorContent(); (*iter)->layer->SetShowSolidColorContent();
mirroring_layers_.erase(iter); 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_) if (mirroring_layers_.empty() && output_surface_)
DetachFromOutputSurface(); 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() { void ReflectorImpl::OnSourceSwapBuffers() {
if (mirroring_layers_.empty()) if (mirroring_layers_.empty()) {
if (!composition_started_callback_.is_null())
composition_started_callback_.Run();
return; return;
}
// Should be attached to the source output surface already. // Should be attached to the source output surface already.
DCHECK(mailbox_.get()); DCHECK(mailbox_.get());
gfx::Size size = output_surface_->SurfaceSize(); 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. // Request full redraw on mirroring compositor.
for (LayerData* layer_data : mirroring_layers_) for (LayerData* layer_data : mirroring_layers_)
UpdateTexture(layer_data, size, layer_data->layer->bounds()); UpdateTexture(layer_data, size, layer_data->layer->bounds());
composition_count_ = mirroring_layers_.size();
} }
void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { 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; return;
}
// Should be attached to the source output surface already. // Should be attached to the source output surface already.
DCHECK(mailbox_.get()); DCHECK(mailbox_.get());
gfx::Size size = output_surface_->SurfaceSize(); 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(); int y = rect.y();
// Flip the coordinates to compositor's one. // Flip the coordinates to compositor's one.
...@@ -162,6 +166,7 @@ void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) { ...@@ -162,6 +166,7 @@ void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) {
// Request redraw of the dirty portion in mirroring compositor. // Request redraw of the dirty portion in mirroring compositor.
for (LayerData* layer_data : mirroring_layers_) for (LayerData* layer_data : mirroring_layers_)
UpdateTexture(layer_data, size, mirroring_rect); UpdateTexture(layer_data, size, mirroring_rect);
composition_count_ = mirroring_layers_.size();
} }
static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox, static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_COMPOSITOR_REFLECTOR_IMPL_H_ #ifndef CONTENT_BROWSER_COMPOSITOR_REFLECTOR_IMPL_H_
#define CONTENT_BROWSER_COMPOSITOR_REFLECTOR_IMPL_H_ #define CONTENT_BROWSER_COMPOSITOR_REFLECTOR_IMPL_H_
#include "base/callback.h"
#include "base/id_map.h" #include "base/id_map.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h" #include "base/memory/scoped_vector.h"
...@@ -13,6 +14,7 @@ ...@@ -13,6 +14,7 @@
#include "content/browser/compositor/image_transport_factory.h" #include "content/browser/compositor/image_transport_factory.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "gpu/command_buffer/common/mailbox_holder.h" #include "gpu/command_buffer/common/mailbox_holder.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/reflector.h" #include "ui/compositor/reflector.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -34,7 +36,8 @@ class BrowserCompositorOutputSurface; ...@@ -34,7 +36,8 @@ class BrowserCompositorOutputSurface;
// to the texture, then draw it onto the mirroring compositor. // to the texture, then draw it onto the mirroring compositor.
class CONTENT_EXPORT ReflectorImpl class CONTENT_EXPORT ReflectorImpl
: public base::SupportsWeakPtr<ReflectorImpl>, : public base::SupportsWeakPtr<ReflectorImpl>,
public ui::Reflector { public ui::Reflector,
public ui::CompositorObserver {
public: public:
ReflectorImpl(ui::Compositor* mirrored_compositor, ReflectorImpl(ui::Compositor* mirrored_compositor,
ui::Layer* mirroring_layer); ui::Layer* mirroring_layer);
...@@ -46,11 +49,20 @@ class CONTENT_EXPORT ReflectorImpl ...@@ -46,11 +49,20 @@ class CONTENT_EXPORT ReflectorImpl
void DetachFromOutputSurface(); void DetachFromOutputSurface();
// ui::Reflector implementation. // ui::Reflector:
void OnMirroringCompositorResized() override; void OnMirroringCompositorResized() override;
void AddMirroringLayer(ui::Layer* layer) override; void AddMirroringLayer(ui::Layer* layer) override;
void RemoveMirroringLayer(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 // Called in |BrowserCompositorOutputSurface::SwapBuffers| to copy
// the full screen image to the |mailbox_| texture. // the full screen image to the |mailbox_| texture.
void OnSourceSwapBuffers(); void OnSourceSwapBuffers();
...@@ -62,6 +74,10 @@ class CONTENT_EXPORT ReflectorImpl ...@@ -62,6 +74,10 @@ class CONTENT_EXPORT ReflectorImpl
// Called when the source surface is bound and available. // Called when the source surface is bound and available.
void OnSourceSurfaceReady(BrowserCompositorOutputSurface* surface); void OnSourceSurfaceReady(BrowserCompositorOutputSurface* surface);
// Called when the mailbox which has the source surface's texture
// is updated.
void OnSourceTextureMailboxUpdated(scoped_refptr<OwnedMailbox> mailbox);
private: private:
struct LayerData; struct LayerData;
...@@ -73,11 +89,12 @@ class CONTENT_EXPORT ReflectorImpl ...@@ -73,11 +89,12 @@ class CONTENT_EXPORT ReflectorImpl
ui::Compositor* mirrored_compositor_; ui::Compositor* mirrored_compositor_;
ScopedVector<LayerData> mirroring_layers_; ScopedVector<LayerData> mirroring_layers_;
scoped_refptr<OwnedMailbox> mailbox_; scoped_refptr<OwnedMailbox> mailbox_;
scoped_ptr<GLHelper> mirrored_compositor_gl_helper_;
int mirrored_compositor_gl_helper_texture_id_;
bool flip_texture_; bool flip_texture_;
int composition_count_;
BrowserCompositorOutputSurface* output_surface_; BrowserCompositorOutputSurface* output_surface_;
base::Closure composition_started_callback_;
}; };
} // namespace content } // namespace content
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "content/browser/compositor/browser_compositor_output_surface.h" #include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h" #include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.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 "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h" #include "ui/compositor/compositor.h"
...@@ -80,6 +81,15 @@ class TestOutputSurface : public BrowserCompositorOutputSurface { ...@@ -80,6 +81,15 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
void SwapBuffers(cc::CompositorFrame* frame) override {} 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) #if defined(OS_MACOSX)
void OnSurfaceDisplayed() override {} void OnSurfaceDisplayed() override {}
void SetSurfaceSuspendedForRecycle(bool suspended) override {} void SetSurfaceSuspendedForRecycle(bool suspended) override {}
...@@ -89,6 +99,9 @@ class TestOutputSurface : public BrowserCompositorOutputSurface { ...@@ -89,6 +99,9 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
#endif #endif
gfx::Size SurfaceSize() const override { return gfx::Size(256, 256); } gfx::Size SurfaceSize() const override { return gfx::Size(256, 256); }
private:
scoped_ptr<ReflectorTexture> reflector_texture_;
}; };
const gfx::Rect kSubRect(0, 0, 64, 64); const gfx::Rect kSubRect(0, 0, 64, 64);
...@@ -118,7 +131,10 @@ class ReflectorImplTest : public testing::Test { ...@@ -118,7 +131,10 @@ class ReflectorImplTest : public testing::Test {
compositor_->vsync_manager())).Pass(); compositor_->vsync_manager())).Pass();
CHECK(output_surface_->BindToClient(&output_surface_client_)); 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)); mirroring_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
compositor_->root_layer()->Add(mirroring_layer_.get());
gfx::Size size = output_surface_->SurfaceSize(); gfx::Size size = output_surface_->SurfaceSize();
mirroring_layer_->SetBounds(gfx::Rect(size.width(), size.height())); mirroring_layer_->SetBounds(gfx::Rect(size.width(), size.height()));
} }
...@@ -130,6 +146,8 @@ class ReflectorImplTest : public testing::Test { ...@@ -130,6 +146,8 @@ class ReflectorImplTest : public testing::Test {
} }
void TearDown() override { void TearDown() override {
if (reflector_)
reflector_->RemoveMirroringLayer(mirroring_layer_.get());
cc::TextureMailbox mailbox; cc::TextureMailbox mailbox;
scoped_ptr<cc::SingleReleaseCallback> release; scoped_ptr<cc::SingleReleaseCallback> release;
if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release, false)) { if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release, false)) {
...@@ -149,6 +167,7 @@ class ReflectorImplTest : public testing::Test { ...@@ -149,6 +167,7 @@ class ReflectorImplTest : public testing::Test {
scoped_ptr<base::MessageLoop> message_loop_; scoped_ptr<base::MessageLoop> message_loop_;
scoped_refptr<base::MessageLoopProxy> proxy_; scoped_refptr<base::MessageLoopProxy> proxy_;
scoped_ptr<ui::Compositor> compositor_; scoped_ptr<ui::Compositor> compositor_;
scoped_ptr<ui::Layer> root_layer_;
scoped_ptr<ui::Layer> mirroring_layer_; scoped_ptr<ui::Layer> mirroring_layer_;
scoped_ptr<ReflectorImpl> reflector_; scoped_ptr<ReflectorImpl> reflector_;
scoped_ptr<TestOutputSurface> output_surface_; 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 @@ ...@@ -1589,6 +1589,8 @@
'browser/compositor/owned_mailbox.h', 'browser/compositor/owned_mailbox.h',
'browser/compositor/reflector_impl.cc', 'browser/compositor/reflector_impl.cc',
'browser/compositor/reflector_impl.h', 'browser/compositor/reflector_impl.h',
'browser/compositor/reflector_texture.cc',
'browser/compositor/reflector_texture.h',
'browser/compositor/resize_lock.cc', 'browser/compositor/resize_lock.cc',
'browser/compositor/resize_lock.h', 'browser/compositor/resize_lock.h',
'browser/compositor/software_browser_compositor_output_surface.cc', '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