| 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 |