summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/ggl/ggl.cc
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 /chrome/renderer/ggl/ggl.cc
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
Diffstat (limited to 'chrome/renderer/ggl/ggl.cc')
-rw-r--r--chrome/renderer/ggl/ggl.cc280
1 files changed, 280 insertions, 0 deletions
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