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.
5 #include "ppapi/proxy/ppb_graphics_2d_proxy.h"
7 #include <string.h> // For memset.
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/ppapi_messages.h"
18 #include "ppapi/shared_impl/tracked_callback.h"
19 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_graphics_2d_api.h"
21 #include "ppapi/thunk/thunk.h"
23 using ppapi::thunk::PPB_Graphics2D_API
;
28 class Graphics2D
: public Resource
, public thunk::PPB_Graphics2D_API
{
30 Graphics2D(const HostResource
& host_resource
,
32 PP_Bool is_always_opaque
);
33 virtual ~Graphics2D();
36 virtual PPB_Graphics2D_API
* AsPPB_Graphics2D_API();
38 // PPB_Graphics_2D_API.
39 PP_Bool
Describe(PP_Size
* size
, PP_Bool
* is_always_opaque
);
40 void PaintImageData(PP_Resource image_data
,
41 const PP_Point
* top_left
,
42 const PP_Rect
* src_rect
);
43 void Scroll(const PP_Rect
* clip_rect
,
44 const PP_Point
* amount
);
45 void ReplaceContents(PP_Resource image_data
);
46 int32_t Flush(scoped_refptr
<TrackedCallback
> callback
);
48 // Notification that the host has sent an ACK for a pending Flush.
49 void FlushACK(int32_t result_code
);
52 PluginDispatcher
* GetDispatcher() const {
53 return PluginDispatcher::GetForResource(this);
56 static const ApiID kApiID
= API_ID_PPB_GRAPHICS_2D
;
59 PP_Bool is_always_opaque_
;
61 // In the plugin, this is the current callback set for Flushes. When the
62 // pointer is non-NULL, we're waiting for a flush ACK.
63 scoped_refptr
<TrackedCallback
> current_flush_callback_
;
65 DISALLOW_COPY_AND_ASSIGN(Graphics2D
);
68 Graphics2D::Graphics2D(const HostResource
& host_resource
,
70 PP_Bool is_always_opaque
)
71 : Resource(OBJECT_IS_PROXY
, host_resource
),
73 is_always_opaque_(is_always_opaque
) {
76 Graphics2D::~Graphics2D() {
79 PPB_Graphics2D_API
* Graphics2D::AsPPB_Graphics2D_API() {
83 PP_Bool
Graphics2D::Describe(PP_Size
* size
, PP_Bool
* is_always_opaque
) {
85 *is_always_opaque
= is_always_opaque_
;
89 void Graphics2D::PaintImageData(PP_Resource image_data
,
90 const PP_Point
* top_left
,
91 const PP_Rect
* src_rect
) {
92 Resource
* image_object
=
93 PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data
);
94 if (!image_object
|| pp_instance() != image_object
->pp_instance()) {
95 Log(PP_LOGLEVEL_ERROR
,
96 "PPB_Graphics2D.PaintImageData: Bad image resource.");
101 memset(&dummy
, 0, sizeof(PP_Rect
));
102 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_PaintImageData(
103 kApiID
, host_resource(), image_object
->host_resource(), *top_left
,
104 !!src_rect
, src_rect
? *src_rect
: dummy
));
107 void Graphics2D::Scroll(const PP_Rect
* clip_rect
,
108 const PP_Point
* amount
) {
110 memset(&dummy
, 0, sizeof(PP_Rect
));
111 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Scroll(
112 kApiID
, host_resource(), !!clip_rect
, clip_rect
? *clip_rect
: dummy
,
116 void Graphics2D::ReplaceContents(PP_Resource image_data
) {
117 Resource
* image_object
=
118 PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data
);
119 if (!image_object
|| pp_instance() != image_object
->pp_instance()) {
120 Log(PP_LOGLEVEL_ERROR
,
121 "PPB_Graphics2D.PaintImageData: Bad image resource.");
125 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_ReplaceContents(
126 kApiID
, host_resource(), image_object
->host_resource()));
129 int32_t Graphics2D::Flush(scoped_refptr
<TrackedCallback
> callback
) {
130 if (TrackedCallback::IsPending(current_flush_callback_
))
131 return PP_ERROR_INPROGRESS
; // Can't have >1 flush pending.
132 current_flush_callback_
= callback
;
134 GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Flush(kApiID
,
136 return PP_OK_COMPLETIONPENDING
;
139 void Graphics2D::FlushACK(int32_t result_code
) {
140 TrackedCallback::ClearAndRun(¤t_flush_callback_
, result_code
);
143 PPB_Graphics2D_Proxy::PPB_Graphics2D_Proxy(Dispatcher
* dispatcher
)
144 : InterfaceProxy(dispatcher
),
145 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
148 PPB_Graphics2D_Proxy::~PPB_Graphics2D_Proxy() {
152 PP_Resource
PPB_Graphics2D_Proxy::CreateProxyResource(
153 PP_Instance instance
,
155 PP_Bool is_always_opaque
) {
156 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
161 dispatcher
->Send(new PpapiHostMsg_PPBGraphics2D_Create(
162 kApiID
, instance
, size
, is_always_opaque
, &result
));
163 if (result
.is_null())
165 return (new Graphics2D(result
, size
, is_always_opaque
))->GetReference();
168 bool PPB_Graphics2D_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
170 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics2D_Proxy
, msg
)
171 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Create
,
173 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_PaintImageData
,
174 OnHostMsgPaintImageData
)
175 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Scroll
,
177 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_ReplaceContents
,
178 OnHostMsgReplaceContents
)
179 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Flush
,
182 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics2D_FlushACK
,
184 IPC_MESSAGE_UNHANDLED(handled
= false)
185 IPC_END_MESSAGE_MAP()
186 // FIXME(brettw) handle bad messages!
190 void PPB_Graphics2D_Proxy::OnHostMsgCreate(PP_Instance instance
,
192 PP_Bool is_always_opaque
,
193 HostResource
* result
) {
194 thunk::EnterResourceCreation
enter(instance
);
195 if (enter
.succeeded()) {
196 result
->SetHostResource(instance
, enter
.functions()->CreateGraphics2D(
197 instance
, size
, is_always_opaque
));
201 void PPB_Graphics2D_Proxy::OnHostMsgPaintImageData(
202 const HostResource
& graphics_2d
,
203 const HostResource
& image_data
,
204 const PP_Point
& top_left
,
205 bool src_rect_specified
,
206 const PP_Rect
& src_rect
) {
207 EnterHostFromHostResource
<PPB_Graphics2D_API
> enter(graphics_2d
);
210 enter
.object()->PaintImageData(image_data
.host_resource(), &top_left
,
211 src_rect_specified
? &src_rect
: NULL
);
214 void PPB_Graphics2D_Proxy::OnHostMsgScroll(const HostResource
& graphics_2d
,
217 const PP_Point
& amount
) {
218 EnterHostFromHostResource
<PPB_Graphics2D_API
> enter(graphics_2d
);
221 enter
.object()->Scroll(clip_specified
? &clip
: NULL
, &amount
);
224 void PPB_Graphics2D_Proxy::OnHostMsgReplaceContents(
225 const HostResource
& graphics_2d
,
226 const HostResource
& image_data
) {
227 EnterHostFromHostResource
<PPB_Graphics2D_API
> enter(graphics_2d
);
230 enter
.object()->ReplaceContents(image_data
.host_resource());
233 void PPB_Graphics2D_Proxy::OnHostMsgFlush(const HostResource
& graphics_2d
) {
234 EnterHostFromHostResourceForceCallback
<PPB_Graphics2D_API
> enter(
235 graphics_2d
, callback_factory_
,
236 &PPB_Graphics2D_Proxy::SendFlushACKToPlugin
, graphics_2d
);
239 enter
.SetResult(enter
.object()->Flush(enter
.callback()));
242 void PPB_Graphics2D_Proxy::OnPluginMsgFlushACK(
243 const HostResource
& host_resource
,
245 EnterPluginFromHostResource
<PPB_Graphics2D_API
> enter(host_resource
);
246 if (enter
.succeeded())
247 static_cast<Graphics2D
*>(enter
.object())->FlushACK(pp_error
);
250 void PPB_Graphics2D_Proxy::SendFlushACKToPlugin(
252 const HostResource
& graphics_2d
) {
253 dispatcher()->Send(new PpapiMsg_PPBGraphics2D_FlushACK(kApiID
, graphics_2d
,