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) {
}
// 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;
}
}
......@@ -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);
};
......
// 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_)
......
......@@ -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();
......
......@@ -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(
......
......@@ -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(
......
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