diff options
-rw-r--r-- | gpu/command_buffer/client/gles2_demo.cc | 9 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_lib.cc | 24 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_lib.h | 22 | ||||
-rw-r--r-- | gpu/command_buffer/common/thread_local.h | 61 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_mock.h | 3 | ||||
-rw-r--r-- | gpu/demos/framework/main_pepper.cc | 3 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.cc | 4 | ||||
-rw-r--r-- | gpu/demos/framework/window.cc | 1 | ||||
-rw-r--r-- | gpu/gpu.gyp | 1 | ||||
-rw-r--r-- | gpu/pgl/pgl.cc | 48 | ||||
-rw-r--r-- | gpu/pgl/pgl.h | 8 | ||||
-rw-r--r-- | webkit/tools/pepper_test_plugin/main.cc | 8 |
12 files changed, 166 insertions, 26 deletions
diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc index 2b96ba8..9b5977e 100644 --- a/gpu/command_buffer/client/gles2_demo.cc +++ b/gpu/command_buffer/client/gles2_demo.cc @@ -77,10 +77,11 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) { return false; - gles2::g_gl_impl = new GLES2Implementation(helper, - transfer_buffer.size, - transfer_buffer.ptr, - transfer_buffer_id); + gles2::Initialize(); + gles2::SetGLContext(new GLES2Implementation(helper, + transfer_buffer.size, + transfer_buffer.ptr, + transfer_buffer_id)); return command_buffer.release() != NULL; } diff --git a/gpu/command_buffer/client/gles2_lib.cc b/gpu/command_buffer/client/gles2_lib.cc index cd7cfed..003a4cc 100644 --- a/gpu/command_buffer/client/gles2_lib.cc +++ b/gpu/command_buffer/client/gles2_lib.cc @@ -3,11 +3,29 @@ // found in the LICENSE file. #include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/common/thread_local.h" namespace gles2 { - -THREAD_LOCAL ::gpu::gles2::GLES2Implementation* g_gl_impl; - +namespace { +gpu::ThreadLocalKey g_gl_context_key; +} // namespace anonymous + +void Initialize() { + g_gl_context_key = gpu::ThreadLocalAlloc(); +} + +void Terminate() { + gpu::ThreadLocalFree(g_gl_context_key); +} + +gpu::gles2::GLES2Implementation* GetGLContext() { + return static_cast<gpu::gles2::GLES2Implementation*>( + gpu::ThreadLocalGetValue(g_gl_context_key)); +} + +void SetGLContext(gpu::gles2::GLES2Implementation* context) { + gpu::ThreadLocalSetValue(g_gl_context_key, context); +} } // namespace gles2 diff --git a/gpu/command_buffer/client/gles2_lib.h b/gpu/command_buffer/client/gles2_lib.h index e2825fa..2242cc8 100644 --- a/gpu/command_buffer/client/gles2_lib.h +++ b/gpu/command_buffer/client/gles2_lib.h @@ -9,23 +9,19 @@ #include "gpu/command_buffer/client/gles2_implementation.h" -#if defined(_MSC_VER) -#define THREAD_LOCAL __declspec(thread) -#else -#define THREAD_LOCAL __thread -#endif - namespace gles2 { -extern THREAD_LOCAL gpu::gles2::GLES2Implementation* g_gl_impl; +// Initialize the GLES2 library. +void Initialize(); + +// Terminate the GLES2 library. +void Terminate(); -inline gpu::gles2::GLES2Implementation* GetGLContext() { - return g_gl_impl; -} +// Get the current GL context. +gpu::gles2::GLES2Implementation* GetGLContext(); -inline void SetGLContext(gpu::gles2::GLES2Implementation* impl) { - g_gl_impl = impl; -} +// Set the current GL context. +void SetGLContext(gpu::gles2::GLES2Implementation* impl); } // namespace gles2 diff --git a/gpu/command_buffer/common/thread_local.h b/gpu/command_buffer/common/thread_local.h new file mode 100644 index 0000000..4981c5d --- /dev/null +++ b/gpu/command_buffer/common/thread_local.h @@ -0,0 +1,61 @@ +// 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. + +// Functions for allocating and accessing thread local values via key. + +#ifndef GPU_COMMAND_BUFFER_COMMON_THREAD_LOCAL_H_ +#define GPU_COMMAND_BUFFER_COMMON_THREAD_LOCAL_H_ + +#include <build/build_config.h> + +#if defined(OS_WIN) +#include <windows.h> +#else +#include <pthread.h> +#endif + +namespace gpu { + +#if defined(OS_WIN) +typedef DWORD ThreadLocalKey; +#else +typedef pthread_key_t ThreadLocalKey; +#endif + +inline ThreadLocalKey ThreadLocalAlloc() { +#if defined(OS_WIN) + return TlsAlloc(); +#else + ThreadLocalKey key; + pthread_key_create(&key, NULL); + return key; +#endif +} + +inline void ThreadLocalFree(ThreadLocalKey key) { +#if defined(OS_WIN) + TlsFree(key); +#else + pthread_key_delete(key); +#endif +} + +inline void ThreadLocalSetValue(ThreadLocalKey key, void* value) { +#if defined(OS_WIN) + TlsSetValue(key, value); +#else + pthread_setspecific(key, value); +#endif +} + +inline void* ThreadLocalGetValue(ThreadLocalKey key) { +#if defined(OS_WIN) + return TlsGetValue(key); +#else + return pthread_getspecific(key); +#endif +} +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_COMMON_THREAD_LOCAL_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index 2edea92..ccedc95 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -18,12 +18,13 @@ class MockGLES2Decoder : public GLES2Decoder { MockGLES2Decoder() { ON_CALL(*this, GetCommandName(testing::_)) .WillByDefault(testing::Return("")); + ON_CALL(*this, MakeCurrent()) + .WillByDefault(testing::Return(true)); } MOCK_METHOD0(Initialize, bool()); MOCK_METHOD0(Destroy, void()); MOCK_METHOD0(MakeCurrent, bool()); - MOCK_METHOD0(ReleaseCurrent, void()); MOCK_METHOD1(GetServiceIdForTesting, uint32(uint32 client_id)); MOCK_METHOD3(DoCommand, parse_error::ParseError(unsigned int command, unsigned int arg_count, diff --git a/gpu/demos/framework/main_pepper.cc b/gpu/demos/framework/main_pepper.cc index d97cbd0..4d4ae4e 100644 --- a/gpu/demos/framework/main_pepper.cc +++ b/gpu/demos/framework/main_pepper.cc @@ -5,6 +5,7 @@ #include "base/at_exit.h" #include "base/logging.h" #include "gpu/demos/framework/plugin.h" +#include "gpu/pgl/pgl.h" #include "webkit/glue/plugins/nphostapi.h" namespace { @@ -139,10 +140,12 @@ NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) { NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs) { g_at_exit_manager_ = new base::AtExitManager(); gpu::demos::g_browser = browser_funcs; + pglInitialize(); return NPERR_NO_ERROR; } void API_CALL NP_Shutdown() { + pglTerminate(); delete g_at_exit_manager_; } } // extern "C" diff --git a/gpu/demos/framework/plugin.cc b/gpu/demos/framework/plugin.cc index b5278b1..dafcffe 100644 --- a/gpu/demos/framework/plugin.cc +++ b/gpu/demos/framework/plugin.cc @@ -92,7 +92,11 @@ Plugin::Plugin(NPP npp) } Plugin::~Plugin() { + // Destroy demo while GL context is current and before it is destroyed. + pglMakeCurrent(pgl_context_); + demo_.reset(); pglMakeCurrent(NULL); + pglDestroyContext(pgl_context_); } diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc index 6833feb..41538d5 100644 --- a/gpu/demos/framework/window.cc +++ b/gpu/demos/framework/window.cc @@ -117,6 +117,7 @@ bool InitRenderContext(HWND hwnd) { command_buffer->GetTransferBuffer(transfer_buffer_id); if (transfer_buffer.ptr == NULL) return false; + gles2::Initialize(); gles2::SetGLContext(new GLES2Implementation(helper, transfer_buffer.size, transfer_buffer.ptr, diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 38e8059..dd98c60 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -114,6 +114,7 @@ 'command_buffer/common/mocks.h', 'command_buffer/common/resource.cc', 'command_buffer/common/resource.h', + 'command_buffer/common/thread_local.h', 'command_buffer/common/types.h', ], }, diff --git a/gpu/pgl/pgl.cc b/gpu/pgl/pgl.cc index 2fd3d8b..41903e1 100644 --- a/gpu/pgl/pgl.cc +++ b/gpu/pgl/pgl.cc @@ -2,9 +2,12 @@ // 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 "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/thread_local.h" #include "gpu/pgl/command_buffer_pepper.h" #include "gpu/pgl/pgl.h" @@ -43,7 +46,7 @@ class PGLContextImpl { gpu::gles2::GLES2Implementation* gles2_implementation_; }; -THREAD_LOCAL PGLContextImpl* g_current_pgl_context; +gpu::ThreadLocalKey g_pgl_context_key; PGLContextImpl::PGLContextImpl(NPP npp, NPDevice* device, @@ -103,7 +106,10 @@ void PGLContextImpl::Destroy() { } bool PGLContextImpl::MakeCurrent(PGLContextImpl* pgl_context) { - g_current_pgl_context = pgl_context; + if (!g_pgl_context_key) + return false; + + gpu::ThreadLocalSetValue(g_pgl_context_key, pgl_context); if (pgl_context) gles2::SetGLContext(pgl_context->gles2_implementation_); else @@ -120,9 +126,30 @@ bool PGLContextImpl::SwapBuffers() { extern "C" { +PGLBoolean pglInitialize() { + if (g_pgl_context_key) + return true; + + gles2::Initialize(); + g_pgl_context_key = gpu::ThreadLocalAlloc(); + return true; +} + +PGLBoolean pglTerminate() { + if (!g_pgl_context_key) + return true; + + gpu::ThreadLocalFree(g_pgl_context_key); + gles2::Terminate(); + return true; +} + PGLContext pglCreateContext(NPP npp, NPDevice* device, NPDeviceContext3D* device_context) { + if (!g_pgl_context_key) + return NULL; + PGLContextImpl* pgl_context = new PGLContextImpl( npp, device, device_context); if (pgl_context->Initialize(kTransferBufferSize)) { @@ -138,20 +165,31 @@ PGLBoolean pglMakeCurrent(PGLContext pgl_context) { } PGLContext pglGetCurrentContext(void) { - return g_current_pgl_context; + if (!g_pgl_context_key) + return NULL; + + return static_cast<PGLContext>(gpu::ThreadLocalGetValue(g_pgl_context_key)); } PGLBoolean pglSwapBuffers(void) { - if (!g_current_pgl_context) + PGLContextImpl* context = static_cast<PGLContextImpl*>( + pglGetCurrentContext()); + if (!context) return false; - return g_current_pgl_context->SwapBuffers(); + return context->SwapBuffers(); } PGLBoolean pglDestroyContext(PGLContext pgl_context) { + if (!g_pgl_context_key) + return NULL; + if (!pgl_context) return false; + if (pgl_context == pglGetCurrentContext()) + pglMakeCurrent(NULL); + delete static_cast<PGLContextImpl*>(pgl_context); return true; } diff --git a/gpu/pgl/pgl.h b/gpu/pgl/pgl.h index f848968..3a7735e 100644 --- a/gpu/pgl/pgl.h +++ b/gpu/pgl/pgl.h @@ -15,6 +15,14 @@ extern "C" { typedef void* PGLContext; typedef bool PGLBoolean; +// Initialize the PGL library. This must have completed before any other PGL +// functions are invoked. +PGLBoolean pglInitialize(); + +// Terminate the PGL library. This must be called after any other PGL functions +// have completed. +PGLBoolean pglTerminate(); + // Create A PGL context from a Pepper 3D device context. PGLContext pglCreateContext(NPP npp, NPDevice* device, diff --git a/webkit/tools/pepper_test_plugin/main.cc b/webkit/tools/pepper_test_plugin/main.cc index 851674c..81c963d 100644 --- a/webkit/tools/pepper_test_plugin/main.cc +++ b/webkit/tools/pepper_test_plugin/main.cc @@ -34,6 +34,8 @@ #include <stdlib.h> #include <stdio.h> +#include "gpu/pgl/pgl.h" + #if defined(INDEPENDENT_PLUGIN) #include <iostream> #define LOG(x) std::cerr @@ -118,6 +120,9 @@ EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs EXPORT NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* plugin_funcs); EXPORT void API_CALL NP_Shutdown() { +#if !defined(INDEPENDENT_PLUGIN) + pglTerminate(); +#endif } #if defined(OS_LINUX) @@ -136,6 +141,9 @@ EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs #endif ) { browser = browser_funcs; +#if !defined(INDEPENDENT_PLUGIN) + pglInitialize(); +#endif #if defined(OS_LINUX) return NP_GetEntryPoints(plugin_funcs); #else |