RendererGLContext supports reparenting a GL context.
This will allow the parenting of offscreen canvas contexts to be deferred until the compositor's view context exists, which in some cases needs to be deferred until the window is asynchronously created by the browser's UI thread. An example is JavaScript opening a popup window and then immediately using canvas to attempt to render to it.
This patch alone does not fix the bug.
BUG=80703
Review URL: http://codereview.chromium.org/7205012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89715 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index 0031602..571ca0f 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -151,9 +151,9 @@
#if defined(ENABLE_GPU)
*route_id = GenerateRouteID();
scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
- this, window, NULL, gfx::Size(), disallowed_extensions_,
+ this, window, gfx::Size(), disallowed_extensions_,
init_params.allowed_extensions,
- init_params.attribs, 0, *route_id, renderer_id_, render_view_id,
+ init_params.attribs, *route_id, renderer_id_, render_view_id,
watchdog_));
router_.AddRoute(*route_id, stub.get());
stubs_.AddWithID(stub.release(), *route_id);
@@ -168,6 +168,10 @@
stub->ViewResized();
}
+GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) {
+ return stubs_.Lookup(route_id);
+}
+
#if defined(OS_MACOSX)
void GpuChannel::AcceleratedSurfaceBuffersSwapped(
int32 route_id, uint64 swap_buffers_count) {
@@ -231,27 +235,20 @@
}
void GpuChannel::OnCreateOffscreenCommandBuffer(
- int32 parent_route_id,
const gfx::Size& size,
const GPUCreateCommandBufferConfig& init_params,
- uint32 parent_texture_id,
int32* route_id) {
content::GetContentClient()->SetActiveURL(init_params.active_url);
#if defined(ENABLE_GPU)
*route_id = GenerateRouteID();
- GpuCommandBufferStub* parent_stub = NULL;
- if (parent_route_id != 0)
- parent_stub = stubs_.Lookup(parent_route_id);
scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
this,
gfx::kNullPluginWindow,
- parent_stub,
size,
disallowed_extensions_,
init_params.allowed_extensions,
init_params.attribs,
- parent_texture_id,
*route_id,
0, 0, watchdog_));
router_.AddRoute(*route_id, stub.get());
diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h
index 10b2315..acf63dcb 100644
--- a/content/common/gpu/gpu_channel.h
+++ b/content/common/gpu/gpu_channel.h
@@ -88,6 +88,8 @@
gfx::GLShareGroup* share_group() const { return share_group_.get(); }
+ GpuCommandBufferStub* LookupCommandBuffer(int32 route_id);
+
#if defined(OS_MACOSX)
virtual void AcceleratedSurfaceBuffersSwapped(
int32 route_id, uint64 swap_buffers_count);
@@ -119,10 +121,8 @@
// Message handlers.
void OnInitialize(base::ProcessHandle renderer_process);
void OnCreateOffscreenCommandBuffer(
- int32 parent_route_id,
const gfx::Size& size,
const GPUCreateCommandBufferConfig& init_params,
- uint32 parent_texture_id,
int32* route_id);
void OnDestroyCommandBuffer(int32 route_id);
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index a88161d2..52c2074f 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -28,25 +28,20 @@
GpuCommandBufferStub::GpuCommandBufferStub(
GpuChannel* channel,
gfx::PluginWindowHandle handle,
- GpuCommandBufferStub* parent,
const gfx::Size& size,
const gpu::gles2::DisallowedExtensions& disallowed_extensions,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
- uint32 parent_texture_id,
int32 route_id,
int32 renderer_id,
int32 render_view_id,
GpuWatchdog* watchdog)
: channel_(channel),
handle_(handle),
- parent_(
- parent ? parent->AsWeakPtr() : base::WeakPtr<GpuCommandBufferStub>()),
initial_size_(size),
disallowed_extensions_(disallowed_extensions),
allowed_extensions_(allowed_extensions),
requested_attribs_(attribs),
- parent_texture_id_(parent_texture_id),
route_id_(route_id),
last_flush_count_(0),
renderer_id_(renderer_id),
@@ -82,6 +77,8 @@
IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message)
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Initialize,
OnInitialize);
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetParent,
+ OnSetParent);
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_GetState, OnGetState);
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Flush, OnFlush);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
@@ -132,8 +129,6 @@
// Initialize the CommandBufferService and GpuScheduler.
if (command_buffer_->Initialize(&shared_memory, size)) {
- gpu::GpuScheduler* parent_processor =
- parent_ ? parent_->scheduler_.get() : NULL;
scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
channel_,
NULL));
@@ -143,8 +138,6 @@
disallowed_extensions_,
allowed_extensions_.c_str(),
requested_attribs_,
- parent_processor,
- parent_texture_id_,
channel_->share_group())) {
command_buffer_->SetPutOffsetChangeCallback(
NewCallback(scheduler_.get(),
@@ -189,6 +182,26 @@
Send(reply_message);
}
+void GpuCommandBufferStub::OnSetParent(int32 parent_route_id,
+ uint32 parent_texture_id,
+ IPC::Message* reply_message) {
+ bool result = false;
+
+ if (parent_route_id == MSG_ROUTING_NONE) {
+ result = scheduler_->SetParent(NULL, 0);
+ } else {
+ GpuCommandBufferStub* parent_stub = channel_->LookupCommandBuffer(
+ parent_route_id);
+ if (parent_stub) {
+ result = scheduler_->SetParent(parent_stub->scheduler_.get(),
+ parent_texture_id);
+ }
+ }
+
+ GpuCommandBufferMsg_SetParent::WriteReplyParams(reply_message, result);
+ Send(reply_message);
+}
+
void GpuCommandBufferStub::OnGetState(IPC::Message* reply_message) {
gpu::CommandBuffer::State state = command_buffer_->GetState();
if (state.error == gpu::error::kLostContext &&
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index 99c2464..1b8e3c48 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -33,12 +33,10 @@
GpuCommandBufferStub(
GpuChannel* channel,
gfx::PluginWindowHandle handle,
- GpuCommandBufferStub* parent,
const gfx::Size& size,
const gpu::gles2::DisallowedExtensions& disallowed_extensions,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
- uint32 parent_texture_id,
int32 route_id,
int32 renderer_id,
int32 render_view_id,
@@ -86,6 +84,9 @@
void OnInitialize(base::SharedMemoryHandle ring_buffer,
int32 size,
IPC::Message* reply_message);
+ void OnSetParent(int32 parent_route_id,
+ uint32 parent_texture_id,
+ IPC::Message* reply_message);
void OnGetState(IPC::Message* reply_message);
void OnFlush(int32 put_offset,
int32 last_known_get,
@@ -123,12 +124,10 @@
GpuChannel* channel_;
gfx::PluginWindowHandle handle_;
- base::WeakPtr<GpuCommandBufferStub> parent_;
gfx::Size initial_size_;
gpu::gles2::DisallowedExtensions disallowed_extensions_;
std::string allowed_extensions_;
std::vector<int32> requested_attribs_;
- uint32 parent_texture_id_;
int32 route_id_;
uint32 last_flush_count_;
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index bd390c2..ab0fb23 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -231,15 +231,10 @@
base::ProcessHandle /* renderer_process_for_gpu */)
// Tells the GPU process to create a new command buffer that renders to an
-// offscreen frame buffer. If parent_route_id is not zero, the texture backing
-// the frame buffer is mapped into the corresponding parent command buffer's
-// namespace, with the name of parent_texture_id. This ID is in the parent's
-// namespace.
-IPC_SYNC_MESSAGE_CONTROL4_1(GpuChannelMsg_CreateOffscreenCommandBuffer,
- int32, /* parent_route_id */
+// offscreen frame buffer.
+IPC_SYNC_MESSAGE_CONTROL2_1(GpuChannelMsg_CreateOffscreenCommandBuffer,
gfx::Size, /* size */
GPUCreateCommandBufferConfig, /* init_params */
- uint32, /* parent_texture_id */
int32 /* route_id */)
// The CommandBufferProxy sends this to the GpuCommandBufferStub in its
@@ -296,6 +291,13 @@
int32 /* size */,
bool /* result */)
+// Sets the parent command buffer. This allows the parent and child to share
+// textures.
+IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_SetParent,
+ int32 /* parent_route_id */,
+ uint32 /* parent_texture_id */,
+ bool /* result */)
+
// Get the current state of the command buffer.
IPC_SYNC_MESSAGE_ROUTED0_1(GpuCommandBufferMsg_GetState,
gpu::CommandBuffer::State /* state */)
diff --git a/content/renderer/gpu/command_buffer_proxy.cc b/content/renderer/gpu/command_buffer_proxy.cc
index 71762ff..5177ba4 100644
--- a/content/renderer/gpu/command_buffer_proxy.cc
+++ b/content/renderer/gpu/command_buffer_proxy.cc
@@ -332,6 +332,33 @@
swap_buffers_callback_->Run();
}
+bool CommandBufferProxy::SetParent(CommandBufferProxy* parent_command_buffer,
+ uint32 parent_texture_id) {
+ if (last_state_.error != gpu::error::kNoError)
+ return false;
+
+ bool result;
+ if (parent_command_buffer) {
+ if (!Send(new GpuCommandBufferMsg_SetParent(
+ route_id_,
+ parent_command_buffer->route_id_,
+ parent_texture_id,
+ &result))) {
+ return false;
+ }
+ } else {
+ if (!Send(new GpuCommandBufferMsg_SetParent(
+ route_id_,
+ MSG_ROUTING_NONE,
+ 0,
+ &result))) {
+ return false;
+ }
+ }
+
+ return result;
+}
+
void CommandBufferProxy::SetSwapBuffersCallback(Callback0::Type* callback) {
swap_buffers_callback_.reset(callback);
}
diff --git a/content/renderer/gpu/command_buffer_proxy.h b/content/renderer/gpu/command_buffer_proxy.h
index d86b4171..ab5d22de 100644
--- a/content/renderer/gpu/command_buffer_proxy.h
+++ b/content/renderer/gpu/command_buffer_proxy.h
@@ -61,6 +61,13 @@
virtual void SetParseError(gpu::error::Error error);
virtual void OnSwapBuffers();
+ // Reparent a command buffer. TODO(apatrick): going forward, the notion of
+ // the parent / child relationship between command buffers is going away in
+ // favor of the notion of surfaces that can be drawn to in one command buffer
+ // and bound as a texture in any other.
+ virtual bool SetParent(CommandBufferProxy* parent_command_buffer,
+ uint32 parent_texture_id);
+
// Set a callback that will be invoked when the SwapBuffers call has been
// issued.
void SetSwapBuffersCallback(Callback0::Type* callback);
diff --git a/content/renderer/gpu/gpu_channel_host.cc b/content/renderer/gpu/gpu_channel_host.cc
index 70b8870..90d5b73e 100644
--- a/content/renderer/gpu/gpu_channel_host.cc
+++ b/content/renderer/gpu/gpu_channel_host.cc
@@ -139,11 +139,9 @@
}
CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer(
- CommandBufferProxy* parent,
const gfx::Size& size,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
- uint32 parent_texture_id,
const GURL& active_url) {
#if defined(ENABLE_GPU)
// An error occurred. Need to get the host again to reinitialize it.
@@ -154,12 +152,9 @@
init_params.allowed_extensions = allowed_extensions;
init_params.attribs = attribs;
init_params.active_url = active_url;
- int32 parent_route_id = parent ? parent->route_id() : 0;
int32 route_id;
- if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(parent_route_id,
- size,
+ if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(size,
init_params,
- parent_texture_id,
&route_id))) {
return NULL;
}
diff --git a/content/renderer/gpu/gpu_channel_host.h b/content/renderer/gpu/gpu_channel_host.h
index 111f696a..affd128 100644
--- a/content/renderer/gpu/gpu_channel_host.h
+++ b/content/renderer/gpu/gpu_channel_host.h
@@ -76,11 +76,9 @@
// Create and connect to a command buffer in the GPU process.
CommandBufferProxy* CreateOffscreenCommandBuffer(
- CommandBufferProxy* parent,
const gfx::Size& size,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
- uint32 parent_texture_id,
const GURL& active_url);
// Destroy a command buffer created by this channel.
diff --git a/content/renderer/gpu/renderer_gl_context.cc b/content/renderer/gpu/renderer_gl_context.cc
index 260b9d5..d5ec2b9 100644
--- a/content/renderer/gpu/renderer_gl_context.cc
+++ b/content/renderer/gpu/renderer_gl_context.cc
@@ -161,7 +161,7 @@
const int32* attrib_list,
const GURL& active_url) {
#if defined(ENABLE_GPU)
- scoped_ptr<RendererGLContext> context(new RendererGLContext(channel, NULL));
+ scoped_ptr<RendererGLContext> context(new RendererGLContext(channel));
if (!context->Initialize(
true,
render_surface,
@@ -188,13 +188,12 @@
RendererGLContext* RendererGLContext::CreateOffscreenContext(
GpuChannelHost* channel,
- RendererGLContext* parent,
const gfx::Size& size,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
#if defined(ENABLE_GPU)
- scoped_ptr<RendererGLContext> context(new RendererGLContext(channel, parent));
+ scoped_ptr<RendererGLContext> context(new RendererGLContext(channel));
if (!context->Initialize(
false,
gfx::kNullPluginWindow,
@@ -211,6 +210,42 @@
#endif
}
+bool RendererGLContext::SetParent(RendererGLContext* new_parent) {
+ // Allocate a texture ID with respect to the parent and change the parent.
+ uint32 new_parent_texture_id = 0;
+ if (new_parent) {
+ TRACE_EVENT0("gpu", "RendererGLContext::SetParent::flushParent");
+ // Flush any remaining commands in the parent context to make sure the
+ // texture id accounting stays consistent.
+ int32 token = new_parent->gles2_helper_->InsertToken();
+ new_parent->gles2_helper_->WaitForToken(token);
+ new_parent_texture_id = new_parent->gles2_implementation_->MakeTextureId();
+
+ if (!command_buffer_->SetParent(new_parent->command_buffer_,
+ new_parent_texture_id)) {
+ new_parent->gles2_implementation_->FreeTextureId(parent_texture_id_);
+ return false;
+ }
+ } else {
+ if (!command_buffer_->SetParent(NULL, 0))
+ return false;
+ }
+
+ // Free the previous parent's texture ID.
+ if (parent_.get() && parent_texture_id_ != 0)
+ parent_->gles2_implementation_->FreeTextureId(parent_texture_id_);
+
+ if (new_parent) {
+ parent_ = new_parent->AsWeakPtr();
+ parent_texture_id_ = new_parent_texture_id;
+ } else {
+ parent_.reset();
+ parent_texture_id_ = 0;
+ }
+
+ return true;
+}
+
void RendererGLContext::ResizeOffscreen(const gfx::Size& size) {
DCHECK(size.width() > 0 && size.height() > 0);
if (size_ != size) {
@@ -342,11 +377,9 @@
return gles2_implementation_;
}
-RendererGLContext::RendererGLContext(GpuChannelHost* channel,
- RendererGLContext* parent)
+RendererGLContext::RendererGLContext(GpuChannelHost* channel)
: channel_(channel),
- parent_(parent ?
- parent->AsWeakPtr() : base::WeakPtr<RendererGLContext>()),
+ parent_(base::WeakPtr<RendererGLContext>()),
parent_texture_id_(0),
child_to_parent_latch_(kInvalidLatchId),
parent_to_child_latch_(kInvalidLatchId),
@@ -377,16 +410,6 @@
// Ensure the gles2 library is initialized first in a thread safe way.
g_gles2_initializer.Get();
- // Allocate a frame buffer ID with respect to the parent.
- if (parent_.get()) {
- TRACE_EVENT0("gpu", "RendererGLContext::Initialize::flushParent");
- // Flush any remaining commands in the parent context to make sure the
- // texture id accounting stays consistent.
- int32 token = parent_->gles2_helper_->InsertToken();
- parent_->gles2_helper_->WaitForToken(token);
- parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId();
- }
-
std::vector<int32> attribs;
while (attrib_list) {
int32 attrib = *attrib_list++;
@@ -431,14 +454,10 @@
active_url);
}
} else {
- CommandBufferProxy* parent_command_buffer =
- parent_.get() ? parent_->command_buffer_ : NULL;
command_buffer_ = channel_->CreateOffscreenCommandBuffer(
- parent_command_buffer,
size,
allowed_extensions,
attribs,
- parent_texture_id_,
active_url);
}
if (!command_buffer_) {
@@ -501,12 +520,10 @@
// If this is a child context, setup latches for synchronization between child
// and parent.
- if (parent_.get()) {
- if (!CreateLatch(&child_to_parent_latch_) ||
- !CreateLatch(&parent_to_child_latch_)) {
- Destroy();
- return false;
- }
+ if (!CreateLatch(&child_to_parent_latch_) ||
+ !CreateLatch(&parent_to_child_latch_)) {
+ Destroy();
+ return false;
}
// Create the object exposing the OpenGL API.
@@ -523,10 +540,7 @@
}
void RendererGLContext::Destroy() {
- if (parent_.get() && parent_texture_id_ != 0) {
- parent_->gles2_implementation_->FreeTextureId(parent_texture_id_);
- parent_texture_id_ = 0;
- }
+ SetParent(NULL);
delete gles2_implementation_;
gles2_implementation_ = NULL;
diff --git a/content/renderer/gpu/renderer_gl_context.h b/content/renderer/gpu/renderer_gl_context.h
index 3798892..49cf83f 100644
--- a/content/renderer/gpu/renderer_gl_context.h
+++ b/content/renderer/gpu/renderer_gl_context.h
@@ -108,12 +108,15 @@
// attribute/value pairs.
static RendererGLContext* CreateOffscreenContext(
GpuChannelHost* channel,
- RendererGLContext* parent,
const gfx::Size& size,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url);
+ // Sets the parent context. If any parent textures have been created for
+ // 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
@@ -183,8 +186,7 @@
bool GetChildToParentLatch(uint32* child_to_parent_latch);
private:
- RendererGLContext(GpuChannelHost* channel,
- RendererGLContext* parent);
+ explicit RendererGLContext(GpuChannelHost* channel);
bool Initialize(bool onscreen,
gfx::PluginWindowHandle render_surface,
diff --git a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
index 69ab6dba..10e8f4a 100644
--- a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
@@ -104,6 +104,7 @@
if (web_view && web_view->mainFrame())
active_url = GURL(web_view->mainFrame()->url());
+ RendererGLContext* parent_context = NULL;
if (render_directly_to_web_view) {
RenderView* renderview = RenderView::FromWebView(web_view);
if (!renderview)
@@ -125,7 +126,6 @@
} else {
bool compositing_enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableAcceleratedCompositing);
- RendererGLContext* parent_context = NULL;
// If GPU compositing is enabled we need to create a GL context that shares
// resources with the compositor's context.
if (compositing_enabled) {
@@ -142,7 +142,6 @@
}
context_ = RendererGLContext::CreateOffscreenContext(
host,
- parent_context,
gfx::Size(1, 1),
preferred_extensions,
attribs,
@@ -152,6 +151,9 @@
if (!context_)
return false;
+ if (!context_->SetParent(parent_context))
+ return false;
+
gl_ = context_->GetImplementation();
context_->SetContextLostCallback(
NewCallback(this,
diff --git a/content/renderer/pepper_platform_context_3d_impl.cc b/content/renderer/pepper_platform_context_3d_impl.cc
index acd19f6..3556db7 100644
--- a/content/renderer/pepper_platform_context_3d_impl.cc
+++ b/content/renderer/pepper_platform_context_3d_impl.cc
@@ -75,14 +75,16 @@
CommandBufferProxy* parent_command_buffer =
parent_context_->GetCommandBufferProxy();
command_buffer_ = channel_->CreateOffscreenCommandBuffer(
- parent_command_buffer,
gfx::Size(1, 1),
"*",
attribs,
- parent_texture_id_,
GURL::EmptyGURL());
if (!command_buffer_)
return false;
+
+ if (!command_buffer_->SetParent(parent_command_buffer, parent_texture_id_))
+ return false;
+
command_buffer_->SetChannelErrorCallback(callback_factory_.NewCallback(
&PlatformContext3DImpl::OnContextLost));
diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc
index b95a2c2..c9595df 100644
--- a/gpu/command_buffer/client/gles2_demo.cc
+++ b/gpu/command_buffer/client/gles2_demo.cc
@@ -64,8 +64,6 @@
gpu::gles2::DisallowedExtensions(),
NULL,
std::vector<int32>(),
- NULL,
- 0,
NULL)) {
return NULL;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 28d6557..3207c70 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -712,10 +712,10 @@
const gfx::Size& size,
const DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
- const std::vector<int32>& attribs,
- GLES2Decoder* parent,
- uint32 parent_client_texture_id);
+ const std::vector<int32>& attribs);
virtual void Destroy();
+ virtual bool SetParent(GLES2Decoder* parent_decoder,
+ uint32 parent_texture_id);
virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
virtual bool UpdateOffscreenFrameBufferSize();
virtual bool MakeCurrent();
@@ -1890,9 +1890,7 @@
const gfx::Size& size,
const DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
- const std::vector<int32>& attribs,
- GLES2Decoder* parent,
- uint32 parent_client_texture_id) {
+ const std::vector<int32>& attribs) {
DCHECK(context);
DCHECK(!context_.get());
@@ -1906,11 +1904,6 @@
// Take ownership of the GLContext.
context_ = context;
- // Keep only a weak pointer to the parent so we don't unmap its client
- // frame buffer after it has been destroyed.
- if (parent)
- parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
-
if (!MakeCurrent()) {
LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
<< "MakeCurrent failed.";
@@ -2068,16 +2061,6 @@
offscreen_saved_color_texture_.reset(new Texture(this));
offscreen_saved_color_texture_->Create();
- // Map the ID of the saved offscreen texture into the parent so that
- // it can reference it.
- if (parent_) {
- GLuint service_id = offscreen_saved_color_texture_->id();
- TextureManager::TextureInfo* info =
- parent_->CreateTextureInfo(parent_client_texture_id, service_id);
- info->SetNotOwned();
- parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
- }
-
// Allocate the render buffers at their initial size and check the status
// of the frame buffers is okay.
pending_offscreen_size_ = size;
@@ -2558,6 +2541,8 @@
if (group_.get())
group_->set_have_context(have_context);
+ SetParent(NULL, 0);
+
if (have_context) {
if (current_program_) {
program_manager()->UnuseProgram(shader_manager(), current_program_);
@@ -2571,20 +2556,8 @@
glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
}
- // Remove the saved frame buffer mapping from the parent decoder. The
- // parent pointer is a weak pointer so it will be null if the parent has
- // already been destroyed.
- if (parent_) {
- // First check the texture has been mapped into the parent. This might not
- // be the case if initialization failed midway through.
- GLuint service_id = offscreen_saved_color_texture_->id();
- GLuint client_id = 0;
- if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
- parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
- }
-
+ if (copy_texture_to_parent_texture_fb_)
glDeleteFramebuffersEXT(1, ©_texture_to_parent_texture_fb_);
- }
if (offscreen_target_frame_buffer_.get())
offscreen_target_frame_buffer_->Destroy();
@@ -2636,6 +2609,40 @@
offscreen_saved_color_texture_.reset();
}
+bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
+ uint32 new_parent_texture_id) {
+ // Remove the saved frame buffer mapping from the parent decoder. The
+ // parent pointer is a weak pointer so it will be null if the parent has
+ // already been destroyed.
+ if (parent_) {
+ // First check the texture has been mapped into the parent. This might not
+ // be the case if initialization failed midway through.
+ GLuint service_id = offscreen_saved_color_texture_->id();
+ GLuint client_id = 0;
+ if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
+ parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
+ }
+ }
+
+ GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
+ new_parent);
+ if (new_parent_impl) {
+ // Map the ID of the saved offscreen texture into the parent so that
+ // it can reference it.
+ GLuint service_id = offscreen_saved_color_texture_->id();
+ TextureManager::TextureInfo* info =
+ new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
+ info->SetNotOwned();
+ new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
+
+ parent_ = new_parent_impl->AsWeakPtr();
+ } else {
+ parent_.reset();
+ }
+
+ 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
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 699f85e..0551e5a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -65,10 +65,6 @@
// allowed_extensions: A string in the same format as
// glGetString(GL_EXTENSIONS) that lists the extensions this context
// should allow. Passing NULL or "*" means allow all extensions.
- // parent: the GLES2 decoder that can access this decoder's front buffer
- // through a texture ID in its namespace.
- // parent_client_texture_id: the texture ID of the front buffer in the
- // parent's namespace.
// Returns:
// true if successful.
virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
@@ -76,13 +72,14 @@
const gfx::Size& size,
const DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
- const std::vector<int32>& attribs,
- GLES2Decoder* parent,
- uint32 parent_client_texture_id) = 0;
+ const std::vector<int32>& attribs) = 0;
// Destroys the graphics context.
virtual void Destroy() = 0;
+ virtual bool SetParent(GLES2Decoder* parent_decoder,
+ uint32 parent_texture_id) = 0;
+
// Resize an offscreen frame buffer.
virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size) = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index f775625..0a44ecfc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -29,16 +29,15 @@
MockGLES2Decoder();
virtual ~MockGLES2Decoder();
- MOCK_METHOD8(Initialize,
+ MOCK_METHOD6(Initialize,
bool(const scoped_refptr<gfx::GLSurface>& surface,
const scoped_refptr<gfx::GLContext>& context,
const gfx::Size& size,
const DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
- const std::vector<int32>& attribs,
- GLES2Decoder* parent,
- uint32 parent_texture_id));
+ const std::vector<int32>& attribs));
MOCK_METHOD0(Destroy, void());
+ MOCK_METHOD2(SetParent, bool(GLES2Decoder* parent, uint32 parent_texture_id));
MOCK_METHOD1(ResizeOffscreenFrameBuffer, void(const gfx::Size& size));
MOCK_METHOD0(UpdateOffscreenFrameBufferSize, bool());
MOCK_METHOD0(MakeCurrent, bool());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 9470d08..0f20e67 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -137,7 +137,7 @@
decoder_.reset(GLES2Decoder::Create(surface_manager_.get(), group_.get()));
decoder_->Initialize(
surface_, context_, surface_->GetSize(), DisallowedExtensions(),
- NULL, std::vector<int32>(), NULL, 0);
+ NULL, std::vector<int32>());
decoder_->set_engine(engine_.get());
EXPECT_CALL(*gl_, GenBuffersARB(_, _))
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index b3711aa..d4ac593 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -66,9 +66,7 @@
const gfx::Size& size,
const gles2::DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
- const std::vector<int32>& attribs,
- gles2::GLES2Decoder* parent_decoder,
- uint32 parent_texture_id) {
+ const std::vector<int32>& attribs) {
DCHECK(context);
if (!context->MakeCurrent(surface))
@@ -111,9 +109,7 @@
size,
disallowed_extensions,
allowed_extensions,
- attribs,
- parent_decoder,
- parent_texture_id)) {
+ attribs)) {
LOG(ERROR) << "GpuScheduler::InitializeCommon failed because decoder "
<< "failed to initialize.";
Destroy();
@@ -134,6 +130,15 @@
parser_.reset();
}
+bool GpuScheduler::SetParent(GpuScheduler* parent_scheduler,
+ uint32 parent_texture_id) {
+ if (parent_scheduler)
+ return decoder_->SetParent(parent_scheduler->decoder_.get(),
+ parent_texture_id);
+ else
+ return decoder_->SetParent(NULL, 0);
+}
+
#if defined(OS_MACOSX)
namespace {
const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1;
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index 78845df..31b6a955 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -63,13 +63,13 @@
const gles2::DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
const std::vector<int32>& attribs,
- GpuScheduler* parent,
- uint32 parent_texture_id,
gfx::GLShareGroup* share_group);
void Destroy();
void DestroyCommon();
+ bool SetParent(GpuScheduler* parent_scheduler, uint32 parent_texture_id);
+
void PutChanged(bool sync);
// Sets whether commands should be processed by this scheduler. Setting to
@@ -152,9 +152,7 @@
const gfx::Size& size,
const gles2::DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
- const std::vector<int32>& attribs,
- gles2::GLES2Decoder* parent_decoder,
- uint32 parent_texture_id);
+ const std::vector<int32>& attribs);
private:
diff --git a/gpu/command_buffer/service/gpu_scheduler_linux.cc b/gpu/command_buffer/service/gpu_scheduler_linux.cc
index 84d821e..6adaba6 100644
--- a/gpu/command_buffer/service/gpu_scheduler_linux.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_linux.cc
@@ -17,16 +17,7 @@
const gles2::DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
const std::vector<int32>& attribs,
- GpuScheduler* parent,
- uint32 parent_texture_id,
gfx::GLShareGroup* share_group) {
- // Get the parent decoder.
- gles2::GLES2Decoder* parent_decoder = NULL;
- if (parent) {
- parent_decoder = parent->decoder_.get();
- DCHECK(parent_decoder);
- }
-
// Create either a view or pbuffer based GLSurface.
scoped_refptr<gfx::GLSurface> surface;
if (window)
@@ -54,9 +45,7 @@
size,
disallowed_extensions,
allowed_extensions,
- attribs,
- parent_decoder,
- parent_texture_id);
+ attribs);
}
void GpuScheduler::Destroy() {
diff --git a/gpu/command_buffer/service/gpu_scheduler_mac.cc b/gpu/command_buffer/service/gpu_scheduler_mac.cc
index 0e4d8d60..2835088 100644
--- a/gpu/command_buffer/service/gpu_scheduler_mac.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_mac.cc
@@ -17,16 +17,7 @@
const gles2::DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
const std::vector<int32>& attribs,
- GpuScheduler* parent,
- uint32 parent_texture_id,
gfx::GLShareGroup* share_group) {
- // Get the parent decoder.
- gles2::GLES2Decoder* parent_decoder = NULL;
- if (parent) {
- parent_decoder = parent->decoder_.get();
- DCHECK(parent_decoder);
- }
-
scoped_refptr<gfx::GLSurface> surface(
gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)));
if (!surface.get()) {
@@ -69,9 +60,7 @@
size,
disallowed_extensions,
allowed_extensions,
- attribs,
- parent_decoder,
- parent_texture_id);
+ attribs);
}
void GpuScheduler::Destroy() {
diff --git a/gpu/command_buffer/service/gpu_scheduler_win.cc b/gpu/command_buffer/service/gpu_scheduler_win.cc
index a92d225..20e53824 100644
--- a/gpu/command_buffer/service/gpu_scheduler_win.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_win.cc
@@ -19,16 +19,7 @@
const gles2::DisallowedExtensions& disallowed_extensions,
const char* allowed_extensions,
const std::vector<int32>& attribs,
- GpuScheduler* parent,
- uint32 parent_texture_id,
gfx::GLShareGroup* share_group) {
- // Get the parent decoder.
- gles2::GLES2Decoder* parent_decoder = NULL;
- if (parent) {
- parent_decoder = parent->decoder_.get();
- DCHECK(parent_decoder);
- }
-
// Create either a view or pbuffer based GLSurface.
scoped_refptr<gfx::GLSurface> surface;
if (window) {
@@ -57,9 +48,7 @@
size,
disallowed_extensions,
allowed_extensions,
- attribs,
- parent_decoder,
- parent_texture_id);
+ attribs);
}
void GpuScheduler::Destroy() {
diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc
index 01ce0d8..30ba86caff 100644
--- a/gpu/demos/framework/window.cc
+++ b/gpu/demos/framework/window.cc
@@ -64,8 +64,6 @@
if (!gpu_scheduler->Initialize(hwnd, gfx::Size(),
gpu::gles2::DisallowedExtensions(),
NULL, std::vector<int32>(),
- NULL,
- 0,
NULL)) {
return false;
}
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc
index 3f18c7e3..cfadf0f3 100644
--- a/gpu/gles2_conform_support/egl/display.cc
+++ b/gpu/gles2_conform_support/egl/display.cc
@@ -112,7 +112,7 @@
new GpuScheduler(command_buffer_.get(), NULL, NULL));
if (!gpu_scheduler->Initialize(
win, gfx::Size(), gpu::gles2::DisallowedExtensions(), NULL,
- attribs, NULL, 0, NULL))
+ attribs, NULL))
return EGL_NO_SURFACE;
command_buffer_->SetPutOffsetChangeCallback(
diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
index 1f7e672..68a34864 100644
--- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
+++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -588,24 +588,17 @@
::gpu::gles2::DisallowedExtensions(),
allowed_extensions,
attribs,
- NULL,
- 0,
share_group.get())) {
LOG(ERROR) << "Could not initialize GpuScheduler.";
command_buffer_.reset();
}
}
} else {
- GpuScheduler* parent_scheduler =
- parent_.get() ? parent_->gpu_scheduler_ : NULL;
-
if (!gpu_scheduler_->Initialize(render_surface,
size,
::gpu::gles2::DisallowedExtensions(),
allowed_extensions,
attribs,
- parent_scheduler,
- parent_texture_id_,
share_group.get())) {
LOG(ERROR) << "Could not initialize offscreen GpuScheduler.";
command_buffer_.reset();