summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-26 04:08:04 +0000
committersievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-26 04:08:04 +0000
commitd7cf393aac07d1db221d3899b62098bcd26e2fd0 (patch)
tree5d009c371b420fe8a1a312c0b95dd3912b4bac3d
parentabb786b1feaabd3318a436fac1245d978581fad1 (diff)
downloadchromium_src-d7cf393aac07d1db221d3899b62098bcd26e2fd0.zip
chromium_src-d7cf393aac07d1db221d3899b62098bcd26e2fd0.tar.gz
chromium_src-d7cf393aac07d1db221d3899b62098bcd26e2fd0.tar.bz2
Factor out code from WebGraphicsContext3DInProcessImpl
Move the internal GLInProcessContext class to gpu/command_buffer/client. This works towards these goals: - Unifying the WGC3D impls to be able to have one unified class that is simply a shim from WGC3D to GLES2 - Factor out the in-process version so that non-webkit code can use it without depending on webkit TBR=jamesr@chromium.org, piman@chromium.org Review URL: https://codereview.chromium.org/16851003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208612 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--android_webview/DEPS2
-rw-r--r--android_webview/browser/DEPS2
-rw-r--r--android_webview/browser/gpu_memory_buffer_impl.cc5
-rw-r--r--android_webview/lib/main/aw_main_delegate.cc4
-rw-r--r--gpu/command_buffer/client/gl_in_process_context.cc638
-rw-r--r--gpu/command_buffer/client/gl_in_process_context.h77
-rw-r--r--gpu/gpu.gyp4
-rw-r--r--webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc860
-rw-r--r--webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h23
-rw-r--r--webkit/common/gpu/webkit_gpu.gyp2
10 files changed, 763 insertions, 854 deletions
diff --git a/android_webview/DEPS b/android_webview/DEPS
index 02d8ca9..5f848d2 100644
--- a/android_webview/DEPS
+++ b/android_webview/DEPS
@@ -7,8 +7,8 @@ include_rules = [
# lib is the top-level target, and must remain a leaf in the dependency tree.
"-android_webview/lib",
- "!chrome/browser/component",
"+content/public/common",
+ "+gpu/command_buffer/client",
"+jni",
"+net",
"+skia",
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS
index c535f31..891ec4f 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -18,8 +18,6 @@ include_rules = [
"+content/public/browser",
"+content/public/test",
- "+gpu/command_buffer/client",
-
"+ui/gfx",
"+ui/gl",
diff --git a/android_webview/browser/gpu_memory_buffer_impl.cc b/android_webview/browser/gpu_memory_buffer_impl.cc
index 9ee37738..7a2e864 100644
--- a/android_webview/browser/gpu_memory_buffer_impl.cc
+++ b/android_webview/browser/gpu_memory_buffer_impl.cc
@@ -7,9 +7,9 @@
#include "android_webview/public/browser/draw_gl.h"
#include "base/bind.h"
#include "base/logging.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "gpu/command_buffer/client/gpu_memory_buffer.h"
#include "ui/gfx/size.h"
-#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace android_webview {
@@ -93,8 +93,7 @@ scoped_ptr<gpu::GpuMemoryBuffer> GpuMemoryBufferImpl::CreateGpuMemoryBuffer(
void GpuMemoryBufferImpl::SetAwDrawGLFunctionTable(
AwDrawGLFunctionTable* table) {
g_gl_draw_functions = table;
- ::webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
- SetGpuMemoryBufferCreator(&CreateGpuMemoryBuffer);
+ gpu::GLInProcessContext::SetGpuMemoryBufferCreator(&CreateGpuMemoryBuffer);
}
} // namespace android_webview
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index 210131c..476f705 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -20,6 +20,7 @@
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace android_webview {
@@ -42,8 +43,7 @@ AwMainDelegate::~AwMainDelegate() {
bool AwMainDelegate::BasicStartupComplete(int* exit_code) {
content::SetContentClient(&content_client_);
- webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl
- ::EnableVirtualizedContext();
+ gpu::GLInProcessContext::EnableVirtualizedContext();
CommandLine* cl = CommandLine::ForCurrentProcess();
cl->AppendSwitch(switches::kEnableBeginFrameScheduling);
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc
new file mode 100644
index 0000000..7e17929
--- /dev/null
+++ b/gpu/command_buffer/client/gl_in_process_context.cc
@@ -0,0 +1,638 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/gl_in_process_context.h"
+
+#include <utility>
+#include <vector>
+
+#include <GLES2/gl2.h>
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES 1
+#endif
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+#include "base/synchronization/lock.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer.h"
+#include "gpu/command_buffer/client/image_factory.h"
+#include "gpu/command_buffer/client/transfer_buffer.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/service/gl_context_virtual.h"
+#include "gpu/command_buffer/service/gpu_scheduler.h"
+#include "gpu/command_buffer/service/image_manager.h"
+#include "gpu/command_buffer/service/transfer_buffer_manager.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_share_group.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gpu {
+
+using gles2::ImageManager;
+
+namespace {
+
+const int32 kCommandBufferSize = 1024 * 1024;
+// TODO(kbr): make the transfer buffer size configurable via context
+// creation attributes.
+const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
+const size_t kMinTransferBufferSize = 1 * 256 * 1024;
+const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
+
+// In the normal command buffer implementation, all commands are passed over IPC
+// to the gpu process where they are fed to the GLES2Decoder from a single
+// thread. In layout tests, any thread could call this function. GLES2Decoder,
+// and in particular the GL implementations behind it, are not generally
+// threadsafe, so we guard entry points with a mutex.
+static base::LazyInstance<base::Lock> g_decoder_lock =
+ LAZY_INSTANCE_INITIALIZER;
+
+class GLInProcessContextImpl;
+class ImageFactoryInProcess;
+
+static base::LazyInstance<
+ std::set<GLInProcessContextImpl*> >
+ g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
+
+static bool g_use_virtualized_gl_context = false;
+
+static GLInProcessContext::GpuMemoryBufferCreator* g_gpu_memory_buffer_creator =
+ NULL;
+
+// Also calls DetachFromThreadHack on all GLES2Decoders before the lock is
+// released to maintain the invariant that all decoders are unbound while the
+// lock is not held. This is to workaround DumpRenderTree using WGC3DIPCBI with
+// shared resources on different threads.
+// Remove this as part of crbug.com/234964.
+class AutoLockAndDecoderDetachThread {
+ public:
+ AutoLockAndDecoderDetachThread(
+ base::Lock& lock,
+ const std::set<GLInProcessContextImpl*>& contexts);
+ ~AutoLockAndDecoderDetachThread();
+
+ private:
+ base::AutoLock auto_lock_;
+ const std::set<GLInProcessContextImpl*>& contexts_;
+};
+
+class GLInProcessContextImpl
+ : public GLInProcessContext,
+ public base::SupportsWeakPtr<GLInProcessContextImpl> {
+ public:
+ explicit GLInProcessContextImpl(bool share_resources);
+ virtual ~GLInProcessContextImpl();
+
+ bool Initialize(bool is_offscreen,
+ gfx::AcceleratedWidget window,
+ const gfx::Size& size,
+ const char* allowed_extensions,
+ const int32* attrib_list,
+ gfx::GpuPreference gpu_preference,
+ const base::Closure& context_lost_callback);
+
+ // GLInProcessContext implementation:
+ virtual void SignalSyncPoint(unsigned sync_point,
+ const base::Closure& callback) OVERRIDE;
+ virtual void SignalQuery(unsigned query, const base::Closure& callback)
+ OVERRIDE;
+ virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE;
+
+ // Other methods:
+ gles2::GLES2Decoder* GetDecoder();
+ bool GetBufferChanged(int32 transfer_buffer_id);
+ void PumpCommands();
+ void OnResizeView(gfx::Size size, float scale_factor);
+ void OnContextLost();
+
+ private:
+ void Destroy();
+ bool IsCommandBufferContextLost();
+ void PollQueryCallbacks();
+ void CallQueryCallback(size_t index);
+
+ gles2::ImageManager* GetImageManager();
+
+ base::Closure context_lost_callback_;
+ scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
+ scoped_ptr<CommandBuffer> command_buffer_;
+ scoped_ptr<GpuScheduler> gpu_scheduler_;
+ scoped_ptr<gles2::GLES2Decoder> decoder_;
+ scoped_refptr<gfx::GLContext> context_;
+ scoped_refptr<gfx::GLSurface> surface_;
+ scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_;
+ scoped_ptr<TransferBuffer> transfer_buffer_;
+ scoped_ptr<gles2::GLES2Implementation> gles2_implementation_;
+ scoped_refptr<ImageFactoryInProcess> image_factory_;
+ base::Closure signal_sync_point_callback_;
+ bool share_resources_;
+ bool context_lost_;
+
+ typedef std::pair<unsigned, base::Closure> QueryCallback;
+ std::vector<QueryCallback> query_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl);
+};
+
+AutoLockAndDecoderDetachThread::AutoLockAndDecoderDetachThread(
+ base::Lock& lock,
+ const std::set<GLInProcessContextImpl*>& contexts)
+ : auto_lock_(lock),
+ contexts_(contexts) {
+}
+
+void DetachThread(GLInProcessContextImpl* context) {
+ if (context->GetDecoder())
+ context->GetDecoder()->DetachFromThreadHack();
+}
+
+AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() {
+ std::for_each(contexts_.begin(),
+ contexts_.end(),
+ &DetachThread);
+}
+
+class ImageFactoryInProcess
+ : public gles2::ImageFactory,
+ public base::RefCountedThreadSafe<ImageFactoryInProcess> {
+ public:
+ explicit ImageFactoryInProcess(ImageManager* image_manager);
+
+ // methods from ImageFactory
+ virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
+ int width, int height, GLenum internalformat,
+ unsigned* image_id) OVERRIDE;
+ virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE;
+ private:
+ friend class base::RefCountedThreadSafe<ImageFactoryInProcess>;
+ virtual ~ImageFactoryInProcess();
+
+ // ImageManager is referred by the ContextGroup and the
+ // ContextGroup outlives the client.
+ ImageManager* image_manager_;
+ unsigned next_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageFactoryInProcess);
+};
+
+ImageFactoryInProcess::ImageFactoryInProcess(
+ ImageManager* image_manager) : image_manager_(image_manager),
+ next_id_(0) {
+}
+
+ImageFactoryInProcess::~ImageFactoryInProcess() {
+}
+
+scoped_ptr<GpuMemoryBuffer> ImageFactoryInProcess::CreateGpuMemoryBuffer(
+ int width, int height, GLenum internalformat, unsigned int* image_id) {
+ // We're taking the lock here because we're accessing the ContextGroup's
+ // shared ImageManager and next_id_.
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ // For Android WebView we assume the |internalformat| will always be
+ // GL_RGBA8_OES.
+ DCHECK_EQ(static_cast<GLenum>(GL_RGBA8_OES), internalformat);
+ scoped_ptr<GpuMemoryBuffer> buffer =
+ g_gpu_memory_buffer_creator(width, height);
+
+ if (buffer.get() == NULL)
+ return buffer.Pass();
+
+ scoped_refptr<gfx::GLImage> gl_image =
+ gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(),
+ gfx::Size(width, height));
+ *image_id = ++next_id_; // Valid image_ids start from 1.
+ image_manager_->AddImage(gl_image.get(), *image_id);
+ return buffer.Pass();
+}
+
+void ImageFactoryInProcess::DeleteGpuMemoryBuffer(unsigned int image_id) {
+ // We're taking the lock here because we're accessing the ContextGroup's
+ // shared ImageManager.
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ image_manager_->RemoveImage(image_id);
+}
+
+GLInProcessContextImpl::GLInProcessContextImpl(bool share_resources)
+ : share_resources_(share_resources),
+ context_lost_(false) {
+}
+
+GLInProcessContextImpl::~GLInProcessContextImpl() {
+ Destroy();
+}
+
+void GLInProcessContextImpl::PumpCommands() {
+ if (!context_lost_) {
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ decoder_->MakeCurrent();
+ gpu_scheduler_->PutChanged();
+ CommandBuffer::State state = command_buffer_->GetState();
+ if (error::IsError(state.error))
+ context_lost_ = true;
+ }
+
+ if (!context_lost_ && !signal_sync_point_callback_.is_null()) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, signal_sync_point_callback_);
+ signal_sync_point_callback_.Reset();
+ }
+}
+
+bool GLInProcessContextImpl::GetBufferChanged(int32 transfer_buffer_id) {
+ return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
+}
+
+void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point,
+ const base::Closure& callback) {
+ signal_sync_point_callback_ = callback;
+}
+
+bool GLInProcessContextImpl::IsCommandBufferContextLost() {
+ if (context_lost_ || !command_buffer_) {
+ return true;
+ }
+ CommandBuffer::State state = command_buffer_->GetState();
+ return error::IsError(state.error);
+}
+
+gles2::GLES2Decoder* GLInProcessContextImpl::GetDecoder() {
+ return decoder_.get();
+}
+
+void GLInProcessContextImpl::OnResizeView(gfx::Size size, float scale_factor) {
+ DCHECK(!surface_->IsOffscreen());
+ surface_->Resize(size);
+}
+
+gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() {
+ return gles2_implementation_.get();
+}
+
+gles2::ImageManager* GLInProcessContextImpl::GetImageManager() {
+ return decoder_->GetContextGroup()->image_manager();
+}
+
+bool GLInProcessContextImpl::Initialize(
+ bool is_offscreen,
+ gfx::AcceleratedWidget window,
+ const gfx::Size& size,
+ const char* allowed_extensions,
+ const int32* attrib_list,
+ gfx::GpuPreference gpu_preference,
+ const base::Closure& context_lost_callback) {
+ // Use one share group for all contexts.
+ CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
+ (new gfx::GLShareGroup));
+
+ DCHECK(size.width() >= 0 && size.height() >= 0);
+
+ std::vector<int32> attribs;
+ while (attrib_list) {
+ int32 attrib = *attrib_list++;
+ switch (attrib) {
+ // Known attributes
+ case ALPHA_SIZE:
+ case BLUE_SIZE:
+ case GREEN_SIZE:
+ case RED_SIZE:
+ case DEPTH_SIZE:
+ case STENCIL_SIZE:
+ case SAMPLES:
+ case SAMPLE_BUFFERS:
+ attribs.push_back(attrib);
+ attribs.push_back(*attrib_list++);
+ break;
+ case NONE:
+ attribs.push_back(attrib);
+ attrib_list = NULL;
+ break;
+ default:
+ attribs.push_back(NONE);
+ attrib_list = NULL;
+ break;
+ }
+ }
+
+ {
+ TransferBufferManager* manager = new TransferBufferManager();
+ transfer_buffer_manager_.reset(manager);
+ manager->Initialize();
+ }
+
+ scoped_ptr<CommandBufferService> command_buffer(
+ new CommandBufferService(transfer_buffer_manager_.get()));
+ command_buffer->SetPutOffsetChangeCallback(base::Bind(
+ &GLInProcessContextImpl::PumpCommands, base::Unretained(this)));
+ command_buffer->SetGetBufferChangeCallback(base::Bind(
+ &GLInProcessContextImpl::GetBufferChanged, base::Unretained(this)));
+ command_buffer->SetParseErrorCallback(base::Bind(
+ &GLInProcessContextImpl::OnContextLost, base::Unretained(this)));
+
+ command_buffer_ = command_buffer.Pass();
+ if (!command_buffer_->Initialize()) {
+ LOG(ERROR) << "Could not initialize command buffer.";
+ Destroy();
+ return false;
+ }
+
+ GLInProcessContextImpl* context_group = NULL;
+
+ {
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ if (share_resources_ && !g_all_shared_contexts.Get().empty()) {
+ for (std::set<GLInProcessContextImpl*>::iterator it =
+ g_all_shared_contexts.Get().begin();
+ it != g_all_shared_contexts.Get().end();
+ ++it) {
+ if (!(*it)->IsCommandBufferContextLost()) {
+ context_group = *it;
+ break;
+ }
+ }
+ if (!context_group)
+ share_group = new gfx::GLShareGroup;
+ }
+
+ // TODO(gman): This needs to be true if this is Pepper.
+ bool bind_generates_resource = false;
+ decoder_.reset(gles2::GLES2Decoder::Create(
+ context_group ? context_group->decoder_->GetContextGroup()
+ : new gles2::ContextGroup(
+ NULL, NULL, NULL, bind_generates_resource)));
+
+ gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
+ decoder_.get(),
+ decoder_.get()));
+
+ decoder_->set_engine(gpu_scheduler_.get());
+
+ if (is_offscreen)
+ surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
+ else
+ surface_ = gfx::GLSurface::CreateViewGLSurface(window);
+
+ if (!surface_.get()) {
+ LOG(ERROR) << "Could not create GLSurface.";
+ Destroy();
+ return false;
+ }
+
+ if (g_use_virtualized_gl_context) {
+ context_ = share_group->GetSharedContext();
+ if (!context_.get()) {
+ context_ = gfx::GLContext::CreateGLContext(
+ share_group.get(), surface_.get(), gpu_preference);
+ share_group->SetSharedContext(context_.get());
+ }
+
+ context_ = new GLContextVirtual(
+ share_group.get(), context_.get(), decoder_->AsWeakPtr());
+ if (context_->Initialize(surface_.get(), gpu_preference)) {
+ VLOG(1) << "Created virtual GL context.";
+ } else {
+ context_ = NULL;
+ }
+ } else {
+ context_ = gfx::GLContext::CreateGLContext(share_group.get(),
+ surface_.get(),
+ gpu_preference);
+ }
+
+ if (!context_.get()) {
+ LOG(ERROR) << "Could not create GLContext.";
+ Destroy();
+ return false;
+ }
+
+ if (!context_->MakeCurrent(surface_.get())) {
+ LOG(ERROR) << "Could not make context current.";
+ Destroy();
+ return false;
+ }
+
+ gles2::DisallowedFeatures disallowed_features;
+ disallowed_features.swap_buffer_complete_callback = true;
+ disallowed_features.gpu_memory_manager = true;
+ if (!decoder_->Initialize(surface_,
+ context_,
+ is_offscreen,
+ size,
+ disallowed_features,
+ allowed_extensions,
+ attribs)) {
+ LOG(ERROR) << "Could not initialize decoder.";
+ Destroy();
+ return false;
+ }
+
+ if (!is_offscreen) {
+ decoder_->SetResizeCallback(base::Bind(
+ &GLInProcessContextImpl::OnResizeView, base::Unretained(this)));
+ }
+ }
+
+ // Create the GLES2 helper, which writes the command buffer protocol.
+ gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
+ if (!gles2_helper_->Initialize(kCommandBufferSize)) {
+ Destroy();
+ return false;
+ }
+
+ // Create a transfer buffer.
+ transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
+
+ if (share_resources_) {
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ if (g_all_shared_contexts.Get().empty()) {
+ // Create the image factory for the first context.
+ image_factory_ = new ImageFactoryInProcess(GetImageManager());
+ } else {
+ // Share the image factory created by the first context.
+ GLInProcessContextImpl* first_context =
+ *g_all_shared_contexts.Get().begin();
+ image_factory_ = first_context->image_factory_;
+ }
+ } else {
+ // Create the image factory, this object retains its ownership.
+ image_factory_ = new ImageFactoryInProcess(GetImageManager());
+ }
+
+ // Create the object exposing the OpenGL API.
+ gles2_implementation_.reset(new gles2::GLES2Implementation(
+ gles2_helper_.get(),
+ context_group ? context_group->GetImplementation()->share_group() : NULL,
+ transfer_buffer_.get(),
+ true,
+ false,
+ image_factory_.get()));
+
+ if (!gles2_implementation_->Initialize(
+ kStartTransferBufferSize,
+ kMinTransferBufferSize,
+ kMaxTransferBufferSize)) {
+ return false;
+ }
+
+ if (share_resources_) {
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ g_all_shared_contexts.Pointer()->insert(this);
+ }
+
+ context_lost_callback_ = context_lost_callback;
+ return true;
+}
+
+void GLInProcessContextImpl::Destroy() {
+ while (!query_callbacks_.empty()) {
+ CallQueryCallback(0);
+ }
+
+ bool context_lost = IsCommandBufferContextLost();
+
+ 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();
+
+ gles2_implementation_.reset();
+ }
+
+ transfer_buffer_.reset();
+ gles2_helper_.reset();
+ command_buffer_.reset();
+
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ if (decoder_) {
+ decoder_->Destroy(!context_lost);
+ }
+
+ g_all_shared_contexts.Pointer()->erase(this);
+}
+
+void GLInProcessContextImpl::OnContextLost() {
+ if (!context_lost_callback_.is_null())
+ context_lost_callback_.Run();
+
+ context_lost_ = true;
+ if (share_resources_) {
+ for (std::set<GLInProcessContextImpl*>::iterator it =
+ g_all_shared_contexts.Get().begin();
+ it != g_all_shared_contexts.Get().end();
+ ++it)
+ (*it)->context_lost_ = true;
+ }
+}
+
+void GLInProcessContextImpl::CallQueryCallback(size_t index) {
+ DCHECK_LT(index, query_callbacks_.size());
+ QueryCallback query_callback = query_callbacks_[index];
+ query_callbacks_[index] = query_callbacks_.back();
+ query_callbacks_.pop_back();
+ query_callback.second.Run();
+}
+
+void GLInProcessContextImpl::PollQueryCallbacks() {
+ for (size_t i = 0; i < query_callbacks_.size();) {
+ unsigned query = query_callbacks_[i].first;
+ GLuint param = 0;
+ gles2::GLES2Implementation* gl = GetImplementation();
+ if (gl->IsQueryEXT(query)) {
+ gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param);
+ } else {
+ param = 1;
+ }
+ if (param) {
+ CallQueryCallback(i);
+ } else {
+ i++;
+ }
+ }
+ if (!query_callbacks_.empty()) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&GLInProcessContextImpl::PollQueryCallbacks,
+ this->AsWeakPtr()),
+ base::TimeDelta::FromMilliseconds(5));
+ }
+}
+
+void GLInProcessContextImpl::SignalQuery(
+ unsigned query,
+ const base::Closure& callback) {
+ query_callbacks_.push_back(std::make_pair(query, callback));
+ // If size > 1, there is already a poll callback pending.
+ if (query_callbacks_.size() == 1) {
+ PollQueryCallbacks();
+ }
+}
+
+} // anonymous namespace
+
+// static
+GLInProcessContext* GLInProcessContext::CreateContext(
+ bool is_offscreen,
+ gfx::AcceleratedWidget window,
+ const gfx::Size& size,
+ bool share_resources,
+ const char* allowed_extensions,
+ const int32* attrib_list,
+ gfx::GpuPreference gpu_preference,
+ const base::Closure& callback) {
+ scoped_ptr<GLInProcessContextImpl> context(
+ new GLInProcessContextImpl(share_resources));
+ if (!context->Initialize(
+ is_offscreen,
+ window,
+ size,
+ allowed_extensions,
+ attrib_list,
+ gpu_preference,
+ callback))
+ return NULL;
+
+ return context.release();
+}
+
+// static
+void GLInProcessContext::SetGpuMemoryBufferCreator(
+ GpuMemoryBufferCreator* creator) {
+ g_gpu_memory_buffer_creator = creator;
+}
+
+// static
+void GLInProcessContext::EnableVirtualizedContext() {
+#if !defined(NDEBUG)
+ {
+ AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
+ g_all_shared_contexts.Get());
+ DCHECK(g_all_shared_contexts.Get().empty());
+ }
+#endif // !defined(NDEBUG)
+ g_use_virtualized_gl_context = true;
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/client/gl_in_process_context.h b/gpu/command_buffer/client/gl_in_process_context.h
new file mode 100644
index 0000000..c4fb70f
--- /dev/null
+++ b/gpu/command_buffer/client/gl_in_process_context.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_GL_IN_PROCESS_CONTEXT_H_
+#define GPU_COMMAND_BUFFER_CLIENT_GL_IN_PROCESS_CONTEXT_H_
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "gles2_impl_export.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gpu_preference.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace gpu {
+
+namespace gles2 {
+class GLES2Implementation;
+}
+
+class GpuMemoryBuffer;
+
+class GLES2_IMPL_EXPORT GLInProcessContext {
+ public:
+ virtual ~GLInProcessContext() {}
+
+ typedef scoped_ptr< ::gpu::GpuMemoryBuffer> GpuMemoryBufferCreator(
+ int width, int height);
+ static void SetGpuMemoryBufferCreator(GpuMemoryBufferCreator* creator);
+
+ // Must be called before any GLInProcessContext instances are created.
+ // Default value is false.
+ static void EnableVirtualizedContext();
+
+ // GLInProcessContext configuration attributes. These are the same as used by
+ // EGL. Attributes are matched using a closest fit algorithm.
+ enum Attribute {
+ ALPHA_SIZE = 0x3021,
+ BLUE_SIZE = 0x3022,
+ GREEN_SIZE = 0x3023,
+ RED_SIZE = 0x3024,
+ DEPTH_SIZE = 0x3025,
+ STENCIL_SIZE = 0x3026,
+ SAMPLES = 0x3031,
+ SAMPLE_BUFFERS = 0x3032,
+ NONE = 0x3038 // Attrib list = terminator
+ };
+
+ // Create a GLInProcessContext, if |is_offscreen| is true, renders to an
+ // offscreen context. |attrib_list| must be NULL or a NONE-terminated list
+ // of attribute/value pairs.
+ static GLInProcessContext* CreateContext(
+ bool is_offscreen,
+ gfx::AcceleratedWidget window,
+ const gfx::Size& size,
+ bool share_resources,
+ const char* allowed_extensions,
+ const int32* attrib_list,
+ gfx::GpuPreference gpu_preference,
+ const base::Closure& callback);
+
+ virtual void SignalSyncPoint(unsigned sync_point,
+ const base::Closure& callback) = 0;
+
+ virtual void SignalQuery(unsigned query, const base::Closure& callback) = 0;
+
+ // Allows direct access to the GLES2 implementation so a GLInProcessContext
+ // can be used without making it current.
+ virtual gles2::GLES2Implementation* GetImplementation() = 0;
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_CLIENT_GL_IN_PROCESS_CONTEXT_H_
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 687e02a..35e771e 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -16,8 +16,10 @@
'type': '<(component)',
'dependencies': [
'../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../third_party/khronos/khronos.gyp:khronos_headers',
'../ui/gl/gl.gyp:gl',
+ '../ui/ui.gyp:ui',
'command_buffer/command_buffer.gyp:gles2_utils',
'gles2_cmd_helper',
],
@@ -26,6 +28,8 @@
],
'sources': [
'<@(gles2_implementation_source_files)',
+ 'command_buffer/client/gl_in_process_context.h',
+ 'command_buffer/client/gl_in_process_context.cc',
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [4267, ],
diff --git a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
index 8d9798f..203ffac 100644
--- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
+++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -11,208 +11,25 @@
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>
-#include <algorithm>
-#include <set>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
-#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "base/synchronization/lock.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_lib.h"
-#include "gpu/command_buffer/client/image_factory.h"
-#include "gpu/command_buffer/client/transfer_buffer.h"
-#include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/service/command_buffer_service.h"
-#include "gpu/command_buffer/service/context_group.h"
-#include "gpu/command_buffer/service/gl_context_virtual.h"
-#include "gpu/command_buffer/service/gpu_scheduler.h"
-#include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_image.h"
-#include "ui/gl/gl_share_group.h"
+#include "ui/gfx/size.h"
#include "ui/gl/gl_surface.h"
#include "webkit/common/gpu/gl_bindings_skia_cmd_buffer.h"
-using gpu::Buffer;
-using gpu::CommandBuffer;
-using gpu::CommandBufferService;
-using gpu::gles2::GLES2CmdHelper;
using gpu::gles2::GLES2Implementation;
-using gpu::gles2::ImageFactory;
-using gpu::gles2::ImageManager;
-using gpu::GpuMemoryBuffer;
-using gpu::GpuScheduler;
-using gpu::TransferBuffer;
-using gpu::TransferBufferManager;
-using gpu::TransferBufferManagerInterface;
-
-namespace {
-typedef WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback
- WebGraphicsSyncPointCallback;
-}
+using gpu::GLInProcessContext;
namespace webkit {
namespace gpu {
-namespace {
-class ImageFactoryInProcess;
-}
-
-class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> {
- public:
- // These are the same error codes as used by EGL.
- enum Error {
- SUCCESS = 0x3000,
- NOT_INITIALIZED = 0x3001,
- BAD_ATTRIBUTE = 0x3004,
- BAD_GLContext = 0x3006,
- CONTEXT_LOST = 0x300E
- };
-
- // GLInProcessContext configuration attributes. These are the same as used by
- // EGL. Attributes are matched using a closest fit algorithm.
- enum Attribute {
- ALPHA_SIZE = 0x3021,
- BLUE_SIZE = 0x3022,
- GREEN_SIZE = 0x3023,
- RED_SIZE = 0x3024,
- DEPTH_SIZE = 0x3025,
- STENCIL_SIZE = 0x3026,
- SAMPLES = 0x3031,
- SAMPLE_BUFFERS = 0x3032,
- NONE = 0x3038 // Attrib list = terminator
- };
-
- // Initialize the library. This must have completed before any other
- // functions are invoked.
- static bool Initialize();
-
- // Terminate the library. This must be called after any other functions
- // have completed.
- static bool Terminate();
-
- ~GLInProcessContext();
-
- void PumpCommands();
- bool GetBufferChanged(int32 transfer_buffer_id);
-
- // Create a GLInProcessContext, if |is_offscreen| is true, renders to an
- // offscreen context. |attrib_list| must be NULL or a NONE-terminated list
- // of attribute/value pairs.
- static GLInProcessContext* CreateContext(
- bool is_offscreen,
- gfx::AcceleratedWidget window,
- const gfx::Size& size,
- bool share_resources,
- const char* allowed_extensions,
- const int32* attrib_list,
- gfx::GpuPreference gpu_preference);
-
- // Create a new texture in the parent's GLInProcessContext. Returns zero if
- // GLInProcessContext does not have a parent.
- uint32 CreateParentTexture(const gfx::Size& size);
-
- // Deletes a texture in the parent's GLInProcessContext.
- void DeleteParentTexture(uint32 texture);
-
- void SetContextLostCallback(const base::Closure& callback);
-
- // Set the current GLInProcessContext for the calling thread.
- static bool MakeCurrent(GLInProcessContext* context);
-
- // For a view GLInProcessContext, display everything that has been rendered
- // since the last call. For an offscreen GLInProcessContext, resolve
- // everything that has been rendered since the last call to a copy that can be
- // accessed by the parent GLInProcessContext.
- bool SwapBuffers();
-
- // TODO(gman): Remove this
- void DisableShaderTranslation();
-
- // Allows direct access to the GLES2 implementation so a GLInProcessContext
- // can be used without making it current.
- GLES2Implementation* GetImplementation();
-
- // Return the current error.
- Error GetError();
-
- // Return true if GPU process reported GLInProcessContext lost or there was a
- // problem communicating with the GPU process.
- bool IsCommandBufferContextLost();
-
- void LoseContext(uint32 current, uint32 other);
-
- void SetSignalSyncPointCallback(
- scoped_ptr<WebGraphicsSyncPointCallback> callback);
-
- CommandBufferService* GetCommandBufferService();
-
- ::gpu::gles2::GLES2Decoder* GetDecoder();
-
- void OnResizeView(gfx::Size size, float scale_factor);
-
- void signalQuery(unsigned query, WebGraphicsSyncPointCallback* callback);
-
- private:
- explicit GLInProcessContext(bool share_resources);
-
- bool Initialize(bool is_offscreen,
- gfx::AcceleratedWidget window,
- const gfx::Size& size,
- const char* allowed_extensions,
- const int32* attrib_list,
- gfx::GpuPreference gpu_preference);
- void Destroy();
-
- void OnContextLost();
-
- ::gpu::gles2::ImageManager* GetImageManager();
-
- scoped_refptr<ImageFactoryInProcess> GetImageFactory();
-
- void PollQueryCallbacks();
- void CallQueryCallback(size_t index);
-
-
- base::Closure context_lost_callback_;
- scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
- scoped_ptr<CommandBufferService> command_buffer_;
- scoped_ptr< ::gpu::GpuScheduler> gpu_scheduler_;
- scoped_ptr< ::gpu::gles2::GLES2Decoder> decoder_;
- scoped_refptr<gfx::GLContext> context_;
- scoped_refptr<gfx::GLSurface> surface_;
- scoped_ptr<GLES2CmdHelper> gles2_helper_;
- scoped_ptr<TransferBuffer> transfer_buffer_;
- scoped_ptr<GLES2Implementation> gles2_implementation_;
- scoped_refptr<ImageFactoryInProcess> image_factory_;
- scoped_ptr<WebGraphicsSyncPointCallback> signal_sync_point_callback_;
- Error last_error_;
- bool share_resources_;
- bool context_lost_;
-
- struct QueryCallback {
- QueryCallback(unsigned query_,
- WebGraphicsSyncPointCallback* callback_)
- : query(query_),
- callback(callback_) {
- }
- unsigned query;
- linked_ptr<WebGraphicsSyncPointCallback> callback;
- };
-
- std::vector<QueryCallback> query_callbacks_;
-
- DISALLOW_COPY_AND_ASSIGN(GLInProcessContext);
-};
namespace {
@@ -223,583 +40,31 @@ const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
const size_t kMinTransferBufferSize = 1 * 256 * 1024;
const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
+void OnSignalSyncPoint(
+ WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback* callback) {
+ callback->onSyncPointReached();
+}
+
// Singleton used to initialize and terminate the gles2 library.
class GLES2Initializer {
public:
GLES2Initializer() {
- gles2::Initialize();
+ ::gles2::Initialize();
}
~GLES2Initializer() {
- gles2::Terminate();
+ ::gles2::Terminate();
}
private:
DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
};
-////////////////////////////////////////////////////////////////////////////////
-
static base::LazyInstance<GLES2Initializer> g_gles2_initializer =
LAZY_INSTANCE_INITIALIZER;
} // namespace anonymous
-GLInProcessContext::~GLInProcessContext() {
- Destroy();
-}
-
-GLInProcessContext* GLInProcessContext::CreateContext(
- bool is_offscreen,
- gfx::AcceleratedWidget window,
- const gfx::Size& size,
- bool share_resources,
- const char* allowed_extensions,
- const int32* attrib_list,
- gfx::GpuPreference gpu_preference) {
- scoped_ptr<GLInProcessContext> context(
- new GLInProcessContext(share_resources));
- if (!context->Initialize(
- is_offscreen,
- window,
- size,
- allowed_extensions,
- attrib_list,
- gpu_preference))
- return NULL;
-
- return context.release();
-}
-
-// In the normal command buffer implementation, all commands are passed over IPC
-// to the gpu process where they are fed to the GLES2Decoder from a single
-// thread. In layout tests, any thread could call this function. GLES2Decoder,
-// and in particular the GL implementations behind it, are not generally
-// threadsafe, so we guard entry points with a mutex.
-static base::LazyInstance<base::Lock> g_decoder_lock =
- LAZY_INSTANCE_INITIALIZER;
-
-static base::LazyInstance<
- std::set<GLInProcessContext*> >
- g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
-
-static bool g_use_virtualized_gl_context = false;
-
-namespace {
-
-// Also calls DetachFromThreadHack on all GLES2Decoders before the lock is
-// released to maintain the invariant that all decoders are unbound while the
-// lock is not held. This is to workaround DumpRenderTree using WGC3DIPCBI with
-// shared resources on different threads.
-// Remove this as part of crbug.com/234964.
-class AutoLockAndDecoderDetachThread {
- public:
- AutoLockAndDecoderDetachThread(base::Lock& lock,
- const std::set<GLInProcessContext*>& contexts);
- ~AutoLockAndDecoderDetachThread();
-
- private:
- base::AutoLock auto_lock_;
- const std::set<GLInProcessContext*>& contexts_;
-};
-
-AutoLockAndDecoderDetachThread::AutoLockAndDecoderDetachThread(
- base::Lock& lock,
- const std::set<GLInProcessContext*>& contexts)
- : auto_lock_(lock),
- contexts_(contexts) {
-}
-
-void DetachThread(GLInProcessContext* context) {
- if (context->GetDecoder())
- context->GetDecoder()->DetachFromThreadHack();
-}
-
-AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() {
- std::for_each(contexts_.begin(),
- contexts_.end(),
- &DetachThread);
-}
-
-static WebGraphicsContext3DInProcessCommandBufferImpl::GpuMemoryBufferCreator*
- g_gpu_memory_buffer_creator = NULL;
-
-class ImageFactoryInProcess
- : public ImageFactory,
- public base::RefCountedThreadSafe<ImageFactoryInProcess> {
- public:
- explicit ImageFactoryInProcess(ImageManager* image_manager);
-
- // methods from ImageFactory
- virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
- int width, int height, GLenum internalformat,
- unsigned* image_id) OVERRIDE;
- virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE;
- private:
- friend class base::RefCountedThreadSafe<ImageFactoryInProcess>;
- virtual ~ImageFactoryInProcess();
-
- // ImageManager is referred by the ContextGroup and the
- // ContextGroup outlives the client.
- ImageManager* image_manager_;
- unsigned next_id_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageFactoryInProcess);
-};
-
-ImageFactoryInProcess::ImageFactoryInProcess(
- ImageManager* image_manager) : image_manager_(image_manager),
- next_id_(0) {
-}
-
-ImageFactoryInProcess::~ImageFactoryInProcess() {
-}
-
-scoped_ptr<GpuMemoryBuffer> ImageFactoryInProcess::CreateGpuMemoryBuffer(
- int width, int height, GLenum internalformat, unsigned int* image_id) {
- // We're taking the lock here because we're accessing the ContextGroup's
- // shared ImageManager and next_id_.
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- // For Android WebView we assume the |internalformat| will always be
- // GL_RGBA8_OES.
- DCHECK_EQ(GL_RGBA8_OES, internalformat);
- scoped_ptr<GpuMemoryBuffer> buffer =
- g_gpu_memory_buffer_creator(width, height);
-
- if (buffer.get() == NULL)
- return buffer.Pass();
-
- scoped_refptr<gfx::GLImage> gl_image =
- gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(),
- gfx::Size(width, height));
- *image_id = ++next_id_; // Valid image_ids start from 1.
- image_manager_->AddImage(gl_image.get(), *image_id);
- return buffer.Pass();
-}
-
-void ImageFactoryInProcess::DeleteGpuMemoryBuffer(unsigned int image_id) {
- // We're taking the lock here because we're accessing the ContextGroup's
- // shared ImageManager.
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- image_manager_->RemoveImage(image_id);
-}
-
-} // namespace
-
-static void CallAndDestroy(scoped_ptr<WebGraphicsSyncPointCallback> callback) {
- callback->onSyncPointReached();
-}
-
-void GLInProcessContext::PumpCommands() {
- if (!context_lost_) {
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- decoder_->MakeCurrent();
- gpu_scheduler_->PutChanged();
- ::gpu::CommandBuffer::State state = command_buffer_->GetState();
- if (::gpu::error::IsError(state.error))
- context_lost_ = true;
- }
-
- if (!context_lost_ && signal_sync_point_callback_) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&CallAndDestroy,
- base::Passed(&signal_sync_point_callback_)));
- }
-}
-
-bool GLInProcessContext::GetBufferChanged(int32 transfer_buffer_id) {
- return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
-}
-
-uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) {
- uint32 texture = 0;
- gles2_implementation_->GenTextures(1, &texture);
- gles2_implementation_->Flush();
- return texture;
-}
-
-void GLInProcessContext::DeleteParentTexture(uint32 texture) {
- gles2_implementation_->DeleteTextures(1, &texture);
-}
-
-void GLInProcessContext::SetContextLostCallback(const base::Closure& callback) {
- context_lost_callback_ = callback;
-}
-
-bool GLInProcessContext::MakeCurrent(GLInProcessContext* context) {
- if (context) {
- gles2::SetGLContext(context->gles2_implementation_.get());
-
- // Don't request latest error status from service. Just use the locally
- // cached information from the last flush.
- // TODO(apatrick): I'm not sure if this should actually change the
- // current context if it fails. For now it gets changed even if it fails
- // because making GL calls with a NULL context crashes.
- if (context->command_buffer_->GetState().error != ::gpu::error::kNoError)
- return false;
- } else {
- gles2::SetGLContext(NULL);
- }
-
- return true;
-}
-
-bool GLInProcessContext::SwapBuffers() {
- // Don't request latest error status from service. Just use the locally cached
- // information from the last flush.
- if (command_buffer_->GetState().error != ::gpu::error::kNoError)
- return false;
-
- gles2_implementation_->SwapBuffers();
- gles2_implementation_->Finish();
- return true;
-}
-
-GLInProcessContext::Error GLInProcessContext::GetError() {
- CommandBuffer::State state = command_buffer_->GetState();
- if (state.error == ::gpu::error::kNoError) {
- // TODO(gman): Figure out and document what this logic is for.
- Error old_error = last_error_;
- last_error_ = SUCCESS;
- return old_error;
- } else {
- // All command buffer errors are unrecoverable. The error is treated as a
- // lost context: destroy the context and create another one.
- return CONTEXT_LOST;
- }
-}
-
-bool GLInProcessContext::IsCommandBufferContextLost() {
- if (context_lost_ || !command_buffer_) {
- return true;
- }
- CommandBuffer::State state = command_buffer_->GetState();
- return ::gpu::error::IsError(state.error);
-}
-
-void GLInProcessContext::LoseContext(uint32 current, uint32 other) {
- gles2_implementation_->LoseContextCHROMIUM(current, other);
- gles2_implementation_->Finish();
- DCHECK(IsCommandBufferContextLost());
-}
-
-void GLInProcessContext::SetSignalSyncPointCallback(
- scoped_ptr<WebGraphicsSyncPointCallback> callback) {
- signal_sync_point_callback_ = callback.Pass();
-}
-
-CommandBufferService* GLInProcessContext::GetCommandBufferService() {
- return command_buffer_.get();
-}
-
-::gpu::gles2::GLES2Decoder* GLInProcessContext::GetDecoder() {
- return decoder_.get();
-}
-
-void GLInProcessContext::OnResizeView(gfx::Size size, float scale_factor) {
- DCHECK(!surface_->IsOffscreen());
- surface_->Resize(size);
-}
-
-// TODO(gman): Remove This
-void GLInProcessContext::DisableShaderTranslation() {
- NOTREACHED();
-}
-
-GLES2Implementation* GLInProcessContext::GetImplementation() {
- return gles2_implementation_.get();
-}
-
-::gpu::gles2::ImageManager* GLInProcessContext::GetImageManager() {
- return decoder_->GetContextGroup()->image_manager();
-}
-
-scoped_refptr<ImageFactoryInProcess> GLInProcessContext::GetImageFactory() {
- return image_factory_;
-}
-
-GLInProcessContext::GLInProcessContext(bool share_resources)
- : last_error_(SUCCESS),
- share_resources_(share_resources),
- context_lost_(false) {
-}
-
-bool GLInProcessContext::Initialize(
- bool is_offscreen,
- gfx::AcceleratedWidget window,
- const gfx::Size& size,
- const char* allowed_extensions,
- const int32* attrib_list,
- gfx::GpuPreference gpu_preference) {
- // Use one share group for all contexts.
- CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
- (new gfx::GLShareGroup));
-
- DCHECK(size.width() >= 0 && size.height() >= 0);
-
- // Ensure the gles2 library is initialized first in a thread safe way.
- g_gles2_initializer.Get();
-
- std::vector<int32> attribs;
- while (attrib_list) {
- int32 attrib = *attrib_list++;
- switch (attrib) {
- // Known attributes
- case ALPHA_SIZE:
- case BLUE_SIZE:
- case GREEN_SIZE:
- case RED_SIZE:
- case DEPTH_SIZE:
- case STENCIL_SIZE:
- case SAMPLES:
- case SAMPLE_BUFFERS:
- attribs.push_back(attrib);
- attribs.push_back(*attrib_list++);
- break;
- case NONE:
- attribs.push_back(attrib);
- attrib_list = NULL;
- break;
- default:
- last_error_ = BAD_ATTRIBUTE;
- attribs.push_back(NONE);
- attrib_list = NULL;
- break;
- }
- }
-
- {
- TransferBufferManager* manager = new TransferBufferManager();
- transfer_buffer_manager_.reset(manager);
- manager->Initialize();
- }
-
- command_buffer_.reset(
- new CommandBufferService(transfer_buffer_manager_.get()));
- if (!command_buffer_->Initialize()) {
- LOG(ERROR) << "Could not initialize command buffer.";
- Destroy();
- return false;
- }
-
- GLInProcessContext* context_group = NULL;
-
- {
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- if (share_resources_ && !g_all_shared_contexts.Get().empty()) {
- for (std::set<GLInProcessContext*>::iterator it =
- g_all_shared_contexts.Get().begin();
- it != g_all_shared_contexts.Get().end();
- ++it) {
- if (!(*it)->IsCommandBufferContextLost()) {
- context_group = *it;
- break;
- }
- }
- if (!context_group)
- share_group = new gfx::GLShareGroup;
- }
-
- // TODO(gman): This needs to be true if this is Pepper.
- bool bind_generates_resource = false;
- decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group ?
- context_group->decoder_->GetContextGroup() :
- new ::gpu::gles2::ContextGroup(
- NULL, NULL, NULL, bind_generates_resource)));
-
- gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
- decoder_.get(),
- decoder_.get()));
-
- decoder_->set_engine(gpu_scheduler_.get());
-
- if (is_offscreen)
- surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
- else
- surface_ = gfx::GLSurface::CreateViewGLSurface(window);
-
- if (!surface_.get()) {
- LOG(ERROR) << "Could not create GLSurface.";
- Destroy();
- return false;
- }
-
- if (g_use_virtualized_gl_context) {
- context_ = share_group->GetSharedContext();
- if (!context_.get()) {
- context_ = gfx::GLContext::CreateGLContext(
- share_group.get(), surface_.get(), gpu_preference);
- share_group->SetSharedContext(context_.get());
- }
-
- context_ = new ::gpu::GLContextVirtual(
- share_group.get(), context_.get(), decoder_->AsWeakPtr());
- if (context_->Initialize(surface_.get(), gpu_preference)) {
- VLOG(1) << "Created virtual GL context.";
- } else {
- context_ = NULL;
- }
- } else {
- context_ = gfx::GLContext::CreateGLContext(share_group.get(),
- surface_.get(),
- gpu_preference);
- }
-
- if (!context_.get()) {
- LOG(ERROR) << "Could not create GLContext.";
- Destroy();
- return false;
- }
-
- if (!context_->MakeCurrent(surface_.get())) {
- LOG(ERROR) << "Could not make context current.";
- Destroy();
- return false;
- }
-
- ::gpu::gles2::DisallowedFeatures disallowed_features;
- disallowed_features.swap_buffer_complete_callback = true;
- disallowed_features.gpu_memory_manager = true;
- if (!decoder_->Initialize(surface_,
- context_,
- is_offscreen,
- size,
- disallowed_features,
- allowed_extensions,
- attribs)) {
- LOG(ERROR) << "Could not initialize decoder.";
- Destroy();
- return false;
- }
-
- if (!is_offscreen) {
- decoder_->SetResizeCallback(base::Bind(&GLInProcessContext::OnResizeView,
- base::Unretained(this)));
- }
- }
-
- command_buffer_->SetPutOffsetChangeCallback(
- base::Bind(&GLInProcessContext::PumpCommands, base::Unretained(this)));
- command_buffer_->SetGetBufferChangeCallback(
- base::Bind(
- &GLInProcessContext::GetBufferChanged, base::Unretained(this)));
- command_buffer_->SetParseErrorCallback(
- base::Bind(&GLInProcessContext::OnContextLost, base::Unretained(this)));
-
- // Create the GLES2 helper, which writes the command buffer protocol.
- gles2_helper_.reset(new GLES2CmdHelper(command_buffer_.get()));
- if (!gles2_helper_->Initialize(kCommandBufferSize)) {
- Destroy();
- return false;
- }
-
- // Create a transfer buffer.
- transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
-
- if (share_resources_) {
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- if (g_all_shared_contexts.Get().empty()) {
- // Create the image factory for the first context.
- image_factory_ = new ImageFactoryInProcess(GetImageManager());
- } else {
- // Share the image factory created by the first context.
- GLInProcessContext* first_context = *g_all_shared_contexts.Get().begin();
- image_factory_ = first_context->GetImageFactory();
- }
- } else {
- // Create the image factory, this object retains its ownership.
- image_factory_ = new ImageFactoryInProcess(GetImageManager());
- }
-
- // Create the object exposing the OpenGL API.
- gles2_implementation_.reset(new GLES2Implementation(
- gles2_helper_.get(),
- context_group ? context_group->GetImplementation()->share_group() : NULL,
- transfer_buffer_.get(),
- true,
- false,
- image_factory_.get()));
-
- if (!gles2_implementation_->Initialize(
- kStartTransferBufferSize,
- kMinTransferBufferSize,
- kMaxTransferBufferSize)) {
- return false;
- }
-
- if (share_resources_) {
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- g_all_shared_contexts.Pointer()->insert(this);
- }
-
- return true;
-}
-
-void GLInProcessContext::Destroy() {
- while (!query_callbacks_.empty()) {
- CallQueryCallback(0);
- }
-
- bool context_lost = IsCommandBufferContextLost();
-
- 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();
-
- gles2_implementation_.reset();
- }
-
- transfer_buffer_.reset();
- gles2_helper_.reset();
- command_buffer_.reset();
-
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- if (decoder_) {
- decoder_->Destroy(!context_lost);
- }
-
- g_all_shared_contexts.Pointer()->erase(this);
-}
-
-void GLInProcessContext::OnContextLost() {
- if (!context_lost_callback_.is_null())
- context_lost_callback_.Run();
-
- context_lost_ = true;
- if (share_resources_) {
- for (std::set<GLInProcessContext*>::iterator it =
- g_all_shared_contexts.Get().begin();
- it != g_all_shared_contexts.Get().end();
- ++it)
- (*it)->context_lost_ = true;
- }
-}
-
-// static
-void
-WebGraphicsContext3DInProcessCommandBufferImpl::EnableVirtualizedContext() {
-#if !defined(NDEBUG)
- {
- AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
- g_all_shared_contexts.Get());
- DCHECK(g_all_shared_contexts.Get().empty());
- }
-#endif // !defined(NDEBUG)
- g_use_virtualized_gl_context = true;
-}
-
// static
scoped_ptr<WebKit::WebGraphicsContext3D>
WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
@@ -852,6 +117,9 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
if (initialize_failed_)
return false;
+ // Ensure the gles2 library is initialized first in a thread safe way.
+ g_gles2_initializer.Get();
+
// Convert WebGL context creation attributes into GLInProcessContext / EGL
// size requests.
const int alpha_size = attributes_.alpha ? 8 : 0;
@@ -877,6 +145,10 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
// discrete GPU is created, or the last one is destroyed.
gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
+ base::Closure context_lost_callback =
+ base::Bind(&WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost,
+ base::Unretained(this));
+
context_ = GLInProcessContext::CreateContext(
is_offscreen_,
window_,
@@ -884,7 +156,8 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
attributes_.shareResources,
preferred_extensions,
attribs,
- gpu_preference);
+ gpu_preference,
+ context_lost_callback);
if (!context_) {
initialize_failed_ = true;
@@ -896,11 +169,6 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
if (gl_ && attributes_.noExtensions)
gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");
- context_->SetContextLostCallback(
- base::Bind(
- &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost,
- base::Unretained(this)));
-
// Set attributes_ from created offscreen context.
{
GLint alpha_bits = 0;
@@ -924,8 +192,8 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() {
if (!MaybeInitializeGL())
return false;
-
- return GLInProcessContext::MakeCurrent(context_);
+ ::gles2::SetGLContext(gl_);
+ return context_ && !isContextLost();
}
void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() {
@@ -951,9 +219,10 @@ int WebGraphicsContext3DInProcessCommandBufferImpl::height() {
}
void WebGraphicsContext3DInProcessCommandBufferImpl::prepareTexture() {
- // Copies the contents of the off-screen render target into the texture
- // used by the compositor.
- context_->SwapBuffers();
+ if (!isContextLost()) {
+ gl_->SwapBuffers();
+ gl_->Finish();
+ }
}
void WebGraphicsContext3DInProcessCommandBufferImpl::postSubBufferCHROMIUM(
@@ -977,20 +246,6 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::reshapeWithScaleFactor(
gl_->ResizeCHROMIUM(width, height, scale_factor);
}
-WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createCompositorTexture(
- WGC3Dsizei width, WGC3Dsizei height) {
- // TODO(gmam): See if we can comment this in.
- // ClearContext();
- return context_->CreateParentTexture(gfx::Size(width, height));
-}
-
-void WebGraphicsContext3DInProcessCommandBufferImpl::deleteCompositorTexture(
- WebGLId parent_texture) {
- // TODO(gmam): See if we can comment this in.
- // ClearContext();
- context_->DeleteParentTexture(parent_texture);
-}
-
void WebGraphicsContext3DInProcessCommandBufferImpl::FlipVertically(
uint8* framebuffer,
unsigned int width,
@@ -1477,7 +732,7 @@ WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::getError() {
}
bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() {
- return context_->IsCommandBufferContextLost();
+ return context_lost_reason_ != GL_NO_ERROR;
}
DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*)
@@ -1861,11 +1116,6 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::deleteTexture(
gl_->DeleteTextures(1, &texture);
}
-void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToCompositor(
- WebGLId texture, WebGLId parentTexture) {
- NOTIMPLEMENTED();
-}
-
void WebGraphicsContext3DInProcessCommandBufferImpl::OnSwapBuffersComplete() {
}
@@ -1985,62 +1235,25 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::signalSyncPoint(
unsigned sync_point,
WebGraphicsSyncPointCallback* callback) {
// Take ownership of the callback.
- context_->SetSignalSyncPointCallback(make_scoped_ptr(callback));
+ context_->SignalSyncPoint(
+ sync_point, base::Bind(&OnSignalSyncPoint, base::Owned(callback)));
// Stick something in the command buffer.
shallowFlushCHROMIUM();
}
-void GLInProcessContext::CallQueryCallback(size_t index) {
- DCHECK_LT(index, query_callbacks_.size());
- QueryCallback query_callback = query_callbacks_[index];
- query_callbacks_[index] = query_callbacks_.back();
- query_callback.callback->onSyncPointReached();
-}
-
-void GLInProcessContext::PollQueryCallbacks() {
- for (size_t i = 0; i < query_callbacks_.size();) {
- unsigned query = query_callbacks_[i].query;
- GLuint param = 0;
- GLES2Implementation* gl = GetImplementation();
- if (gl->IsQueryEXT(query)) {
- gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param);
- } else {
- param = 1;
- }
- if (param) {
- CallQueryCallback(i);
- } else {
- i++;
- }
- }
- if (!query_callbacks_.empty()) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&GLInProcessContext::PollQueryCallbacks,
- this->AsWeakPtr()),
- base::TimeDelta::FromMilliseconds(5));
- }
-}
-
-void GLInProcessContext::signalQuery(
- unsigned query,
- WebGraphicsSyncPointCallback* callback) {
- query_callbacks_.push_back(QueryCallback(query, callback));
- // If size > 1, there is already a poll callback pending.
- if (query_callbacks_.size() == 1) {
- PollQueryCallbacks();
- }
-}
-
void WebGraphicsContext3DInProcessCommandBufferImpl::signalQuery(
unsigned query,
WebGraphicsSyncPointCallback* callback) {
- context_->signalQuery(query, callback);
+ // Take ownership of the callback.
+ context_->SignalQuery(query,
+ base::Bind(&OnSignalSyncPoint, base::Owned(callback)));
}
void WebGraphicsContext3DInProcessCommandBufferImpl::loseContextCHROMIUM(
WGC3Denum current, WGC3Denum other) {
- context_->LoseContext(current, other);
+ gl_->LoseContextCHROMIUM(current, other);
+ gl_->Finish();
+ DCHECK(isContextLost());
}
DELEGATE_TO_GL_9(asyncTexImage2DCHROMIUM, AsyncTexImage2DCHROMIUM,
@@ -2054,10 +1267,5 @@ DELEGATE_TO_GL_9(asyncTexSubImage2DCHROMIUM, AsyncTexSubImage2DCHROMIUM,
DELEGATE_TO_GL_1(waitAsyncTexImage2DCHROMIUM, WaitAsyncTexImage2DCHROMIUM,
WGC3Denum)
-void WebGraphicsContext3DInProcessCommandBufferImpl::SetGpuMemoryBufferCreator(
- GpuMemoryBufferCreator* creator) {
- g_gpu_memory_buffer_creator = creator;
-}
-
} // namespace gpu
} // namespace webkit
diff --git a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h
index bd7645e..bb4f3da 100644
--- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h
+++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h
@@ -11,7 +11,6 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "gpu/command_buffer/client/gpu_memory_buffer.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "ui/gfx/native_widget_types.h"
@@ -38,21 +37,16 @@ using WebKit::WGC3Dclampf;
using WebKit::WGC3Dintptr;
using WebKit::WGC3Dsizeiptr;
-namespace webkit {
namespace gpu {
-
class GLInProcessContext;
+}
+
+namespace webkit {
+namespace gpu {
class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl
: public NON_EXPORTED_BASE(WebKit::WebGraphicsContext3D) {
public:
- typedef scoped_ptr< ::gpu::GpuMemoryBuffer> GpuMemoryBufferCreator(
- int width, int height);
-
- // Must be called before any WebGraphicsContext3DInProcessCommandBufferImpl
- // instances are created. Default value is false.
- static void EnableVirtualizedContext();
-
static scoped_ptr<WebKit::WebGraphicsContext3D> CreateViewContext(
const WebKit::WebGraphicsContext3D::Attributes& attributes,
gfx::AcceleratedWidget window);
@@ -60,8 +54,6 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl
static scoped_ptr<WebKit::WebGraphicsContext3D> CreateOffscreenContext(
const WebKit::WebGraphicsContext3D::Attributes& attributes);
- static void SetGpuMemoryBufferCreator(GpuMemoryBufferCreator* creator);
-
virtual ~WebGraphicsContext3DInProcessCommandBufferImpl();
//----------------------------------------------------------------------
@@ -455,11 +447,6 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl
virtual WebKit::WebString getTranslatedShaderSourceANGLE(WebGLId shader);
- virtual WebGLId createCompositorTexture(WGC3Dsizei width, WGC3Dsizei height);
- virtual void deleteCompositorTexture(WebGLId parent_texture);
- virtual void copyTextureToCompositor(WebGLId texture,
- WebGLId parent_texture);
-
virtual void setContextLostCallback(
WebGraphicsContext3D::WebGraphicsContextLostCallback* callback);
virtual WGC3Denum getGraphicsResetStatusARB();
@@ -576,7 +563,7 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl
bool initialize_failed_;
// The context we use for OpenGL rendering.
- GLInProcessContext* context_;
+ ::gpu::GLInProcessContext* context_;
// The GLES2Implementation we use for OpenGL rendering.
::gpu::gles2::GLES2Implementation* gl_;
diff --git a/webkit/common/gpu/webkit_gpu.gyp b/webkit/common/gpu/webkit_gpu.gyp
index 61ae7ec..37aec39 100644
--- a/webkit/common/gpu/webkit_gpu.gyp
+++ b/webkit/common/gpu/webkit_gpu.gyp
@@ -16,8 +16,6 @@
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '<(DEPTH)/gpu/command_buffer/command_buffer.gyp:gles2_utils',
- '<(DEPTH)/gpu/gpu.gyp:command_buffer_client',
'<(DEPTH)/gpu/gpu.gyp:command_buffer_service',
'<(DEPTH)/gpu/gpu.gyp:gles2_c_lib',
'<(DEPTH)/gpu/gpu.gyp:gles2_implementation',