| OLD | NEW |
| 1 // Copyright (c) 2011 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/plugins/ppapi/ppb_graphics_3d_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h" |
| 6 | 6 |
| 7 #include "base/message_loop.h" | 7 #include "base/logging.h" |
| 8 #include "gpu/command_buffer/client/gles2_implementation.h" | 8 #include "ppapi/c/pp_completion_callback.h" |
| 9 #include "webkit/plugins/ppapi/plugin_module.h" | 9 #include "ppapi/c/pp_errors.h" |
| 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 11 #include "webkit/plugins/ppapi/resource_tracker.h" |
| 11 | 12 |
| 12 using ppapi::thunk::PPB_Graphics3D_API; | 13 using ppapi::thunk::PPB_Graphics3D_API; |
| 13 | 14 |
| 14 namespace webkit { | 15 namespace webkit { |
| 15 namespace ppapi { | 16 namespace ppapi { |
| 16 | 17 |
| 17 namespace { | |
| 18 const int32 kCommandBufferSize = 1024 * 1024; | |
| 19 const int32 kTransferBufferSize = 1024 * 1024; | |
| 20 | |
| 21 PP_Bool ShmToHandle(base::SharedMemory* shm, | |
| 22 size_t size, | |
| 23 int* shm_handle, | |
| 24 uint32_t* shm_size) { | |
| 25 if (!shm || !shm_handle || !shm_size) | |
| 26 return PP_FALSE; | |
| 27 #if defined(OS_POSIX) | |
| 28 *shm_handle = shm->handle().fd; | |
| 29 #elif defined(OS_WIN) | |
| 30 *shm_handle = reinterpret_cast<int>(shm->handle()); | |
| 31 #else | |
| 32 #error "Platform not supported." | |
| 33 #endif | |
| 34 *shm_size = size; | |
| 35 return PP_TRUE; | |
| 36 } | |
| 37 | |
| 38 PP_Graphics3DTrustedState PPStateFromGPUState( | |
| 39 const gpu::CommandBuffer::State& s) { | |
| 40 PP_Graphics3DTrustedState state = { | |
| 41 s.num_entries, | |
| 42 s.get_offset, | |
| 43 s.put_offset, | |
| 44 s.token, | |
| 45 static_cast<PPB_Graphics3DTrustedError>(s.error), | |
| 46 s.generation | |
| 47 }; | |
| 48 return state; | |
| 49 } | |
| 50 } // namespace. | |
| 51 | |
| 52 PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance) | 18 PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance) |
| 53 : Resource(instance), | 19 : Resource(instance) { |
| 54 bound_to_instance_(false), | |
| 55 commit_pending_(false), | |
| 56 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
| 57 } | 20 } |
| 58 | 21 |
| 59 PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { | 22 PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { |
| 60 DestroyGLES2Impl(); | |
| 61 } | 23 } |
| 62 | 24 |
| 63 // static | 25 // static |
| 64 PP_Resource PPB_Graphics3D_Impl::Create(PluginInstance* instance, | 26 PP_Resource PPB_Graphics3D_Impl::Create(PluginInstance* instance, |
| 65 PP_Config3D_Dev config, | 27 PP_Config3D_Dev config, |
| 66 PP_Resource share_context, | 28 PP_Resource share_context, |
| 67 const int32_t* attrib_list) { | 29 const int32_t* attrib_list) { |
| 68 scoped_refptr<PPB_Graphics3D_Impl> graphics_3d( | 30 scoped_refptr<PPB_Graphics3D_Impl> t(new PPB_Graphics3D_Impl(instance)); |
| 69 new PPB_Graphics3D_Impl(instance)); | 31 if (!t->Init(config, share_context, attrib_list)) |
| 70 | |
| 71 if (!graphics_3d->Init(config, share_context, attrib_list)) | |
| 72 return 0; | 32 return 0; |
| 73 | 33 return t->GetReference(); |
| 74 return graphics_3d->GetReference(); | |
| 75 } | |
| 76 | |
| 77 PP_Resource PPB_Graphics3D_Impl::CreateRaw(PluginInstance* instance, | |
| 78 PP_Config3D_Dev config, | |
| 79 PP_Resource share_context, | |
| 80 const int32_t* attrib_list) { | |
| 81 scoped_refptr<PPB_Graphics3D_Impl> graphics_3d( | |
| 82 new PPB_Graphics3D_Impl(instance)); | |
| 83 | |
| 84 if (!graphics_3d->InitRaw(config, share_context, attrib_list)) | |
| 85 return 0; | |
| 86 | |
| 87 return graphics_3d->GetReference(); | |
| 88 } | 34 } |
| 89 | 35 |
| 90 PPB_Graphics3D_API* PPB_Graphics3D_Impl::AsPPB_Graphics3D_API() { | 36 PPB_Graphics3D_API* PPB_Graphics3D_Impl::AsPPB_Graphics3D_API() { |
| 91 return this; | 37 return this; |
| 92 } | 38 } |
| 93 | 39 |
| 94 PP_Bool PPB_Graphics3D_Impl::InitCommandBuffer(int32_t size) { | 40 int32_t PPB_Graphics3D_Impl::GetAttribs(int32_t* attrib_list) { |
| 95 return PP_FromBool(GetCommandBuffer()->Initialize(size)); | 41 // TODO(alokp): Implement me. |
| 42 return PP_ERROR_FAILED; |
| 96 } | 43 } |
| 97 | 44 |
| 98 PP_Bool PPB_Graphics3D_Impl::GetRingBuffer(int* shm_handle, | 45 int32_t PPB_Graphics3D_Impl::SetAttribs(int32_t* attrib_list) { |
| 99 uint32_t* shm_size) { | 46 // TODO(alokp): Implement me. |
| 100 gpu::Buffer buffer = GetCommandBuffer()->GetRingBuffer(); | 47 return PP_ERROR_FAILED; |
| 101 return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size); | |
| 102 } | 48 } |
| 103 | 49 |
| 104 PP_Graphics3DTrustedState PPB_Graphics3D_Impl::GetState() { | 50 int32_t PPB_Graphics3D_Impl::SwapBuffers(PP_CompletionCallback callback) { |
| 105 return PPStateFromGPUState(GetCommandBuffer()->GetState()); | 51 // TODO(alokp): Implement me. |
| 106 } | 52 return PP_ERROR_FAILED; |
| 107 | |
| 108 int32_t PPB_Graphics3D_Impl::CreateTransferBuffer(uint32_t size) { | |
| 109 return GetCommandBuffer()->CreateTransferBuffer(size, -1); | |
| 110 } | |
| 111 | |
| 112 PP_Bool PPB_Graphics3D_Impl::DestroyTransferBuffer(int32_t id) { | |
| 113 GetCommandBuffer()->DestroyTransferBuffer(id); | |
| 114 return PP_TRUE; | |
| 115 } | |
| 116 | |
| 117 PP_Bool PPB_Graphics3D_Impl::GetTransferBuffer(int32_t id, | |
| 118 int* shm_handle, | |
| 119 uint32_t* shm_size) { | |
| 120 gpu::Buffer buffer = GetCommandBuffer()->GetTransferBuffer(id); | |
| 121 return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size); | |
| 122 } | |
| 123 | |
| 124 PP_Bool PPB_Graphics3D_Impl::Flush(int32_t put_offset) { | |
| 125 GetCommandBuffer()->Flush(put_offset); | |
| 126 return PP_TRUE; | |
| 127 } | |
| 128 | |
| 129 PP_Graphics3DTrustedState PPB_Graphics3D_Impl::FlushSync(int32_t put_offset) { | |
| 130 gpu::CommandBuffer::State state = GetCommandBuffer()->GetState(); | |
| 131 return PPStateFromGPUState( | |
| 132 GetCommandBuffer()->FlushSync(put_offset, state.get_offset)); | |
| 133 } | |
| 134 | |
| 135 PP_Graphics3DTrustedState PPB_Graphics3D_Impl::FlushSyncFast( | |
| 136 int32_t put_offset, | |
| 137 int32_t last_known_get) { | |
| 138 return PPStateFromGPUState( | |
| 139 GetCommandBuffer()->FlushSync(put_offset, last_known_get)); | |
| 140 } | |
| 141 | |
| 142 bool PPB_Graphics3D_Impl::BindToInstance(bool bind) { | |
| 143 bound_to_instance_ = bind; | |
| 144 return true; | |
| 145 } | |
| 146 | |
| 147 unsigned int PPB_Graphics3D_Impl::GetBackingTextureId() { | |
| 148 return platform_context_->GetBackingTextureId(); | |
| 149 } | |
| 150 | |
| 151 void PPB_Graphics3D_Impl::ViewInitiatedPaint() { | |
| 152 } | |
| 153 | |
| 154 void PPB_Graphics3D_Impl::ViewFlushedPaint() { | |
| 155 commit_pending_ = false; | |
| 156 | |
| 157 if (HasPendingSwap()) | |
| 158 SwapBuffersACK(PP_OK); | |
| 159 } | |
| 160 | |
| 161 gpu::CommandBuffer* PPB_Graphics3D_Impl::GetCommandBuffer() { | |
| 162 return platform_context_->GetCommandBuffer(); | |
| 163 } | |
| 164 | |
| 165 int32 PPB_Graphics3D_Impl::DoSwapBuffers() { | |
| 166 // We do not have a GLES2 implementation when using an OOP proxy. | |
| 167 // The plugin-side proxy is responsible for adding the SwapBuffers command | |
| 168 // to the command buffer in that case. | |
| 169 if (gles2_impl()) | |
| 170 gles2_impl()->SwapBuffers(); | |
| 171 | |
| 172 return PP_OK_COMPLETIONPENDING; | |
| 173 } | 53 } |
| 174 | 54 |
| 175 bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config, | 55 bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config, |
| 176 PP_Resource share_context, | 56 PP_Resource share_context, |
| 177 const int32_t* attrib_list) { | 57 const int32_t* attrib_list) { |
| 178 if (!InitRaw(config, share_context, attrib_list)) | 58 // TODO(alokp): Implement me. |
| 179 return false; | 59 return false; |
| 180 | |
| 181 gpu::CommandBuffer* command_buffer = GetCommandBuffer(); | |
| 182 if (!command_buffer->Initialize(kCommandBufferSize)) | |
| 183 return false; | |
| 184 | |
| 185 return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize); | |
| 186 } | |
| 187 | |
| 188 bool PPB_Graphics3D_Impl::InitRaw(PP_Config3D_Dev config, | |
| 189 PP_Resource share_context, | |
| 190 const int32_t* attrib_list) { | |
| 191 // TODO(alokp): Support shared context. | |
| 192 DCHECK_EQ(0, share_context); | |
| 193 if (share_context != 0) | |
| 194 return 0; | |
| 195 | |
| 196 platform_context_.reset(instance()->CreateContext3D()); | |
| 197 if (!platform_context_.get()) | |
| 198 return false; | |
| 199 | |
| 200 if (!platform_context_->Init()) | |
| 201 return false; | |
| 202 | |
| 203 platform_context_->SetContextLostCallback( | |
| 204 callback_factory_.NewCallback(&PPB_Graphics3D_Impl::OnContextLost)); | |
| 205 platform_context_->SetSwapBuffersCallback( | |
| 206 callback_factory_.NewCallback(&PPB_Graphics3D_Impl::OnSwapBuffers)); | |
| 207 return true; | |
| 208 } | |
| 209 | |
| 210 void PPB_Graphics3D_Impl::OnSwapBuffers() { | |
| 211 if (bound_to_instance_) { | |
| 212 // If we are bound to the instance, we need to ask the compositor | |
| 213 // to commit our backing texture so that the graphics appears on the page. | |
| 214 // When the backing texture will be committed we get notified via | |
| 215 // ViewFlushedPaint(). | |
| 216 instance()->CommitBackingTexture(); | |
| 217 commit_pending_ = true; | |
| 218 } else if (HasPendingSwap()) { | |
| 219 // If we're off-screen, no need to trigger and wait for compositing. | |
| 220 // Just send the swap-buffers ACK to the plugin immediately. | |
| 221 commit_pending_ = false; | |
| 222 SwapBuffersACK(PP_OK); | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 void PPB_Graphics3D_Impl::OnContextLost() { | |
| 227 if (bound_to_instance_) | |
| 228 instance()->BindGraphics(instance()->pp_instance(), 0); | |
| 229 | |
| 230 // Send context lost to plugin. This may have been caused by a PPAPI call, so | |
| 231 // avoid re-entering. | |
| 232 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | |
| 233 this, &PPB_Graphics3D_Impl::SendContextLost)); | |
| 234 } | |
| 235 | |
| 236 void PPB_Graphics3D_Impl::SendContextLost() { | |
| 237 // By the time we run this, the instance may have been deleted, or in the | |
| 238 // process of being deleted. Even in the latter case, we don't want to send a | |
| 239 // callback after DidDestroy. | |
| 240 if (!instance() || !instance()->container()) | |
| 241 return; | |
| 242 | |
| 243 const PPP_Graphics3D_Dev* ppp_graphics_3d = | |
| 244 static_cast<const PPP_Graphics3D_Dev*>( | |
| 245 instance()->module()->GetPluginInterface( | |
| 246 PPP_GRAPHICS_3D_DEV_INTERFACE)); | |
| 247 if (ppp_graphics_3d) | |
| 248 ppp_graphics_3d->Graphics3DContextLost(instance()->pp_instance()); | |
| 249 } | 60 } |
| 250 | 61 |
| 251 } // namespace ppapi | 62 } // namespace ppapi |
| 252 } // namespace webkit | 63 } // namespace webkit |
| 253 | 64 |
| OLD | NEW |