summaryrefslogtreecommitdiffstats
path: root/content/common
diff options
context:
space:
mode:
authorjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-26 01:01:07 +0000
committerjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-26 01:01:07 +0000
commitc63b4d4f499671b7f55aa264e823ad521f5d6aae (patch)
tree36c62254048a0e3f82ac0f003905ae860db1a3cf /content/common
parent92adf1719ccb5f7734955998006bc22b03210723 (diff)
downloadchromium_src-c63b4d4f499671b7f55aa264e823ad521f5d6aae.zip
chromium_src-c63b4d4f499671b7f55aa264e823ad521f5d6aae.tar.gz
chromium_src-c63b4d4f499671b7f55aa264e823ad521f5d6aae.tar.bz2
Delete background tab IOSurfaces on Mac.
The deleting part is easy: just handle the AcceleratedSurfaceSuspend call by unrefing the IOSurface. The hard part is dealing with a NSView drawRect when we don't have the IOSurface (or software BackingStore). To solve this, I reuse the GetBackingStore code to wait for a new frame from the renderer. When the BuffersSwapped message arrives on the IO thread for Mac, an UpdateRect message is synthesized with the SwapBuffers data. The UpdateRect message wakes up the UI thread and allows GetBackingStore to resume. The accelerated path can have multiple frames in the pipeline, so it is rarely enough to just wait for the next UpdateRect. Instead, the GetBackingStore method is updated to wait up to 40ms to get the correctly-sized frame (whether it's accelerated or software). The original GetBackingStore code waits for a frame that matches current_size_. However, this CL makes GetBackingStore wait for a frame that matches the view_->GetViewBounds(). current_size_ is equal to the last UpdateRect, which may or may not match GetViewBounds. (Anyone know why the original code doesn't use GetViewBounds?) This allows us to recover from missing BackingStores or IOSurfaces if the renderer/GPU can produce a new frame within 40ms. We probably want to increase 40 to something like 60 or 100ms though because of the deep GPU pipeline. In addition, thanks to the blocking GetBackingStore, this fixes some additional bugs: - no more resize gutter jank on accelerated pages (Mac only for now, but should work on Windows with a followup patch). - no more white flash while resizing flicker-test2.html. BUG=117624,58782,85519,124328,106586 Review URL: https://chromiumcodereview.appspot.com/9980016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134033 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common')
-rw-r--r--content/common/gpu/image_transport_surface_mac.cc99
-rw-r--r--content/common/view_messages.h12
2 files changed, 83 insertions, 28 deletions
diff --git a/content/common/gpu/image_transport_surface_mac.cc b/content/common/gpu/image_transport_surface_mac.cc
index 6dc3149..ed9a4aa 100644
--- a/content/common/gpu/image_transport_surface_mac.cc
+++ b/content/common/gpu/image_transport_surface_mac.cc
@@ -37,6 +37,7 @@ class IOSurfaceImageTransportSurface : public gfx::NoOpGLSurfaceCGL,
virtual gfx::Size GetSize() OVERRIDE;
virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
+ virtual void SetBufferAllocation(BufferAllocationState state) OVERRIDE;
protected:
// ImageTransportSurface implementation
@@ -50,6 +51,11 @@ class IOSurfaceImageTransportSurface : public gfx::NoOpGLSurfaceCGL,
private:
virtual ~IOSurfaceImageTransportSurface() OVERRIDE;
+ void UnrefIOSurface();
+ void CreateIOSurface();
+
+ BufferAllocationState buffer_allocation_state_;
+
uint32 fbo_id_;
GLuint texture_id_;
@@ -91,6 +97,7 @@ IOSurfaceImageTransportSurface::IOSurfaceImageTransportSurface(
GpuCommandBufferStub* stub,
gfx::PluginWindowHandle handle)
: gfx::NoOpGLSurfaceCGL(gfx::Size(1, 1)),
+ buffer_allocation_state_(BUFFER_ALLOCATION_FRONT_AND_BACK),
fbo_id_(0),
texture_id_(0),
io_surface_handle_(0),
@@ -141,16 +148,8 @@ bool IOSurfaceImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
if (made_current_)
return true;
- glGenFramebuffersEXT(1, &fbo_id_);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
OnResize(gfx::Size(1, 1));
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- DLOG(ERROR) << "Framebuffer incomplete.";
- return false;
- }
-
made_current_ = true;
return true;
}
@@ -159,6 +158,30 @@ unsigned int IOSurfaceImageTransportSurface::GetBackingFrameBufferObject() {
return fbo_id_;
}
+void IOSurfaceImageTransportSurface::SetBufferAllocation(
+ BufferAllocationState state) {
+ if (buffer_allocation_state_ == state)
+ return;
+ buffer_allocation_state_ = state;
+
+ switch (state) {
+ case BUFFER_ALLOCATION_FRONT_AND_BACK:
+ CreateIOSurface();
+ break;
+
+ case BUFFER_ALLOCATION_FRONT_ONLY:
+ break;
+
+ case BUFFER_ALLOCATION_NONE:
+ UnrefIOSurface();
+ helper_->Suspend();
+ break;
+
+ default:
+ NOTREACHED();
+ }
+}
+
bool IOSurfaceImageTransportSurface::SwapBuffers() {
glFlush();
@@ -217,23 +240,44 @@ void IOSurfaceImageTransportSurface::OnResizeViewACK() {
}
void IOSurfaceImageTransportSurface::OnResize(gfx::Size size) {
- IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
-
// Caching |context_| from OnMakeCurrent. It should still be current.
DCHECK(context_->IsCurrent(this));
size_ = size;
+ CreateIOSurface();
+}
+
+void IOSurfaceImageTransportSurface::UnrefIOSurface() {
+ DCHECK(context_->IsCurrent(this));
+
+ if (fbo_id_) {
+ glDeleteFramebuffersEXT(1, &fbo_id_);
+ fbo_id_ = 0;
+ }
+
if (texture_id_) {
glDeleteTextures(1, &texture_id_);
texture_id_ = 0;
}
- glGenTextures(1, &texture_id_);
+ io_surface_.reset();
+ io_surface_handle_ = 0;
+}
+void IOSurfaceImageTransportSurface::CreateIOSurface() {
GLint previous_texture_id = 0;
glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id);
+ UnrefIOSurface();
+
+ glGenFramebuffersEXT(1, &fbo_id_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
+
+ IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+
+ glGenTextures(1, &texture_id_);
+
// GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
// Mac OS X and is required for IOSurface interoperability.
GLenum target = GL_TEXTURE_RECTANGLE_ARB;
@@ -243,11 +287,6 @@ void IOSurfaceImageTransportSurface::OnResize(gfx::Size size) {
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- GLint previous_fbo_id = 0;
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previous_fbo_id);
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
-
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
target,
@@ -278,22 +317,28 @@ void IOSurfaceImageTransportSurface::OnResize(gfx::Size size) {
// Don't think we need to identify a plane.
GLuint plane = 0;
- io_surface_support->CGLTexImageIOSurface2D(
- static_cast<CGLContextObj>(context_->GetHandle()),
- target,
- GL_RGBA,
- size_.width(),
- size_.height(),
- GL_BGRA,
- GL_UNSIGNED_INT_8_8_8_8_REV,
- io_surface_.get(),
- plane);
+ CGLError cglerror =
+ io_surface_support->CGLTexImageIOSurface2D(
+ static_cast<CGLContextObj>(context_->GetHandle()),
+ target,
+ GL_RGBA,
+ size_.width(),
+ size_.height(),
+ GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ io_surface_.get(),
+ plane);
+ if (cglerror != kCGLNoError) {
+ DLOG(ERROR) << "CGLTexImageIOSurface2D: " << cglerror;
+ UnrefIOSurface();
+ return;
+ }
io_surface_handle_ = io_surface_support->IOSurfaceGetID(io_surface_);
glFlush();
glBindTexture(target, previous_texture_id);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id);
+ // The FBO remains bound for this GL context.
}
} // namespace
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index ecde49a..d94dff2 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -493,7 +493,8 @@ IPC_STRUCT_BEGIN(ViewHostMsg_UpdateRect_Params)
// The size of the RenderView when this message was generated. This is
// included so the host knows how large the view is from the perspective of
// the renderer process. This is necessary in case a resize operation is in
- // progress.
+ // progress. If auto-resize is enabled, this should update the corresponding
+ // view size.
IPC_STRUCT_MEMBER(gfx::Size, view_size)
// New window locations for plugin child windows.
@@ -1906,6 +1907,15 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_AcceleratedSurfaceBuffersSwapped,
uint64 /* surface_handle */)
#endif
+// This message is synthesized by GpuProcessHost to pass through a swap message
+// to the RenderWidgetHelper. This allows GetBackingStore to block for either a
+// software or GPU frame.
+IPC_MESSAGE_ROUTED4(ViewHostMsg_CompositorSurfaceBuffersSwapped,
+ int32 /* surface id */,
+ uint64 /* surface_handle */,
+ int32 /* route_id */,
+ int32 /* gpu_process_host_id */)
+
// Opens a file asynchronously. The response returns a file descriptor
// and an error code from base/platform_file.h.
IPC_MESSAGE_ROUTED3(ViewHostMsg_AsyncOpenFile,