Commit 3159bf93 authored by backer@chromium.org's avatar backer@chromium.org

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
parent d2ce9c8d
...@@ -118,21 +118,38 @@ void AcceleratedSurfaceContainerMac::Draw(CGLContextObj context) { ...@@ -118,21 +118,38 @@ void AcceleratedSurfaceContainerMac::Draw(CGLContextObj context) {
} }
// If using TransportDIBs, the texture needs to be uploaded every frame. // If using TransportDIBs, the texture needs to be uploaded every frame.
if (transport_dib_.get() != NULL) { 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) { if (pixel_memory) {
glBindTexture(target, texture_); glBindTexture(target, texture_);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Needed for NPOT textures. glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Needed for NPOT textures.
glTexSubImage2D(target, if (update_rect_.IsEmpty()) {
0, // mipmap level 0 glTexSubImage2D(target,
0, // x-offset 0, // mipmap level 0
0, // y-offset 0, // x-offset
width_, 0, // y-offset
height_, width_,
GL_BGRA, // The GPU plugin gave us BGRA pixels height_,
GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA, // The GPU plugin gave us BGRA pixels
pixel_memory); 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_) { if (texture_) {
int texture_width = io_surface_support ? surface_width_ : width_; int texture_width = io_surface_support ? surface_width_ : width_;
...@@ -203,6 +220,27 @@ bool AcceleratedSurfaceContainerMac::ShouldBeVisible() const { ...@@ -203,6 +220,27 @@ bool AcceleratedSurfaceContainerMac::ShouldBeVisible() const {
} }
void AcceleratedSurfaceContainerMac::set_was_painted_to(uint64 surface_id) { 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_)) { if (surface_id && (!surface_ || surface_id != surface_id_)) {
// Keep the surface that was most recently painted to around. // Keep the surface that was most recently painted to around.
if (IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize()) { if (IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize()) {
...@@ -222,12 +260,3 @@ void AcceleratedSurfaceContainerMac::set_was_painted_to(uint64 surface_id) { ...@@ -222,12 +260,3 @@ void AcceleratedSurfaceContainerMac::set_was_painted_to(uint64 surface_id) {
} }
was_painted_to_ = true; was_painted_to_ = true;
} }
void AcceleratedSurfaceContainerMac::EnqueueTextureForDeletion() {
if (texture_) {
DCHECK(texture_pending_deletion_ == 0);
texture_pending_deletion_ = texture_;
texture_ = 0;
}
}
...@@ -83,10 +83,17 @@ class AcceleratedSurfaceContainerMac { ...@@ -83,10 +83,17 @@ class AcceleratedSurfaceContainerMac {
// Notifies the the container that its surface was painted to. // 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);
void set_was_painted_to(uint64 surface_id,
const gfx::Rect& update_rect);
// Notifies the container that its surface is invalid. // Notifies the container that its surface is invalid.
void set_surface_invalid() { was_painted_to_ = false; } void set_surface_invalid() { was_painted_to_ = false; }
private: 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. // The manager of this accelerated surface container.
AcceleratedSurfaceContainerManagerMac* manager_; AcceleratedSurfaceContainerManagerMac* manager_;
...@@ -129,6 +136,10 @@ class AcceleratedSurfaceContainerMac { ...@@ -129,6 +136,10 @@ class AcceleratedSurfaceContainerMac {
// True if we need to upload the texture again during the next draw. // True if we need to upload the texture again during the next draw.
bool texture_needs_upload_; 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 // This may refer to an old version of the texture if the container is
// resized, for example. // resized, for example.
GLuint texture_pending_deletion_; GLuint texture_pending_deletion_;
...@@ -140,12 +151,6 @@ class AcceleratedSurfaceContainerMac { ...@@ -140,12 +151,6 @@ class AcceleratedSurfaceContainerMac {
// it before it hasn't been painted to at least once. // it before it hasn't been painted to at least once.
bool was_painted_to_; 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); DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerMac);
}; };
......
// 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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "content/browser/renderer_host/accelerated_surface_container_mac.h" #include "content/browser/renderer_host/accelerated_surface_container_mac.h"
#include "webkit/plugins/npapi/webplugin.h" #include "webkit/plugins/npapi/webplugin.h"
#include "ui/gfx/rect.h"
AcceleratedSurfaceContainerManagerMac::AcceleratedSurfaceContainerManagerMac() AcceleratedSurfaceContainerManagerMac::AcceleratedSurfaceContainerManagerMac()
: current_id_(0), : current_id_(0),
...@@ -145,6 +146,17 @@ void AcceleratedSurfaceContainerManagerMac::SetSurfaceWasPaintedTo( ...@@ -145,6 +146,17 @@ void AcceleratedSurfaceContainerManagerMac::SetSurfaceWasPaintedTo(
container->set_was_painted_to(surface_id); 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() { void AcceleratedSurfaceContainerManagerMac::SetRootSurfaceInvalid() {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
if (root_container_) if (root_container_)
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gfx/surface/transport_dib.h" #include "ui/gfx/surface/transport_dib.h"
namespace gfx {
class Rect;
}
namespace webkit { namespace webkit {
namespace npapi { namespace npapi {
struct WebPluginGeometry; struct WebPluginGeometry;
...@@ -79,6 +83,9 @@ class AcceleratedSurfaceContainerManagerMac { ...@@ -79,6 +83,9 @@ class AcceleratedSurfaceContainerManagerMac {
// Notifies a surface that it has been painted to. // 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);
void SetSurfaceWasPaintedTo(gfx::PluginWindowHandle id,
uint64 surface_id,
const gfx::Rect& update_rect);
// Notifies the root container that its surface is invalid. // Notifies the root container that its surface is invalid.
void SetRootSurfaceInvalid(); void SetRootSurfaceInvalid();
......
...@@ -879,7 +879,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( ...@@ -879,7 +879,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
plugin_container_manager_.SetSurfaceWasPaintedTo(params.window, plugin_container_manager_.SetSurfaceWasPaintedTo(params.window,
params.surface_id); 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)) if (plugin_container_manager_.SurfaceShouldBeVisible(params.window))
[view setHidden:NO]; [view setHidden:NO];
[view drawView]; [view drawView];
...@@ -893,7 +893,28 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( ...@@ -893,7 +893,28 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer( void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer(
const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
int gpu_host_id) { 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( void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility(
......
...@@ -234,14 +234,25 @@ bool IOSurfaceImageTransportSurface::SwapBuffers() { ...@@ -234,14 +234,25 @@ bool IOSurfaceImageTransportSurface::SwapBuffers() {
bool IOSurfaceImageTransportSurface::PostSubBuffer( bool IOSurfaceImageTransportSurface::PostSubBuffer(
int x, int y, int width, int height) { int x, int y, int width, int height) {
NOTREACHED(); glFlush();
return false;
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 IOSurfaceImageTransportSurface::GetExtensions() {
std::string extensions = gfx::GLSurface::GetExtensions(); std::string extensions = gfx::GLSurface::GetExtensions();
extensions += extensions.empty() ? "" : " "; extensions += extensions.empty() ? "" : " ";
extensions += "GL_CHROMIUM_front_buffer_cached"; extensions += "GL_CHROMIUM_front_buffer_cached ";
extensions += "GL_CHROMIUM_post_sub_buffer";
return extensions; return extensions;
} }
...@@ -254,7 +265,7 @@ void IOSurfaceImageTransportSurface::OnBuffersSwappedACK() { ...@@ -254,7 +265,7 @@ void IOSurfaceImageTransportSurface::OnBuffersSwappedACK() {
} }
void IOSurfaceImageTransportSurface::OnPostSubBufferACK() { void IOSurfaceImageTransportSurface::OnPostSubBufferACK() {
NOTREACHED(); helper_->SetScheduled(true);
} }
void IOSurfaceImageTransportSurface::OnNewSurfaceACK( void IOSurfaceImageTransportSurface::OnNewSurfaceACK(
...@@ -457,14 +468,50 @@ bool TransportDIBImageTransportSurface::SwapBuffers() { ...@@ -457,14 +468,50 @@ bool TransportDIBImageTransportSurface::SwapBuffers() {
bool TransportDIBImageTransportSurface::PostSubBuffer( bool TransportDIBImageTransportSurface::PostSubBuffer(
int x, int y, int width, int height) { int x, int y, int width, int height) {
NOTREACHED(); DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
return false;
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 TransportDIBImageTransportSurface::GetExtensions() {
std::string extensions = gfx::GLSurface::GetExtensions(); std::string extensions = gfx::GLSurface::GetExtensions();
extensions += extensions.empty() ? "" : " "; extensions += extensions.empty() ? "" : " ";
extensions += "GL_CHROMIUM_front_buffer_cached"; extensions += "GL_CHROMIUM_front_buffer_cached ";
extensions += "GL_CHROMIUM_post_sub_buffer";
return extensions; return extensions;
} }
...@@ -477,7 +524,7 @@ void TransportDIBImageTransportSurface::OnBuffersSwappedACK() { ...@@ -477,7 +524,7 @@ void TransportDIBImageTransportSurface::OnBuffersSwappedACK() {
} }
void TransportDIBImageTransportSurface::OnPostSubBufferACK() { void TransportDIBImageTransportSurface::OnPostSubBufferACK() {
NOTREACHED(); helper_->SetScheduled(true);
} }
void TransportDIBImageTransportSurface::OnNewSurfaceACK( void TransportDIBImageTransportSurface::OnNewSurfaceACK(
......
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