diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-07 15:45:34 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-07 15:45:34 +0000 |
commit | 3159bf93e94c26778a115159b8857c717cf2f7e5 (patch) | |
tree | 2ad1392beca680537b809610ddd7c79472b2bcb7 | |
parent | d2ce9c8dce139a7e191ae116dad6af52bd2186fd (diff) | |
download | chromium_src-3159bf93e94c26778a115159b8857c717cf2f7e5.zip chromium_src-3159bf93e94c26778a115159b8857c717cf2f7e5.tar.gz chromium_src-3159bf93e94c26778a115159b8857c717cf2f7e5.tar.bz2 |
Partial swaps on OSX
In combination with shawnsingh's scissoring, this is a huge win on 10.5 which uses a readback through main memory. Some numbers given on https://bugs.webkit.org/show_bug.cgi?id=67341
The win on >= 10.6 is probably less because there is not readback through main memory. The 10.6 implementation assumes that nothing outside the partial swap region was damaged (i.e. it's a SwapBuffers that always preserves the backbuffer --- it's not a true partial swap a la GLX_MESA_copy_sub_buffers). This is all that the scissoring needs.
BUG=none
TEST=ran with shawnsingh's patch on http://www.webkit.org/blog-files/3d-transforms/poster-circle.html on 10.6 and 10.5
Review URL: http://codereview.chromium.org/8726046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113397 0039d316-1c4b-4281-b951-d872f2087c98
6 files changed, 157 insertions, 36 deletions
diff --git a/content/browser/renderer_host/accelerated_surface_container_mac.cc b/content/browser/renderer_host/accelerated_surface_container_mac.cc index e76103c..86875f3 100644 --- a/content/browser/renderer_host/accelerated_surface_container_mac.cc +++ b/content/browser/renderer_host/accelerated_surface_container_mac.cc @@ -118,21 +118,38 @@ void AcceleratedSurfaceContainerMac::Draw(CGLContextObj context) { } // If using TransportDIBs, the texture needs to be uploaded every frame. if (transport_dib_.get() != NULL) { - void* pixel_memory = transport_dib_->memory(); + unsigned char* pixel_memory = + static_cast<unsigned char*>(transport_dib_->memory()); if (pixel_memory) { glBindTexture(target, texture_); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Needed for NPOT textures. - glTexSubImage2D(target, - 0, // mipmap level 0 - 0, // x-offset - 0, // y-offset - width_, - height_, - GL_BGRA, // The GPU plugin gave us BGRA pixels - GL_UNSIGNED_INT_8_8_8_8_REV, - pixel_memory); + if (update_rect_.IsEmpty()) { + glTexSubImage2D(target, + 0, // mipmap level 0 + 0, // x-offset + 0, // y-offset + width_, + height_, + GL_BGRA, // The GPU plugin gave us BGRA pixels + GL_UNSIGNED_INT_8_8_8_8_REV, + pixel_memory); + } else { + glPixelStorei(GL_UNPACK_ROW_LENGTH, width_); + glTexSubImage2D(target, + 0, // mipmap level 0 + update_rect_.x(), // x-offset + update_rect_.y(), // y-offset + update_rect_.width(), + update_rect_.height(), + GL_BGRA, // The GPU plugin gave us BGRA pixels + GL_UNSIGNED_INT_8_8_8_8_REV, + &pixel_memory[(update_rect_.x() + + update_rect_.y() * width_) * 4]); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } } } + update_rect_ = gfx::Rect(); if (texture_) { int texture_width = io_surface_support ? surface_width_ : width_; @@ -203,6 +220,27 @@ bool AcceleratedSurfaceContainerMac::ShouldBeVisible() const { } void AcceleratedSurfaceContainerMac::set_was_painted_to(uint64 surface_id) { + set_was_painted_to_common(surface_id); + update_rect_ = gfx::Rect(); +} + +void AcceleratedSurfaceContainerMac::set_was_painted_to( + uint64 surface_id, + const gfx::Rect& update_rect) { + set_was_painted_to_common(surface_id); + update_rect_ = update_rect_.Union(update_rect); +} + +void AcceleratedSurfaceContainerMac::EnqueueTextureForDeletion() { + if (texture_) { + DCHECK(texture_pending_deletion_ == 0); + texture_pending_deletion_ = texture_; + texture_ = 0; + } +} + +void AcceleratedSurfaceContainerMac::set_was_painted_to_common( + uint64 surface_id) { if (surface_id && (!surface_ || surface_id != surface_id_)) { // Keep the surface that was most recently painted to around. if (IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize()) { @@ -222,12 +260,3 @@ void AcceleratedSurfaceContainerMac::set_was_painted_to(uint64 surface_id) { } was_painted_to_ = true; } - -void AcceleratedSurfaceContainerMac::EnqueueTextureForDeletion() { - if (texture_) { - DCHECK(texture_pending_deletion_ == 0); - texture_pending_deletion_ = texture_; - texture_ = 0; - } -} - diff --git a/content/browser/renderer_host/accelerated_surface_container_mac.h b/content/browser/renderer_host/accelerated_surface_container_mac.h index c46430f..1bbf730 100644 --- a/content/browser/renderer_host/accelerated_surface_container_mac.h +++ b/content/browser/renderer_host/accelerated_surface_container_mac.h @@ -83,10 +83,17 @@ class AcceleratedSurfaceContainerMac { // Notifies the the container that its surface was painted to. void set_was_painted_to(uint64 surface_id); + void set_was_painted_to(uint64 surface_id, + const gfx::Rect& update_rect); // Notifies the container that its surface is invalid. void set_surface_invalid() { was_painted_to_ = false; } private: + // Enqueue our texture for later deletion. + void EnqueueTextureForDeletion(); + + void set_was_painted_to_common(uint64 surface_id); + // The manager of this accelerated surface container. AcceleratedSurfaceContainerManagerMac* manager_; @@ -129,6 +136,10 @@ class AcceleratedSurfaceContainerMac { // True if we need to upload the texture again during the next draw. bool texture_needs_upload_; + // The region that was updated via a partial update. |update_rect_.IsEmpty()| + // indicates that the whole region was updated. + gfx::Rect update_rect_; + // This may refer to an old version of the texture if the container is // resized, for example. GLuint texture_pending_deletion_; @@ -140,12 +151,6 @@ class AcceleratedSurfaceContainerMac { // it before it hasn't been painted to at least once. bool was_painted_to_; - // Releases the IOSurface reference, if any, retained by this object. - void ReleaseIOSurface(); - - // Enqueue our texture for later deletion. - void EnqueueTextureForDeletion(); - DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerMac); }; diff --git a/content/browser/renderer_host/accelerated_surface_container_manager_mac.cc b/content/browser/renderer_host/accelerated_surface_container_manager_mac.cc index 8b52967..b31a483 100644 --- a/content/browser/renderer_host/accelerated_surface_container_manager_mac.cc +++ b/content/browser/renderer_host/accelerated_surface_container_manager_mac.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -7,6 +7,7 @@ #include "base/logging.h" #include "content/browser/renderer_host/accelerated_surface_container_mac.h" #include "webkit/plugins/npapi/webplugin.h" +#include "ui/gfx/rect.h" AcceleratedSurfaceContainerManagerMac::AcceleratedSurfaceContainerManagerMac() : current_id_(0), @@ -145,6 +146,17 @@ void AcceleratedSurfaceContainerManagerMac::SetSurfaceWasPaintedTo( container->set_was_painted_to(surface_id); } +void AcceleratedSurfaceContainerManagerMac::SetSurfaceWasPaintedTo( + gfx::PluginWindowHandle id, + uint64 surface_id, + const gfx::Rect& update_rect) { + base::AutoLock lock(lock_); + + AcceleratedSurfaceContainerMac* container = MapIDToContainer(id); + if (container) + container->set_was_painted_to(surface_id, update_rect); +} + void AcceleratedSurfaceContainerManagerMac::SetRootSurfaceInvalid() { base::AutoLock lock(lock_); if (root_container_) diff --git a/content/browser/renderer_host/accelerated_surface_container_manager_mac.h b/content/browser/renderer_host/accelerated_surface_container_manager_mac.h index 8e5cd22..d342971 100644 --- a/content/browser/renderer_host/accelerated_surface_container_manager_mac.h +++ b/content/browser/renderer_host/accelerated_surface_container_manager_mac.h @@ -14,6 +14,10 @@ #include "ui/gfx/native_widget_types.h" #include "ui/gfx/surface/transport_dib.h" +namespace gfx { +class Rect; +} + namespace webkit { namespace npapi { struct WebPluginGeometry; @@ -79,6 +83,9 @@ class AcceleratedSurfaceContainerManagerMac { // Notifies a surface that it has been painted to. void SetSurfaceWasPaintedTo(gfx::PluginWindowHandle id, uint64 surface_id); + void SetSurfaceWasPaintedTo(gfx::PluginWindowHandle id, + uint64 surface_id, + const gfx::Rect& update_rect); // Notifies the root container that its surface is invalid. void SetRootSurfaceInvalid(); diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index d09b0e6..c9655ae 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -879,7 +879,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( plugin_container_manager_.SetSurfaceWasPaintedTo(params.window, params.surface_id); - // The surface is hidden until its first paint, to not show gargabe. + // The surface is hidden until its first paint, to not show garbage. if (plugin_container_manager_.SurfaceShouldBeVisible(params.window)) [view setHidden:NO]; [view drawView]; @@ -893,7 +893,28 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer( const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) { - NOTIMPLEMENTED(); + TRACE_EVENT0("browser", + "RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer"); + CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + AcceleratedPluginView* view = ViewForPluginWindowHandle(params.window); + DCHECK(view); + if (view) { + last_frame_was_accelerated_ = (params.window == + plugin_container_manager_.root_container_handle()); + plugin_container_manager_.SetSurfaceWasPaintedTo( + params.window, + params.surface_id, + gfx::Rect(params.x, params.y, params.width, params.height)); + + // The surface is hidden until its first paint, to not show garbage. + if (plugin_container_manager_.SurfaceShouldBeVisible(params.window)) + [view setHidden:NO]; + [view drawView]; + } + + if (params.route_id != 0) { + RenderWidgetHost::AcknowledgePostSubBuffer(params.route_id, gpu_host_id); + } } void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility( diff --git a/content/common/gpu/image_transport_surface_mac.cc b/content/common/gpu/image_transport_surface_mac.cc index 91af588..21ca564 100644 --- a/content/common/gpu/image_transport_surface_mac.cc +++ b/content/common/gpu/image_transport_surface_mac.cc @@ -234,14 +234,25 @@ bool IOSurfaceImageTransportSurface::SwapBuffers() { bool IOSurfaceImageTransportSurface::PostSubBuffer( int x, int y, int width, int height) { - NOTREACHED(); - return false; + glFlush(); + + GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; + params.surface_id = io_surface_id_; + params.x = x; + params.y = y; + params.width = width; + params.height = height; + helper_->SendAcceleratedSurfacePostSubBuffer(params); + + helper_->SetScheduled(false); + return true; } std::string IOSurfaceImageTransportSurface::GetExtensions() { std::string extensions = gfx::GLSurface::GetExtensions(); extensions += extensions.empty() ? "" : " "; - extensions += "GL_CHROMIUM_front_buffer_cached"; + extensions += "GL_CHROMIUM_front_buffer_cached "; + extensions += "GL_CHROMIUM_post_sub_buffer"; return extensions; } @@ -254,7 +265,7 @@ void IOSurfaceImageTransportSurface::OnBuffersSwappedACK() { } void IOSurfaceImageTransportSurface::OnPostSubBufferACK() { - NOTREACHED(); + helper_->SetScheduled(true); } void IOSurfaceImageTransportSurface::OnNewSurfaceACK( @@ -457,14 +468,50 @@ bool TransportDIBImageTransportSurface::SwapBuffers() { bool TransportDIBImageTransportSurface::PostSubBuffer( int x, int y, int width, int height) { - NOTREACHED(); - return false; + DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); + + GLint previous_fbo_id = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &previous_fbo_id); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); + + GLint current_alignment = 0, current_pack_row_length = 0; + glGetIntegerv(GL_PACK_ALIGNMENT, ¤t_alignment); + glGetIntegerv(GL_PACK_ROW_LENGTH, ¤t_pack_row_length); + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ROW_LENGTH, size_.width()); + + unsigned char* buffer = + static_cast<unsigned char*>(shared_mem_->memory()); + glReadPixels(x, y, + width, height, + GL_BGRA, // This pixel format should have no conversion. + GL_UNSIGNED_INT_8_8_8_8_REV, + &buffer[(x + y * size_.width()) * 4]); + + glPixelStorei(GL_PACK_ALIGNMENT, current_alignment); + glPixelStorei(GL_PACK_ROW_LENGTH, current_pack_row_length); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id); + + GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; + params.surface_id = next_id_; + params.x = x; + params.y = y; + params.width = width; + params.height = height; + helper_->SendAcceleratedSurfacePostSubBuffer(params); + + helper_->SetScheduled(false); + return true; } std::string TransportDIBImageTransportSurface::GetExtensions() { std::string extensions = gfx::GLSurface::GetExtensions(); extensions += extensions.empty() ? "" : " "; - extensions += "GL_CHROMIUM_front_buffer_cached"; + extensions += "GL_CHROMIUM_front_buffer_cached "; + extensions += "GL_CHROMIUM_post_sub_buffer"; return extensions; } @@ -477,7 +524,7 @@ void TransportDIBImageTransportSurface::OnBuffersSwappedACK() { } void TransportDIBImageTransportSurface::OnPostSubBufferACK() { - NOTREACHED(); + helper_->SetScheduled(true); } void TransportDIBImageTransportSurface::OnNewSurfaceACK( |