summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-07 15:45:34 +0000
committerbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-07 15:45:34 +0000
commit3159bf93e94c26778a115159b8857c717cf2f7e5 (patch)
tree2ad1392beca680537b809610ddd7c79472b2bcb7
parentd2ce9c8dce139a7e191ae116dad6af52bd2186fd (diff)
downloadchromium_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
-rw-r--r--content/browser/renderer_host/accelerated_surface_container_mac.cc67
-rw-r--r--content/browser/renderer_host/accelerated_surface_container_mac.h17
-rw-r--r--content/browser/renderer_host/accelerated_surface_container_manager_mac.cc14
-rw-r--r--content/browser/renderer_host/accelerated_surface_container_manager_mac.h7
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm25
-rw-r--r--content/common/gpu/image_transport_surface_mac.cc63
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, &current_alignment);
+ glGetIntegerv(GL_PACK_ROW_LENGTH, &current_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(