summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-22 15:41:46 +0000
committernduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-22 15:41:46 +0000
commitbe128cfc576f164873323bb28dd8939c183af84f (patch)
tree015ced5aa04acdca20f3aa819cb3d94942ef3e11
parentcdf492d1e59e9c162f35294f30d3be52f81cbea7 (diff)
downloadchromium_src-be128cfc576f164873323bb28dd8939c183af84f.zip
chromium_src-be128cfc576f164873323bb28dd8939c183af84f.tar.gz
chromium_src-be128cfc576f164873323bb28dd8939c183af84f.tar.bz2
Revert 97644 - Unify MacOS resizing path with glResizeCHROMIUM.
Review URL: http://codereview.chromium.org/7671035 TBR=nduca@chromium.org Review URL: http://codereview.chromium.org/7713001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97645 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc158
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.h8
-rw-r--r--content/renderer/gpu/command_buffer_proxy.cc16
-rw-r--r--content/renderer/gpu/command_buffer_proxy.h7
-rw-r--r--content/renderer/gpu/renderer_gl_context.cc18
-rw-r--r--content/renderer/gpu/renderer_gl_context.h15
-rw-r--r--content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc12
-rw-r--r--content/renderer/render_widget_fullscreen_pepper.cc4
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py3
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc7
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h5
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc323
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h10
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h8
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h3
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc7
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h3
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_mac.cc9
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc47
19 files changed, 416 insertions, 247 deletions
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index 6076eba..047cfa7 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -99,6 +99,11 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
OnCreateVideoDecoder)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyVideoDecoder,
OnDestroyVideoDecoder)
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer,
+ OnResizeOffscreenFrameBuffer);
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetWindowSize, OnSetWindowSize);
+#endif // defined(OS_MACOSX)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -195,18 +200,38 @@ void GpuCommandBufferStub::OnInitialize(
&gpu::GpuScheduler::PutChanged));
command_buffer_->SetParseErrorCallback(
NewCallback(this, &GpuCommandBufferStub::OnParseError));
- scheduler_->SetScheduledCallback(
- NewCallback(channel_, &GpuChannel::OnScheduled));
scheduler_->SetSwapBuffersCallback(
NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers));
- if (handle_ != gfx::kNullPluginWindow) {
- scheduler_->SetResizeCallback(
- NewCallback(this, &GpuCommandBufferStub::OnResize));
- }
+ scheduler_->SetScheduledCallback(
+ NewCallback(channel_, &GpuChannel::OnScheduled));
if (watchdog_)
scheduler_->SetCommandProcessedCallback(
NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed));
+#if defined(OS_MACOSX)
+ if (handle_) {
+ // This context conceptually puts its output directly on the
+ // screen, rendered by the accelerated plugin layer in
+ // RenderWidgetHostViewMac. Set up a pathway to notify the
+ // browser process when its contents change.
+ scheduler_->SetSwapBuffersCallback(
+ NewCallback(this,
+ &GpuCommandBufferStub::SwapBuffersCallback));
+ }
+#endif // defined(OS_MACOSX)
+
+ // Set up a pathway for resizing the output window or framebuffer at the
+ // right time relative to other GL commands.
+#if defined(TOUCH_UI)
+ if (handle_ == gfx::kNullPluginWindow) {
+ scheduler_->SetResizeCallback(
+ NewCallback(this, &GpuCommandBufferStub::ResizeCallback));
+ }
+#else
+ scheduler_->SetResizeCallback(
+ NewCallback(this, &GpuCommandBufferStub::ResizeCallback));
+#endif
+
if (parent_stub_for_initialization_) {
scheduler_->SetParent(parent_stub_for_initialization_->scheduler_.get(),
parent_texture_for_initialization_);
@@ -402,30 +427,14 @@ void GpuCommandBufferStub::OnGetTransferBuffer(
Send(reply_message);
}
+void GpuCommandBufferStub::OnResizeOffscreenFrameBuffer(const gfx::Size& size) {
+ scheduler_->ResizeOffscreenFrameBuffer(size);
+}
+
void GpuCommandBufferStub::OnSwapBuffers() {
TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSwapBuffers");
ReportState();
-
-#if defined(OS_MACOSX)
- if (handle_) {
- // To swap on OSX, we have to send a message to the browser to get the
- // context put onscreen.
- GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
- params.renderer_id = renderer_id_;
- params.render_view_id = render_view_id_;
- params.window = handle_;
- params.surface_id = scheduler_->GetSurfaceId();
- params.route_id = route_id();
- params.swap_buffers_count = scheduler_->swap_buffers_count();
- gpu_channel_manager->Send(
- new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
- scheduler_->SetScheduled(false);
- }
-#else
- // Notify the upstream commandbuffer that the swapbuffers has completed.
Send(new GpuCommandBufferMsg_SwapBuffers(route_id_));
-#endif
}
void GpuCommandBufferStub::OnCommandProcessed() {
@@ -434,40 +443,9 @@ void GpuCommandBufferStub::OnCommandProcessed() {
}
#if defined(OS_MACOSX)
-void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
- uint64 swap_buffers_count) {
- TRACE_EVENT1("gpu",
- "GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped",
- "frame", swap_buffers_count);
- DCHECK(handle_ != gfx::kNullPluginWindow);
-
- // Multiple swapbuffers may get consolidated together into a single
- // AcceleratedSurfaceBuffersSwapped call. Upstream code listening to the
- // GpuCommandBufferMsg_SwapBuffers expects to be called one time for every
- // swap. So, send one SwapBuffers message for every outstanding swap.
- uint64 delta = swap_buffers_count -
- scheduler_->acknowledged_swap_buffers_count();
- scheduler_->set_acknowledged_swap_buffers_count(swap_buffers_count);
-
- for(uint64 i = 0; i < delta; i++) {
- // Notify the upstream commandbuffer that the swapbuffers has completed.
- Send(new GpuCommandBufferMsg_SwapBuffers(route_id_));
-
- // Wake up the GpuScheduler to start doing work again.
- scheduler_->SetScheduled(true);
- }
-}
-#endif // defined(OS_MACOSX)
-
-void GpuCommandBufferStub::OnResize(gfx::Size size) {
- if (handle_ == gfx::kNullPluginWindow)
- return;
-
+void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) {
GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
-
-#if defined(OS_MACOSX)
- // On Mac, we need to tell the browser about the new IOSurface handle,
- // asynchronously.
+ // Try using the IOSurface version first.
uint64 new_backing_store = scheduler_->SetWindowSizeForIOSurface(size);
if (new_backing_store) {
GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params;
@@ -485,22 +463,62 @@ void GpuCommandBufferStub::OnResize(gfx::Size size) {
// questionable.
NOTREACHED();
}
-#elif defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN)
- // On Windows, Linux, we need to coordinate resizing of onscreen
- // contexts with the resizing of the actual OS-level window. We do this by
- // sending a resize message to the browser process and descheduling the
- // context until the ViewResized message comes back in reply.
- // Send the resize message if needed
+}
+
+void GpuCommandBufferStub::SwapBuffersCallback() {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::SwapBuffersCallback");
+ GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
+ GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
+ params.renderer_id = renderer_id_;
+ params.render_view_id = render_view_id_;
+ params.window = handle_;
+ params.surface_id = scheduler_->GetSurfaceId();
+ params.route_id = route_id();
+ params.swap_buffers_count = scheduler_->swap_buffers_count();
gpu_channel_manager->Send(
- new GpuHostMsg_ResizeView(renderer_id_,
- render_view_id_,
- route_id_,
- size));
+ new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
scheduler_->SetScheduled(false);
-#endif // defined(OS_MACOSX)
}
+void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
+ uint64 swap_buffers_count) {
+ TRACE_EVENT1("gpu",
+ "GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped",
+ "frame", swap_buffers_count);
+
+ // Multiple swapbuffers may get consolidated together into a single
+ // AcceleratedSurfaceBuffersSwapped call. Since OnSwapBuffers expects to be
+ // called one time for every swap, make up the difference here.
+ uint64 delta = swap_buffers_count -
+ scheduler_->acknowledged_swap_buffers_count();
+ scheduler_->set_acknowledged_swap_buffers_count(swap_buffers_count);
+
+ for(uint64 i = 0; i < delta; i++) {
+ OnSwapBuffers();
+ // Wake up the GpuScheduler to start doing work again.
+ scheduler_->SetScheduled(true);
+ }
+}
+#endif // defined(OS_MACOSX)
+
+void GpuCommandBufferStub::ResizeCallback(gfx::Size size) {
+ if (handle_ == gfx::kNullPluginWindow) {
+ scheduler_->decoder()->ResizeOffscreenFrameBuffer(size);
+ scheduler_->decoder()->UpdateOffscreenFrameBufferSize();
+ } else {
+#if defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN)
+ GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
+ gpu_channel_manager->Send(
+ new GpuHostMsg_ResizeView(renderer_id_,
+ render_view_id_,
+ route_id_,
+ size));
+
+ scheduler_->SetScheduled(false);
+#endif
+ }
+}
void GpuCommandBufferStub::ViewResized() {
#if defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN)
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index ef2dabb..9ea9bdb 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -112,6 +112,7 @@ class GpuCommandBufferStub
IPC::Message* reply_message);
void OnDestroyTransferBuffer(int32 id, IPC::Message* reply_message);
void OnGetTransferBuffer(int32 id, IPC::Message* reply_message);
+ void OnResizeOffscreenFrameBuffer(const gfx::Size& size);
void OnCreateVideoDecoder(const std::vector<int32>& configs,
IPC::Message* reply_message);
@@ -121,7 +122,12 @@ class GpuCommandBufferStub
void OnCommandProcessed();
void OnParseError();
- void OnResize(gfx::Size size);
+#if defined(OS_MACOSX)
+ void OnSetWindowSize(const gfx::Size& size);
+ void SwapBuffersCallback();
+#endif // defined(OS_MACOSX)
+
+ void ResizeCallback(gfx::Size size);
void ReportState();
// The lifetime of objects of this class is managed by a GpuChannel. The
diff --git a/content/renderer/gpu/command_buffer_proxy.cc b/content/renderer/gpu/command_buffer_proxy.cc
index 1caeb5a..caa1de5 100644
--- a/content/renderer/gpu/command_buffer_proxy.cc
+++ b/content/renderer/gpu/command_buffer_proxy.cc
@@ -380,6 +380,13 @@ void CommandBufferProxy::SetSwapBuffersCallback(Callback0::Type* callback) {
swap_buffers_callback_.reset(callback);
}
+void CommandBufferProxy::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ Send(new GpuCommandBufferMsg_ResizeOffscreenFrameBuffer(route_id_, size));
+}
+
void CommandBufferProxy::SetNotifyRepaintTask(Task* task) {
notify_repaint_task_.reset(task);
}
@@ -406,6 +413,15 @@ CommandBufferProxy::CreateVideoDecoder(
return decoder_host;
}
+#if defined(OS_MACOSX)
+void CommandBufferProxy::SetWindowSize(const gfx::Size& size) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ Send(new GpuCommandBufferMsg_SetWindowSize(route_id_, size));
+}
+#endif
+
bool CommandBufferProxy::Send(IPC::Message* msg) {
// Caller should not intentionally send a message if the context is lost.
DCHECK(last_state_.error == gpu::error::kNoError);
diff --git a/content/renderer/gpu/command_buffer_proxy.h b/content/renderer/gpu/command_buffer_proxy.h
index 8c62508..2a2e25b 100644
--- a/content/renderer/gpu/command_buffer_proxy.h
+++ b/content/renderer/gpu/command_buffer_proxy.h
@@ -77,6 +77,9 @@ class CommandBufferProxy : public gpu::CommandBuffer,
void SetSwapBuffersCallback(Callback0::Type* callback);
void SetChannelErrorCallback(Callback0::Type* callback);
+ // Asynchronously resizes an offscreen frame buffer.
+ void ResizeOffscreenFrameBuffer(const gfx::Size& size);
+
// Set a task that will be invoked the next time the window becomes invalid
// and needs to be repainted. Takes ownership of task.
void SetNotifyRepaintTask(Task* task);
@@ -91,6 +94,10 @@ class CommandBufferProxy : public gpu::CommandBuffer,
const std::vector<int32>& configs,
media::VideoDecodeAccelerator::Client* client);
+#if defined(OS_MACOSX)
+ virtual void SetWindowSize(const gfx::Size& size);
+#endif
+
private:
// Send an IPC message over the GPU channel. This is private to fully
diff --git a/content/renderer/gpu/renderer_gl_context.cc b/content/renderer/gpu/renderer_gl_context.cc
index 53baa9b..426386e 100644
--- a/content/renderer/gpu/renderer_gl_context.cc
+++ b/content/renderer/gpu/renderer_gl_context.cc
@@ -107,6 +107,14 @@ RendererGLContext* RendererGLContext::CreateViewContext(
#endif
}
+#if defined(OS_MACOSX)
+void RendererGLContext::ResizeOnscreen(const gfx::Size& size) {
+ DCHECK(size.width() > 0 && size.height() > 0);
+ size_ = size;
+ command_buffer_->SetWindowSize(size);
+}
+#endif
+
RendererGLContext* RendererGLContext::CreateOffscreenContext(
GpuChannelHost* channel,
const gfx::Size& size,
@@ -183,6 +191,14 @@ bool RendererGLContext::SetParent(RendererGLContext* new_parent) {
return true;
}
+void RendererGLContext::ResizeOffscreen(const gfx::Size& size) {
+ DCHECK(size.width() > 0 && size.height() > 0);
+ if (size_ != size) {
+ command_buffer_->ResizeOffscreenFrameBuffer(size);
+ size_ = size;
+ }
+}
+
uint32 RendererGLContext::GetParentTextureId() {
return parent_texture_id_;
}
@@ -410,6 +426,8 @@ bool RendererGLContext::Initialize(bool onscreen,
share_resources,
bind_generates_resource);
+ size_ = size;
+
return true;
}
diff --git a/content/renderer/gpu/renderer_gl_context.h b/content/renderer/gpu/renderer_gl_context.h
index 5013dc9..a9f9580 100644
--- a/content/renderer/gpu/renderer_gl_context.h
+++ b/content/renderer/gpu/renderer_gl_context.h
@@ -106,6 +106,13 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
const int32* attrib_list,
const GURL& active_arl);
+#if defined(OS_MACOSX)
+ // On Mac OS X only, view RendererGLContexts actually behave like offscreen
+ // RendererGLContexts, and require an explicit resize operation which is
+ // slightly different from that of offscreen RendererGLContexts.
+ void ResizeOnscreen(const gfx::Size& size);
+#endif
+
// Create a RendererGLContext that renders to an offscreen frame buffer. If
// parent is not NULL, that RendererGLContext can access a copy of the created
// RendererGLContext's frame buffer that is updated every time SwapBuffers is
@@ -127,6 +134,13 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
// another parent, it is important to delete them before changing the parent.
bool SetParent(RendererGLContext* parent);
+ // Resize an offscreen frame buffer. The resize occurs on the next call to
+ // SwapBuffers. This is to avoid waiting until all pending GL calls have been
+ // executed by the GPU process. Everything rendered up to the call to
+ // SwapBuffers will be lost. A lost RendererGLContext will be reported if the
+ // resize fails.
+ void ResizeOffscreen(const gfx::Size& size);
+
// For an offscreen frame buffer RendererGLContext, return the texture ID with
// respect to the parent RendererGLContext. Returns zero if RendererGLContext
// does not have a parent.
@@ -199,6 +213,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
gpu::gles2::GLES2CmdHelper* gles2_helper_;
int32 transfer_buffer_id_;
gpu::gles2::GLES2Implementation* gles2_implementation_;
+ gfx::Size size_;
Error last_error_;
int frame_number_;
diff --git a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
index 0366725..7c721df 100644
--- a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
@@ -241,7 +241,17 @@ void WebGraphicsContext3DCommandBufferImpl::reshape(int width, int height) {
cached_width_ = width;
cached_height_ = height;
- gl_->ResizeCHROMIUM(width, height);
+ if (render_directly_to_web_view_) {
+#if defined(OS_MACOSX)
+ context_->ResizeOnscreen(gfx::Size(width, height));
+#else
+ gl_->ResizeCHROMIUM(width, height);
+#endif
+ } else {
+ context_->ResizeOffscreen(gfx::Size(width, height));
+ // Force a SwapBuffers to get the framebuffer to resize.
+ context_->SwapBuffers();
+ }
#ifdef FLIP_FRAMEBUFFER_VERTICALLY
scanline_.reset(new uint8[width * 4]);
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index 0d5480b..1ccd917 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -316,7 +316,11 @@ void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size,
const gfx::Rect& resizer_rect) {
if (context_) {
gpu::gles2::GLES2Implementation* gl = context_->GetImplementation();
+#if defined(OS_MACOSX)
+ context_->ResizeOnscreen(size);
+#else
gl->ResizeCHROMIUM(size.width(), size.height());
+#endif
gl->Viewport(0, 0, size.width(), size.height());
}
RenderWidget::OnResize(size, resizer_rect);
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index b09e24a..574897e 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1727,8 +1727,7 @@ _FUNCTION_INFO = {
'GLsizei stride, GLuint offset',
},
'ResizeCHROMIUM': {
- 'type': 'Custom',
- 'impl_func': False,
+ 'decoder_func': 'DoResizeCHROMIUM',
'unit_test': False,
'extension': True,
'chromium': True,
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 956ac62..e34e476 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -2482,12 +2482,6 @@ void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem) {
mapped_textures_.erase(it);
}
-void GLES2Implementation::ResizeCHROMIUM(GLuint width, GLuint height) {
- GPU_CLIENT_LOG("[" << this << "] glResizeCHROMIUM("
- << width << ", " << height << ")");
- helper_->ResizeCHROMIUM(width, height);
-}
-
const GLchar* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
GPU_CLIENT_LOG("[" << this << "] glGetRequestableExtensionsCHROMIUM()");
TRACE_EVENT0("gpu",
@@ -2631,3 +2625,4 @@ void GLES2Implementation::GetProgramInfoCHROMIUM(
} // namespace gles2
} // namespace gpu
+
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 021e3e9..ba061a5 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1254,7 +1254,10 @@ void* MapTexSubImage2DCHROMIUM(
void UnmapTexSubImage2DCHROMIUM(const void* mem);
-void ResizeCHROMIUM(GLuint width, GLuint height);
+void ResizeCHROMIUM(GLuint width, GLuint height) {
+ GPU_CLIENT_LOG("[" << this << "] glResizeCHROMIUM(" << width << ", " << height << ")"); // NOLINT
+ helper_->ResizeCHROMIUM(width, height);
+}
const GLchar* GetRequestableExtensionsCHROMIUM();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 5e500bb..4f35103 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -468,7 +468,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual void Destroy();
virtual bool SetParent(GLES2Decoder* parent_decoder,
uint32 parent_texture_id);
- virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
+ virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
+ virtual bool UpdateOffscreenFrameBufferSize();
void UpdateParentTextureInfo();
virtual bool MakeCurrent();
virtual GLES2Util* GetGLES2Util() { return &util_; }
@@ -1034,6 +1035,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glValidateProgram.
void DoValidateProgram(GLuint program_client_id);
+ void DoResizeCHROMIUM(GLuint width, GLuint height);
+
void DoSetSurfaceCHROMIUM(GLint surface_id);
// Gets the number of values that will be returned by glGetXXX. Returns
@@ -1178,6 +1181,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// The parent pointer is reset if the parent is destroyed.
base::WeakPtr<GLES2DecoderImpl> parent_;
+ // Width and height to which an offscreen frame buffer should be resized on
+ // the next call to SwapBuffers.
+ gfx::Size pending_offscreen_size_;
+
// Current width and height of the offscreen frame buffer.
gfx::Size offscreen_size_;
@@ -1910,7 +1917,8 @@ bool GLES2DecoderImpl::Initialize(
// Allocate the render buffers at their initial size and check the status
// of the frame buffers is okay.
- if (!ResizeOffscreenFrameBuffer(size)) {
+ pending_offscreen_size_ = size;
+ if (!UpdateOffscreenFrameBufferSize()) {
LOG(ERROR) << "Could not allocate offscreen buffer storage.";
Destroy();
return false;
@@ -2218,6 +2226,140 @@ GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
}
}
+bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
+ if (offscreen_size_ == pending_offscreen_size_)
+ return true;
+
+ offscreen_size_ = pending_offscreen_size_;
+ int w = offscreen_size_.width();
+ int h = offscreen_size_.height();
+ if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "to allocate storage due to excessive dimensions.";
+ return false;
+ }
+
+ // Reallocate the offscreen target buffers.
+ DCHECK(offscreen_target_color_format_);
+ if (IsOffscreenBufferMultisampled()) {
+ if (!offscreen_target_color_render_buffer_->AllocateStorage(
+ pending_offscreen_size_, offscreen_target_color_format_,
+ offscreen_target_samples_)) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "to allocate storage for offscreen target color buffer.";
+ return false;
+ }
+ } else {
+ if (!offscreen_target_color_texture_->AllocateStorage(
+ pending_offscreen_size_, offscreen_target_color_format_)) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "to allocate storage for offscreen target color texture.";
+ return false;
+ }
+ }
+ if (offscreen_target_depth_format_ &&
+ !offscreen_target_depth_render_buffer_->AllocateStorage(
+ pending_offscreen_size_, offscreen_target_depth_format_,
+ offscreen_target_samples_)) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "to allocate storage for offscreen target depth buffer.";
+ return false;
+ }
+ if (offscreen_target_stencil_format_ &&
+ !offscreen_target_stencil_render_buffer_->AllocateStorage(
+ pending_offscreen_size_, offscreen_target_stencil_format_,
+ offscreen_target_samples_)) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "to allocate storage for offscreen target stencil buffer.";
+ return false;
+ }
+
+ // Attach the offscreen target buffers to the target frame buffer.
+ if (IsOffscreenBufferMultisampled()) {
+ offscreen_target_frame_buffer_->AttachRenderBuffer(
+ GL_COLOR_ATTACHMENT0,
+ offscreen_target_color_render_buffer_.get());
+ } else {
+ offscreen_target_frame_buffer_->AttachRenderTexture(
+ offscreen_target_color_texture_.get());
+ }
+ if (offscreen_target_depth_format_) {
+ offscreen_target_frame_buffer_->AttachRenderBuffer(
+ GL_DEPTH_ATTACHMENT,
+ offscreen_target_depth_render_buffer_.get());
+ }
+ const bool packed_depth_stencil =
+ offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
+ if (packed_depth_stencil) {
+ offscreen_target_frame_buffer_->AttachRenderBuffer(
+ GL_STENCIL_ATTACHMENT,
+ offscreen_target_depth_render_buffer_.get());
+ } else if (offscreen_target_stencil_format_) {
+ offscreen_target_frame_buffer_->AttachRenderBuffer(
+ GL_STENCIL_ATTACHMENT,
+ offscreen_target_stencil_render_buffer_.get());
+ }
+
+ if (offscreen_target_frame_buffer_->CheckStatus() !=
+ GL_FRAMEBUFFER_COMPLETE) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "because offscreen FBO was incomplete.";
+ return false;
+ }
+
+ // Clear the target frame buffer.
+ {
+ ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
+ glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
+ offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearStencil(0);
+ glStencilMaskSeparate(GL_FRONT, -1);
+ glStencilMaskSeparate(GL_BACK, -1);
+ glClearDepth(0);
+ glDepthMask(GL_TRUE);
+ glDisable(GL_SCISSOR_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ RestoreClearState();
+ }
+
+ // Allocate the offscreen saved color texture.
+ DCHECK(offscreen_saved_color_format_);
+ offscreen_saved_color_texture_->AllocateStorage(
+ pending_offscreen_size_, offscreen_saved_color_format_);
+
+ offscreen_saved_frame_buffer_->AttachRenderTexture(
+ offscreen_saved_color_texture_.get());
+ if (offscreen_saved_frame_buffer_->CheckStatus() !=
+ GL_FRAMEBUFFER_COMPLETE) {
+ LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
+ << "because offscreen saved FBO was incomplete.";
+ return false;
+ }
+
+ // Destroy the offscreen resolved framebuffers.
+ if (offscreen_resolved_frame_buffer_.get())
+ offscreen_resolved_frame_buffer_->Destroy();
+ if (offscreen_resolved_color_texture_.get())
+ offscreen_resolved_color_texture_->Destroy();
+ offscreen_resolved_color_texture_.reset();
+ offscreen_resolved_frame_buffer_.reset();
+
+ // Clear the offscreen color texture.
+ {
+ ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
+ glClearColor(0, 0, 0, 0);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDisable(GL_SCISSOR_TEST);
+ glClear(GL_COLOR_BUFFER_BIT);
+ RestoreClearState();
+ }
+
+ UpdateParentTextureInfo();
+
+ return true;
+}
+
void GLES2DecoderImpl::UpdateParentTextureInfo() {
if (parent_) {
// Update the info about the offscreen saved color texture in the parent.
@@ -2236,8 +2378,8 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() {
GL_TEXTURE_2D,
0, // level
GL_RGBA,
- offscreen_size_.width(),
- offscreen_size_.height(),
+ pending_offscreen_size_.width(),
+ pending_offscreen_size_.height(),
1, // depth
0, // border
GL_RGBA,
@@ -2265,8 +2407,7 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() {
}
}
-void GLES2DecoderImpl::SetResizeCallback(
- Callback1<gfx::Size>::Type* callback) {
+void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
resize_callback_.reset(callback);
}
@@ -2412,166 +2553,22 @@ bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
return true;
}
-bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
- bool is_offscreen = !!offscreen_target_frame_buffer_.get();
- if (!is_offscreen) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
- << " with an onscreen framebuffer.";
- return false;
- }
-
- if (offscreen_size_ == size)
- return true;
-
- offscreen_size_ = size;
- int w = offscreen_size_.width();
- int h = offscreen_size_.height();
- if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "to allocate storage due to excessive dimensions.";
- return false;
- }
-
- // Reallocate the offscreen target buffers.
- DCHECK(offscreen_target_color_format_);
- if (IsOffscreenBufferMultisampled()) {
- if (!offscreen_target_color_render_buffer_->AllocateStorage(
- offscreen_size_, offscreen_target_color_format_,
- offscreen_target_samples_)) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "to allocate storage for offscreen target color buffer.";
- return false;
- }
- } else {
- if (!offscreen_target_color_texture_->AllocateStorage(
- offscreen_size_, offscreen_target_color_format_)) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "to allocate storage for offscreen target color texture.";
- return false;
- }
- }
- if (offscreen_target_depth_format_ &&
- !offscreen_target_depth_render_buffer_->AllocateStorage(
- offscreen_size_, offscreen_target_depth_format_,
- offscreen_target_samples_)) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "to allocate storage for offscreen target depth buffer.";
- return false;
- }
- if (offscreen_target_stencil_format_ &&
- !offscreen_target_stencil_render_buffer_->AllocateStorage(
- offscreen_size_, offscreen_target_stencil_format_,
- offscreen_target_samples_)) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "to allocate storage for offscreen target stencil buffer.";
- return false;
- }
-
- // Attach the offscreen target buffers to the target frame buffer.
- if (IsOffscreenBufferMultisampled()) {
- offscreen_target_frame_buffer_->AttachRenderBuffer(
- GL_COLOR_ATTACHMENT0,
- offscreen_target_color_render_buffer_.get());
- } else {
- offscreen_target_frame_buffer_->AttachRenderTexture(
- offscreen_target_color_texture_.get());
- }
- if (offscreen_target_depth_format_) {
- offscreen_target_frame_buffer_->AttachRenderBuffer(
- GL_DEPTH_ATTACHMENT,
- offscreen_target_depth_render_buffer_.get());
- }
- const bool packed_depth_stencil =
- offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
- if (packed_depth_stencil) {
- offscreen_target_frame_buffer_->AttachRenderBuffer(
- GL_STENCIL_ATTACHMENT,
- offscreen_target_depth_render_buffer_.get());
- } else if (offscreen_target_stencil_format_) {
- offscreen_target_frame_buffer_->AttachRenderBuffer(
- GL_STENCIL_ATTACHMENT,
- offscreen_target_stencil_render_buffer_.get());
- }
-
- if (offscreen_target_frame_buffer_->CheckStatus() !=
- GL_FRAMEBUFFER_COMPLETE) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "because offscreen FBO was incomplete.";
- return false;
- }
-
- // Clear the target frame buffer.
- {
- ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
- glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
- offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClearStencil(0);
- glStencilMaskSeparate(GL_FRONT, -1);
- glStencilMaskSeparate(GL_BACK, -1);
- glClearDepth(0);
- glDepthMask(GL_TRUE);
- glDisable(GL_SCISSOR_TEST);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- RestoreClearState();
- }
-
- // Allocate the offscreen saved color texture.
- DCHECK(offscreen_saved_color_format_);
- offscreen_saved_color_texture_->AllocateStorage(
- offscreen_size_, offscreen_saved_color_format_);
-
- offscreen_saved_frame_buffer_->AttachRenderTexture(
- offscreen_saved_color_texture_.get());
- if (offscreen_saved_frame_buffer_->CheckStatus() !=
- GL_FRAMEBUFFER_COMPLETE) {
- LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
- << "because offscreen saved FBO was incomplete.";
- return false;
- }
-
- // Destroy the offscreen resolved framebuffers.
- if (offscreen_resolved_frame_buffer_.get())
- offscreen_resolved_frame_buffer_->Destroy();
- if (offscreen_resolved_color_texture_.get())
- offscreen_resolved_color_texture_->Destroy();
- offscreen_resolved_color_texture_.reset();
- offscreen_resolved_frame_buffer_.reset();
-
- // Clear the offscreen color texture.
- {
- ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
- glClearColor(0, 0, 0, 0);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDisable(GL_SCISSOR_TEST);
- glClear(GL_COLOR_BUFFER_BIT);
- RestoreClearState();
- }
-
- UpdateParentTextureInfo();
-
- return true;
+void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
+ // We can't resize the render buffers immediately because there might be a
+ // partial frame rendered into them and we don't want the tail end of that
+ // rendered into the reallocated storage. Defer until the next SwapBuffers.
+ pending_offscreen_size_ = size;
}
-error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
- uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
- GLuint width = static_cast<GLuint>(c.width);
- GLuint height = static_cast<GLuint>(c.height);
- TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
+void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(TOUCH_UI)
// Make sure that we are done drawing to the back buffer before resizing.
glFinish();
#endif
- bool is_offscreen = !!offscreen_target_frame_buffer_.get();
- if (is_offscreen) {
- if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
- return error::kLostContext;
+ if (resize_callback_.get()) {
+ gfx::Size size(width, height);
+ resize_callback_->Run(size);
}
-
- if (resize_callback_.get())
- resize_callback_->Run(gfx::Size(width, height));
-
- return error::kNoError;
}
void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
@@ -6557,6 +6554,14 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers(
if (is_offscreen) {
ScopedGLErrorSuppressor suppressor(this);
+ // First check to see if a deferred offscreen render buffer resize is
+ // pending.
+ if (!UpdateOffscreenFrameBufferSize()) {
+ LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
+ << "failed.";
+ return error::kLostContext;
+ }
+
if (IsOffscreenBufferMultisampled()) {
// For multisampled buffers, bind the resolved frame buffer so that
// callbacks can call ReadPixels or CopyTexImage2D.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index fc66b3d..23c5e3a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -81,7 +81,12 @@ class GLES2Decoder : public CommonDecoder {
uint32 parent_texture_id) = 0;
// Resize an offscreen frame buffer.
- virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) = 0;
+ virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size) = 0;
+
+ // Force the offscreen frame buffer's size to be updated. This
+ // usually occurs lazily, during SwapBuffers, but on some platforms
+ // (Mac OS X in particular) it must be done immediately.
+ virtual bool UpdateOffscreenFrameBufferSize() = 0;
// Make this decoder's GL context current.
virtual bool MakeCurrent() = 0;
@@ -100,8 +105,7 @@ class GLES2Decoder : public CommonDecoder {
// Sets a callback which is called when a glResizeCHROMIUM command
// is processed.
- virtual void SetResizeCallback(
- Callback1<gfx::Size>::Type* callback) = 0;
+ virtual void SetResizeCallback(Callback1<gfx::Size>::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_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 27ef39b..9023cfe 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -2568,6 +2568,14 @@ error::Error GLES2DecoderImpl::HandleGetMaxValueInBufferCHROMIUM(
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
+ uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
+ GLuint width = static_cast<GLuint>(c.width);
+ GLuint height = static_cast<GLuint>(c.height);
+ DoResizeCHROMIUM(width, height);
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleSetSurfaceCHROMIUM(
uint32 immediate_data_size, const gles2::SetSurfaceCHROMIUM& c) {
GLint surface_id = static_cast<GLint>(c.surface_id);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index fa9d43d..13e60bb 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -38,7 +38,8 @@ class MockGLES2Decoder : public GLES2Decoder {
const std::vector<int32>& attribs));
MOCK_METHOD0(Destroy, void());
MOCK_METHOD2(SetParent, bool(GLES2Decoder* parent, uint32 parent_texture_id));
- MOCK_METHOD1(ResizeOffscreenFrameBuffer, bool(const gfx::Size& size));
+ MOCK_METHOD1(ResizeOffscreenFrameBuffer, void(const gfx::Size& size));
+ MOCK_METHOD0(UpdateOffscreenFrameBufferSize, bool());
MOCK_METHOD0(MakeCurrent, bool());
MOCK_METHOD1(GetServiceIdForTesting, uint32(uint32 client_id));
MOCK_METHOD0(GetGLES2Util, GLES2Util*());
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index 6413cc1..15316ea 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -228,8 +228,11 @@ int32 GpuScheduler::GetGetOffset() {
return parser_->get();
}
-void GpuScheduler::SetResizeCallback(
- Callback1<gfx::Size>::Type* callback) {
+void GpuScheduler::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
+ decoder_->ResizeOffscreenFrameBuffer(size);
+}
+
+void GpuScheduler::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
decoder_->SetResizeCallback(callback);
}
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index 61c60be..75ccc63 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -98,6 +98,9 @@ class GpuScheduler : public CommandBufferEngine {
virtual bool SetGetOffset(int32 offset);
virtual int32 GetGetOffset();
+ // Asynchronously resizes an offscreen frame buffer.
+ void ResizeOffscreenFrameBuffer(const gfx::Size& size);
+
#if defined(OS_MACOSX)
// To prevent the GPU process from overloading the browser process,
// we need to track the number of swap buffers calls issued and
diff --git a/gpu/command_buffer/service/gpu_scheduler_mac.cc b/gpu/command_buffer/service/gpu_scheduler_mac.cc
index 2efa9cb..cfa0d5c 100644
--- a/gpu/command_buffer/service/gpu_scheduler_mac.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_mac.cc
@@ -74,12 +74,21 @@ void GpuScheduler::Destroy() {
}
uint64 GpuScheduler::SetWindowSizeForIOSurface(const gfx::Size& size) {
+ // This is called from an IPC handler, so it's undefined which context is
+ // current. Make sure the right one is.
+ decoder_->GetGLContext()->MakeCurrent(decoder_->GetGLSurface());
+
+ ResizeOffscreenFrameBuffer(size);
+ decoder_->UpdateOffscreenFrameBufferSize();
+
// Note: The following line changes the current context again.
return surface_->SetSurfaceSize(size);
}
TransportDIB::Handle GpuScheduler::SetWindowSizeForTransportDIB(
const gfx::Size& size) {
+ ResizeOffscreenFrameBuffer(size);
+ decoder_->UpdateOffscreenFrameBufferSize();
return surface_->SetTransportDIBSize(size);
}
diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
index 4c4f05e..0e3c77a9 100644
--- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
+++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -102,6 +102,13 @@ class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
const int32* attrib_list,
const GURL& active_arl);
+#if defined(OS_MACOSX)
+ // On Mac OS X only, view GLInProcessContexts actually behave like offscreen
+ // GLInProcessContexts, and require an explicit resize operation which is
+ // slightly different from that of offscreen GLInProcessContexts.
+ void ResizeOnscreen(const gfx::Size& size);
+#endif
+
// Create a GLInProcessContext that renders to an offscreen frame buffer. If
// parent is not NULL, that GLInProcessContext can access a copy of the
// created GLInProcessContext's frame buffer that is updated every time
@@ -118,6 +125,13 @@ class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
const int32* attrib_list,
const GURL& active_url);
+ // Resize an offscreen frame buffer. The resize occurs on the next call to
+ // SwapBuffers. This is to avoid waiting until all pending GL calls have been
+ // executed by the GPU process. Everything rendered up to the call to
+ // SwapBuffers will be lost. A lost GLInProcessContext will be reported if the
+ // resize fails.
+ void ResizeOffscreen(const gfx::Size& size);
+
// For an offscreen frame buffer GLInProcessContext, return the texture ID
// with respect to the parent GLInProcessContext. Returns zero if
// GLInProcessContext does not have a parent.
@@ -185,6 +199,7 @@ class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
GLES2CmdHelper* gles2_helper_;
int32 transfer_buffer_id_;
GLES2Implementation* gles2_implementation_;
+ gfx::Size size_;
Error last_error_;
DISALLOW_COPY_AND_ASSIGN(GLInProcessContext);
@@ -251,6 +266,13 @@ GLInProcessContext* GLInProcessContext::CreateViewContext(
#endif
}
+#if defined(OS_MACOSX)
+void GLInProcessContext::ResizeOnscreen(const gfx::Size& size) {
+ DCHECK(size.width() > 0 && size.height() > 0);
+ size_ = size;
+}
+#endif
+
GLInProcessContext* GLInProcessContext::CreateOffscreenContext(
GLInProcessContext* parent,
const gfx::Size& size,
@@ -276,6 +298,16 @@ GLInProcessContext* GLInProcessContext::CreateOffscreenContext(
#endif
}
+void GLInProcessContext::ResizeOffscreen(const gfx::Size& size) {
+ DCHECK(size.width() > 0 && size.height() > 0);
+ if (size_ != size) {
+ gpu_scheduler_->ResizeOffscreenFrameBuffer(size);
+ // TODO(gman): See if the next line is needed.
+ gles2_implementation_->ResizeCHROMIUM(size.width(), size.height());
+ size_ = size;
+ }
+}
+
void GLInProcessContext::PumpCommands() {
gpu_scheduler_->PutChanged();
::gpu::CommandBuffer::State state = command_buffer_->GetState();
@@ -516,6 +548,8 @@ bool GLInProcessContext::Initialize(bool onscreen,
true,
false);
+ size_ = size;
+
return true;
}
@@ -732,7 +766,17 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::reshape(
// TODO(gmam): See if we can comment this in.
// ClearContext();
- gl_->ResizeCHROMIUM(width, height);
+ if (web_view_) {
+#if defined(OS_MACOSX)
+ context_->ResizeOnscreen(gfx::Size(width, height));
+#else
+ gl_->ResizeCHROMIUM(width, height);
+#endif
+ } else {
+ context_->ResizeOffscreen(gfx::Size(width, height));
+ // Force a SwapBuffers to get the framebuffer to resize.
+ context_->SwapBuffers();
+ }
#ifdef FLIP_FRAMEBUFFER_VERTICALLY
scanline_.reset(new uint8[width * 4]);
@@ -1594,3 +1638,4 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() {
} // namespace webkit
#endif // defined(ENABLE_GPU)
+