OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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. | |
4 | |
5 #include "gpu/pgl/pgl.h" | |
6 | |
7 #include "build/build_config.h" | |
8 #include "gpu/command_buffer/client/gles2_cmd_helper.h" | |
9 #include "gpu/command_buffer/client/gles2_implementation.h" | |
10 #include "gpu/command_buffer/client/gles2_lib.h" | |
11 #include "gpu/command_buffer/common/constants.h" | |
12 #include "gpu/command_buffer/common/thread_local.h" | |
13 #include "gpu/pgl/command_buffer_pepper.h" | |
14 | |
15 namespace { | |
16 const int32 kTransferBufferSize = 512 * 1024; | |
17 | |
18 class PGLContextImpl { | |
19 public: | |
20 PGLContextImpl(NPP npp, | |
21 NPDevice* device, | |
22 NPDeviceContext3D* device_context); | |
23 ~PGLContextImpl(); | |
24 | |
25 // Initlaize a PGL context with a transfer buffer of a particular size. | |
26 PGLBoolean Initialize(int32 transfer_buffer_size); | |
27 | |
28 // Destroy all resources associated with the PGL context. | |
29 void Destroy(); | |
30 | |
31 // Make a PGL context current for the calling thread. | |
32 static PGLBoolean MakeCurrent(PGLContextImpl* pgl_context); | |
33 | |
34 // Display all content rendered since last call to SwapBuffers. | |
35 PGLBoolean SwapBuffers(); | |
36 | |
37 // Get the current error code. | |
38 PGLInt GetError(); | |
39 | |
40 private: | |
41 PGLContextImpl(const PGLContextImpl&); | |
42 void operator=(const PGLContextImpl&); | |
43 | |
44 NPP npp_; | |
45 NPDevice* device_; | |
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_; | |
51 }; | |
52 | |
53 gpu::ThreadLocalKey g_pgl_context_key; | |
54 bool g_pgl_context_key_allocated = false; | |
55 | |
56 PGLContextImpl::PGLContextImpl(NPP npp, | |
57 NPDevice* device, | |
58 NPDeviceContext3D* device_context) | |
59 : npp_(npp), | |
60 device_(device), | |
61 device_context_(device_context), | |
62 command_buffer_(NULL), | |
63 gles2_helper_(NULL), | |
64 transfer_buffer_id_(0), | |
65 gles2_implementation_(NULL) { | |
66 } | |
67 | |
68 PGLContextImpl::~PGLContextImpl() { | |
69 Destroy(); | |
70 } | |
71 | |
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 gpu::Buffer buffer = command_buffer_->GetRingBuffer(); | |
78 if (gles2_helper_->Initialize(buffer.size)) { | |
79 transfer_buffer_id_ = | |
80 command_buffer_->CreateTransferBuffer(kTransferBufferSize, -1); | |
81 gpu::Buffer transfer_buffer = | |
82 command_buffer_->GetTransferBuffer(transfer_buffer_id_); | |
83 if (transfer_buffer.ptr) { | |
84 gles2_implementation_ = new gpu::gles2::GLES2Implementation( | |
85 gles2_helper_, | |
86 transfer_buffer.size, | |
87 transfer_buffer.ptr, | |
88 transfer_buffer_id_, | |
89 false); | |
90 return PGL_TRUE; | |
91 } | |
92 } | |
93 | |
94 // Tear everything down if initialization failed. | |
95 Destroy(); | |
96 return PGL_FALSE; | |
97 } | |
98 | |
99 void PGLContextImpl::Destroy() { | |
100 delete gles2_implementation_; | |
101 gles2_implementation_ = NULL; | |
102 | |
103 if (command_buffer_ && transfer_buffer_id_ != 0) { | |
104 command_buffer_->DestroyTransferBuffer(transfer_buffer_id_); | |
105 transfer_buffer_id_ = 0; | |
106 } | |
107 | |
108 delete gles2_helper_; | |
109 gles2_helper_ = NULL; | |
110 | |
111 delete command_buffer_; | |
112 command_buffer_ = NULL; | |
113 } | |
114 | |
115 PGLBoolean PGLContextImpl::MakeCurrent(PGLContextImpl* pgl_context) { | |
116 if (!g_pgl_context_key_allocated) | |
117 return PGL_FALSE; | |
118 | |
119 gpu::ThreadLocalSetValue(g_pgl_context_key, pgl_context); | |
120 if (pgl_context) { | |
121 gles2::SetGLContext(pgl_context->gles2_implementation_); | |
122 | |
123 // Don't request latest error status from service. Just use the locally | |
124 // cached information from the last flush. | |
125 // TODO(apatrick): I'm not sure if this should actually change the | |
126 // current context if it fails. For now it gets changed even if it fails | |
127 // becuase making GL calls with a NULL context crashes. | |
128 #if defined(ENABLE_NEW_NPDEVICE_API) | |
129 if (pgl_context->command_buffer_->GetCachedError() != gpu::error::kNoError) | |
130 return PGL_FALSE; | |
131 #else | |
132 if (pgl_context->device_context_->error != NPDeviceContext3DError_NoError) | |
133 return PGL_FALSE; | |
134 #endif | |
135 } else { | |
136 gles2::SetGLContext(NULL); | |
137 } | |
138 | |
139 return PGL_TRUE; | |
140 } | |
141 | |
142 PGLBoolean PGLContextImpl::SwapBuffers() { | |
143 // Don't request latest error status from service. Just use the locally cached | |
144 // information from the last flush. | |
145 #if defined(ENABLE_NEW_NPDEVICE_API) | |
146 if (command_buffer_->GetCachedError() != gpu::error::kNoError) | |
147 return PGL_FALSE; | |
148 #else | |
149 if (device_context_->error != NPDeviceContext3DError_NoError) | |
150 return PGL_FALSE; | |
151 #endif | |
152 | |
153 gles2_implementation_->SwapBuffers(); | |
154 return PGL_TRUE; | |
155 } | |
156 | |
157 PGLInt PGLContextImpl::GetError() { | |
158 gpu::CommandBuffer::State state = command_buffer_->GetState(); | |
159 if (state.error == gpu::error::kNoError) { | |
160 return PGL_SUCCESS; | |
161 } else { | |
162 // All command buffer errors are unrecoverable. The error is treated as a | |
163 // lost context: destroy the context and create another one. | |
164 return PGL_CONTEXT_LOST; | |
165 } | |
166 } | |
167 } // namespace anonymous | |
168 | |
169 extern "C" { | |
170 PGLBoolean pglInitialize() { | |
171 if (g_pgl_context_key_allocated) | |
172 return PGL_TRUE; | |
173 | |
174 gles2::Initialize(); | |
175 g_pgl_context_key = gpu::ThreadLocalAlloc(); | |
176 g_pgl_context_key_allocated = true; | |
177 return PGL_TRUE; | |
178 } | |
179 | |
180 PGLBoolean pglTerminate() { | |
181 if (!g_pgl_context_key_allocated) | |
182 return PGL_TRUE; | |
183 | |
184 gpu::ThreadLocalFree(g_pgl_context_key); | |
185 g_pgl_context_key_allocated = false; | |
186 g_pgl_context_key = 0; | |
187 | |
188 gles2::Terminate(); | |
189 return PGL_TRUE; | |
190 } | |
191 | |
192 PGLContext pglCreateContext(NPP npp, | |
193 NPDevice* device, | |
194 NPDeviceContext3D* device_context) { | |
195 if (!g_pgl_context_key_allocated) | |
196 return NULL; | |
197 | |
198 PGLContextImpl* pgl_context = new PGLContextImpl( | |
199 npp, device, device_context); | |
200 if (pgl_context->Initialize(kTransferBufferSize)) { | |
201 return pgl_context; | |
202 } | |
203 | |
204 delete pgl_context; | |
205 return NULL; | |
206 } | |
207 | |
208 PGLBoolean pglMakeCurrent(PGLContext pgl_context) { | |
209 return PGLContextImpl::MakeCurrent(static_cast<PGLContextImpl*>(pgl_context)); | |
210 } | |
211 | |
212 PGLContext pglGetCurrentContext(void) { | |
213 if (!g_pgl_context_key_allocated) | |
214 return NULL; | |
215 | |
216 return static_cast<PGLContext>(gpu::ThreadLocalGetValue(g_pgl_context_key)); | |
217 } | |
218 | |
219 PGLBoolean pglSwapBuffers(void) { | |
220 PGLContextImpl* context = static_cast<PGLContextImpl*>( | |
221 pglGetCurrentContext()); | |
222 if (!context) | |
223 return PGL_FALSE; | |
224 | |
225 return context->SwapBuffers(); | |
226 } | |
227 | |
228 PGLBoolean pglDestroyContext(PGLContext pgl_context) { | |
229 if (!g_pgl_context_key_allocated) | |
230 return PGL_FALSE; | |
231 | |
232 if (!pgl_context) | |
233 return PGL_FALSE; | |
234 | |
235 if (pgl_context == pglGetCurrentContext()) | |
236 pglMakeCurrent(PGL_NO_CONTEXT); | |
237 | |
238 delete static_cast<PGLContextImpl*>(pgl_context); | |
239 return PGL_TRUE; | |
240 } | |
241 | |
242 PGLInt pglGetError() { | |
243 if (!g_pgl_context_key) | |
244 return PGL_NOT_INITIALIZED; | |
245 | |
246 PGLContextImpl* context = static_cast<PGLContextImpl*>( | |
247 pglGetCurrentContext()); | |
248 if (!context) | |
249 return PGL_BAD_CONTEXT; | |
250 | |
251 return context->GetError(); | |
252 } | |
253 } // extern "C" | |
OLD | NEW |