summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-08 21:32:38 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-08 21:32:38 +0000
commit6ee6972c5746bb59309c80d8f96ea0dbbcd44789 (patch)
tree9f4731a33d1de53b7b0b78defde495762ffa30a7
parent02c92c499441303f58312463b30deb53f02dba63 (diff)
downloadchromium_src-6ee6972c5746bb59309c80d8f96ea0dbbcd44789.zip
chromium_src-6ee6972c5746bb59309c80d8f96ea0dbbcd44789.tar.gz
chromium_src-6ee6972c5746bb59309c80d8f96ea0dbbcd44789.tar.bz2
GGL library is a variant of the WGL, EGL and PGL libraries.
It is used to create and destroy OpenGL contexts and make them current. TEST=none BUG=none Review URL: http://codereview.chromium.org/661043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40940 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-xchrome/chrome_renderer.gypi5
-rw-r--r--chrome/renderer/ggl/ggl.cc280
-rw-r--r--chrome/renderer/ggl/ggl.h55
3 files changed, 340 insertions, 0 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 6802bf1..5e735a7 100755
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -55,6 +55,8 @@
'renderer/extensions/js_only_v8_extensions.h',
'renderer/extensions/renderer_extension_bindings.cc',
'renderer/extensions/renderer_extension_bindings.h',
+ 'renderer/ggl/ggl.cc',
+ 'renderer/ggl/ggl.h',
'renderer/loadtimes_extension_bindings.h',
'renderer/loadtimes_extension_bindings.cc',
'renderer/media/audio_renderer_impl.cc',
@@ -204,6 +206,9 @@
],
}],
['enable_gpu==1', {
+ 'dependencies': [
+ '../gpu/gpu.gyp:gles2_c_lib',
+ ],
'sources': [
'renderer/command_buffer_proxy.cc',
'renderer/command_buffer_proxy.h',
diff --git a/chrome/renderer/ggl/ggl.cc b/chrome/renderer/ggl/ggl.cc
new file mode 100644
index 0000000..6b5fbc2
--- /dev/null
+++ b/chrome/renderer/ggl/ggl.cc
@@ -0,0 +1,280 @@
+// Copyright (c) 2010 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 "build/build_config.h"
+
+#include "base/ref_counted.h"
+#include "base/singleton.h"
+#include "base/thread_local.h"
+#include "chrome/renderer/command_buffer_proxy.h"
+#include "chrome/renderer/ggl/ggl.h"
+#include "chrome/renderer/gpu_channel_host.h"
+#include "chrome/renderer/render_widget.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "ipc/ipc_channel_handle.h"
+
+namespace ggl {
+
+#if defined(ENABLE_GPU)
+
+namespace {
+
+const int32 kCommandBufferSize = 1024 * 1024;
+const int32 kTransferBufferSize = 1024 * 1024;
+
+base::ThreadLocalPointer<Context> g_current_context;
+
+// Singleton used to initialize and terminate the gles2 library.
+class GLES2Initializer {
+ public:
+ GLES2Initializer() {
+ gles2::Initialize();
+ }
+
+ ~GLES2Initializer() {
+ gles2::Terminate();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
+};
+} // namespace anonymous
+
+// Manages a GL context.
+class Context {
+ public:
+ Context();
+ ~Context();
+
+ // Initialize a GGL context that can be used in association with a a GPU
+ // channel acquired from a RenderWidget or RenderView.
+ bool Initialize(GpuChannelHost* channel);
+
+ // Destroy all resources associated with the GGL context.
+ void Destroy();
+
+ // Make a GGL context current for the calling thread.
+ static bool MakeCurrent(Context* context);
+
+ // Display all content rendered since last call to SwapBuffers.
+ // TODO(apatrick): support rendering to browser window. This function is
+ // not useful at this point.
+ bool SwapBuffers();
+
+ // Get the current error code.
+ Error GetError();
+
+ private:
+ scoped_refptr<GpuChannelHost> channel_;
+ CommandBufferProxy* command_buffer_;
+ gpu::gles2::GLES2CmdHelper* gles2_helper_;
+ int32 transfer_buffer_id_;
+ gpu::gles2::GLES2Implementation* gles2_implementation_;
+
+ DISALLOW_COPY_AND_ASSIGN(Context);
+};
+
+Context::Context()
+ : channel_(NULL),
+ command_buffer_(NULL),
+ gles2_helper_(NULL),
+ transfer_buffer_id_(0),
+ gles2_implementation_(NULL) {
+}
+
+Context::~Context() {
+ Destroy();
+}
+
+bool Context::Initialize(GpuChannelHost* channel) {
+ DCHECK(channel);
+
+ if (!channel->ready())
+ return false;
+
+ channel_ = channel;
+
+ // Ensure the gles2 library is initialized first in a thread safe way.
+ Singleton<GLES2Initializer>::get();
+
+ // Create a proxy to a command buffer in the GPU process.
+ command_buffer_ = channel_->CreateCommandBuffer();
+ if (!command_buffer_) {
+ Destroy();
+ return false;
+ }
+
+ // Initiaize the command buffer.
+ if (!command_buffer_->Initialize(kCommandBufferSize)) {
+ Destroy();
+ return false;
+ }
+
+ // Create the GLES2 helper, which writes the command buffer protocol.
+ gles2_helper_ = new gpu::gles2::GLES2CmdHelper(command_buffer_);
+ if (!gles2_helper_->Initialize()) {
+ Destroy();
+ return false;
+ }
+
+ // Create a transfer buffer used to copy resources between the renderer
+ // process and the GPU process.
+ transfer_buffer_id_ =
+ command_buffer_->CreateTransferBuffer(kTransferBufferSize);
+ if (transfer_buffer_id_ < 0) {
+ Destroy();
+ return false;
+ }
+
+ // Map the buffer into the renderer process's address space.
+ gpu::Buffer transfer_buffer =
+ command_buffer_->GetTransferBuffer(transfer_buffer_id_);
+ if (!transfer_buffer.ptr) {
+ Destroy();
+ return false;
+ }
+
+ // Create the object exposing the OpenGL API.
+ gles2_implementation_ = new gpu::gles2::GLES2Implementation(
+ gles2_helper_,
+ transfer_buffer.size,
+ transfer_buffer.ptr,
+ transfer_buffer_id_);
+
+ return true;
+}
+
+void Context::Destroy() {
+ delete gles2_implementation_;
+ gles2_implementation_ = NULL;
+
+ if (command_buffer_ && transfer_buffer_id_ != 0) {
+ command_buffer_->DestroyTransferBuffer(transfer_buffer_id_);
+ transfer_buffer_id_ = 0;
+ }
+
+ delete gles2_helper_;
+ gles2_helper_ = NULL;
+
+ if (channel_ && command_buffer_) {
+ channel_->DestroyCommandBuffer(command_buffer_);
+ command_buffer_ = NULL;
+ }
+
+ channel_ = NULL;
+}
+
+bool Context::MakeCurrent(Context* context) {
+ g_current_context.Set(context);
+ if (context) {
+ gles2::SetGLContext(context->gles2_implementation_);
+
+ // 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_->GetLastState().error != gpu::error::kNoError)
+ return false;
+ } else {
+ gles2::SetGLContext(NULL);
+ }
+
+ return true;
+}
+
+bool Context::SwapBuffers() {
+ // Don't request latest error status from service. Just use the locally cached
+ // information from the last flush.
+ if (command_buffer_->GetLastState().error != gpu::error::kNoError)
+ return false;
+
+ gles2_implementation_->SwapBuffers();
+ return true;
+}
+
+Error Context::GetError() {
+ gpu::CommandBuffer::State state = command_buffer_->GetState();
+ if (state.error == gpu::error::kNoError) {
+ return SUCCESS;
+ } 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;
+ }
+}
+
+#endif // ENABLE_GPU
+
+Context* CreateContext(GpuChannelHost* channel) {
+#if defined(ENABLE_GPU)
+ scoped_ptr<Context> context(new Context);
+ if (!context->Initialize(channel))
+ return NULL;
+
+ return context.release();
+#else
+ return NULL;
+#endif
+}
+
+bool MakeCurrent(Context* context) {
+#if defined(ENABLE_GPU)
+ return Context::MakeCurrent(context);
+#else
+ return false;
+#endif
+}
+
+Context* GetCurrentContext() {
+#if defined(ENABLE_GPU)
+ return g_current_context.Get();
+#else
+ return NULL;
+#endif
+}
+
+bool SwapBuffers() {
+#if defined(ENABLE_GPU)
+ Context* context = GetCurrentContext();
+ if (!context)
+ return false;
+
+ return context->SwapBuffers();
+#else
+ return false;
+#endif
+}
+
+bool DestroyContext(Context* context) {
+#if defined(ENABLE_GPU)
+ if (!context)
+ return false;
+
+ if (context == GetCurrentContext())
+ MakeCurrent(NULL);
+
+ delete context;
+ return true;
+#else
+ return false;
+#endif
+}
+
+Error GetError() {
+#if defined(ENABLE_GPU)
+ Context* context = GetCurrentContext();
+ if (!context)
+ return BAD_CONTEXT;
+
+ return context->GetError();
+#else
+ return NOT_INITIALIZED;
+#endif
+}
+
+} // namespace ggl
diff --git a/chrome/renderer/ggl/ggl.h b/chrome/renderer/ggl/ggl.h
new file mode 100644
index 0000000..26607ec
--- /dev/null
+++ b/chrome/renderer/ggl/ggl.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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.
+
+// This API is consistent with other OpenGL setup APIs like window's WGL
+// and pepper's PGL. This API is used to manage OpenGL contexts in the Chrome
+// renderer process in a way that is consistent with other platforms. It is
+// a C style API to ease porting of existing OpenGL software to Chrome.
+
+#ifndef CHROME_RENDERER_GGL_GGL_H_
+#define CHROME_RENDERER_GGL_GGL_H_
+
+class GpuChannelHost;
+
+namespace ggl {
+
+class Context;
+
+// These are the same error codes as used by EGL.
+enum Error {
+ SUCCESS = 0x3000,
+ NOT_INITIALIZED = 0x3001,
+ BAD_CONTEXT = 0x3006,
+ CONTEXT_LOST = 0x300E
+};
+
+// Initialize the GGL library. This must have completed before any other GGL
+// functions are invoked.
+bool Initialize();
+
+// Terminate the GGL library. This must be called after any other GGL functions
+// have completed.
+bool Terminate();
+
+// Create A GGL context for an offscreen 1 x 1 pbuffer.
+Context* CreateContext(GpuChannelHost* channel);
+
+// Set the current GGL context for the calling thread.
+bool MakeCurrent(Context* context);
+
+// Get the calling thread's current GGL context.
+Context* GetCurrentContext();
+
+// Display everything that has been rendered since the last call.
+bool SwapBuffers();
+
+// Destroy the given GGL context.
+bool DestroyContext(Context* context);
+
+// Return the current GGL error.
+Error GetError();
+
+} // namespace ggl
+
+#endif // CHROME_RENDERER_GGL_GGL_H_