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/graphics_2d_resource.h"
6 
7 #include "base/bind.h"
8 #include "ppapi/c/pp_bool.h"
9 #include "ppapi/c/pp_point.h"
10 #include "ppapi/c/pp_rect.h"
11 #include "ppapi/c/pp_resource.h"
12 #include "ppapi/c/pp_size.h"
13 #include "ppapi/c/ppb_graphics_2d.h"
14 #include "ppapi/proxy/dispatch_reply_message.h"
15 #include "ppapi/proxy/plugin_dispatcher.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/shared_impl/ppapi_globals.h"
18 #include "ppapi/shared_impl/resource_tracker.h"
19 #include "ppapi/shared_impl/tracked_callback.h"
20 #include "ppapi/thunk/enter.h"
21 #include "ppapi/thunk/ppb_image_data_api.h"
22 
23 namespace ppapi {
24 namespace proxy {
25 
Graphics2DResource(Connection connection,PP_Instance instance,const PP_Size & size,PP_Bool is_always_opaque)26 Graphics2DResource::Graphics2DResource(Connection connection,
27                                        PP_Instance instance,
28                                        const PP_Size& size,
29                                        PP_Bool is_always_opaque)
30     : PluginResource(connection, instance),
31       size_(size),
32       is_always_opaque_(is_always_opaque),
33       scale_(1.0f) {
34   // These checks are copied from PPB_ImageData_Impl::Init to make tests passed.
35   // Let's remove/refactor this when start to refactor ImageData.
36   bool bad_args =
37       size.width <= 0 || size.height <= 0 ||
38       static_cast<int64_t>(size.width) * static_cast<int64_t>(size.height) >=
39           std::numeric_limits<int32_t>::max() / 4;
40   if (!bad_args && !sent_create_to_renderer()) {
41     SendCreate(RENDERER,
42         PpapiHostMsg_Graphics2D_Create(size, is_always_opaque));
43   }
44 }
45 
~Graphics2DResource()46 Graphics2DResource::~Graphics2DResource() {
47 }
48 
Describe(PP_Size * size,PP_Bool * is_always_opaque)49 PP_Bool Graphics2DResource::Describe(PP_Size* size, PP_Bool* is_always_opaque) {
50   *size = size_;
51   *is_always_opaque = is_always_opaque_;
52   return PP_TRUE;
53 }
54 
AsPPB_Graphics2D_API()55 thunk::PPB_Graphics2D_API* Graphics2DResource::AsPPB_Graphics2D_API() {
56   return this;
57 }
58 
PaintImageData(PP_Resource image_data,const PP_Point * top_left,const PP_Rect * src_rect)59 void Graphics2DResource::PaintImageData(PP_Resource image_data,
60                                         const PP_Point* top_left,
61                                         const PP_Rect* src_rect) {
62   Resource* image_object =
63       PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data);
64   if (!image_object || pp_instance() != image_object->pp_instance()) {
65     Log(PP_LOGLEVEL_ERROR,
66         "Graphics2DResource.PaintImageData: Bad image resource.");
67     return;
68   }
69 
70   PP_Rect dummy;
71   memset(&dummy, 0, sizeof(PP_Rect));
72   Post(RENDERER, PpapiHostMsg_Graphics2D_PaintImageData(
73       image_object->host_resource(), *top_left,
74       !!src_rect, src_rect ? *src_rect : dummy));
75 }
76 
Scroll(const PP_Rect * clip_rect,const PP_Point * amount)77 void Graphics2DResource::Scroll(const PP_Rect* clip_rect,
78                                 const PP_Point* amount) {
79   PP_Rect dummy;
80   memset(&dummy, 0, sizeof(PP_Rect));
81   Post(RENDERER, PpapiHostMsg_Graphics2D_Scroll(
82       !!clip_rect, clip_rect ? *clip_rect : dummy, *amount));
83 }
84 
ReplaceContents(PP_Resource image_data)85 void Graphics2DResource::ReplaceContents(PP_Resource image_data) {
86   thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_image(
87       image_data, true);
88   if (enter_image.failed())
89     return;
90 
91   // Check that the PP_Instance matches.
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         "Graphics2DResource.PaintImageData: Bad image resource.");
97     return;
98   }
99   enter_image.object()->SetIsCandidateForReuse();
100 
101   Post(RENDERER, PpapiHostMsg_Graphics2D_ReplaceContents(
102       image_object->host_resource()));
103 }
104 
SetScale(float scale)105 PP_Bool Graphics2DResource::SetScale(float scale) {
106   if (scale <= 0.0f)
107     return PP_FALSE;
108   Post(RENDERER, PpapiHostMsg_Graphics2D_SetScale(scale));
109   scale_ = scale;
110   return PP_TRUE;
111 }
112 
GetScale()113 float Graphics2DResource::GetScale() {
114   return scale_;
115 }
116 
SetLayerTransform(float scale,const PP_Point * origin,const PP_Point * translate)117 PP_Bool Graphics2DResource::SetLayerTransform(float scale,
118                                               const PP_Point* origin,
119                                               const PP_Point* translate) {
120   if (scale <= 0.0f)
121     return PP_FALSE;
122   // Adding the origin to the transform.
123   PP_FloatPoint translate_with_origin;
124   translate_with_origin.x = (1 - scale) * origin->x - translate->x;
125   translate_with_origin.y = (1 - scale) * origin->y - translate->y;
126   Post(RENDERER,
127        PpapiHostMsg_Graphics2D_SetLayerTransform(scale, translate_with_origin));
128   return PP_TRUE;
129 }
130 
Flush(scoped_refptr<TrackedCallback> callback)131 int32_t Graphics2DResource::Flush(scoped_refptr<TrackedCallback> callback) {
132   // If host is not even created, return failure immediately.  This can happen
133   // when failed to initialize (in constructor).
134   if (!sent_create_to_renderer())
135     return PP_ERROR_FAILED;
136 
137   if (TrackedCallback::IsPending(current_flush_callback_))
138     return PP_ERROR_INPROGRESS;  // Can't have >1 flush pending.
139   current_flush_callback_ = callback;
140 
141   Call<PpapiPluginMsg_Graphics2D_FlushAck>(
142       RENDERER,
143       PpapiHostMsg_Graphics2D_Flush(),
144       base::Bind(&Graphics2DResource::OnPluginMsgFlushACK, this));
145   return PP_OK_COMPLETIONPENDING;
146 }
147 
ReadImageData(PP_Resource image,const PP_Point * top_left)148 bool Graphics2DResource::ReadImageData(PP_Resource image,
149                                        const PP_Point* top_left) {
150   if (!top_left)
151     return false;
152   int32_t result = SyncCall<PpapiPluginMsg_Graphics2D_ReadImageDataAck>(
153       RENDERER,
154       PpapiHostMsg_Graphics2D_ReadImageData(image, *top_left));
155   return result == PP_OK;
156 }
157 
OnPluginMsgFlushACK(const ResourceMessageReplyParams & params)158 void Graphics2DResource::OnPluginMsgFlushACK(
159     const ResourceMessageReplyParams& params) {
160   current_flush_callback_->Run(params.result());
161 }
162 
163 }  // namespace proxy
164 }  // namespace ppapi
165