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

Unified Diff: content/browser/renderer_host/render_widget_host_view_aura.cc

Issue 11194042: Implement TextureImageTransportSurface using texture mailbox (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased, fixed post sub buffer, use multiple mailbox names Created 8 years, 1 month 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
Index: content/browser/renderer_host/render_widget_host_view_aura.cc
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 78cc267c681e336ecb8b82b188a7dab6fe8222b2..6ac4c524ca98f168d699a438a6edf1ec411bdf55 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -277,10 +277,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
has_composition_text_(false),
device_scale_factor_(1.0f),
current_surface_(0),
- current_surface_is_protected_(true),
- current_surface_in_use_by_compositor_(true),
- protection_state_id_(0),
- surface_route_id_(0),
paint_canvas_(NULL),
synthetic_move_sent_(false),
accelerated_compositing_state_changed_(false),
@@ -367,8 +363,6 @@ void RenderWidgetHostViewAura::WasShown() {
released_front_lock_ = GetCompositor()->GetCompositorLock();
}
- AdjustSurfaceProtection();
-
#if defined(OS_WIN)
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
@@ -382,14 +376,6 @@ void RenderWidgetHostViewAura::WasHidden() {
released_front_lock_ = NULL;
- if (ShouldReleaseFrontSurface() &&
- host_->is_accelerated_compositing_active()) {
- current_surface_ = 0;
- UpdateExternalTexture();
- }
-
- AdjustSurfaceProtection();
-
#if defined(OS_WIN)
aura::RootWindow* root_window = window_->GetRootWindow();
if (root_window) {
@@ -678,7 +664,7 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurface(
if (it == image_transport_clients_.end())
return;
- ui::Texture* container = it->second;
+ scoped_refptr<ui::Texture> container = it->second;
DCHECK(container);
gfx::Size dst_size_in_pixel = ConvertSizeToPixel(this, dst_size);
@@ -695,11 +681,12 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurface(
output->GetBitmap().getPixels());
scoped_callback_runner.Release();
// Wrap the callback with an internal handler so that we can inject our
- // own completion handlers (where we can call AdjustSurfaceProtection).
+ // own completion handlers (where we can try to free the frontbuffer).
base::Callback<void(bool)> wrapper_callback = base::Bind(
&RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished,
AsWeakPtr(),
- callback);
+ callback,
+ container); // Hold a reference to the texture
piman 2012/11/09 22:02:01 I think we don't need this. By the time CropScaleR
no sievers 2012/11/19 20:30:44 Right it does the copy first on the UI thread. Rem
++pending_thumbnail_tasks_;
// Convert |src_subrect| from the views coordinate (upper-left origin) into
@@ -728,16 +715,13 @@ void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
accelerated_compositing_state_changed_ = true;
}
-bool RenderWidgetHostViewAura::ShouldFastACK(uint64 surface_id) {
- ui::Texture* container = image_transport_clients_[surface_id];
- DCHECK(container);
-
+bool RenderWidgetHostViewAura::ShouldFastACK(const gfx::Size& size) {
if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
can_lock_compositor_ == NO_PENDING_COMMIT ||
resize_locks_.empty())
return false;
- gfx::Size container_size = ConvertSizeToDIP(this, container->size());
+ gfx::Size container_size = ConvertSizeToDIP(this, size);
ResizeLockList::iterator it = resize_locks_.begin();
while (it != resize_locks_.end()) {
if ((*it)->expected_size() == container_size)
@@ -760,7 +744,6 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
if (current_surface_ != 0 && host_->is_accelerated_compositing_active()) {
ui::Texture* container = image_transport_clients_[current_surface_];
window_->SetExternalTexture(container);
- current_surface_in_use_by_compositor_ = true;
if (!container) {
resize_locks_.clear();
@@ -796,120 +779,143 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
}
} else {
window_->SetExternalTexture(NULL);
- if (ShouldReleaseFrontSurface() &&
- host_->is_accelerated_compositing_active()) {
- // We need to wait for a commit to clear to guarantee that all we
- // will not issue any more GL referencing the previous surface.
- ui::Compositor* compositor = GetCompositor();
- if (compositor) {
- can_lock_compositor_ = NO_PENDING_COMMIT;
- on_compositing_did_commit_callbacks_.push_back(
- base::Bind(&RenderWidgetHostViewAura::
- SetSurfaceNotInUseByCompositor,
- AsWeakPtr()));
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
- }
- }
resize_locks_.clear();
}
}
+void RenderWidgetHostViewAura::SwapBuffersCompleted(
+ int gpu_host_id,
+ int route_id,
+ uint64 surface_handle,
+ scoped_refptr<ui::Texture> texture) {
+ ui::Compositor* compositor = GetCompositor();
+ if (!compositor) {
+ InsertSyncPointAndACK(route_id, gpu_host_id, surface_handle, texture);
+ } else {
+ // Add sending an ACK to the list of things to do OnCompositingDidCommit
+ can_lock_compositor_ = NO_PENDING_COMMIT;
+ on_compositing_did_commit_callbacks_.push_back(
+ base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
+ route_id,
+ gpu_host_id,
+ surface_handle,
+ texture));
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+ }
+}
+
void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
int gpu_host_id) {
- surface_route_id_ = params_in_pixel.route_id;
- // If protection state changed, then this swap is stale. We must still ACK but
- // do not update current_surface_ since it may have been discarded.
- if (params_in_pixel.protection_state_id &&
- params_in_pixel.protection_state_id != protection_state_id_) {
- DCHECK(!current_surface_);
- if (!params_in_pixel.skip_ack)
- InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
+ const gfx::Rect surface_rect = gfx::Rect(gfx::Point(), params_in_pixel.size);
+ if (ShouldFastACK(params_in_pixel.size)) {
jonathan.backer 2012/11/12 16:52:15 I'm torn as to handle the detached (no compositor
no sievers 2012/11/19 20:30:44 When exactly would this happen? It sounds though l
piman 2012/11/19 22:09:52 When detached, there'll be no commit either since
piman 2012/11/19 22:31:54 GetCompositor() walks the window tree to find the
+ skipped_damage_ = UnionRects(skipped_damage_, surface_rect);
+ InsertSyncPointAndACK(params_in_pixel.route_id,
+ gpu_host_id,
+ params_in_pixel.surface_handle,
+ NULL);
return;
}
- if (ShouldFastACK(params_in_pixel.surface_handle)) {
- if (!params_in_pixel.skip_ack)
- InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
- return;
- }
+ const uint64 previous_surface = current_surface_;
+ scoped_refptr<ui::Texture> texture_to_return;
+ if (previous_surface)
+ texture_to_return = image_transport_clients_[previous_surface];
current_surface_ = params_in_pixel.surface_handle;
- // If we don't require an ACK that means the content is not a fresh updated
- // new frame, rather we are just resetting our handle to some old content
- // that we still hadn't discarded. Although we could display immediately,
- // by not resetting the compositor lock here, we give us some time to get
- // a fresh frame which means fewer content flashes.
- if (!params_in_pixel.skip_ack)
- released_front_lock_ = NULL;
+ DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) !=
+ image_transport_clients_.end());
+ image_transport_clients_[current_surface_]->Consume(params_in_pixel.size);
+ released_front_lock_ = NULL;
UpdateExternalTexture();
+ previous_damage_rect_ = surface_rect;
+ if (!skipped_damage_.IsEmpty())
piman 2012/11/09 22:02:01 The test isn't useful, since you always end up wit
no sievers 2012/11/19 20:30:44 Done.
+ skipped_damage_ = gfx::Rect();
+
ui::Compositor* compositor = GetCompositor();
- if (!compositor) {
- if (!params_in_pixel.skip_ack)
- InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, true, NULL);
- } else {
- DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) !=
- image_transport_clients_.end());
- gfx::Size surface_size_in_pixel =
- image_transport_clients_[params_in_pixel.surface_handle]->size();
- gfx::Size surface_size = ConvertSizeToDIP(this, surface_size_in_pixel);
+ if (compositor) {
+ gfx::Size surface_size = ConvertSizeToDIP(this, params_in_pixel.size);
window_->SchedulePaintInRect(gfx::Rect(surface_size));
-
- if (!params_in_pixel.skip_ack) {
- // Add sending an ACK to the list of things to do OnCompositingDidCommit
- can_lock_compositor_ = NO_PENDING_COMMIT;
- on_compositing_did_commit_callbacks_.push_back(
- base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
- params_in_pixel.route_id,
- gpu_host_id,
- true));
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
- }
}
+
+ SwapBuffersCompleted(gpu_host_id,
+ params_in_pixel.route_id,
+ previous_surface,
+ texture_to_return);
}
void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
int gpu_host_id) {
- surface_route_id_ = params_in_pixel.route_id;
- // If visible state changed, then this PSB is stale. We must still ACK but
- // do not update current_surface_.
- if (params_in_pixel.protection_state_id &&
- params_in_pixel.protection_state_id != protection_state_id_) {
- DCHECK(!current_surface_);
- InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
+ const gfx::Rect surface_rect =
+ gfx::Rect(gfx::Point(), params_in_pixel.surface_size);
+ gfx::Rect damage_rect(params_in_pixel.x,
+ params_in_pixel.y,
+ params_in_pixel.width,
+ params_in_pixel.height);
+ if (ShouldFastACK(params_in_pixel.surface_size)) {
+ skipped_damage_ = UnionRects(skipped_damage_, damage_rect);
+ InsertSyncPointAndACK(params_in_pixel.route_id,
+ gpu_host_id,
+ params_in_pixel.surface_handle,
+ NULL);
return;
}
- if (ShouldFastACK(params_in_pixel.surface_handle)) {
- InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
- return;
- }
+ const uint64 previous_surface = current_surface_;
+ scoped_refptr<ui::Texture> texture_to_return;
+ if (previous_surface)
+ texture_to_return = image_transport_clients_[previous_surface];
current_surface_ = params_in_pixel.surface_handle;
+ DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) !=
+ image_transport_clients_.end());
+
+ scoped_refptr<ui::Texture>& current_texture =
piman 2012/11/09 22:02:01 scoped_refptr<ui::Texture>& -> ui::Texture*? You'r
no sievers 2012/11/19 20:30:44 Done.
+ image_transport_clients_[current_surface_];
+ current_texture->Consume(params_in_pixel.surface_size);
released_front_lock_ = NULL;
- DCHECK(current_surface_);
UpdateExternalTexture();
+ if (!surface_rect.Contains(skipped_damage_)) {
+ // The surface could have shrunk since we skipped an update, in which
+ // case we can expect a full update.
+ DCHECK(damage_rect == surface_rect);
piman 2012/11/09 22:02:01 mmh, you're really asserting something that's comi
no sievers 2012/11/19 20:30:44 Done.
+ skipped_damage_ = gfx::Rect();
+ }
+
+ if (!skipped_damage_.IsEmpty()) {
+ damage_rect = UnionRects(skipped_damage_, damage_rect);
piman 2012/11/09 22:02:01 So the problem here (and when we union the skipped
jonathan.backer 2012/11/12 16:52:15 Good catch.
no sievers 2012/11/19 20:30:44 Done.
+ skipped_damage_ = gfx::Rect();
+ }
+
+ DCHECK(surface_rect.Contains(damage_rect));
ui::Compositor* compositor = GetCompositor();
- if (!compositor) {
- InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, true, NULL);
- } else {
- DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) !=
- image_transport_clients_.end());
- gfx::Size surface_size_in_pixel =
- image_transport_clients_[params_in_pixel.surface_handle]->size();
+ if (compositor) {
piman 2012/11/09 22:02:01 I think you should do this always. At least the co
jonathan.backer 2012/11/12 16:52:15 As I've mentioned above, I have a slight preferenc
no sievers 2012/11/19 20:30:44 Done, I let it skip the frame if !GetCompositor().
+ const gfx::Size surface_size_in_pixel = params_in_pixel.surface_size;
+ DCHECK(!texture_to_return ||
+ texture_to_return->size() == current_texture->size() ||
+ damage_rect == surface_rect);
+ if (texture_to_return && !previous_damage_rect_.IsEmpty() &&
+ texture_to_return->size() == current_texture->size()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ gl_helper->CopySubBufferDamage(current_texture->PrepareTexture(),
+ texture_to_return->PrepareTexture(),
+ damage_rect,
+ previous_damage_rect_);
jonathan.backer 2012/11/12 16:52:15 Which context is current here? Maybe it doesn't ma
no sievers 2012/11/19 20:30:44 Yes, the thumbnailer also uses the GLHelper and re
piman 2012/11/19 22:09:52 On the client side, makeContextCurrent is essentia
+ }
+ previous_damage_rect_ = damage_rect;
// Co-ordinates come in OpenGL co-ordinate space.
// We need to convert to layer space.
gfx::Rect rect_to_paint = ConvertRectToDIP(this, gfx::Rect(
params_in_pixel.x,
surface_size_in_pixel.height() - params_in_pixel.y -
- params_in_pixel.height,
+ params_in_pixel.height,
params_in_pixel.width,
params_in_pixel.height));
@@ -919,17 +925,12 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
rect_to_paint.Intersect(window_->bounds());
window_->SchedulePaintInRect(rect_to_paint);
-
- // Add sending an ACK to the list of things to do OnCompositingDidCommit
- can_lock_compositor_ = NO_PENDING_COMMIT;
- on_compositing_did_commit_callbacks_.push_back(
- base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
- params_in_pixel.route_id,
- gpu_host_id,
- true));
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
}
+
+ SwapBuffersCompleted(gpu_host_id,
+ params_in_pixel.route_id,
+ previous_surface,
+ texture_to_return);
}
void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
@@ -948,72 +949,59 @@ bool RenderWidgetHostViewAura::HasAcceleratedSurface(
void RenderWidgetHostViewAura::AcceleratedSurfaceNew(
int32 width_in_pixel,
int32 height_in_pixel,
- uint64 surface_handle) {
+ uint64 surface_handle,
+ const std::vector<signed char>& mailbox_name) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
scoped_refptr<ui::Texture> surface(factory->CreateTransportClient(
gfx::Size(width_in_pixel, height_in_pixel), device_scale_factor_,
- surface_handle));
+ mailbox_name));
if (!surface) {
LOG(ERROR) << "Failed to create ImageTransport texture";
return;
}
-
image_transport_clients_[surface_handle] = surface;
}
void RenderWidgetHostViewAura::AcceleratedSurfaceRelease(
uint64 surface_handle) {
- DCHECK(image_transport_clients_.find(surface_handle) !=
- image_transport_clients_.end());
- if (current_surface_ == surface_handle) {
+ // This really tells us to release the frontbuffer.
+ if (current_surface_ && ShouldReleaseFrontSurface() &&
piman 2012/11/09 22:02:01 We should only do this if current_surface_==surfac
no sievers 2012/11/19 20:30:44 Well, I guess I changed the semantics of the messa
+ host_->is_accelerated_compositing_active()) {
piman 2012/11/09 22:02:01 Why is this test needed? Note, it's almost positiv
no sievers 2012/11/19 20:30:44 Done.
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ // We need to wait for a commit to clear to guarantee that all we
+ // will not issue any more GL referencing the previous surface.
+ can_lock_compositor_ = NO_PENDING_COMMIT;
+ scoped_refptr<ui::Texture> surface_ref =
+ image_transport_clients_[surface_handle];
+ on_compositing_did_commit_callbacks_.push_back(
+ base::Bind(&RenderWidgetHostViewAura::
+ SetSurfaceNotInUseByCompositor,
+ AsWeakPtr(),
+ surface_ref));
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+ }
+ image_transport_clients_.erase(current_surface_);
piman 2012/11/09 22:02:01 This should still happen always
current_surface_ = 0;
UpdateExternalTexture();
}
- image_transport_clients_.erase(surface_handle);
}
-void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(ui::Compositor*) {
- if (current_surface_ || !host_->is_hidden())
- return;
- current_surface_in_use_by_compositor_ = false;
- AdjustSurfaceProtection();
-}
-
-void RenderWidgetHostViewAura::AdjustSurfaceProtection() {
- // If the current surface is non null, it is protected.
- // If we are visible, it is protected.
- // Otherwise, change to not proctected once done thumbnailing and compositing.
- bool surface_is_protected =
- current_surface_ ||
- !host_->is_hidden() ||
- (current_surface_is_protected_ &&
- (pending_thumbnail_tasks_ > 0 ||
- current_surface_in_use_by_compositor_));
- if (current_surface_is_protected_ == surface_is_protected)
- return;
- current_surface_is_protected_ = surface_is_protected;
- ++protection_state_id_;
-
- if (!surface_route_id_ || !shared_surface_handle_.parent_gpu_process_id)
- return;
-
- RenderWidgetHostImpl::SendFrontSurfaceIsProtected(
- surface_is_protected,
- protection_state_id_,
- surface_route_id_,
- shared_surface_handle_.parent_gpu_process_id);
+void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(
+ scoped_refptr<ui::Texture>) {
}
void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished(
base::WeakPtr<RenderWidgetHostViewAura> render_widget_host_view,
const base::Callback<void(bool)>& callback,
+ scoped_refptr<ui::Texture>,
bool result) {
callback.Run(result);
if (!render_widget_host_view.get())
return;
--render_widget_host_view->pending_thumbnail_tasks_;
- render_widget_host_view->AdjustSurfaceProtection();
}
void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
@@ -1694,7 +1682,7 @@ void RenderWidgetHostViewAura::OnCompositingDidCommit(
if ((*it)->GrabDeferredLock())
can_lock_compositor_ = YES_DID_LOCK;
}
- RunCompositingDidCommitCallbacks(compositor);
+ RunCompositingDidCommitCallbacks();
locks_pending_commit_.clear();
}
@@ -1725,10 +1713,6 @@ void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
void RenderWidgetHostViewAura::OnLostResources() {
image_transport_clients_.clear();
current_surface_ = 0;
- protection_state_id_ = 0;
- current_surface_is_protected_ = true;
- current_surface_in_use_by_compositor_ = true;
- surface_route_id_ = 0;
UpdateExternalTexture();
locks_pending_commit_.clear();
@@ -1863,30 +1847,34 @@ bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
global_mouse_position_.y() > rect.bottom() - border_y;
}
-void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks(
- ui::Compositor* compositor) {
- for (std::vector< base::Callback<void(ui::Compositor*)> >::const_iterator
+void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks() {
+ for (std::vector<base::Closure>::const_iterator
it = on_compositing_did_commit_callbacks_.begin();
it != on_compositing_did_commit_callbacks_.end(); ++it) {
- it->Run(compositor);
+ it->Run();
}
on_compositing_did_commit_callbacks_.clear();
}
// static
void RenderWidgetHostViewAura::InsertSyncPointAndACK(
- int32 route_id, int gpu_host_id, bool presented,
- ui::Compositor* compositor) {
+ int32 route_id,
+ int gpu_host_id,
+ uint64 surface_handle,
+ scoped_refptr<ui::Texture> texture_to_produce) {
+ if (texture_to_produce)
+ texture_to_produce->Produce();
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+
uint32 sync_point = 0;
- // If we have no compositor, so we must still send the ACK. A zero
- // sync point will not be waited for in the GPU process.
- if (compositor) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- sync_point = factory->InsertSyncPoint();
- }
+ // If we did at least consume a texture (not skipped a frame), we have
+ // to insert a sync point.
+ if (texture_to_produce || !surface_handle)
+ sync_point = factory->InsertSyncPoint();
RenderWidgetHostImpl::AcknowledgeBufferPresent(
- route_id, gpu_host_id, presented, sync_point);
+ route_id, gpu_host_id, surface_handle, sync_point);
}
void RenderWidgetHostViewAura::AddingToRootWindow() {
@@ -1902,7 +1890,7 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
// frame though, because we will reissue a new frame right away without that
// composited data.
ui::Compositor* compositor = GetCompositor();
- RunCompositingDidCommitCallbacks(compositor);
+ RunCompositingDidCommitCallbacks();
locks_pending_commit_.clear();
if (compositor && compositor->HasObserver(this))
compositor->RemoveObserver(this);

Powered by Google App Engine
This is Rietveld 408576698