| Index: chrome/renderer/ggl/ggl.cc
|
| ===================================================================
|
| --- chrome/renderer/ggl/ggl.cc (revision 78386)
|
| +++ chrome/renderer/ggl/ggl.cc (working copy)
|
| @@ -1,607 +0,0 @@
|
| -// 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/lazy_instance.h"
|
| -#include "base/ref_counted.h"
|
| -#include "base/weak_ptr.h"
|
| -#include "chrome/renderer/command_buffer_proxy.h"
|
| -#include "chrome/renderer/ggl/ggl.h"
|
| -#include "chrome/renderer/gpu_channel_host.h"
|
| -#include "chrome/renderer/gpu_video_service_host.h"
|
| -#include "chrome/renderer/media/gles2_video_decode_context.h"
|
| -#include "chrome/renderer/render_widget.h"
|
| -#include "ipc/ipc_channel_handle.h"
|
| -
|
| -
|
| -#if defined(ENABLE_GPU)
|
| -#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 "gpu/common/gpu_trace_event.h"
|
| -#include "gpu/GLES2/gles2_command_buffer.h"
|
| -#endif // ENABLE_GPU
|
| -
|
| -namespace ggl {
|
| -
|
| -#if defined(ENABLE_GPU)
|
| -
|
| -namespace {
|
| -
|
| -const int32 kCommandBufferSize = 1024 * 1024;
|
| -// TODO(kbr): make the transfer buffer size configurable via context
|
| -// creation attributes.
|
| -const int32 kTransferBufferSize = 1024 * 1024;
|
| -
|
| -// Singleton used to initialize and terminate the gles2 library.
|
| -class GLES2Initializer {
|
| - public:
|
| - GLES2Initializer() {
|
| - gles2::Initialize();
|
| - }
|
| -
|
| - ~GLES2Initializer() {
|
| - gles2::Terminate();
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
|
| -};
|
| -
|
| -static base::LazyInstance<GLES2Initializer> g_gles2_initializer(
|
| - base::LINKER_INITIALIZED);
|
| -
|
| -} // namespace anonymous
|
| -
|
| -// Manages a GL context.
|
| -class Context : public base::SupportsWeakPtr<Context> {
|
| - public:
|
| - Context(GpuChannelHost* channel, Context* parent);
|
| - ~Context();
|
| -
|
| - // Initialize a GGL context that can be used in association with a a GPU
|
| - // channel acquired from a RenderWidget or RenderView.
|
| - bool Initialize(bool onscreen,
|
| - int render_view_id,
|
| - const gfx::Size& size,
|
| - const char* allowed_extensions,
|
| - const int32* attrib_list);
|
| -
|
| -#if defined(OS_MACOSX)
|
| - // Asynchronously resizes an onscreen frame buffer.
|
| - void ResizeOnscreen(const gfx::Size& size);
|
| -#endif
|
| -
|
| - // Asynchronously resizes an offscreen frame buffer.
|
| - void ResizeOffscreen(const gfx::Size& size);
|
| -
|
| - // Provides a callback that will be invoked when SwapBuffers has completed
|
| - // service side.
|
| - void SetSwapBuffersCallback(Callback0::Type* callback) {
|
| - swap_buffers_callback_.reset(callback);
|
| - }
|
| -
|
| - void SetContextLostCallback(Callback0::Type* callback) {
|
| - context_lost_callback_.reset(callback);
|
| - }
|
| -
|
| - // For an offscreen frame buffer context, return the frame buffer ID with
|
| - // respect to the parent.
|
| - uint32 parent_texture_id() const {
|
| - return parent_texture_id_;
|
| - }
|
| -
|
| - uint32 CreateParentTexture(const gfx::Size& size) const;
|
| - void DeleteParentTexture(uint32 texture) const;
|
| -
|
| - // 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();
|
| -
|
| - // Create a hardware accelerated video decoder associated with this context.
|
| - media::VideoDecodeEngine* CreateVideoDecodeEngine();
|
| -
|
| - // Create a hardware video decode context associated with this context.
|
| - media::VideoDecodeContext* CreateVideoDecodeContext(MessageLoop* message_loop,
|
| - bool hardware_decoder);
|
| -
|
| - // Get the current error code. Clears context's error code afterwards.
|
| - Error GetError();
|
| -
|
| - // Replace the current error code with this.
|
| - void SetError(Error error);
|
| -
|
| - bool IsCommandBufferContextLost();
|
| -
|
| - // TODO(gman): Remove this.
|
| - void DisableShaderTranslation();
|
| -
|
| - gpu::gles2::GLES2Implementation* gles2_implementation() const {
|
| - return gles2_implementation_;
|
| - }
|
| -
|
| - CommandBufferProxy* command_buffer() const {
|
| - return command_buffer_;
|
| - }
|
| -
|
| - private:
|
| - void OnSwapBuffers();
|
| - void OnContextLost();
|
| -
|
| - scoped_refptr<GpuChannelHost> channel_;
|
| - base::WeakPtr<Context> parent_;
|
| - scoped_ptr<Callback0::Type> swap_buffers_callback_;
|
| - scoped_ptr<Callback0::Type> context_lost_callback_;
|
| - uint32 parent_texture_id_;
|
| - CommandBufferProxy* command_buffer_;
|
| - gpu::gles2::GLES2CmdHelper* gles2_helper_;
|
| - int32 transfer_buffer_id_;
|
| - gpu::gles2::GLES2Implementation* gles2_implementation_;
|
| - gfx::Size size_;
|
| - Error last_error_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Context);
|
| -};
|
| -
|
| -Context::Context(GpuChannelHost* channel, Context* parent)
|
| - : channel_(channel),
|
| - parent_(parent ? parent->AsWeakPtr() : base::WeakPtr<Context>()),
|
| - parent_texture_id_(0),
|
| - command_buffer_(NULL),
|
| - gles2_helper_(NULL),
|
| - transfer_buffer_id_(0),
|
| - gles2_implementation_(NULL),
|
| - last_error_(SUCCESS) {
|
| - DCHECK(channel);
|
| -}
|
| -
|
| -Context::~Context() {
|
| - Destroy();
|
| -}
|
| -
|
| -bool Context::Initialize(bool onscreen,
|
| - int render_view_id,
|
| - const gfx::Size& size,
|
| - const char* allowed_extensions,
|
| - const int32* attrib_list) {
|
| - DCHECK(size.width() >= 0 && size.height() >= 0);
|
| -
|
| - if (channel_->state() != GpuChannelHost::kConnected)
|
| - return false;
|
| -
|
| - // Ensure the gles2 library is initialized first in a thread safe way.
|
| - g_gles2_initializer.Get();
|
| -
|
| - // Allocate a frame buffer ID with respect to the parent.
|
| - if (parent_.get()) {
|
| - // Flush any remaining commands in the parent context to make sure the
|
| - // texture id accounting stays consistent.
|
| - int32 token = parent_->gles2_helper_->InsertToken();
|
| - parent_->gles2_helper_->WaitForToken(token);
|
| - parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId();
|
| - }
|
| -
|
| - std::vector<int32> attribs;
|
| - while (attrib_list) {
|
| - int32 attrib = *attrib_list++;
|
| - switch (attrib) {
|
| - // Known attributes
|
| - case ggl::GGL_ALPHA_SIZE:
|
| - case ggl::GGL_BLUE_SIZE:
|
| - case ggl::GGL_GREEN_SIZE:
|
| - case ggl::GGL_RED_SIZE:
|
| - case ggl::GGL_DEPTH_SIZE:
|
| - case ggl::GGL_STENCIL_SIZE:
|
| - case ggl::GGL_SAMPLES:
|
| - case ggl::GGL_SAMPLE_BUFFERS:
|
| - attribs.push_back(attrib);
|
| - attribs.push_back(*attrib_list++);
|
| - break;
|
| - case ggl::GGL_NONE:
|
| - attribs.push_back(attrib);
|
| - attrib_list = NULL;
|
| - break;
|
| - default:
|
| - SetError(ggl::BAD_ATTRIBUTE);
|
| - attribs.push_back(ggl::GGL_NONE);
|
| - attrib_list = NULL;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // Create a proxy to a command buffer in the GPU process.
|
| - if (onscreen) {
|
| - command_buffer_ = channel_->CreateViewCommandBuffer(
|
| - render_view_id,
|
| - allowed_extensions,
|
| - attribs);
|
| - } else {
|
| - CommandBufferProxy* parent_command_buffer =
|
| - parent_.get() ? parent_->command_buffer_ : NULL;
|
| - command_buffer_ = channel_->CreateOffscreenCommandBuffer(
|
| - parent_command_buffer,
|
| - size,
|
| - allowed_extensions,
|
| - attribs,
|
| - parent_texture_id_);
|
| - }
|
| - if (!command_buffer_) {
|
| - Destroy();
|
| - return false;
|
| - }
|
| -
|
| - // Initiaize the command buffer.
|
| - if (!command_buffer_->Initialize(kCommandBufferSize)) {
|
| - Destroy();
|
| - return false;
|
| - }
|
| -
|
| - command_buffer_->SetSwapBuffersCallback(
|
| - NewCallback(this, &Context::OnSwapBuffers));
|
| -
|
| - command_buffer_->SetChannelErrorCallback(
|
| - NewCallback(this, &Context::OnContextLost));
|
| -
|
| - // Create the GLES2 helper, which writes the command buffer protocol.
|
| - gles2_helper_ = new gpu::gles2::GLES2CmdHelper(command_buffer_);
|
| - if (!gles2_helper_->Initialize(kCommandBufferSize)) {
|
| - 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_,
|
| - false);
|
| -
|
| - size_ = size;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -#if defined(OS_MACOSX)
|
| -void Context::ResizeOnscreen(const gfx::Size& size) {
|
| - DCHECK(size.width() > 0 && size.height() > 0);
|
| - size_ = size;
|
| - command_buffer_->SetWindowSize(size);
|
| -}
|
| -#endif
|
| -
|
| -void Context::ResizeOffscreen(const gfx::Size& size) {
|
| - DCHECK(size.width() > 0 && size.height() > 0);
|
| - if (size_ != size) {
|
| - command_buffer_->ResizeOffscreenFrameBuffer(size);
|
| - size_ = size;
|
| - }
|
| -}
|
| -
|
| -uint32 Context::CreateParentTexture(const gfx::Size& size) const {
|
| - // 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;
|
| -}
|
| -
|
| -void Context::DeleteParentTexture(uint32 texture) const {
|
| - if (parent_.get()) {
|
| - if (!MakeCurrent(parent_.get()))
|
| - return;
|
| - parent_->gles2_implementation_->DeleteTextures(1, &texture);
|
| - }
|
| -}
|
| -
|
| -void Context::Destroy() {
|
| - if (parent_.get() && parent_texture_id_ != 0)
|
| - parent_->gles2_implementation_->FreeTextureId(parent_texture_id_);
|
| -
|
| - 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) {
|
| - 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() {
|
| - GPU_TRACE_EVENT0("gpu", "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;
|
| -}
|
| -
|
| -media::VideoDecodeEngine* Context::CreateVideoDecodeEngine() {
|
| - return channel_->gpu_video_service_host()->CreateVideoDecoder(
|
| - command_buffer_->route_id());
|
| -}
|
| -
|
| -media::VideoDecodeContext* Context::CreateVideoDecodeContext(
|
| - MessageLoop* message_loop, bool hardware_decoder) {
|
| - return new Gles2VideoDecodeContext(message_loop, hardware_decoder, this);
|
| -}
|
| -
|
| -Error Context::GetError() {
|
| - gpu::CommandBuffer::State state = command_buffer_->GetState();
|
| - if (state.error == gpu::error::kNoError) {
|
| - 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;
|
| - }
|
| -}
|
| -
|
| -void Context::SetError(Error error) {
|
| - last_error_ = error;
|
| -}
|
| -
|
| -bool Context::IsCommandBufferContextLost() {
|
| - gpu::CommandBuffer::State state = command_buffer_->GetLastState();
|
| - return state.error == gpu::error::kLostContext;
|
| -}
|
| -
|
| -// TODO(gman): Remove This
|
| -void Context::DisableShaderTranslation() {
|
| - gles2_implementation_->CommandBufferEnableCHROMIUM(
|
| - PEPPER3D_SKIP_GLSL_TRANSLATION);
|
| -}
|
| -
|
| -void Context::OnSwapBuffers() {
|
| - if (swap_buffers_callback_.get())
|
| - swap_buffers_callback_->Run();
|
| -}
|
| -
|
| -void Context::OnContextLost() {
|
| - if (context_lost_callback_.get())
|
| - context_lost_callback_->Run();
|
| -}
|
| -
|
| -#endif // ENABLE_GPU
|
| -
|
| -Context* CreateViewContext(GpuChannelHost* channel,
|
| - int render_view_id,
|
| - const char* allowed_extensions,
|
| - const int32* attrib_list) {
|
| -#if defined(ENABLE_GPU)
|
| - scoped_ptr<Context> context(new Context(channel, NULL));
|
| - if (!context->Initialize(
|
| - true, render_view_id, gfx::Size(), allowed_extensions, attrib_list))
|
| - return NULL;
|
| -
|
| - return context.release();
|
| -#else
|
| - return NULL;
|
| -#endif
|
| -}
|
| -
|
| -#if defined(OS_MACOSX)
|
| -void ResizeOnscreenContext(Context* context, const gfx::Size& size) {
|
| -#if defined(ENABLE_GPU)
|
| - context->ResizeOnscreen(size);
|
| -#endif
|
| -}
|
| -#endif
|
| -
|
| -Context* CreateOffscreenContext(GpuChannelHost* channel,
|
| - Context* parent,
|
| - const gfx::Size& size,
|
| - const char* allowed_extensions,
|
| - const int32* attrib_list) {
|
| -#if defined(ENABLE_GPU)
|
| - scoped_ptr<Context> context(new Context(channel, parent));
|
| - if (!context->Initialize(false, 0, size, allowed_extensions, attrib_list))
|
| - return NULL;
|
| -
|
| - return context.release();
|
| -#else
|
| - return NULL;
|
| -#endif
|
| -}
|
| -
|
| -void ResizeOffscreenContext(Context* context, const gfx::Size& size) {
|
| -#if defined(ENABLE_GPU)
|
| - context->ResizeOffscreen(size);
|
| -#endif
|
| -}
|
| -
|
| -uint32 GetParentTextureId(Context* context) {
|
| -#if defined(ENABLE_GPU)
|
| - return context->parent_texture_id();
|
| -#else
|
| - return 0;
|
| -#endif
|
| -}
|
| -
|
| -uint32 CreateParentTexture(Context* context, const gfx::Size& size) {
|
| -#if defined(ENABLE_GPU)
|
| - return context->CreateParentTexture(size);
|
| -#else
|
| - return 0;
|
| -#endif
|
| -}
|
| -
|
| -void DeleteParentTexture(Context* context, uint32 texture) {
|
| -#if defined(ENABLE_GPU)
|
| - context->DeleteParentTexture(texture);
|
| -#endif
|
| -}
|
| -
|
| -void SetSwapBuffersCallback(Context* context,
|
| - Callback0::Type* callback) {
|
| -#if defined(ENABLE_GPU)
|
| - context->SetSwapBuffersCallback(callback);
|
| -#endif
|
| -}
|
| -
|
| -void SetContextLostCallback(Context* context,
|
| - Callback0::Type* callback) {
|
| -#if defined(ENABLE_GPU)
|
| - context->SetContextLostCallback(callback);
|
| -#endif
|
| -}
|
| -
|
| -bool MakeCurrent(Context* context) {
|
| -#if defined(ENABLE_GPU)
|
| - return Context::MakeCurrent(context);
|
| -#else
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -bool SwapBuffers(Context* context) {
|
| -#if defined(ENABLE_GPU)
|
| - if (!context)
|
| - return false;
|
| -
|
| - return context->SwapBuffers();
|
| -#else
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -bool DestroyContext(Context* context) {
|
| -#if defined(ENABLE_GPU)
|
| - if (!context)
|
| - return false;
|
| -
|
| - delete context;
|
| - return true;
|
| -#else
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -media::VideoDecodeEngine* CreateVideoDecodeEngine(Context* context) {
|
| - return context->CreateVideoDecodeEngine();
|
| -}
|
| -
|
| -media::VideoDecodeContext* CreateVideoDecodeContext(
|
| - Context* context, MessageLoop* message_loop, bool hardware_decoder) {
|
| - return context->CreateVideoDecodeContext(message_loop, hardware_decoder);
|
| -}
|
| -
|
| -Error GetError(Context* context) {
|
| -#if defined(ENABLE_GPU)
|
| - return context->GetError();
|
| -#else
|
| - return NOT_INITIALIZED;
|
| -#endif
|
| -}
|
| -
|
| -bool IsCommandBufferContextLost(Context* context) {
|
| - return context->IsCommandBufferContextLost();
|
| -}
|
| -
|
| -// TODO(gman): Remove This
|
| -void DisableShaderTranslation(Context* context) {
|
| -#if defined(ENABLE_GPU)
|
| - if (context) {
|
| - context->DisableShaderTranslation();
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -gpu::gles2::GLES2Implementation* GetImplementation(Context* context) {
|
| - if (!context)
|
| - return NULL;
|
| -
|
| - return context->gles2_implementation();
|
| -}
|
| -
|
| -CommandBufferProxy* GetCommandBufferProxy(Context* context) {
|
| - DCHECK(context);
|
| - return context->command_buffer();
|
| -}
|
| -
|
| -} // namespace ggl
|
|
|