summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-27 20:30:45 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-27 20:30:45 +0000
commit1b1bba77bb2fe952a651c07b11d617709ccd2fcf (patch)
tree2941d33c7ea0f1fc40b10e823771a03f3dcd6287
parent80ec6548d3f012c9b01e5dd5db39cb78c94c904b (diff)
downloadchromium_src-1b1bba77bb2fe952a651c07b11d617709ccd2fcf.zip
chromium_src-1b1bba77bb2fe952a651c07b11d617709ccd2fcf.tar.gz
chromium_src-1b1bba77bb2fe952a651c07b11d617709ccd2fcf.tar.bz2
Windows now uses the TLS API instead of __declspec(thread) for client side command buffer code compiled into DLLs. Other platforms use the pthreads API. This is because the __declspec(thread) approach does not on some platforms, including Windows XP and Mac.
This is used for thread local pointers to the GL and PGL contexts. This unfortunate because the PGL and GL APIs do not generally explicitly reference a context. The current context is set with a call to pglMakeCurrent. An unfortunate consequence is that now in Pepper plugins, every call to a GL function will call TlsGetValue to get the thread's current context, which could have performance issues. I can't use base::ThreadLocalPointer because this code is compiled into an untrusted NaCl module and we don't want Chromium dependencies. TEST=try BUG=none Review URL: http://codereview.chromium.org/553050 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37300 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--gpu/command_buffer/client/gles2_demo.cc9
-rw-r--r--gpu/command_buffer/client/gles2_lib.cc24
-rw-r--r--gpu/command_buffer/client/gles2_lib.h22
-rw-r--r--gpu/command_buffer/common/thread_local.h61
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h3
-rw-r--r--gpu/demos/framework/main_pepper.cc3
-rw-r--r--gpu/demos/framework/plugin.cc4
-rw-r--r--gpu/demos/framework/window.cc1
-rw-r--r--gpu/gpu.gyp1
-rw-r--r--gpu/pgl/pgl.cc48
-rw-r--r--gpu/pgl/pgl.h8
-rw-r--r--webkit/tools/pepper_test_plugin/main.cc8
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