| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/glue/plugins/pepper_graphics_3d.h" | 5 #include "webkit/glue/plugins/pepper_graphics_3d.h" |
| 6 | 6 |
| 7 #include "gpu/command_buffer/common/command_buffer.h" | 7 #include "gpu/command_buffer/common/command_buffer.h" |
| 8 #include "base/singleton.h" | 8 #include "base/singleton.h" |
| 9 #include "base/thread_local.h" | 9 #include "base/thread_local.h" |
| 10 #include "ppapi/c/dev/ppb_graphics_3d_dev.h" | 10 #include "ppapi/c/dev/ppb_graphics_3d_dev.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 if (!graphics3d) { | 84 if (!graphics3d) { |
| 85 Graphics3D::ResetCurrent(); | 85 Graphics3D::ResetCurrent(); |
| 86 return true; | 86 return true; |
| 87 } else { | 87 } else { |
| 88 scoped_refptr<Graphics3D> context(Resource::GetAs<Graphics3D>(graphics3d)); | 88 scoped_refptr<Graphics3D> context(Resource::GetAs<Graphics3D>(graphics3d)); |
| 89 return context.get() && context->MakeCurrent(); | 89 return context.get() && context->MakeCurrent(); |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 PP_Resource GetCurrentContext() { | 93 PP_Resource GetCurrentContext() { |
| 94 Graphics3D* currentContext = Graphics3D::GetCurrent(); | 94 Graphics3D* current_context = Graphics3D::GetCurrent(); |
| 95 return currentContext ? currentContext->GetReference() : 0; | 95 return current_context ? current_context->GetReference() : 0; |
| 96 } | 96 } |
| 97 | 97 |
| 98 bool SwapBuffers(PP_Resource graphics3d) { | 98 bool SwapBuffers(PP_Resource graphics3d) { |
| 99 scoped_refptr<Graphics3D> context(Resource::GetAs<Graphics3D>(graphics3d)); | 99 scoped_refptr<Graphics3D> context(Resource::GetAs<Graphics3D>(graphics3d)); |
| 100 return context && context->SwapBuffers(); | 100 return context && context->SwapBuffers(); |
| 101 } | 101 } |
| 102 | 102 |
| 103 uint32_t GetError() { | 103 uint32_t GetError() { |
| 104 // TODO(neb): Figure out error checking. | 104 // Technically, this should return the last error that occurred on the current |
| 105 return PP_GRAPHICS_3D_ERROR_SUCCESS; | 105 // thread, rather than an error associated with a particular context. |
| 106 // TODO(apatrick): Fix this. |
| 107 Graphics3D* current_context = Graphics3D::GetCurrent(); |
| 108 if (!current_context) |
| 109 return 0; |
| 110 |
| 111 return current_context->GetError(); |
| 106 } | 112 } |
| 107 | 113 |
| 108 const PPB_Graphics3D_Dev ppb_graphics3d = { | 114 const PPB_Graphics3D_Dev ppb_graphics3d = { |
| 109 &IsGraphics3D, | 115 &IsGraphics3D, |
| 110 &GetConfigs, | 116 &GetConfigs, |
| 111 &ChooseConfig, | 117 &ChooseConfig, |
| 112 &GetConfigAttrib, | 118 &GetConfigAttrib, |
| 113 &QueryString, | 119 &QueryString, |
| 114 &CreateContext, | 120 &CreateContext, |
| 115 &GetProcAddress, | 121 &GetProcAddress, |
| 116 &MakeCurrent, | 122 &MakeCurrent, |
| 117 &GetCurrentContext, | 123 &GetCurrentContext, |
| 118 &SwapBuffers, | 124 &SwapBuffers, |
| 119 &GetError | 125 &GetError |
| 120 }; | 126 }; |
| 121 | 127 |
| 122 } // namespace | 128 } // namespace |
| 123 | 129 |
| 124 Graphics3D::Graphics3D(PluginModule* module) | 130 Graphics3D::Graphics3D(PluginModule* module) |
| 125 : Resource(module), | 131 : Resource(module), |
| 126 command_buffer_(NULL), | 132 bound_instance_(NULL) { |
| 127 transfer_buffer_id_(0), | |
| 128 method_factory3d_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
| 129 } | 133 } |
| 130 | 134 |
| 131 const PPB_Graphics3D_Dev* Graphics3D::GetInterface() { | 135 const PPB_Graphics3D_Dev* Graphics3D::GetInterface() { |
| 132 return &ppb_graphics3d; | 136 return &ppb_graphics3d; |
| 133 } | 137 } |
| 134 | 138 |
| 135 Graphics3D* Graphics3D::GetCurrent() { | 139 Graphics3D* Graphics3D::GetCurrent() { |
| 136 return CurrentContextKey::get()->Get(); | 140 return CurrentContextKey::get()->Get(); |
| 137 } | 141 } |
| 138 | 142 |
| 139 void Graphics3D::ResetCurrent() { | 143 void Graphics3D::ResetCurrent() { |
| 140 CurrentContextKey::get()->Set(NULL); | 144 CurrentContextKey::get()->Set(NULL); |
| 141 } | 145 } |
| 142 | 146 |
| 143 Graphics3D::~Graphics3D() { | 147 Graphics3D::~Graphics3D() { |
| 144 Destroy(); | 148 Destroy(); |
| 145 } | 149 } |
| 146 | 150 |
| 147 bool Graphics3D::Init(PP_Instance instance_id, int32_t config, | 151 bool Graphics3D::Init(PP_Instance instance_id, int32_t config, |
| 148 const int32_t* attrib_list) { | 152 const int32_t* attrib_list) { |
| 149 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); | 153 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); |
| 150 if (!instance) { | 154 if (!instance) { |
| 151 return false; | 155 return false; |
| 152 } | 156 } |
| 153 | 157 |
| 154 // Create and initialize the objects required to issue GLES2 calls. | 158 // Create and initialize the objects required to issue GLES2 calls. |
| 155 platform_context_.reset(instance->delegate()->CreateContext3D()); | 159 platform_context_.reset(instance->delegate()->CreateContext3D()); |
| 156 if (!platform_context_.get()) | 160 if (!platform_context_.get()) { |
| 157 return false; | 161 Destroy(); |
| 158 | |
| 159 if (!platform_context_->Init(instance->position(), | |
| 160 instance->clip())) { | |
| 161 platform_context_.reset(); | |
| 162 return false; | 162 return false; |
| 163 } | 163 } |
| 164 command_buffer_ = platform_context_->GetCommandBuffer(); | 164 |
| 165 gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_)); | 165 if (!platform_context_->Init()) { |
| 166 gpu::Buffer buffer = command_buffer_->GetRingBuffer(); | 166 Destroy(); |
| 167 if (gles2_helper_->Initialize(buffer.size)) { | 167 return false; |
| 168 transfer_buffer_id_ = | |
| 169 command_buffer_->CreateTransferBuffer(kTransferBufferSize); | |
| 170 gpu::Buffer transfer_buffer = | |
| 171 command_buffer_->GetTransferBuffer(transfer_buffer_id_); | |
| 172 if (transfer_buffer.ptr) { | |
| 173 gles2_implementation_.reset(new gpu::gles2::GLES2Implementation( | |
| 174 gles2_helper_.get(), | |
| 175 transfer_buffer.size, | |
| 176 transfer_buffer.ptr, | |
| 177 transfer_buffer_id_, | |
| 178 false)); | |
| 179 platform_context_->SetNotifyRepaintTask( | |
| 180 method_factory3d_.NewRunnableMethod(&Graphics3D::HandleRepaint, | |
| 181 instance_id)); | |
| 182 return true; | |
| 183 } | |
| 184 } | 168 } |
| 185 | 169 |
| 186 // Tear everything down if initialization failed. | 170 gles2_implementation_ = platform_context_->GetGLES2Implementation(); |
| 187 Destroy(); | 171 DCHECK(gles2_implementation_); |
| 188 return false; | 172 |
| 173 return true; |
| 174 } |
| 175 |
| 176 bool Graphics3D::BindToInstance(PluginInstance* new_instance) { |
| 177 if (bound_instance_ == new_instance) |
| 178 return true; // Rebinding the same device, nothing to do. |
| 179 if (bound_instance_ && new_instance) |
| 180 return false; // Can't change a bound device. |
| 181 |
| 182 if (new_instance) { |
| 183 // Resize the backing texture to the size of the instance when it is bound. |
| 184 platform_context_->ResizeBackingTexture(new_instance->position().size()); |
| 185 |
| 186 // This is a temporary hack. The SwapBuffers is issued to force the resize |
| 187 // to take place before any subsequent rendering. This might lead to a |
| 188 // partially rendered frame being displayed. It is also not thread safe |
| 189 // since the SwapBuffers is written to the command buffer and that command |
| 190 // buffer might be written to by another thread. |
| 191 // TODO(apatrick): Figure out the semantics of binding and resizing. |
| 192 platform_context_->SwapBuffers(); |
| 193 } |
| 194 |
| 195 bound_instance_ = new_instance; |
| 196 return true; |
| 189 } | 197 } |
| 190 | 198 |
| 191 bool Graphics3D::MakeCurrent() { | 199 bool Graphics3D::MakeCurrent() { |
| 192 if (!command_buffer_) | 200 if (!platform_context_.get()) |
| 193 return false; | 201 return false; |
| 194 | 202 |
| 195 CurrentContextKey::get()->Set(this); | 203 CurrentContextKey::get()->Set(this); |
| 196 | 204 |
| 197 // Don't request latest error status from service. Just use the locally | 205 // TODO(apatrick): Return false on context lost. |
| 198 // cached information from the last flush. | |
| 199 // TODO(apatrick): I'm not sure if this should actually change the | |
| 200 // current context if it fails. For now it gets changed even if it fails | |
| 201 // becuase making GL calls with a NULL context crashes. | |
| 202 // TODO(neb): Figure out error checking. | |
| 203 // if (command_buffer_->GetCachedError() != gpu::error::kNoError) | |
| 204 // return false; | |
| 205 return true; | 206 return true; |
| 206 } | 207 } |
| 207 | 208 |
| 208 bool Graphics3D::SwapBuffers() { | 209 bool Graphics3D::SwapBuffers() { |
| 209 if (!command_buffer_) | 210 if (!platform_context_.get()) |
| 210 return false; | 211 return false; |
| 211 | 212 |
| 212 // Don't request latest error status from service. Just use the locally cached | 213 return platform_context_->SwapBuffers(); |
| 213 // information from the last flush. | 214 } |
| 214 // TODO(neb): Figure out error checking. | |
| 215 // if (command_buffer_->GetCachedError() != gpu::error::kNoError) | |
| 216 // return false; | |
| 217 | 215 |
| 218 gles2_implementation_->SwapBuffers(); | 216 unsigned Graphics3D::GetError() { |
| 219 return true; | 217 if (!platform_context_.get()) |
| 218 return 0; |
| 219 |
| 220 return platform_context_->GetError(); |
| 221 } |
| 222 |
| 223 void Graphics3D::ResizeBackingTexture(const gfx::Size& size) { |
| 224 if (!platform_context_.get()) |
| 225 return; |
| 226 |
| 227 platform_context_->ResizeBackingTexture(size); |
| 228 } |
| 229 |
| 230 void Graphics3D::SetSwapBuffersCallback(Callback0::Type* callback) { |
| 231 if (!platform_context_.get()) |
| 232 return; |
| 233 |
| 234 platform_context_->SetSwapBuffersCallback(callback); |
| 235 } |
| 236 |
| 237 unsigned Graphics3D::GetBackingTextureId() { |
| 238 if (!platform_context_.get()) |
| 239 return 0; |
| 240 |
| 241 return platform_context_->GetBackingTextureId(); |
| 220 } | 242 } |
| 221 | 243 |
| 222 void Graphics3D::Destroy() { | 244 void Graphics3D::Destroy() { |
| 223 if (GetCurrent() == this) { | 245 if (GetCurrent() == this) { |
| 224 ResetCurrent(); | 246 ResetCurrent(); |
| 225 } | 247 } |
| 226 | 248 |
| 227 method_factory3d_.RevokeAll(); | 249 gles2_implementation_ = NULL; |
| 228 | 250 |
| 229 gles2_implementation_.reset(); | |
| 230 | |
| 231 if (command_buffer_ && transfer_buffer_id_ != 0) { | |
| 232 command_buffer_->DestroyTransferBuffer(transfer_buffer_id_); | |
| 233 transfer_buffer_id_ = 0; | |
| 234 } | |
| 235 | |
| 236 gles2_helper_.reset(); | |
| 237 | |
| 238 // Platform context owns the command buffer. | |
| 239 platform_context_.reset(); | 251 platform_context_.reset(); |
| 240 command_buffer_ = NULL; | |
| 241 } | |
| 242 | |
| 243 void Graphics3D::HandleRepaint(PP_Instance instance_id) { | |
| 244 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); | |
| 245 if (instance) { | |
| 246 instance->Graphics3DContextLost(); | |
| 247 if (platform_context_.get()) { | |
| 248 platform_context_->SetNotifyRepaintTask( | |
| 249 method_factory3d_.NewRunnableMethod(&Graphics3D::HandleRepaint, | |
| 250 instance_id)); | |
| 251 } | |
| 252 } | |
| 253 } | 252 } |
| 254 | 253 |
| 255 } // namespace pepper | 254 } // namespace pepper |
| 256 | 255 |
| OLD | NEW |