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