Index: webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
=================================================================== |
--- webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc (revision 95161) |
+++ webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc (working copy) |
@@ -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 @@ |
// |
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 @@ |
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 @@ |
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 @@ |
// 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::CreateViewContext( |
gfx::PluginWindowHandle render_surface, |
+ GLInProcessContext* context_group, |
const char* allowed_extensions, |
const int32* attrib_list, |
const GURL& active_url) { |
@@ -245,6 +255,7 @@ |
true, |
render_surface, |
gfx::Size(), |
+ context_group, |
allowed_extensions, |
attrib_list, |
active_url)) |
@@ -266,6 +277,7 @@ |
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 @@ |
false, |
gfx::kNullPluginWindow, |
size, |
+ context_group, |
allowed_extensions, |
attrib_list, |
active_url)) |
@@ -302,6 +315,7 @@ |
gpu_scheduler_->PutChanged(); |
MessageLoop::current()->RunAllPending(); |
state = command_buffer_->GetState(); |
+ CHECK(state.error == ::gpu::error::kNoError); |
jamesr
2011/08/03 21:51:20
On second thought, can you get rid of the RunAllPe
|
} while (state.get_offset != state.put_offset); |
} |
@@ -310,45 +324,14 @@ |
} |
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 +417,7 @@ |
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 +470,11 @@ |
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() : NULL); |
if (onscreen) { |
if (render_surface == gfx::kNullPluginWindow) { |
@@ -562,7 +548,7 @@ |
transfer_buffer.size, |
transfer_buffer.ptr, |
transfer_buffer_id_, |
- false); |
+ true); |
size_ = size; |
@@ -575,9 +561,18 @@ |
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_); |
transfer_buffer_id_ = -1; |
@@ -616,6 +611,7 @@ |
WebGraphicsContext3DInProcessCommandBufferImpl:: |
~WebGraphicsContext3DInProcessCommandBufferImpl() { |
+ g_all_contexts.Pointer()->erase(this); |
} |
// This string should only be passed for WebGL contexts. Nothing ELSE!!! |
@@ -667,9 +663,19 @@ |
} |
} |
+ // 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 +708,9 @@ |
} |
makeContextCurrent(); |
+ if (!attributes.noExtensions) |
+ g_all_contexts.Pointer()->insert(this); |
+ |
return true; |
} |