OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "ppapi/proxy/ppb_graphics_2d_proxy.h" | |
6 | |
7 #include <string.h> // For memset. | |
8 | |
9 #include "base/compiler_specific.h" | |
10 #include "base/logging.h" | |
11 #include "ppapi/c/pp_completion_callback.h" | |
12 #include "ppapi/c/pp_errors.h" | |
13 #include "ppapi/c/pp_resource.h" | |
14 #include "ppapi/c/ppb_graphics_2d.h" | |
15 #include "ppapi/proxy/enter_proxy.h" | |
16 #include "ppapi/proxy/plugin_dispatcher.h" | |
17 #include "ppapi/proxy/plugin_resource_tracker.h" | |
18 #include "ppapi/proxy/ppapi_messages.h" | |
19 #include "ppapi/proxy/ppb_image_data_proxy.h" | |
20 #include "ppapi/shared_impl/tracked_callback.h" | |
21 #include "ppapi/thunk/enter.h" | |
22 #include "ppapi/thunk/ppb_graphics_2d_api.h" | |
23 #include "ppapi/thunk/thunk.h" | |
24 | |
25 using ppapi::thunk::PPB_Graphics2D_API; | |
26 | |
27 namespace ppapi { | |
28 namespace proxy { | |
29 | |
30 class Graphics2D : public Resource, public thunk::PPB_Graphics2D_API { | |
31 public: | |
32 Graphics2D(const HostResource& host_resource, | |
33 const PP_Size& size, | |
34 PP_Bool is_always_opaque); | |
35 virtual ~Graphics2D(); | |
36 | |
37 // Resource. | |
38 virtual PPB_Graphics2D_API* AsPPB_Graphics2D_API(); | |
39 | |
40 // PPB_Graphics_2D_API. | |
41 PP_Bool Describe(PP_Size* size, PP_Bool* is_always_opaque); | |
42 void PaintImageData(PP_Resource image_data, | |
43 const PP_Point* top_left, | |
44 const PP_Rect* src_rect); | |
45 void Scroll(const PP_Rect* clip_rect, | |
46 const PP_Point* amount); | |
47 void ReplaceContents(PP_Resource image_data); | |
48 bool SetScale(float scale); | |
49 float GetScale(); | |
50 int32_t Flush(scoped_refptr<TrackedCallback> callback, | |
51 PP_Resource* old_image_data); | |
52 | |
53 // Notification that the host has sent an ACK for a pending Flush. | |
54 void FlushACK(int32_t result_code); | |
55 | |
56 private: | |
57 PluginDispatcher* GetDispatcher() const { | |
58 return PluginDispatcher::GetForResource(this); | |
59 } | |
60 | |
61 static const ApiID kApiID = API_ID_PPB_GRAPHICS_2D; | |
62 | |
63 PP_Size size_; | |
64 PP_Bool is_always_opaque_; | |
65 float scale_; | |
66 | |
67 // In the plugin, this is the current callback set for Flushes. When the | |
68 // pointer is non-NULL, we're waiting for a flush ACK. | |
69 scoped_refptr<TrackedCallback> current_flush_callback_; | |
70 | |
71 DISALLOW_COPY_AND_ASSIGN(Graphics2D); | |
72 }; | |
73 | |
74 Graphics2D::Graphics2D(const HostResource& host_resource, | |
75 const PP_Size& size, | |
76 PP_Bool is_always_opaque) | |
77 : Resource(OBJECT_IS_PROXY, host_resource), | |
78 size_(size), | |
79 is_always_opaque_(is_always_opaque), | |
80 scale_(1.0f) { | |
81 } | |
82 | |
83 Graphics2D::~Graphics2D() { | |
84 } | |
85 | |
86 PPB_Graphics2D_API* Graphics2D::AsPPB_Graphics2D_API() { | |
87 return this; | |
88 } | |
89 | |
90 PP_Bool Graphics2D::Describe(PP_Size* size, PP_Bool* is_always_opaque) { | |
91 *size = size_; | |
92 *is_always_opaque = is_always_opaque_; | |
93 return PP_TRUE; | |
94 } | |
95 | |
96 void Graphics2D::PaintImageData(PP_Resource image_data, | |
97 const PP_Point* top_left, | |
98 const PP_Rect* src_rect) { | |
99 Resource* image_object = | |
100 PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data); | |
101 if (!image_object || pp_instance() != image_object->pp_instance()) { | |
102 Log(PP_LOGLEVEL_ERROR, | |
103 "PPB_Graphics2D.PaintImageData: Bad image resource."); | |
104 return; | |
105 } | |
106 | |
107 PP_Rect dummy; | |
108 memset(&dummy, 0, sizeof(PP_Rect)); | |
109 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_PaintImageData( | |
110 kApiID, host_resource(), image_object->host_resource(), *top_left, | |
111 !!src_rect, src_rect ? *src_rect : dummy)); | |
112 } | |
113 | |
114 void Graphics2D::Scroll(const PP_Rect* clip_rect, | |
115 const PP_Point* amount) { | |
116 PP_Rect dummy; | |
117 memset(&dummy, 0, sizeof(PP_Rect)); | |
118 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Scroll( | |
119 kApiID, host_resource(), !!clip_rect, clip_rect ? *clip_rect : dummy, | |
120 *amount)); | |
121 } | |
122 | |
123 void Graphics2D::ReplaceContents(PP_Resource image_data) { | |
124 thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_image( | |
125 image_data, true); | |
126 if (enter_image.failed()) | |
127 return; | |
128 | |
129 ImageData* image_object = static_cast<ImageData*>(enter_image.object()); | |
130 if (pp_instance() != image_object->pp_instance()) { | |
131 Log(PP_LOGLEVEL_ERROR, | |
132 "PPB_Graphics2D.ReplaceContents: Image resource for another instance."); | |
133 return; | |
134 } | |
135 image_object->set_used_in_replace_contents(); | |
136 | |
137 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_ReplaceContents( | |
138 kApiID, host_resource(), image_object->host_resource())); | |
139 } | |
140 | |
141 bool Graphics2D::SetScale(float scale) { | |
142 if (scale <= 0.0f) | |
143 return false; | |
144 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Dev_SetScale( | |
145 kApiID, host_resource(), scale)); | |
146 scale_ = scale; | |
147 return true; | |
148 } | |
149 | |
150 float Graphics2D::GetScale() { | |
151 return scale_; | |
152 } | |
153 | |
154 int32_t Graphics2D::Flush(scoped_refptr<TrackedCallback> callback, | |
155 PP_Resource* old_image_data) { | |
156 // We don't support this feature, it's for in-renderer only. | |
157 if (old_image_data) | |
158 *old_image_data = 0; | |
159 | |
160 if (TrackedCallback::IsPending(current_flush_callback_)) | |
161 return PP_ERROR_INPROGRESS; // Can't have >1 flush pending. | |
162 current_flush_callback_ = callback; | |
163 | |
164 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Flush(kApiID, | |
165 host_resource())); | |
166 return PP_OK_COMPLETIONPENDING; | |
167 } | |
168 | |
169 void Graphics2D::FlushACK(int32_t result_code) { | |
170 TrackedCallback::ClearAndRun(¤t_flush_callback_, result_code); | |
171 } | |
172 | |
173 PPB_Graphics2D_Proxy::PPB_Graphics2D_Proxy(Dispatcher* dispatcher) | |
174 : InterfaceProxy(dispatcher), | |
175 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
176 } | |
177 | |
178 PPB_Graphics2D_Proxy::~PPB_Graphics2D_Proxy() { | |
179 } | |
180 | |
181 // static | |
182 PP_Resource PPB_Graphics2D_Proxy::CreateProxyResource( | |
183 PP_Instance instance, | |
184 const PP_Size& size, | |
185 PP_Bool is_always_opaque) { | |
186 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | |
187 if (!dispatcher) | |
188 return 0; | |
189 | |
190 HostResource result; | |
191 dispatcher->Send(new PpapiHostMsg_PPBGraphics2D_Create( | |
192 kApiID, instance, size, is_always_opaque, &result)); | |
193 if (result.is_null()) | |
194 return 0; | |
195 return (new Graphics2D(result, size, is_always_opaque))->GetReference(); | |
196 } | |
197 | |
198 bool PPB_Graphics2D_Proxy::OnMessageReceived(const IPC::Message& msg) { | |
199 bool handled = true; | |
200 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics2D_Proxy, msg) | |
201 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Create, | |
202 OnHostMsgCreate) | |
203 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_PaintImageData, | |
204 OnHostMsgPaintImageData) | |
205 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Scroll, | |
206 OnHostMsgScroll) | |
207 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_ReplaceContents, | |
208 OnHostMsgReplaceContents) | |
209 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Flush, | |
210 OnHostMsgFlush) | |
211 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Dev_SetScale, | |
212 OnHostMsgSetScale) | |
213 | |
214 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics2D_FlushACK, | |
215 OnPluginMsgFlushACK) | |
216 IPC_MESSAGE_UNHANDLED(handled = false) | |
217 IPC_END_MESSAGE_MAP() | |
218 // FIXME(brettw) handle bad messages! | |
219 return handled; | |
220 } | |
221 | |
222 void PPB_Graphics2D_Proxy::OnHostMsgCreate(PP_Instance instance, | |
223 const PP_Size& size, | |
224 PP_Bool is_always_opaque, | |
225 HostResource* result) { | |
226 thunk::EnterResourceCreation enter(instance); | |
227 if (enter.succeeded()) { | |
228 result->SetHostResource(instance, enter.functions()->CreateGraphics2D( | |
229 instance, size, is_always_opaque)); | |
230 } | |
231 } | |
232 | |
233 void PPB_Graphics2D_Proxy::OnHostMsgPaintImageData( | |
234 const HostResource& graphics_2d, | |
235 const HostResource& image_data, | |
236 const PP_Point& top_left, | |
237 bool src_rect_specified, | |
238 const PP_Rect& src_rect) { | |
239 EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d); | |
240 if (enter.failed()) | |
241 return; | |
242 enter.object()->PaintImageData(image_data.host_resource(), &top_left, | |
243 src_rect_specified ? &src_rect : NULL); | |
244 } | |
245 | |
246 void PPB_Graphics2D_Proxy::OnHostMsgScroll(const HostResource& graphics_2d, | |
247 bool clip_specified, | |
248 const PP_Rect& clip, | |
249 const PP_Point& amount) { | |
250 EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d); | |
251 if (enter.failed()) | |
252 return; | |
253 enter.object()->Scroll(clip_specified ? &clip : NULL, &amount); | |
254 } | |
255 | |
256 void PPB_Graphics2D_Proxy::OnHostMsgReplaceContents( | |
257 const HostResource& graphics_2d, | |
258 const HostResource& image_data) { | |
259 EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d); | |
260 if (enter.failed()) | |
261 return; | |
262 enter.object()->ReplaceContents(image_data.host_resource()); | |
263 } | |
264 | |
265 void PPB_Graphics2D_Proxy::OnHostMsgFlush(const HostResource& graphics_2d) { | |
266 EnterHostFromHostResourceForceCallback<PPB_Graphics2D_API> enter( | |
267 graphics_2d, callback_factory_, | |
268 &PPB_Graphics2D_Proxy::SendFlushACKToPlugin, graphics_2d); | |
269 if (enter.failed()) | |
270 return; | |
271 PP_Resource old_image_data = 0; | |
272 enter.SetResult(enter.object()->Flush(enter.callback(), &old_image_data)); | |
273 if (old_image_data) { | |
274 // If the Graphics2D has an old image data it's not using any more, send | |
275 // it back to the plugin for possible re-use. See ppb_image_data_proxy.cc | |
276 // for a description how this process works. | |
277 HostResource old_image_data_host_resource; | |
278 old_image_data_host_resource.SetHostResource(graphics_2d.instance(), | |
279 old_image_data); | |
280 dispatcher()->Send(new PpapiMsg_PPBImageData_NotifyUnusedImageData( | |
281 API_ID_PPB_IMAGE_DATA, old_image_data_host_resource)); | |
282 } | |
283 } | |
284 | |
285 void PPB_Graphics2D_Proxy::OnHostMsgSetScale(const HostResource& graphics_2d, | |
286 float scale) { | |
287 EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d); | |
288 if (enter.failed()) | |
289 return; | |
290 enter.object()->SetScale(scale); | |
291 } | |
292 | |
293 void PPB_Graphics2D_Proxy::OnPluginMsgFlushACK( | |
294 const HostResource& host_resource, | |
295 int32_t pp_error) { | |
296 EnterPluginFromHostResource<PPB_Graphics2D_API> enter(host_resource); | |
297 if (enter.succeeded()) | |
298 static_cast<Graphics2D*>(enter.object())->FlushACK(pp_error); | |
299 } | |
300 | |
301 void PPB_Graphics2D_Proxy::SendFlushACKToPlugin( | |
302 int32_t result, | |
303 const HostResource& graphics_2d) { | |
304 dispatcher()->Send(new PpapiMsg_PPBGraphics2D_FlushACK(kApiID, graphics_2d, | |
305 result)); | |
306 } | |
307 | |
308 } // namespace proxy | |
309 } // namespace ppapi | |
OLD | NEW |