From 7ff86b93008f19aaddac784323ce4117d6725aa0 Mon Sep 17 00:00:00 2001 From: "backer@chromium.org" Date: Thu, 25 Nov 2010 17:50:00 +0000 Subject: Resize synchronization for Linux. This patch makes synchronous calls from the GPU to the Browser process to resize windows. It must be synchronous because we must be sure when the resize happens, it must be initiated by the GPU because we have to time the resize with GL drawing, and the resize must be done by the Browser because of how GDK/GTK is structured. Specifically, when a window that a GL context is associated with is resized, the back buffer gets blanked. So it is important that we synchronize the resize with the drawing to the back buffer. On Linux, the X window that we are drawing to is wrapped in a GdkWindow inside the Browser process. GDK/GTK assumes that all changes to the window happen via GDK calls. In particular, the size of the window is cached inside the GdkWindow object so that it does not have to make a call to the X server in order to get window geometry. Unfortunately, this necessitates resizing the window inside of the Browser process. For more discussion of this approach and (some unsuccessfully attempted) alternatives see https://docs.google.com/a/google.com/document/d/1ZNouL-X_Ml1x8sqy-sofz63pDAeo36VWi_yQihaE2YI/edit?hl=en This patch set uncovered another bug: - open in two separate windows http://webkit.org/blog/386/3d-transforms/ and http://webkit.org/blog-files/3d-transforms/poster-circle.html - resize the former until it is smallish - watch the root layer of the former show up as the root layer of the later. To my knowledge, this is first trigger of this bug. If and when this patch is accepted, I will file the bug. BUG=http://code.google.com/p/chromium/issues/detail?id=54430 TEST=Go to http://peter.sh/2010/06/chromium-now-features-gpu-acceleration-and-css-3d-transforms/ . Rotate Z with the slider to trigger the compositor. Resize the window. The resize may be janky (we're uploading large textures), but it should display properly. Contributed by backer@chromium.org Review URL: http://codereview.chromium.org/5105006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67416 0039d316-1c4b-4281-b951-d872f2087c98 --- gpu/command_buffer/service/gles2_cmd_decoder.cc | 16 ++++++++++++++-- gpu/command_buffer/service/gles2_cmd_decoder.h | 4 ++++ gpu/command_buffer/service/gles2_cmd_decoder_mock.h | 1 + gpu/command_buffer/service/gpu_processor.cc | 4 ++++ gpu/command_buffer/service/gpu_processor.h | 4 ++++ 5 files changed, 27 insertions(+), 2 deletions(-) (limited to 'gpu/command_buffer/service') diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index fbb6ca4..d120744 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -677,6 +677,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr, virtual gfx::GLContext* GetGLContext() { return context_.get(); } virtual ContextGroup* GetContextGroup() { return group_.get(); } + virtual void SetResizeCallback(Callback1::Type* callback); virtual void SetSwapBuffersCallback(Callback0::Type* callback); virtual bool GetServiceTextureId(uint32 client_texture_id, uint32* service_texture_id); @@ -1424,6 +1425,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr, scoped_ptr offscreen_saved_color_texture_; GLenum offscreen_saved_color_format_; + scoped_ptr::Type> resize_callback_; scoped_ptr swap_buffers_callback_; // The last error message set. @@ -2422,6 +2424,10 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { return true; } +void GLES2DecoderImpl::SetResizeCallback(Callback1::Type* callback) { + resize_callback_.reset(callback); +} + void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) { swap_buffers_callback_.reset(callback); } @@ -2552,8 +2558,14 @@ void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM( } void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) { - gfx::Size size(width, height); - context_->SetSize(size); +#if defined(OS_LINUX) + // Make sure that we are done drawing to the back buffer before resizing. + glFinish(); +#endif + if (resize_callback_.get()) { + gfx::Size size(width, height); + resize_callback_->Run(size); + } } const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 5c8b735..eddd7fe 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -89,6 +89,10 @@ class GLES2Decoder : public CommonDecoder { // Gets the associated ContextGroup virtual ContextGroup* GetContextGroup() = 0; + // Sets a callback which is called when a glResizeCHROMIUM command + // is processed. + virtual void SetResizeCallback(Callback1::Type* callback) = 0; + // Sets a callback which is called when a SwapBuffers command is processed. virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index bee0202..a0e5c7e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -44,6 +44,7 @@ class MockGLES2Decoder : public GLES2Decoder { MOCK_METHOD0(GetGLES2Util, GLES2Util*()); MOCK_METHOD0(GetGLContext, gfx::GLContext*()); MOCK_METHOD0(GetContextGroup, ContextGroup*()); + MOCK_METHOD1(SetResizeCallback, void(Callback1::Type*)); MOCK_METHOD1(SetSwapBuffersCallback, void(Callback0::Type*)); MOCK_METHOD3(DoCommand, error::Error(unsigned int command, unsigned int arg_count, diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc index d32cb62..275f3cb 100644 --- a/gpu/command_buffer/service/gpu_processor.cc +++ b/gpu/command_buffer/service/gpu_processor.cc @@ -145,6 +145,10 @@ void GPUProcessor::ResizeOffscreenFrameBuffer(const gfx::Size& size) { decoder_->ResizeOffscreenFrameBuffer(size); } +void GPUProcessor::SetResizeCallback(Callback1::Type* callback) { + decoder_->SetResizeCallback(callback); +} + void GPUProcessor::SetSwapBuffersCallback( Callback0::Type* callback) { wrapped_swap_buffers_callback_.reset(callback); diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h index 986ab03..247c4c5 100644 --- a/gpu/command_buffer/service/gpu_processor.h +++ b/gpu/command_buffer/service/gpu_processor.h @@ -87,6 +87,10 @@ class GPUProcessor : public CommandBufferEngine { virtual uint64 GetSurfaceId(); #endif + // Sets a callback that is called when a glResizeCHROMIUM command + // is processed. + virtual void SetResizeCallback(Callback1::Type* callback); + // Sets a callback which is called when a SwapBuffers command is processed. // Must be called after Initialize(). // It is not defined on which thread this callback is called. -- cgit v1.1