OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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/logging.h" |
8 #include "base/message_loop.h" | |
9 #include "gpu/command_buffer/client/gles2_cmd_helper.h" | |
10 #include "gpu/command_buffer/client/gles2_implementation.h" | |
11 #include "gpu/command_buffer/common/command_buffer.h" | |
8 #include "ppapi/c/pp_completion_callback.h" | 12 #include "ppapi/c/pp_completion_callback.h" |
9 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/c/pp_errors.h" |
10 #include "webkit/plugins/ppapi/common.h" | 14 #include "webkit/plugins/ppapi/common.h" |
15 #include "webkit/plugins/ppapi/plugin_module.h" | |
16 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | |
11 | 17 |
12 namespace webkit { | 18 namespace webkit { |
13 namespace ppapi { | 19 namespace ppapi { |
14 | 20 |
15 namespace { | 21 namespace { |
22 const int32 kCommandBufferSize = 1024 * 1024; | |
23 const int32 kTransferBufferSize = 1024 * 1024; | |
16 | 24 |
17 int32_t GetConfigs(PP_Config3D_Dev* configs, | 25 int32_t GetConfigs(PP_Config3D_Dev* configs, |
18 int32_t config_size, | 26 int32_t config_size, |
19 int32_t* num_config) { | 27 int32_t* num_config) { |
20 // TODO(alokp): Implement me. | 28 // TODO(alokp): Implement me. |
21 return PP_ERROR_FAILED; | 29 return PP_ERROR_FAILED; |
22 } | 30 } |
23 | 31 |
24 int32_t GetConfigAttribs(PP_Config3D_Dev config, int32_t* attrib_list) { | 32 int32_t GetConfigAttribs(PP_Config3D_Dev config, int32_t* attrib_list) { |
25 // TODO(alokp): Implement me. | 33 // TODO(alokp): Implement me. |
(...skipping 19 matching lines...) Expand all Loading... | |
45 return 0; | 53 return 0; |
46 | 54 |
47 scoped_refptr<PPB_Graphics3D_Impl> context( | 55 scoped_refptr<PPB_Graphics3D_Impl> context( |
48 new PPB_Graphics3D_Impl(instance)); | 56 new PPB_Graphics3D_Impl(instance)); |
49 if (!context->Init(config, share_context, attrib_list)) | 57 if (!context->Init(config, share_context, attrib_list)) |
50 return 0; | 58 return 0; |
51 | 59 |
52 return context->GetReference(); | 60 return context->GetReference(); |
53 } | 61 } |
54 | 62 |
55 PP_Bool IsGraphics3D(PP_Resource resource) { | 63 PP_Bool IsGraphics3D(PP_Resource resource_id) { |
56 return BoolToPPBool(!!Resource::GetAs<PPB_Graphics3D_Impl>(resource)); | 64 return BoolToPPBool(!!Resource::GetAs<PPB_Graphics3D_Impl>(resource_id)); |
57 } | 65 } |
58 | 66 |
59 int32_t GetAttribs(PP_Resource context, int32_t* attrib_list) { | 67 int32_t GetAttribs(PP_Resource context_id, int32_t* attrib_list) { |
60 // TODO(alokp): Implement me. | 68 // TODO(alokp): Implement me. |
61 return 0; | 69 return 0; |
62 } | 70 } |
63 | 71 |
64 int32_t SetAttribs(PP_Resource context, int32_t* attrib_list) { | 72 int32_t SetAttribs(PP_Resource context_id, int32_t* attrib_list) { |
65 // TODO(alokp): Implement me. | 73 // TODO(alokp): Implement me. |
66 return 0; | 74 return 0; |
67 } | 75 } |
68 | 76 |
69 int32_t SwapBuffers(PP_Resource context, PP_CompletionCallback callback) { | 77 int32_t SwapBuffers(PP_Resource context_id, PP_CompletionCallback callback) { |
70 // TODO(alokp): Implement me. | 78 scoped_refptr<PPB_Graphics3D_Impl> context( |
71 return 0; | 79 Resource::GetAs<PPB_Graphics3D_Impl>(context_id)); |
80 return context->SwapBuffers(callback); | |
72 } | 81 } |
73 | 82 |
74 const PPB_Graphics3D_Dev ppb_graphics3d = { | 83 const PPB_Graphics3D_Dev ppb_graphics3d = { |
75 &GetConfigs, | 84 &GetConfigs, |
76 &GetConfigAttribs, | 85 &GetConfigAttribs, |
77 &GetString, | 86 &GetString, |
78 &Create, | 87 &Create, |
79 &IsGraphics3D, | 88 &IsGraphics3D, |
80 &GetAttribs, | 89 &GetAttribs, |
81 &SetAttribs, | 90 &SetAttribs, |
82 &SwapBuffers | 91 &SwapBuffers |
83 }; | 92 }; |
84 | 93 |
85 } // namespace | 94 } // namespace |
86 | 95 |
87 PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance) | 96 PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance) |
88 : Resource(instance) { | 97 : Resource(instance), |
98 bound_to_instance_(false), | |
99 transfer_buffer_id_(0), | |
100 commit_initiated_(false), | |
101 swap_callback_(PP_BlockUntilComplete()), | |
102 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
89 } | 103 } |
90 | 104 |
91 PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { | 105 PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { |
106 gles2_impl_.reset(); | |
107 | |
108 gpu::CommandBuffer* command_buffer = GetCommandBuffer(); | |
109 if (command_buffer && transfer_buffer_id_ != 0) { | |
110 command_buffer->DestroyTransferBuffer(transfer_buffer_id_); | |
111 transfer_buffer_id_ = 0; | |
112 } | |
113 | |
114 command_buffer_helper_.reset(); | |
115 platform_context_.reset(); | |
92 } | 116 } |
93 | 117 |
94 const PPB_Graphics3D_Dev* PPB_Graphics3D_Impl::GetInterface() { | 118 const PPB_Graphics3D_Dev* PPB_Graphics3D_Impl::GetInterface() { |
95 return &ppb_graphics3d; | 119 return &ppb_graphics3d; |
96 } | 120 } |
97 | 121 |
98 PPB_Graphics3D_Impl* PPB_Graphics3D_Impl::AsPPB_Graphics3D_Impl() { | 122 PPB_Graphics3D_Impl* PPB_Graphics3D_Impl::AsPPB_Graphics3D_Impl() { |
99 return this; | 123 return this; |
100 } | 124 } |
101 | 125 |
102 bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config, | 126 bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config, |
103 PP_Resource share_context, | 127 PP_Resource share_context, |
104 const int32_t* attrib_list) { | 128 const int32_t* attrib_list) { |
piman
2011/04/12 03:23:40
Somewhere, something needs to parse the attrib_lis
| |
105 // TODO(alokp): Implement me. | 129 if (!InitRaw(config, share_context, attrib_list)) |
106 return false; | 130 return false; |
131 | |
132 if (!CreateImplementation()) | |
133 return false; | |
134 | |
135 return true; | |
136 } | |
137 | |
138 bool PPB_Graphics3D_Impl::InitRaw(PP_Config3D_Dev config, | |
139 PP_Resource share_context, | |
140 const int32_t* attrib_list) { | |
141 platform_context_.reset(instance()->CreateContext3D()); | |
142 if (!platform_context_.get()) | |
143 return false; | |
144 | |
145 if (!platform_context_->Init()) | |
146 return false; | |
147 | |
148 platform_context_->SetContextLostCallback( | |
149 callback_factory_.NewCallback(&PPB_Graphics3D_Impl::OnContextLost)); | |
150 platform_context_->SetSwapBuffersCallback( | |
151 callback_factory_.NewCallback(&PPB_Graphics3D_Impl::OnSwapBuffers)); | |
152 return true; | |
153 } | |
154 | |
155 gpu::CommandBuffer* PPB_Graphics3D_Impl::GetCommandBuffer() { | |
156 DCHECK(platform_context_.get()); | |
157 return platform_context_->GetCommandBuffer(); | |
158 } | |
159 | |
160 unsigned int PPB_Graphics3D_Impl::GetBackingTextureId() { | |
161 DCHECK(platform_context_.get()); | |
162 return platform_context_->GetBackingTextureId(); | |
163 } | |
164 | |
165 bool PPB_Graphics3D_Impl::BindToInstance(bool bind) { | |
166 bound_to_instance_ = bind; | |
167 return true; | |
168 } | |
169 | |
170 void PPB_Graphics3D_Impl::ViewInitiatedPaint() { | |
171 } | |
172 | |
173 void PPB_Graphics3D_Impl::ViewFlushedPaint() { | |
174 if (commit_initiated_ && swap_callback_.func) { | |
175 commit_initiated_ = false; | |
176 SendSwapBuffers(); | |
177 } | |
178 } | |
179 | |
180 int32_t PPB_Graphics3D_Impl::SwapBuffers(PP_CompletionCallback callback) { | |
181 if (!callback.func) { | |
182 // Blocking SwapBuffers isn't supported (since we have to be on the main | |
183 // thread). | |
184 return PP_ERROR_BADARGUMENT; | |
185 } | |
186 | |
187 if (swap_callback_.func) { | |
188 // Already a pending SwapBuffers that hasn't returned yet. | |
189 return PP_ERROR_INPROGRESS; | |
190 } | |
191 | |
192 swap_callback_ = callback; | |
193 DCHECK(gles2_impl()); | |
piman
2011/04/12 03:23:40
This DCHECK will fail when the interface is proxie
| |
194 gles2_impl()->SwapBuffers(); | |
195 return PP_ERROR_WOULDBLOCK; | |
196 } | |
197 | |
198 bool PPB_Graphics3D_Impl::CreateImplementation() { | |
199 gpu::CommandBuffer* command_buffer = platform_context_->GetCommandBuffer(); | |
200 DCHECK(command_buffer); | |
201 | |
202 if (!command_buffer->Initialize(kCommandBufferSize)) | |
203 return false; | |
204 | |
205 // Create the GLES2 helper, which writes the command buffer protocol. | |
206 command_buffer_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer)); | |
207 if (!command_buffer_helper_->Initialize(kCommandBufferSize)) | |
208 return false; | |
209 | |
210 // Create a transfer buffer used to copy resources between the renderer | |
211 // process and the GPU process. | |
212 transfer_buffer_id_ = | |
213 command_buffer->CreateTransferBuffer(kTransferBufferSize); | |
214 if (transfer_buffer_id_ < 0) | |
215 return false; | |
216 | |
217 // Map the buffer into the renderer process's address space. | |
218 gpu::Buffer transfer_buffer = | |
219 command_buffer->GetTransferBuffer(transfer_buffer_id_); | |
220 if (!transfer_buffer.ptr) | |
221 return false; | |
222 | |
223 // Create the object exposing the OpenGL API. | |
224 gles2_impl_.reset(new gpu::gles2::GLES2Implementation( | |
225 command_buffer_helper_.get(), | |
226 transfer_buffer.size, | |
227 transfer_buffer.ptr, | |
228 transfer_buffer_id_, | |
229 false)); | |
230 | |
231 return gles2_impl_.get() != NULL; | |
232 } | |
233 | |
234 void PPB_Graphics3D_Impl::OnSwapBuffers() { | |
235 if (bound_to_instance_) { | |
236 // If we are bound to the instance, we need to ask the compositor | |
237 // to commit our backing texture so that the graphics appears on the page. | |
238 // When the backing texture will be committed we get notified via | |
239 // ViewFlushedPaint(). | |
240 // TODO(alokp): Check if we really need to wait for the compositor to | |
241 // complete before sending the swap buffers acknowledgement. It will be | |
242 // nice if we could let plugin start drawing the next frame while the | |
243 // compositor is busy. | |
244 instance()->CommitBackingTexture(); | |
245 } else if (swap_callback_.func) { | |
246 // If we're off-screen, no need to trigger and wait for compositing. | |
247 // Just run the swap-buffers callback immediately. | |
248 SendSwapBuffers(); | |
249 } | |
250 } | |
251 | |
252 void PPB_Graphics3D_Impl::OnContextLost() { | |
253 if (bound_to_instance_) | |
254 instance()->BindGraphics(0); | |
255 | |
256 // Send context lost to plugin. This may have been caused by a PPAPI call, so | |
257 // avoid re-entering. | |
258 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | |
259 this, &PPB_Graphics3D_Impl::SendContextLost)); | |
260 } | |
261 | |
262 void PPB_Graphics3D_Impl::SendSwapBuffers() { | |
263 // We must clear swap_callback_ before issuing the callback. It will be | |
264 // common for the plugin to issue another SwapBuffers in response to the | |
265 // callback, and we don't want to think that a callback is already pending. | |
266 DCHECK(swap_callback_.func); | |
267 PP_CompletionCallback callback = PP_BlockUntilComplete(); | |
268 std::swap(callback, swap_callback_); | |
269 PP_RunCompletionCallback(&callback, PP_OK); | |
270 } | |
271 | |
272 void PPB_Graphics3D_Impl::SendContextLost() { | |
273 const PPP_Graphics3D_Dev* ppp_graphics3d = | |
274 static_cast<const PPP_Graphics3D_Dev*>( | |
275 instance()->module()->GetPluginInterface( | |
276 PPP_GRAPHICS_3D_DEV_INTERFACE)); | |
277 if (ppp_graphics3d) | |
278 ppp_graphics3d->Graphics3DContextLost(instance()->pp_instance()); | |
107 } | 279 } |
108 | 280 |
109 } // namespace ppapi | 281 } // namespace ppapi |
110 } // namespace webkit | 282 } // namespace webkit |
111 | 283 |
OLD | NEW |