summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/common/gpu/gpu_channel.cc19
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc7
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.h5
-rw-r--r--content/common/gpu/gpu_messages.h1
-rw-r--r--content/renderer/gpu/gpu_channel_host.cc10
-rw-r--r--content/renderer/gpu/gpu_channel_host.h2
-rw-r--r--content/renderer/gpu/renderer_gl_context.cc63
-rw-r--r--content/renderer/gpu/renderer_gl_context.h3
-rw-r--r--content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc21
-rw-r--r--content/renderer/pepper_platform_context_3d_impl.cc1
-rw-r--r--content/renderer/render_widget_fullscreen_pepper.cc1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format.h3
-rw-r--r--gpu/command_buffer/common/id_allocator.cc33
-rw-r--r--gpu/command_buffer/common/id_allocator.h56
-rw-r--r--gpu/command_buffer/service/context_group.cc19
-rw-r--r--gpu/command_buffer/service/context_group.h9
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc18
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h2
-rw-r--r--webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc102
20 files changed, 253 insertions, 124 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index 17de5c4..459c5ec 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -189,12 +189,22 @@ void GpuChannel::CreateViewCommandBuffer(
content::GetContentClient()->SetActiveURL(init_params.active_url);
#if defined(ENABLE_GPU)
+ GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
+
*route_id = GenerateRouteID();
scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
- this, window, gfx::Size(), disallowed_extensions_,
+ this,
+ share_group,
+ window,
+ gfx::Size(),
+ disallowed_extensions_,
init_params.allowed_extensions,
- init_params.attribs, *route_id, renderer_id_, render_view_id,
- watchdog_, software_));
+ init_params.attribs,
+ *route_id,
+ renderer_id_,
+ render_view_id,
+ watchdog_,
+ software_));
router_.AddRoute(*route_id, stub.get());
stubs_.AddWithID(stub.release(), *route_id);
#endif // ENABLE_GPU
@@ -293,10 +303,13 @@ void GpuChannel::OnCreateOffscreenCommandBuffer(
content::GetContentClient()->SetActiveURL(init_params.active_url);
#if defined(ENABLE_GPU)
+ GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
+
route_id = GenerateRouteID();
scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
this,
+ share_group,
gfx::kNullPluginWindow,
size,
disallowed_extensions_,
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index e1e95bb..8291648 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -29,6 +29,7 @@ using gpu::Buffer;
GpuCommandBufferStub::GpuCommandBufferStub(
GpuChannel* channel,
+ GpuCommandBufferStub* share_group,
gfx::PluginWindowHandle handle,
const gfx::Size& size,
const gpu::gles2::DisallowedExtensions& disallowed_extensions,
@@ -54,6 +55,10 @@ GpuCommandBufferStub::GpuCommandBufferStub(
parent_texture_for_initialization_(0),
watchdog_(watchdog),
task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ if (share_group)
+ context_group_ = share_group->context_group_;
+ else
+ context_group_ = new gpu::gles2::ContextGroup;
}
GpuCommandBufferStub::~GpuCommandBufferStub() {
@@ -147,7 +152,7 @@ void GpuCommandBufferStub::OnInitialize(
if (command_buffer_->Initialize(&shared_memory, size)) {
scheduler_.reset(gpu::GpuScheduler::Create(command_buffer_.get(),
channel_,
- NULL));
+ context_group_.get()));
#if defined(TOUCH_UI)
if (software_) {
OnInitializeFailed(reply_message);
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index a6e91fb..f6e31f8 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -17,6 +17,7 @@
#include "base/task.h"
#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message.h"
@@ -33,6 +34,7 @@ class GpuCommandBufferStub
public:
GpuCommandBufferStub(
GpuChannel* channel,
+ GpuCommandBufferStub* share_group,
gfx::PluginWindowHandle handle,
const gfx::Size& size,
const gpu::gles2::DisallowedExtensions& disallowed_extensions,
@@ -133,6 +135,9 @@ class GpuCommandBufferStub
// are destroyed. So a raw pointer is safe.
GpuChannel* channel_;
+ // The group of contexts that share namespaces with this context.
+ scoped_refptr<gpu::gles2::ContextGroup> context_group_;
+
gfx::PluginWindowHandle handle_;
gfx::Size initial_size_;
gpu::gles2::DisallowedExtensions disallowed_extensions_;
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index 1b48b53..2861a25 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -23,6 +23,7 @@
#define IPC_MESSAGE_START GpuMsgStart
IPC_STRUCT_BEGIN(GPUCreateCommandBufferConfig)
+ IPC_STRUCT_MEMBER(int32, share_group_id)
IPC_STRUCT_MEMBER(std::string, allowed_extensions)
IPC_STRUCT_MEMBER(std::vector<int>, attribs)
IPC_STRUCT_MEMBER(GURL, active_url)
diff --git a/content/renderer/gpu/gpu_channel_host.cc b/content/renderer/gpu/gpu_channel_host.cc
index ee79249..a82ce74 100644
--- a/content/renderer/gpu/gpu_channel_host.cc
+++ b/content/renderer/gpu/gpu_channel_host.cc
@@ -97,6 +97,7 @@ bool GpuChannelHost::Send(IPC::Message* message) {
CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer(
int render_view_id,
+ CommandBufferProxy* share_group,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
const GURL& active_url) {
@@ -106,13 +107,17 @@ CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer(
return NULL;
GPUCreateCommandBufferConfig init_params;
+ init_params.share_group_id =
+ share_group ? share_group->route_id() : MSG_ROUTING_NONE;
init_params.allowed_extensions = allowed_extensions;
init_params.attribs = attribs;
init_params.active_url = active_url;
int32 route_id;
if (!RenderThread::current()->Send(
new GpuHostMsg_CreateViewCommandBuffer(
- render_view_id, init_params, &route_id))) {
+ render_view_id,
+ init_params,
+ &route_id))) {
return NULL;
}
@@ -140,6 +145,7 @@ GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder(
CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer(
const gfx::Size& size,
+ CommandBufferProxy* share_group,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
const GURL& active_url) {
@@ -149,6 +155,8 @@ CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer(
return NULL;
GPUCreateCommandBufferConfig init_params;
+ init_params.share_group_id =
+ share_group ? share_group->route_id() : MSG_ROUTING_NONE;
init_params.allowed_extensions = allowed_extensions;
init_params.attribs = attribs;
init_params.active_url = active_url;
diff --git a/content/renderer/gpu/gpu_channel_host.h b/content/renderer/gpu/gpu_channel_host.h
index c2eb9ff..4f77738 100644
--- a/content/renderer/gpu/gpu_channel_host.h
+++ b/content/renderer/gpu/gpu_channel_host.h
@@ -69,6 +69,7 @@ class GpuChannelHost : public IPC::Channel::Listener,
// Create and connect to a command buffer in the GPU process.
CommandBufferProxy* CreateViewCommandBuffer(
int render_view_id,
+ CommandBufferProxy* share_group,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
const GURL& active_url);
@@ -76,6 +77,7 @@ class GpuChannelHost : public IPC::Channel::Listener,
// Create and connect to a command buffer in the GPU process.
CommandBufferProxy* CreateOffscreenCommandBuffer(
const gfx::Size& size,
+ CommandBufferProxy* share_group,
const std::string& allowed_extensions,
const std::vector<int32>& attribs,
const GURL& active_url);
diff --git a/content/renderer/gpu/renderer_gl_context.cc b/content/renderer/gpu/renderer_gl_context.cc
index 894a950..4a969d3 100644
--- a/content/renderer/gpu/renderer_gl_context.cc
+++ b/content/renderer/gpu/renderer_gl_context.cc
@@ -83,6 +83,7 @@ RendererGLContext::~RendererGLContext() {
RendererGLContext* RendererGLContext::CreateViewContext(
GpuChannelHost* channel,
int render_view_id,
+ RendererGLContext* share_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
@@ -92,6 +93,7 @@ RendererGLContext* RendererGLContext::CreateViewContext(
true,
render_view_id,
gfx::Size(),
+ share_group,
allowed_extensions,
attrib_list,
active_url))
@@ -114,6 +116,7 @@ void RendererGLContext::ResizeOnscreen(const gfx::Size& size) {
RendererGLContext* RendererGLContext::CreateOffscreenContext(
GpuChannelHost* channel,
const gfx::Size& size,
+ RendererGLContext* share_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
@@ -123,6 +126,7 @@ RendererGLContext* RendererGLContext::CreateOffscreenContext(
false,
0,
size,
+ share_group,
allowed_extensions,
attrib_list,
active_url))
@@ -195,45 +199,14 @@ uint32 RendererGLContext::GetParentTextureId() {
}
uint32 RendererGLContext::CreateParentTexture(const gfx::Size& size) {
- // Allocate a texture ID with respect to the parent.
- if (parent_.get()) {
- if (!MakeCurrent(parent_.get()))
- return 0;
- uint32 texture_id = parent_->gles2_implementation_->MakeTextureId();
- parent_->gles2_implementation_->BindTexture(GL_TEXTURE_2D, texture_id);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- parent_->gles2_implementation_->TexImage2D(GL_TEXTURE_2D,
- 0, // mip level
- GL_RGBA,
- size.width(),
- size.height(),
- 0, // border
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
- // Make sure that the parent texture's storage is allocated before we let
- // the caller attempt to use it.
- int32 token = parent_->gles2_helper_->InsertToken();
- parent_->gles2_helper_->WaitForToken(token);
- return texture_id;
- }
- return 0;
+ uint32 texture_id = 0;
+ gles2_implementation_->GenTextures(1, &texture_id);
+ gles2_implementation_->Flush();
+ return texture_id;
}
void RendererGLContext::DeleteParentTexture(uint32 texture) {
- if (parent_.get()) {
- if (!MakeCurrent(parent_.get()))
- return;
- parent_->gles2_implementation_->DeleteTextures(1, &texture);
- }
+ gles2_implementation_->DeleteTextures(1, &texture);
}
void RendererGLContext::SetSwapBuffersCallback(Callback0::Type* callback) {
@@ -330,6 +303,7 @@ RendererGLContext::RendererGLContext(GpuChannelHost* channel)
bool RendererGLContext::Initialize(bool onscreen,
int render_view_id,
const gfx::Size& size,
+ RendererGLContext* share_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
@@ -377,12 +351,14 @@ bool RendererGLContext::Initialize(bool onscreen,
"RendererGLContext::Initialize::CreateViewCommandBuffer");
command_buffer_ = channel_->CreateViewCommandBuffer(
render_view_id,
+ share_group ? share_group->command_buffer_ : NULL,
allowed_extensions,
attribs,
active_url);
} else {
command_buffer_ = channel_->CreateOffscreenCommandBuffer(
size,
+ share_group ? share_group->command_buffer_ : NULL,
allowed_extensions,
attribs,
active_url);
@@ -441,7 +417,7 @@ bool RendererGLContext::Initialize(bool onscreen,
transfer_buffer.size,
transfer_buffer.ptr,
transfer_buffer_id_,
- false);
+ true);
size_ = size;
@@ -452,8 +428,17 @@ void RendererGLContext::Destroy() {
TRACE_EVENT0("gpu", "RendererGLContext::Destroy");
SetParent(NULL);
- delete gles2_implementation_;
- gles2_implementation_ = NULL;
+ if (gles2_implementation_) {
+ // First flush the context to ensure that any pending frees of resources
+ // are completed. Otherwise, if this context is part of a share group,
+ // those resources might leak. Also, any remaining side effects of commands
+ // issued on this context might not be visible to other contexts in the
+ // share group.
+ gles2_implementation_->Flush();
+
+ delete gles2_implementation_;
+ gles2_implementation_ = NULL;
+ }
// Do not destroy this transfer buffer here, because commands are still
// in flight on the GPU process that may access them. When the command buffer
diff --git a/content/renderer/gpu/renderer_gl_context.h b/content/renderer/gpu/renderer_gl_context.h
index 9fa3315..ad69f4b 100644
--- a/content/renderer/gpu/renderer_gl_context.h
+++ b/content/renderer/gpu/renderer_gl_context.h
@@ -100,6 +100,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
static RendererGLContext* CreateViewContext(
GpuChannelHost* channel,
int render_view_id,
+ RendererGLContext* share_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_arl);
@@ -122,6 +123,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
static RendererGLContext* CreateOffscreenContext(
GpuChannelHost* channel,
const gfx::Size& size,
+ RendererGLContext* share_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url);
@@ -189,6 +191,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
bool Initialize(bool onscreen,
int render_view_id,
const gfx::Size& size,
+ RendererGLContext* share_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url);
diff --git a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
index 88f1505..35bf246 100644
--- a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
@@ -13,7 +13,9 @@
#include <GLES2/gl2ext.h>
#include <algorithm>
+#include <set>
+#include "base/lazy_instance.h"
#include "base/string_tokenizer.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
@@ -30,6 +32,9 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "webkit/glue/gl_bindings_skia_cmd_buffer.h"
+static base::LazyInstance<std::set<WebGraphicsContext3DCommandBufferImpl*> >
+ g_all_contexts(base::LINKER_INITIALIZED);
+
WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl()
: context_(NULL),
gl_(NULL),
@@ -47,6 +52,7 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl()
WebGraphicsContext3DCommandBufferImpl::
~WebGraphicsContext3DCommandBufferImpl() {
+ g_all_contexts.Pointer()->erase(this);
delete context_;
}
@@ -107,6 +113,16 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize(
if (web_view && web_view->mainFrame())
active_url = GURL(web_view->mainFrame()->document().url());
+ // HACK: Assume this is a WebGL context by looking for the noExtensions
+ // attribute. WebGL contexts must not go in the share group because they
+ // rely on destruction of the context to clean up owned resources. Putting
+ // them in a share group would prevent this from happening.
+ RendererGLContext* share_group = NULL;
+ if (!attributes.noExtensions) {
+ share_group = g_all_contexts.Pointer()->empty() ?
+ NULL : (*g_all_contexts.Pointer()->begin())->context_;
+ }
+
if (render_directly_to_web_view) {
RenderView* renderview = RenderView::FromWebView(web_view);
if (!renderview)
@@ -116,6 +132,7 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize(
context_ = RendererGLContext::CreateViewContext(
host,
renderview->routing_id(),
+ share_group,
preferred_extensions,
attribs,
active_url);
@@ -128,6 +145,7 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize(
context_ = RendererGLContext::CreateOffscreenContext(
host,
gfx::Size(1, 1),
+ share_group,
preferred_extensions,
attribs,
active_url);
@@ -164,6 +182,9 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize(
attributes_.antialias = samples > 0;
}
+ if (!attributes.noExtensions)
+ g_all_contexts.Pointer()->insert(this);
+
return true;
}
diff --git a/content/renderer/pepper_platform_context_3d_impl.cc b/content/renderer/pepper_platform_context_3d_impl.cc
index 60c9603..a2a898f 100644
--- a/content/renderer/pepper_platform_context_3d_impl.cc
+++ b/content/renderer/pepper_platform_context_3d_impl.cc
@@ -95,6 +95,7 @@ bool PlatformContext3DImpl::Init(const int32* attrib_list) {
parent_context_->GetCommandBufferProxy();
command_buffer_ = channel_->CreateOffscreenCommandBuffer(
surface_size,
+ NULL,
"*",
attribs,
GURL::EmptyGURL());
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index f596d47..78df423 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -346,6 +346,7 @@ void RenderWidgetFullscreenPepper::CreateContext() {
context_ = RendererGLContext::CreateViewContext(
host,
routing_id(),
+ NULL,
"GL_OES_packed_depth_stencil GL_OES_depth24",
attribs,
active_url_);
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
index ec9ea33..484b266 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.h
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -52,7 +52,8 @@ enum IdNamespaces {
kFramebuffers,
kProgramsAndShaders,
kRenderbuffers,
- kTextures
+ kTextures,
+ kNumIdNamespaces
};
// These numbers must not change
diff --git a/gpu/command_buffer/common/id_allocator.cc b/gpu/command_buffer/common/id_allocator.cc
index eb450f3..e3fbdd5 100644
--- a/gpu/command_buffer/common/id_allocator.cc
+++ b/gpu/command_buffer/common/id_allocator.cc
@@ -9,6 +9,9 @@
namespace gpu {
+IdAllocatorInterface::~IdAllocatorInterface() {
+}
+
IdAllocator::IdAllocator() {}
IdAllocator::~IdAllocator() {}
@@ -85,4 +88,34 @@ ResourceId IdAllocator::FindFirstUnusedId() const {
return id;
}
+NonReusedIdAllocator::NonReusedIdAllocator() : last_id_(0) {
+}
+
+NonReusedIdAllocator::~NonReusedIdAllocator() {
+}
+
+ResourceId NonReusedIdAllocator::AllocateID() {
+ return ++last_id_;
+}
+
+ResourceId NonReusedIdAllocator::AllocateIDAtOrAbove(ResourceId desired_id) {
+ if (desired_id > last_id_)
+ last_id_ = desired_id;
+
+ return ++last_id_;
+}
+
+bool NonReusedIdAllocator::MarkAsUsed(ResourceId id) {
+ GPU_NOTREACHED();
+ return false;
+}
+
+void NonReusedIdAllocator::FreeID(ResourceId id) {
+}
+
+bool NonReusedIdAllocator::InUse(ResourceId id) const {
+ GPU_NOTREACHED();
+ return false;
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/common/id_allocator.h b/gpu/command_buffer/common/id_allocator.h
index 4e80290..23c93d2 100644
--- a/gpu/command_buffer/common/id_allocator.h
+++ b/gpu/command_buffer/common/id_allocator.h
@@ -11,6 +11,10 @@
#include <utility>
#include "../common/types.h"
+// TODO(apatrick): Having regular GL flush semantics on the client side, it
+// probably isn't necessary to round trip to the service to allocate IDs.
+// Retire this code.
+
namespace gpu {
// A resource ID, key to the resource maps.
@@ -18,27 +22,39 @@ typedef uint32 ResourceId;
// Invalid resource ID.
static const ResourceId kInvalidResource = 0u;
-// A class to manage the allocation of resource IDs.
-class IdAllocator {
+class IdAllocatorInterface {
public:
- IdAllocator();
- ~IdAllocator();
+ virtual ~IdAllocatorInterface();
// Allocates a new resource ID.
- ResourceId AllocateID();
+ virtual ResourceId AllocateID() = 0;
// Allocates an Id starting at or above desired_id.
// Note: may wrap if it starts near limit.
- ResourceId AllocateIDAtOrAbove(ResourceId desired_id);
+ virtual ResourceId AllocateIDAtOrAbove(ResourceId desired_id) = 0;
// Marks an id as used. Returns false if id was already used.
- bool MarkAsUsed(ResourceId id);
+ virtual bool MarkAsUsed(ResourceId id) = 0;
// Frees a resource ID.
- void FreeID(ResourceId id);
+ virtual void FreeID(ResourceId id) = 0;
// Checks whether or not a resource ID is in use.
- bool InUse(ResourceId id) const;
+ virtual bool InUse(ResourceId id) const = 0;
+};
+
+// A class to manage the allocation of resource IDs.
+class IdAllocator : public IdAllocatorInterface {
+ public:
+ IdAllocator();
+ virtual ~IdAllocator();
+
+ // Implement IdAllocatorInterface.
+ virtual ResourceId AllocateID();
+ virtual ResourceId AllocateIDAtOrAbove(ResourceId desired_id);
+ virtual bool MarkAsUsed(ResourceId id);
+ virtual void FreeID(ResourceId id);
+ virtual bool InUse(ResourceId id) const;
private:
// TODO(gman): This would work much better with ranges or a hash table.
@@ -56,6 +72,28 @@ class IdAllocator {
DISALLOW_COPY_AND_ASSIGN(IdAllocator);
};
+// A class to manage the allocation of resource IDs that are never reused. This
+// implementation does not track which IDs are currently used. It is useful for
+// shared and programs which cannot be implicitly created by binding a
+// previously unused ID.
+class NonReusedIdAllocator : public IdAllocatorInterface {
+ public:
+ NonReusedIdAllocator();
+ virtual ~NonReusedIdAllocator();
+
+ // Implement IdAllocatorInterface.
+ virtual ResourceId AllocateID();
+ virtual ResourceId AllocateIDAtOrAbove(ResourceId desired_id);
+ virtual bool MarkAsUsed(ResourceId id);
+ virtual void FreeID(ResourceId id);
+ virtual bool InUse(ResourceId id) const;
+
+ private:
+ ResourceId last_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonReusedIdAllocator);
+};
+
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_CLIENT_ID_ALLOCATOR_H_
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 7b474d3..f852835 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -27,6 +27,12 @@ ContextGroup::ContextGroup()
max_fragment_uniform_vectors_(0u),
max_varying_vectors_(0u),
max_vertex_uniform_vectors_(0u) {
+ id_namespaces_[id_namespaces::kBuffers].reset(new IdAllocator);
+ id_namespaces_[id_namespaces::kFramebuffers].reset(new IdAllocator);
+ id_namespaces_[id_namespaces::kProgramsAndShaders].reset(
+ new NonReusedIdAllocator);
+ id_namespaces_[id_namespaces::kRenderbuffers].reset(new IdAllocator);
+ id_namespaces_[id_namespaces::kTextures].reset(new IdAllocator);
}
ContextGroup::~ContextGroup() {
@@ -145,14 +151,11 @@ void ContextGroup::Destroy() {
}
}
-IdAllocator* ContextGroup::GetIdAllocator(unsigned namespace_id) {
- IdAllocatorMap::iterator it = id_namespaces_.find(namespace_id);
- if (it != id_namespaces_.end()) {
- return it->second.get();
- }
- IdAllocator* id_allocator = new IdAllocator();
- id_namespaces_[namespace_id] = linked_ptr<IdAllocator>(id_allocator);
- return id_allocator;
+IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) {
+ if (namespace_id >= arraysize(id_namespaces_))
+ return NULL;
+
+ return id_namespaces_[namespace_id].get();
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 9bd3a58..a2e6382 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -11,12 +11,13 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
#include "gpu/command_buffer/service/feature_info.h"
namespace gpu {
-class IdAllocator;
+class IdAllocatorInterface;
namespace gles2 {
@@ -103,7 +104,7 @@ class ContextGroup : public base::RefCounted<ContextGroup> {
return shader_manager_.get();
}
- IdAllocator* GetIdAllocator(unsigned namepsace_id);
+ IdAllocatorInterface* GetIdAllocator(unsigned namespace_id);
private:
// Destroys all the resources.
@@ -133,8 +134,8 @@ class ContextGroup : public base::RefCounted<ContextGroup> {
scoped_ptr<ShaderManager> shader_manager_;
- typedef base::hash_map<uint32, linked_ptr<IdAllocator> > IdAllocatorMap;
- IdAllocatorMap id_namespaces_;
+ linked_ptr<IdAllocatorInterface>
+ id_namespaces_[id_namespaces::kNumIdNamespaces];
FeatureInfo feature_info_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index c982c9a..1dd1bfd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1649,7 +1649,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
ContextGroup* group)
: GLES2Decoder(),
surface_manager_(surface_manager),
- group_(ContextGroup::Ref(group ? group : new ContextGroup())),
+ group_(group),
error_bits_(0),
pack_alignment_(4),
unpack_alignment_(4),
@@ -1695,6 +1695,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
frame_number_(0),
has_arb_robustness_(false),
reset_status_(GL_NO_ERROR) {
+ DCHECK(group);
+
attrib_0_value_.v[0] = 0.0f;
attrib_0_value_.v[1] = 0.0f;
attrib_0_value_.v[2] = 0.0f;
@@ -2727,7 +2729,7 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
glGenBuffersARB(1, &service_id);
CreateBufferInfo(client_id, service_id);
info = GetBufferInfo(client_id);
- IdAllocator* id_allocator =
+ IdAllocatorInterface* id_allocator =
group_->GetIdAllocator(id_namespaces::kBuffers);
id_allocator->MarkAsUsed(client_id);
}
@@ -2806,7 +2808,7 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
glGenFramebuffersEXT(1, &service_id);
CreateFramebufferInfo(client_id, service_id);
info = GetFramebufferInfo(client_id);
- IdAllocator* id_allocator =
+ IdAllocatorInterface* id_allocator =
group_->GetIdAllocator(id_namespaces::kFramebuffers);
id_allocator->MarkAsUsed(client_id);
} else {
@@ -2845,7 +2847,7 @@ void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
glGenRenderbuffersEXT(1, &service_id);
CreateRenderbufferInfo(client_id, service_id);
info = GetRenderbufferInfo(client_id);
- IdAllocator* id_allocator =
+ IdAllocatorInterface* id_allocator =
group_->GetIdAllocator(id_namespaces::kRenderbuffers);
id_allocator->MarkAsUsed(client_id);
} else {
@@ -2867,7 +2869,7 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
glGenTextures(1, &service_id);
CreateTextureInfo(client_id, service_id);
info = GetTextureInfo(client_id);
- IdAllocator* id_allocator =
+ IdAllocatorInterface* id_allocator =
group_->GetIdAllocator(id_namespaces::kTextures);
id_allocator->MarkAsUsed(client_id);
}
@@ -3360,7 +3362,7 @@ error::Error GLES2DecoderImpl::HandleDeleteProgram(
void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
GLuint namespace_id, GLsizei n, const GLuint* ids) {
- IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
+ IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
for (GLsizei ii = 0; ii < n; ++ii) {
id_allocator->FreeID(ids[ii]);
}
@@ -3389,7 +3391,7 @@ error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
- IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
+ IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
if (id_offset == 0) {
for (GLsizei ii = 0; ii < n; ++ii) {
ids[ii] = id_allocator->AllocateID();
@@ -3426,7 +3428,7 @@ error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
GLuint namespace_id, GLsizei n, const GLuint* ids) {
- IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
+ IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
for (GLsizei ii = 0; ii < n; ++ii) {
if (!id_allocator->MarkAsUsed(ids[ii])) {
for (GLsizei jj = 0; jj < ii; ++jj) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 823cc1a..e145a79 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -2310,7 +2310,7 @@ TEST_F(GLES2DecoderTest, SharedIds) {
GLuint* ids = GetSharedMemoryAs<GLuint*>();
gen_cmd.Init(kNamespaceId, 0, 2, kSharedMemoryId, kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(gen_cmd));
- IdAllocator* id_allocator = GetIdAllocator(kNamespaceId);
+ IdAllocatorInterface* id_allocator = GetIdAllocator(kNamespaceId);
ASSERT_TRUE(id_allocator != NULL);
// This check is implementation dependant but it's kind of hard to check
// otherwise.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 3762952..b7379a4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -128,7 +128,7 @@ class GLES2DecoderTestBase : public testing::Test {
return reinterpret_cast<T>(ptr);
}
- IdAllocator* GetIdAllocator(GLuint namespace_id) {
+ IdAllocatorInterface* GetIdAllocator(GLuint namespace_id) {
return group_->GetIdAllocator(namespace_id);
}
diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
index c046bc3..0c70da7 100644
--- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
+++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -13,6 +13,7 @@
#include <GLES2/gl2ext.h>
#include <algorithm>
+#include <set>
#include "base/string_tokenizer.h"
#include "base/command_line.h"
@@ -24,6 +25,7 @@
#include "gpu/command_buffer/client/gles2_lib.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/GLES2/gles2_command_buffer.h"
@@ -96,6 +98,7 @@ class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
//
static GLInProcessContext* CreateViewContext(
gfx::PluginWindowHandle render_surface,
+ GLInProcessContext* context_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_arl);
@@ -118,6 +121,7 @@ class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
static GLInProcessContext* CreateOffscreenContext(
GLInProcessContext* parent,
const gfx::Size& size,
+ GLInProcessContext* context_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url);
@@ -178,6 +182,7 @@ class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
bool Initialize(bool onscreen,
gfx::PluginWindowHandle render_surface,
const gfx::Size& size,
+ GLInProcessContext* context_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url);
@@ -208,6 +213,10 @@ const int32 kCommandBufferSize = 1024 * 1024;
// creation attributes.
const int32 kTransferBufferSize = 1024 * 1024;
+static base::LazyInstance<
+ std::set<WebGraphicsContext3DInProcessCommandBufferImpl*> > g_all_contexts(
+ base::LINKER_INITIALIZED);
+
// Singleton used to initialize and terminate the gles2 library.
class GLES2Initializer {
public:
@@ -236,6 +245,7 @@ GLInProcessContext::~GLInProcessContext() {
GLInProcessContext* GLInProcessContext::CreateViewContext(
gfx::PluginWindowHandle render_surface,
+ GLInProcessContext* context_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
@@ -245,6 +255,7 @@ GLInProcessContext* GLInProcessContext::CreateViewContext(
true,
render_surface,
gfx::Size(),
+ context_group,
allowed_extensions,
attrib_list,
active_url))
@@ -266,6 +277,7 @@ void GLInProcessContext::ResizeOnscreen(const gfx::Size& size) {
GLInProcessContext* GLInProcessContext::CreateOffscreenContext(
GLInProcessContext* parent,
const gfx::Size& size,
+ GLInProcessContext* context_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
@@ -275,6 +287,7 @@ GLInProcessContext* GLInProcessContext::CreateOffscreenContext(
false,
gfx::kNullPluginWindow,
size,
+ context_group,
allowed_extensions,
attrib_list,
active_url))
@@ -297,12 +310,9 @@ void GLInProcessContext::ResizeOffscreen(const gfx::Size& size) {
}
void GLInProcessContext::PumpCommands() {
- ::gpu::CommandBuffer::State state;
- do {
- gpu_scheduler_->PutChanged();
- MessageLoop::current()->RunAllPending();
- state = command_buffer_->GetState();
- } while (state.get_offset != state.put_offset);
+ gpu_scheduler_->PutChanged();
+ ::gpu::CommandBuffer::State state = command_buffer_->GetState();
+ CHECK(state.error == ::gpu::error::kNoError);
}
uint32 GLInProcessContext::GetParentTextureId() {
@@ -310,45 +320,14 @@ uint32 GLInProcessContext::GetParentTextureId() {
}
uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) {
- // Allocate a texture ID with respect to the parent.
- if (parent_.get()) {
- if (!MakeCurrent(parent_.get()))
- return 0;
- uint32 texture_id = parent_->gles2_implementation_->MakeTextureId();
- parent_->gles2_implementation_->BindTexture(GL_TEXTURE_2D, texture_id);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- parent_->gles2_implementation_->TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- parent_->gles2_implementation_->TexImage2D(GL_TEXTURE_2D,
- 0, // mip level
- GL_RGBA,
- size.width(),
- size.height(),
- 0, // border
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
- // Make sure that the parent texture's storage is allocated before we let
- // the caller attempt to use it.
- int32 token = parent_->gles2_helper_->InsertToken();
- parent_->gles2_helper_->WaitForToken(token);
- return texture_id;
- }
- return 0;
+ uint32 texture = 0;
+ gles2_implementation_->GenTextures(1, &texture);
+ gles2_implementation_->Flush();
+ return texture;
}
void GLInProcessContext::DeleteParentTexture(uint32 texture) {
- if (parent_.get()) {
- if (!MakeCurrent(parent_.get()))
- return;
- parent_->gles2_implementation_->DeleteTextures(1, &texture);
- }
+ gles2_implementation_->DeleteTextures(1, &texture);
}
void GLInProcessContext::SetSwapBuffersCallback(Callback0::Type* callback) {
@@ -434,6 +413,7 @@ GLInProcessContext::GLInProcessContext(GLInProcessContext* parent)
bool GLInProcessContext::Initialize(bool onscreen,
gfx::PluginWindowHandle render_surface,
const gfx::Size& size,
+ GLInProcessContext* context_group,
const char* allowed_extensions,
const int32* attrib_list,
const GURL& active_url) {
@@ -486,9 +466,12 @@ bool GLInProcessContext::Initialize(bool onscreen,
if (!command_buffer_->Initialize(kCommandBufferSize))
return false;
- gpu_scheduler_ = GpuScheduler::Create(command_buffer_.get(),
- NULL,
- NULL);
+ gpu_scheduler_ = GpuScheduler::Create(
+ command_buffer_.get(),
+ NULL,
+ context_group ?
+ context_group->gpu_scheduler_->decoder()->GetContextGroup() :
+ new ::gpu::gles2::ContextGroup);
if (onscreen) {
if (render_surface == gfx::kNullPluginWindow) {
@@ -562,7 +545,7 @@ bool GLInProcessContext::Initialize(bool onscreen,
transfer_buffer.size,
transfer_buffer.ptr,
transfer_buffer_id_,
- false);
+ true);
size_ = size;
@@ -575,8 +558,17 @@ void GLInProcessContext::Destroy() {
parent_texture_id_ = 0;
}
- delete gles2_implementation_;
- gles2_implementation_ = NULL;
+ if (gles2_implementation_) {
+ // First flush the context to ensure that any pending frees of resources
+ // are completed. Otherwise, if this context is part of a share group,
+ // those resources might leak. Also, any remaining side effects of commands
+ // issued on this context might not be visible to other contexts in the
+ // share group.
+ gles2_implementation_->Flush();
+
+ delete gles2_implementation_;
+ gles2_implementation_ = NULL;
+ }
if (command_buffer_.get() && transfer_buffer_id_ != -1) {
command_buffer_->DestroyTransferBuffer(transfer_buffer_id_);
@@ -616,6 +608,7 @@ WebGraphicsContext3DInProcessCommandBufferImpl::
WebGraphicsContext3DInProcessCommandBufferImpl::
~WebGraphicsContext3DInProcessCommandBufferImpl() {
+ g_all_contexts.Pointer()->erase(this);
}
// This string should only be passed for WebGL contexts. Nothing ELSE!!!
@@ -667,9 +660,19 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::initialize(
}
}
+ // HACK: Assume this is a WebGL context by looking for the noExtensions
+ // attribute. WebGL contexts must not go in the share group because they
+ // rely on destruction of the context to clean up owned resources. Putting
+ // them in a share group would prevent this from happening.
+ WebGraphicsContext3DInProcessCommandBufferImpl* context_group = NULL;
+ if (!attributes.noExtensions)
+ context_group = g_all_contexts.Pointer()->empty() ?
+ NULL : *g_all_contexts.Pointer()->begin();
+
context_ = GLInProcessContext::CreateOffscreenContext(
parent_context,
gfx::Size(1, 1),
+ context_group ? context_group->context_ : NULL,
preferred_extensions,
attribs,
active_url);
@@ -702,6 +705,9 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::initialize(
}
makeContextCurrent();
+ if (!attributes.noExtensions)
+ g_all_contexts.Pointer()->insert(this);
+
return true;
}