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/plugins/ppapi/ppb_graphics_3d_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/message_loop.h" |
8 #include "ppapi/c/pp_completion_callback.h" | 8 #include "gpu/command_buffer/client/gles2_implementation.h" |
9 #include "ppapi/c/pp_errors.h" | 9 #include "webkit/plugins/ppapi/plugin_module.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" | |
12 | 11 |
13 using ppapi::thunk::PPB_Graphics3D_API; | 12 using ppapi::thunk::PPB_Graphics3D_API; |
14 | 13 |
15 namespace webkit { | 14 namespace webkit { |
16 namespace ppapi { | 15 namespace ppapi { |
17 | 16 |
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 | |
18 PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance) | 52 PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance) |
19 : Resource(instance) { | 53 : Resource(instance), |
54 bound_to_instance_(false), | |
55 commit_pending_(false), | |
56 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
20 } | 57 } |
21 | 58 |
22 PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { | 59 PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { |
60 DestroyGLES2Impl(); | |
23 } | 61 } |
24 | 62 |
25 // static | 63 // static |
26 PP_Resource PPB_Graphics3D_Impl::Create(PluginInstance* instance, | 64 PP_Resource PPB_Graphics3D_Impl::Create(PluginInstance* instance, |
27 PP_Config3D_Dev config, | 65 PP_Config3D_Dev config, |
28 PP_Resource share_context, | 66 PP_Resource share_context, |
29 const int32_t* attrib_list) { | 67 const int32_t* attrib_list) { |
30 scoped_refptr<PPB_Graphics3D_Impl> t(new PPB_Graphics3D_Impl(instance)); | 68 scoped_refptr<PPB_Graphics3D_Impl> graphics_3d( |
31 if (!t->Init(config, share_context, attrib_list)) | 69 new PPB_Graphics3D_Impl(instance)); |
70 | |
71 if (!graphics_3d->Init(config, share_context, attrib_list)) | |
32 return 0; | 72 return 0; |
33 return t->GetReference(); | 73 |
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(); | |
34 } | 88 } |
35 | 89 |
36 PPB_Graphics3D_API* PPB_Graphics3D_Impl::AsPPB_Graphics3D_API() { | 90 PPB_Graphics3D_API* PPB_Graphics3D_Impl::AsPPB_Graphics3D_API() { |
37 return this; | 91 return this; |
38 } | 92 } |
39 | 93 |
40 int32_t PPB_Graphics3D_Impl::GetAttribs(int32_t* attrib_list) { | 94 PP_Bool PPB_Graphics3D_Impl::InitCommandBuffer(int32_t size) { |
41 // TODO(alokp): Implement me. | 95 return PP_FromBool(GetCommandBuffer()->Initialize(size)); |
42 return PP_ERROR_FAILED; | |
43 } | 96 } |
44 | 97 |
45 int32_t PPB_Graphics3D_Impl::SetAttribs(int32_t* attrib_list) { | 98 PP_Bool PPB_Graphics3D_Impl::GetRingBuffer(int* shm_handle, |
46 // TODO(alokp): Implement me. | 99 uint32_t* shm_size) { |
47 return PP_ERROR_FAILED; | 100 gpu::Buffer buffer = GetCommandBuffer()->GetRingBuffer(); |
101 return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size); | |
48 } | 102 } |
49 | 103 |
50 int32_t PPB_Graphics3D_Impl::SwapBuffers(PP_CompletionCallback callback) { | 104 PP_Graphics3DTrustedState PPB_Graphics3D_Impl::GetState() { |
51 // TODO(alokp): Implement me. | 105 return PPStateFromGPUState(GetCommandBuffer()->GetState()); |
52 return PP_ERROR_FAILED; | 106 } |
107 | |
108 PP_Bool PPB_Graphics3D_Impl::Flush(int32_t put_offset) { | |
109 GetCommandBuffer()->Flush(put_offset); | |
110 return PP_TRUE; | |
111 } | |
112 | |
113 PP_Graphics3DTrustedState PPB_Graphics3D_Impl::FlushSync(int32_t put_offset) { | |
114 gpu::CommandBuffer::State state = GetCommandBuffer()->GetState(); | |
115 return PPStateFromGPUState( | |
116 GetCommandBuffer()->FlushSync(put_offset, state.get_offset)); | |
117 } | |
118 | |
119 int32_t PPB_Graphics3D_Impl::CreateTransferBuffer(uint32_t size) { | |
120 return GetCommandBuffer()->CreateTransferBuffer(size, -1); | |
121 } | |
122 | |
123 PP_Bool PPB_Graphics3D_Impl::DestroyTransferBuffer(int32_t id) { | |
124 GetCommandBuffer()->DestroyTransferBuffer(id); | |
125 return PP_TRUE; | |
126 } | |
127 | |
128 PP_Bool PPB_Graphics3D_Impl::GetTransferBuffer(int32_t id, | |
129 int* shm_handle, | |
130 uint32_t* shm_size) { | |
131 gpu::Buffer buffer = GetCommandBuffer()->GetTransferBuffer(id); | |
132 return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size); | |
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; | |
53 } | 173 } |
54 | 174 |
55 bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config, | 175 bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config, |
56 PP_Resource share_context, | 176 PP_Resource share_context, |
57 const int32_t* attrib_list) { | 177 const int32_t* attrib_list) { |
58 // TODO(alokp): Implement me. | 178 if (!InitRaw(config, share_context, attrib_list)) |
59 return false; | 179 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 // TODO(alokp): Check if we really need to wait for the compositor to | |
217 // complete before sending the swap buffers acknowledgement. It will be | |
218 // nice if we could let plugin start drawing the next frame while the | |
219 // compositor is busy. | |
piman
2011/07/15 18:38:11
We really need to wait here, otherwise the plugin
| |
220 instance()->CommitBackingTexture(); | |
221 commit_pending_ = true; | |
222 } else if (HasPendingSwap()) { | |
223 // If we're off-screen, no need to trigger and wait for compositing. | |
224 // Just send the swap-buffers ACK to the plugin immediately. | |
225 commit_pending_ = false; | |
226 SwapBuffersACK(PP_OK); | |
227 } | |
228 } | |
229 | |
230 void PPB_Graphics3D_Impl::OnContextLost() { | |
231 if (bound_to_instance_) | |
232 instance()->BindGraphics(instance()->pp_instance(), 0); | |
233 | |
234 // Send context lost to plugin. This may have been caused by a PPAPI call, so | |
235 // avoid re-entering. | |
236 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | |
237 this, &PPB_Graphics3D_Impl::SendContextLost)); | |
238 } | |
239 | |
240 void PPB_Graphics3D_Impl::SendContextLost() { | |
241 // By the time we run this, the instance may have been deleted, or in the | |
242 // process of being deleted. Even in the latter case, we don't want to send a | |
243 // callback after DidDestroy. | |
244 if (!instance() || !instance()->container()) | |
245 return; | |
246 | |
247 const PPP_Graphics3D_Dev* ppp_graphics_3d = | |
248 static_cast<const PPP_Graphics3D_Dev*>( | |
249 instance()->module()->GetPluginInterface( | |
250 PPP_GRAPHICS_3D_DEV_INTERFACE)); | |
251 if (ppp_graphics_3d) | |
252 ppp_graphics_3d->Graphics3DContextLost(instance()->pp_instance()); | |
60 } | 253 } |
61 | 254 |
62 } // namespace ppapi | 255 } // namespace ppapi |
63 } // namespace webkit | 256 } // namespace webkit |
64 | 257 |
OLD | NEW |