1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <build/build_config.h>
7 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
8 #include "gpu/command_buffer/client/gles2_implementation.h"
9 #include "gpu/command_buffer/client/gles2_lib.h"
10 #include "gpu/command_buffer/common/constants.h"
11 #include "gpu/command_buffer/common/thread_local.h"
12 #include "gpu/pgl/command_buffer_pepper.h"
13 #include "gpu/pgl/pgl.h"
16 const int32 kTransferBufferSize
= 512 * 1024;
18 class PGLContextImpl
{
20 PGLContextImpl(NPP npp
,
22 NPDeviceContext3D
* device_context
);
25 // Initlaize a PGL context with a transfer buffer of a particular size.
26 PGLBoolean
Initialize(int32 transfer_buffer_size
);
28 // Destroy all resources associated with the PGL context.
31 // Make a PGL context current for the calling thread.
32 static PGLBoolean
MakeCurrent(PGLContextImpl
* pgl_context
);
34 // Display all content rendered since last call to SwapBuffers.
35 PGLBoolean
SwapBuffers();
37 // Get the current error code.
41 PGLContextImpl(const PGLContextImpl
&);
42 void operator=(const PGLContextImpl
&);
46 NPDeviceContext3D
* device_context_
;
47 CommandBufferPepper
* command_buffer_
;
48 gpu::gles2::GLES2CmdHelper
* gles2_helper_
;
49 int32 transfer_buffer_id_
;
50 gpu::gles2::GLES2Implementation
* gles2_implementation_
;
53 gpu::ThreadLocalKey g_pgl_context_key
;
54 bool g_pgl_context_key_allocated
= false;
56 PGLContextImpl::PGLContextImpl(NPP npp
,
58 NPDeviceContext3D
* device_context
)
61 device_context_(device_context
),
62 command_buffer_(NULL
),
64 transfer_buffer_id_(0),
65 gles2_implementation_(NULL
) {
68 PGLContextImpl::~PGLContextImpl() {
72 PGLBoolean
PGLContextImpl::Initialize(int32 transfer_buffer_size
) {
73 // Create and initialize the objects required to issue GLES2 calls.
74 command_buffer_
= new CommandBufferPepper(
75 npp_
, device_
, device_context_
);
76 gles2_helper_
= new gpu::gles2::GLES2CmdHelper(command_buffer_
);
77 if (gles2_helper_
->Initialize()) {
79 command_buffer_
->CreateTransferBuffer(kTransferBufferSize
);
80 gpu::Buffer transfer_buffer
=
81 command_buffer_
->GetTransferBuffer(transfer_buffer_id_
);
82 if (transfer_buffer
.ptr
) {
83 gles2_implementation_
= new gpu::gles2::GLES2Implementation(
92 // Tear everything down if initialization failed.
97 void PGLContextImpl::Destroy() {
98 delete gles2_implementation_
;
99 gles2_implementation_
= NULL
;
101 if (command_buffer_
&& transfer_buffer_id_
!= 0) {
102 command_buffer_
->DestroyTransferBuffer(transfer_buffer_id_
);
103 transfer_buffer_id_
= 0;
106 delete gles2_helper_
;
107 gles2_helper_
= NULL
;
109 delete command_buffer_
;
110 command_buffer_
= NULL
;
113 PGLBoolean
PGLContextImpl::MakeCurrent(PGLContextImpl
* pgl_context
) {
114 if (!g_pgl_context_key_allocated
)
117 gpu::ThreadLocalSetValue(g_pgl_context_key
, pgl_context
);
119 gles2::SetGLContext(pgl_context
->gles2_implementation_
);
121 // Don't request latest error status from service. Just use the locally
122 // cached information from the last flush.
123 // TODO(apatrick): I'm not sure if this should actually change the
124 // current context if it fails. For now it gets changed even if it fails
125 // becuase making GL calls with a NULL context crashes.
126 if (pgl_context
->device_context_
->error
!= NPDeviceContext3DError_NoError
)
130 gles2::SetGLContext(NULL
);
136 PGLBoolean
PGLContextImpl::SwapBuffers() {
137 // Don't request latest error status from service. Just use the locally cached
138 // information from the last flush.
139 if (device_context_
->error
!= NPDeviceContext3DError_NoError
)
142 gles2_implementation_
->SwapBuffers();
146 PGLInt
PGLContextImpl::GetError() {
147 gpu::CommandBuffer::State state
= command_buffer_
->GetState();
148 if (state
.error
== gpu::error::kNoError
) {
151 // All command buffer errors are unrecoverable. The error is treated as a
152 // lost context: destroy the context and create another one.
153 return PGL_CONTEXT_LOST
;
156 } // namespace anonymous
160 PGLBoolean
pglInitialize() {
161 if (g_pgl_context_key_allocated
)
165 g_pgl_context_key
= gpu::ThreadLocalAlloc();
166 g_pgl_context_key_allocated
= true;
170 PGLBoolean
pglTerminate() {
171 if (!g_pgl_context_key_allocated
)
174 gpu::ThreadLocalFree(g_pgl_context_key
);
175 g_pgl_context_key_allocated
= false;
176 g_pgl_context_key
= 0;
182 PGLContext
pglCreateContext(NPP npp
,
184 NPDeviceContext3D
* device_context
) {
185 if (!g_pgl_context_key_allocated
)
188 PGLContextImpl
* pgl_context
= new PGLContextImpl(
189 npp
, device
, device_context
);
190 if (pgl_context
->Initialize(kTransferBufferSize
)) {
198 PGLBoolean
pglMakeCurrent(PGLContext pgl_context
) {
199 return PGLContextImpl::MakeCurrent(static_cast<PGLContextImpl
*>(pgl_context
));
202 PGLContext
pglGetCurrentContext(void) {
203 if (!g_pgl_context_key_allocated
)
206 return static_cast<PGLContext
>(gpu::ThreadLocalGetValue(g_pgl_context_key
));
209 PGLBoolean
pglSwapBuffers(void) {
210 PGLContextImpl
* context
= static_cast<PGLContextImpl
*>(
211 pglGetCurrentContext());
215 return context
->SwapBuffers();
218 PGLBoolean
pglDestroyContext(PGLContext pgl_context
) {
219 if (!g_pgl_context_key_allocated
)
225 if (pgl_context
== pglGetCurrentContext())
226 pglMakeCurrent(NULL
);
228 delete static_cast<PGLContextImpl
*>(pgl_context
);
232 PGLInt
pglGetError() {
233 if (!g_pgl_context_key
)
234 return PGL_NOT_INITIALIZED
;
236 PGLContextImpl
* context
= static_cast<PGLContextImpl
*>(
237 pglGetCurrentContext());
239 return PGL_BAD_CONTEXT
;
241 return context
->GetError();