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 "content/renderer/pepper/pepper_graphics_2d_host.h"
7 #include "base/basictypes.h"
8 #include "base/message_loop/message_loop.h"
9 #include "content/renderer/pepper/gfx_conversion.h"
10 #include "content/renderer/pepper/mock_renderer_ppapi_host.h"
11 #include "content/renderer/pepper/ppb_image_data_impl.h"
12 #include "ppapi/shared_impl/ppb_view_shared.h"
13 #include "ppapi/shared_impl/proxy_lock.h"
14 #include "ppapi/shared_impl/test_globals.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebCanvas.h"
17 #include "third_party/skia/include/core/SkCanvas.h"
18 #include "ui/gfx/point.h"
19 #include "ui/gfx/rect.h"
21 using blink::WebCanvas;
25 class PepperGraphics2DHostTest : public testing::Test {
27 static bool ConvertToLogicalPixels(float scale,
30 return PepperGraphics2DHost::ConvertToLogicalPixels(scale, op_rect, delta);
33 PepperGraphics2DHostTest() : renderer_ppapi_host_(NULL, 12345) {}
35 virtual ~PepperGraphics2DHostTest() {
36 ppapi::ProxyAutoLock proxy_lock;
40 void Init(PP_Instance instance,
41 const PP_Size& backing_store_size,
42 const PP_Rect& plugin_rect) {
43 renderer_view_data_.rect = plugin_rect;
45 test_globals_.GetResourceTracker()->DidCreateInstance(instance);
46 scoped_refptr<PPB_ImageData_Impl> backing_store(
47 new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
48 host_.reset(PepperGraphics2DHost::Create(
49 &renderer_ppapi_host_, instance, 12345, backing_store_size, PP_FALSE,
54 void PaintImageData(PPB_ImageData_Impl* image_data) {
55 ppapi::HostResource image_data_resource;
56 image_data_resource.SetHostResource(image_data->pp_instance(),
57 image_data->pp_resource());
58 host_->OnHostMsgPaintImageData(NULL, image_data_resource,
59 PP_Point(), false, PP_Rect());
62 void SetOffset(const PP_Point& point) {
63 host_->OnHostMsgSetOffset(NULL, point);
67 ppapi::host::HostMessageContext context(
68 ppapi::proxy::ResourceMessageCallParams(host_->pp_resource(), 0));
69 host_->OnHostMsgFlush(&context, plugin_view_data_);
70 host_->ViewFlushedPaint();
71 host_->SendOffscreenFlushAck();
74 void PaintToWebCanvas(SkBitmap* bitmap) {
75 scoped_ptr<WebCanvas> canvas(new WebCanvas(*bitmap));
76 gfx::Rect plugin_rect(PP_ToGfxRect(renderer_view_data_.rect));
77 host_->Paint(canvas.get(), plugin_rect,
78 gfx::Rect(0, 0, plugin_rect.width(), plugin_rect.height()));
81 void DidChangeView(const PP_Rect& plugin_rect) {
82 renderer_view_data_.rect = plugin_rect;
83 host_->DidChangeView(renderer_view_data_);
86 void PluginViewUpdated() {
87 plugin_view_data_ = renderer_view_data_;
90 void SetResizeMode(PP_Graphics2D_Dev_ResizeMode resize_mode) {
91 host_->OnHostMsgSetResizeMode(NULL, resize_mode);
94 void ResetPageBitmap(SkBitmap* bitmap) {
95 PP_Rect plugin_rect = renderer_view_data_.rect;
96 int width = plugin_rect.point.x + plugin_rect.size.width;
97 int height = plugin_rect.point.y + plugin_rect.size.height;
98 if (bitmap->isNull() || bitmap->width() != width ||
99 bitmap->height() != height) {
100 bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
101 bitmap->allocPixels();
103 bitmap->eraseColor(0);
107 ppapi::ViewData renderer_view_data_;
108 ppapi::ViewData plugin_view_data_;
109 scoped_ptr<PepperGraphics2DHost> host_;
110 base::MessageLoop message_loop_;
111 MockRendererPpapiHost renderer_ppapi_host_;
112 ppapi::TestGlobals test_globals_;
115 TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) {
116 static const struct {
132 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, true },
133 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.0, true },
134 { 0, 0, 4, 4, 0, 0, 2, 2, 0, 0, 0, 0, 0.5, true },
135 { 1, 1, 4, 4, 0, 0, 3, 3, 0, 0, 0, 0, 0.5, false },
136 { 53, 75, 100, 100, 53, 75, 100, 100, 0, 0, 0, 0, 1.0, true },
137 { 53, 75, 100, 100, 106, 150, 200, 200, 0, 0, 0, 0, 2.0, true },
138 { 53, 75, 100, 100, 26, 37, 51, 51, 0, 0, 0, 0, 0.5, false },
139 { 53, 74, 100, 100, 26, 37, 51, 50, 0, 0, 0, 0, 0.5, false },
140 { -1, -1, 100, 100, -1, -1, 51, 51, 0, 0, 0, 0, 0.5, false },
141 { -2, -2, 100, 100, -1, -1, 50, 50, 4, -4, 2, -2, 0.5, true },
142 { -101, -100, 50, 50, -51, -50, 26, 25, 0, 0, 0, 0, 0.5, false },
143 { 10, 10, 20, 20, 5, 5, 10, 10, 0, 0, 0, 0, 0.5, true },
144 // Cannot scroll due to partial coverage on sides
145 { 11, 10, 20, 20, 5, 5, 11, 10, 0, 0, 0, 0, 0.5, false },
146 // Can scroll since backing store is actually smaller/scaling up
147 { 11, 20, 100, 100, 22, 40, 200, 200, 7, 3, 14, 6, 2.0, true },
148 // Can scroll due to delta and bounds being aligned
149 { 10, 10, 20, 20, 5, 5, 10, 10, 6, 4, 3, 2, 0.5, true },
150 // Cannot scroll due to dx
151 { 10, 10, 20, 20, 5, 5, 10, 10, 5, 4, 2, 2, 0.5, false },
152 // Cannot scroll due to dy
153 { 10, 10, 20, 20, 5, 5, 10, 10, 6, 3, 3, 1, 0.5, false },
154 // Cannot scroll due to top
155 { 10, 11, 20, 20, 5, 5, 10, 11, 6, 4, 3, 2, 0.5, false },
156 // Cannot scroll due to left
157 { 7, 10, 20, 20, 3, 5, 11, 10, 6, 4, 3, 2, 0.5, false },
158 // Cannot scroll due to width
159 { 10, 10, 21, 20, 5, 5, 11, 10, 6, 4, 3, 2, 0.5, false },
160 // Cannot scroll due to height
161 { 10, 10, 20, 51, 5, 5, 10, 26, 6, 4, 3, 2, 0.5, false },
162 // Check negative scroll deltas
163 { 10, 10, 20, 20, 5, 5, 10, 10, -6, -4, -3, -2, 0.5, true },
164 { 10, 10, 20, 20, 5, 5, 10, 10, -6, -3, -3, -1, 0.5, false },
166 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
167 gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
168 gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
170 gfx::Point delta(tests[i].dx1, tests[i].dy1);
171 bool res = ConvertToLogicalPixels(tests[i].scale, &r1, &delta);
172 EXPECT_EQ(r2.ToString(), r1.ToString());
173 EXPECT_EQ(res, tests[i].result);
175 EXPECT_EQ(delta, gfx::Point(tests[i].dx2, tests[i].dy2));
177 // Reverse the scale and ensure all the original pixels are still inside
179 ConvertToLogicalPixels(1.0f / tests[i].scale, &r1, NULL);
180 EXPECT_TRUE(r1.Contains(orig));
184 TEST_F(PepperGraphics2DHostTest, SetOffset) {
185 ppapi::ProxyAutoLock proxy_lock;
187 // Initialize the backing store.
188 PP_Instance instance = 12345;
189 PP_Size backing_store_size = { 300, 300 };
190 PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 500, 500);
191 Init(instance, backing_store_size, plugin_rect);
193 // Paint the entire backing store red.
194 scoped_refptr<PPB_ImageData_Impl> image_data(
195 new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
196 image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
197 backing_store_size.width,
198 backing_store_size.height,
201 ImageDataAutoMapper auto_mapper(image_data.get());
202 image_data->GetMappedBitmap()->eraseColor(
203 SkColorSetARGBMacro(255, 255, 0, 0));
205 PaintImageData(image_data.get());
208 // Set up the actual and expected bitmaps/canvas.
209 SkBitmap actual_bitmap;
210 ResetPageBitmap(&actual_bitmap);
211 SkBitmap expected_bitmap;
212 ResetPageBitmap(&expected_bitmap);
214 // Paint the backing store to the canvas.
215 PaintToWebCanvas(&actual_bitmap);
216 expected_bitmap.eraseArea(
217 SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
218 SkColorSetARGBMacro(255, 255, 0, 0));
219 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
220 actual_bitmap.getAddr(0, 0),
221 expected_bitmap.getSize()), 0);
224 PP_Point offset = { 20, 20 };
226 ResetPageBitmap(&actual_bitmap);
227 PaintToWebCanvas(&actual_bitmap);
228 // No flush has occurred so the result should be the same.
229 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
230 actual_bitmap.getAddr(0, 0),
231 expected_bitmap.getSize()), 0);
233 // Flush the offset and the location of the rectangle should have shifted.
235 ResetPageBitmap(&actual_bitmap);
236 PaintToWebCanvas(&actual_bitmap);
237 ResetPageBitmap(&expected_bitmap);
238 expected_bitmap.eraseArea(
239 SkIRect::MakeXYWH(offset.x, offset.y,
240 backing_store_size.width, backing_store_size.height),
241 SkColorSetARGBMacro(255, 255, 0, 0));
242 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
243 actual_bitmap.getAddr(0, 0),
244 expected_bitmap.getSize()), 0);
247 TEST_F(PepperGraphics2DHostTest, ResizeModeDefault) {
248 ppapi::ProxyAutoLock proxy_lock;
250 // Initialize the backing store.
251 PP_Instance instance = 12345;
252 PP_Size backing_store_size = { 300, 300 };
253 PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 300, 300);
254 Init(instance, backing_store_size, plugin_rect);
256 // Paint the entire backing store red.
257 scoped_refptr<PPB_ImageData_Impl> image_data(
258 new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
259 image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
260 backing_store_size.width,
261 backing_store_size.height,
264 ImageDataAutoMapper auto_mapper(image_data.get());
265 image_data->GetMappedBitmap()->eraseColor(
266 SkColorSetARGBMacro(255, 255, 0, 0));
268 PaintImageData(image_data.get());
271 // Set up the actual and expected bitmaps/canvas.
272 SkBitmap actual_bitmap;
273 ResetPageBitmap(&actual_bitmap);
274 SkBitmap expected_bitmap;
275 ResetPageBitmap(&expected_bitmap);
277 // Paint the backing store to the canvas.
278 PaintToWebCanvas(&actual_bitmap);
279 expected_bitmap.eraseArea(
280 SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
281 SkColorSetARGBMacro(255, 255, 0, 0));
282 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
283 actual_bitmap.getAddr(0, 0),
284 expected_bitmap.getSize()), 0);
286 // Resize the plugin.
287 DidChangeView(PP_MakeRectFromXYWH(0, 0, 500, 500));
288 // Paint the backing store again, it shouldn't have changed.
289 ResetPageBitmap(&actual_bitmap);
290 PaintToWebCanvas(&actual_bitmap);
291 ResetPageBitmap(&expected_bitmap);
292 expected_bitmap.eraseArea(
293 SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
294 SkColorSetARGBMacro(255, 255, 0, 0));
295 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
296 actual_bitmap.getAddr(0, 0),
297 expected_bitmap.getSize()), 0);
299 // Let the plugin know about the updated view and reflush the original image.
301 PaintImageData(image_data.get());
303 // Paint the backing store again, it shouldn't have changed.
304 ResetPageBitmap(&actual_bitmap);
305 PaintToWebCanvas(&actual_bitmap);
306 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
307 actual_bitmap.getAddr(0, 0),
308 expected_bitmap.getSize()), 0);
311 TEST_F(PepperGraphics2DHostTest, ResizeModeStretch) {
312 ppapi::ProxyAutoLock proxy_lock;
314 // Initialize the backing store.
315 PP_Instance instance = 12345;
316 PP_Size backing_store_size = { 300, 300 };
317 PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 300, 300);
318 Init(instance, backing_store_size, plugin_rect);
319 SetResizeMode(PP_GRAPHICS2D_DEV_RESIZEMODE_STRETCH);
321 // Paint the entire backing store red.
322 scoped_refptr<PPB_ImageData_Impl> image_data(
323 new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
324 image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
325 backing_store_size.width,
326 backing_store_size.height,
329 ImageDataAutoMapper auto_mapper(image_data.get());
330 image_data->GetMappedBitmap()->eraseColor(
331 SkColorSetARGBMacro(255, 255, 0, 0));
333 PaintImageData(image_data.get());
336 // Set up the actual and expected bitmaps/canvas.
337 SkBitmap actual_bitmap;
338 ResetPageBitmap(&actual_bitmap);
339 SkBitmap expected_bitmap;
340 ResetPageBitmap(&expected_bitmap);
342 // Paint the backing store to the canvas.
343 PaintToWebCanvas(&actual_bitmap);
344 expected_bitmap.eraseArea(
345 SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
346 SkColorSetARGBMacro(255, 255, 0, 0));
347 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
348 actual_bitmap.getAddr(0, 0),
349 expected_bitmap.getSize()), 0);
351 // Resize the plugin.
352 plugin_rect = PP_MakeRectFromXYWH(0, 0, 500, 500);
353 DidChangeView(plugin_rect);
354 ResetPageBitmap(&actual_bitmap);
355 ResetPageBitmap(&expected_bitmap);
357 // Paint the backing store again, it should be stretched even though no new
358 // image has been flushed.
359 PaintToWebCanvas(&actual_bitmap);
360 expected_bitmap.eraseColor(SkColorSetARGBMacro(255, 255, 0, 0));
361 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
362 actual_bitmap.getAddr(0, 0),
363 expected_bitmap.getSize()), 0);
365 // Re-flush the original image data and paint it, it should be stretched as
367 PaintImageData(image_data.get());
369 ResetPageBitmap(&actual_bitmap);
370 PaintToWebCanvas(&actual_bitmap);
371 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
372 actual_bitmap.getAddr(0, 0),
373 expected_bitmap.getSize()), 0);
375 // Let the plugin know about the updated view.
378 // Now flush the image data again, it should be at the original size.
379 PaintImageData(image_data.get());
381 ResetPageBitmap(&actual_bitmap);
382 PaintToWebCanvas(&actual_bitmap);
383 ResetPageBitmap(&expected_bitmap);
384 expected_bitmap.eraseArea(
385 SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
386 SkColorSetARGBMacro(255, 255, 0, 0));
387 EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
388 actual_bitmap.getAddr(0, 0),
389 expected_bitmap.getSize()), 0);
392 } // namespace content