Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: webkit/glue/plugins/pepper_graphics_2d.cc

Issue 5828003: Move the Pepper implementation from webkit/glue/plugins/pepper_* to... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/pepper_graphics_2d.h ('k') | webkit/glue/plugins/pepper_graphics_3d.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "webkit/glue/plugins/pepper_graphics_2d.h"
6
7 #include <iterator>
8
9 #include "base/logging.h"
10 #include "base/message_loop.h"
11 #include "base/task.h"
12 #include "gfx/blit.h"
13 #include "gfx/point.h"
14 #include "gfx/rect.h"
15 #include "skia/ext/platform_canvas.h"
16 #include "ppapi/c/pp_errors.h"
17 #include "ppapi/c/pp_module.h"
18 #include "ppapi/c/pp_rect.h"
19 #include "ppapi/c/pp_resource.h"
20 #include "ppapi/c/ppb_graphics_2d.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "webkit/glue/plugins/pepper_common.h"
23 #include "webkit/glue/plugins/pepper_image_data.h"
24 #include "webkit/glue/plugins/pepper_plugin_instance.h"
25 #include "webkit/glue/plugins/pepper_plugin_module.h"
26
27 #if defined(OS_MACOSX)
28 #include "base/mac_util.h"
29 #include "base/mac/scoped_cftyperef.h"
30 #endif
31
32 namespace pepper {
33
34 namespace {
35
36 // Converts a rect inside an image of the given dimensions. The rect may be
37 // NULL to indicate it should be the entire image. If the rect is outside of
38 // the image, this will do nothing and return false.
39 bool ValidateAndConvertRect(const PP_Rect* rect,
40 int image_width, int image_height,
41 gfx::Rect* dest) {
42 if (!rect) {
43 // Use the entire image area.
44 *dest = gfx::Rect(0, 0, image_width, image_height);
45 } else {
46 // Validate the passed-in area.
47 if (rect->point.x < 0 || rect->point.y < 0 ||
48 rect->size.width <= 0 || rect->size.height <= 0)
49 return false;
50
51 // Check the max bounds, being careful of overflow.
52 if (static_cast<int64>(rect->point.x) +
53 static_cast<int64>(rect->size.width) >
54 static_cast<int64>(image_width))
55 return false;
56 if (static_cast<int64>(rect->point.y) +
57 static_cast<int64>(rect->size.height) >
58 static_cast<int64>(image_height))
59 return false;
60
61 *dest = gfx::Rect(rect->point.x, rect->point.y,
62 rect->size.width, rect->size.height);
63 }
64 return true;
65 }
66
67 // Converts BGRA <-> RGBA.
68 void ConvertBetweenBGRAandRGBA(const uint32_t* input,
69 int pixel_length,
70 uint32_t* output) {
71 for (int i = 0; i < pixel_length; i++) {
72 const unsigned char* pixel_in =
73 reinterpret_cast<const unsigned char*>(&input[i]);
74 unsigned char* pixel_out = reinterpret_cast<unsigned char*>(&output[i]);
75 pixel_out[0] = pixel_in[2];
76 pixel_out[1] = pixel_in[1];
77 pixel_out[2] = pixel_in[0];
78 pixel_out[3] = pixel_in[3];
79 }
80 }
81
82 // Converts ImageData from PP_IMAGEDATAFORMAT_BGRA_PREMUL to
83 // PP_IMAGEDATAFORMAT_RGBA_PREMUL, or reverse.
84 void ConvertImageData(ImageData* src_image, const SkIRect& src_rect,
85 ImageData* dest_image, const SkRect& dest_rect) {
86 DCHECK(src_image->format() != dest_image->format());
87 DCHECK(ImageData::IsImageDataFormatSupported(src_image->format()));
88 DCHECK(ImageData::IsImageDataFormatSupported(dest_image->format()));
89
90 const SkBitmap* src_bitmap = src_image->GetMappedBitmap();
91 const SkBitmap* dest_bitmap = dest_image->GetMappedBitmap();
92 if (src_rect.width() == src_image->width() &&
93 dest_rect.width() == dest_image->width()) {
94 // Fast path if the full line needs to be converted.
95 ConvertBetweenBGRAandRGBA(
96 src_bitmap->getAddr32(static_cast<int>(src_rect.fLeft),
97 static_cast<int>(src_rect.fTop)),
98 src_rect.width() * src_rect.height(),
99 dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
100 static_cast<int>(dest_rect.fTop)));
101 } else {
102 // Slow path where we convert line by line.
103 for (int y = 0; y < src_rect.height(); y++) {
104 ConvertBetweenBGRAandRGBA(
105 src_bitmap->getAddr32(static_cast<int>(src_rect.fLeft),
106 static_cast<int>(src_rect.fTop + y)),
107 src_rect.width(),
108 dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
109 static_cast<int>(dest_rect.fTop + y)));
110 }
111 }
112 }
113
114 PP_Resource Create(PP_Module module_id,
115 const PP_Size* size,
116 PP_Bool is_always_opaque) {
117 PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
118 if (!module)
119 return 0;
120
121 scoped_refptr<Graphics2D> context(new Graphics2D(module));
122 if (!context->Init(size->width, size->height, PPBoolToBool(is_always_opaque)))
123 return 0;
124 return context->GetReference();
125 }
126
127 PP_Bool IsGraphics2D(PP_Resource resource) {
128 return BoolToPPBool(!!Resource::GetAs<Graphics2D>(resource));
129 }
130
131 PP_Bool Describe(PP_Resource graphics_2d,
132 PP_Size* size,
133 PP_Bool* is_always_opaque) {
134 scoped_refptr<Graphics2D> context(
135 Resource::GetAs<Graphics2D>(graphics_2d));
136 if (!context)
137 return PP_FALSE;
138 return context->Describe(size, is_always_opaque);
139 }
140
141 void PaintImageData(PP_Resource graphics_2d,
142 PP_Resource image_data,
143 const PP_Point* top_left,
144 const PP_Rect* src_rect) {
145 scoped_refptr<Graphics2D> context(
146 Resource::GetAs<Graphics2D>(graphics_2d));
147 if (context)
148 context->PaintImageData(image_data, top_left, src_rect);
149 }
150
151 void Scroll(PP_Resource graphics_2d,
152 const PP_Rect* clip_rect,
153 const PP_Point* amount) {
154 scoped_refptr<Graphics2D> context(
155 Resource::GetAs<Graphics2D>(graphics_2d));
156 if (context)
157 context->Scroll(clip_rect, amount);
158 }
159
160 void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) {
161 scoped_refptr<Graphics2D> context(
162 Resource::GetAs<Graphics2D>(graphics_2d));
163 if (context)
164 context->ReplaceContents(image_data);
165 }
166
167 int32_t Flush(PP_Resource graphics_2d,
168 PP_CompletionCallback callback) {
169 scoped_refptr<Graphics2D> context(
170 Resource::GetAs<Graphics2D>(graphics_2d));
171 if (!context)
172 return PP_ERROR_BADRESOURCE;
173 return context->Flush(callback);
174 }
175
176 const PPB_Graphics2D ppb_graphics_2d = {
177 &Create,
178 &IsGraphics2D,
179 &Describe,
180 &PaintImageData,
181 &Scroll,
182 &ReplaceContents,
183 &Flush
184 };
185
186 } // namespace
187
188 struct Graphics2D::QueuedOperation {
189 enum Type {
190 PAINT,
191 SCROLL,
192 REPLACE
193 };
194
195 QueuedOperation(Type t)
196 : type(t),
197 paint_x(0),
198 paint_y(0),
199 scroll_dx(0),
200 scroll_dy(0) {
201 }
202
203 Type type;
204
205 // Valid when type == PAINT.
206 scoped_refptr<ImageData> paint_image;
207 int paint_x, paint_y;
208 gfx::Rect paint_src_rect;
209
210 // Valid when type == SCROLL.
211 gfx::Rect scroll_clip_rect;
212 int scroll_dx, scroll_dy;
213
214 // Valid when type == REPLACE.
215 scoped_refptr<ImageData> replace_image;
216 };
217
218 Graphics2D::Graphics2D(PluginModule* module)
219 : Resource(module),
220 bound_instance_(NULL),
221 flushed_any_data_(false),
222 offscreen_flush_pending_(false),
223 is_always_opaque_(false) {
224 }
225
226 Graphics2D::~Graphics2D() {
227 }
228
229 // static
230 const PPB_Graphics2D* Graphics2D::GetInterface() {
231 return &ppb_graphics_2d;
232 }
233
234 bool Graphics2D::Init(int width, int height, bool is_always_opaque) {
235 // The underlying ImageData will validate the dimensions.
236 image_data_ = new ImageData(module());
237 if (!image_data_->Init(ImageData::GetNativeImageDataFormat(), width, height,
238 true) || !image_data_->Map()) {
239 image_data_ = NULL;
240 return false;
241 }
242 is_always_opaque_ = is_always_opaque;
243 return true;
244 }
245
246 Graphics2D* Graphics2D::AsGraphics2D() {
247 return this;
248 }
249
250 PP_Bool Graphics2D::Describe(PP_Size* size, PP_Bool* is_always_opaque) {
251 size->width = image_data_->width();
252 size->height = image_data_->height();
253 *is_always_opaque = PP_FALSE; // TODO(brettw) implement this.
254 return PP_TRUE;
255 }
256
257 void Graphics2D::PaintImageData(PP_Resource image_data,
258 const PP_Point* top_left,
259 const PP_Rect* src_rect) {
260 if (!top_left)
261 return;
262
263 scoped_refptr<ImageData> image_resource(
264 Resource::GetAs<ImageData>(image_data));
265 if (!image_resource)
266 return;
267
268 QueuedOperation operation(QueuedOperation::PAINT);
269 operation.paint_image = image_resource;
270 if (!ValidateAndConvertRect(src_rect, image_resource->width(),
271 image_resource->height(),
272 &operation.paint_src_rect))
273 return;
274
275 // Validate the bitmap position using the previously-validated rect, there
276 // should be no painted area outside of the image.
277 int64 x64 = static_cast<int64>(top_left->x);
278 int64 y64 = static_cast<int64>(top_left->y);
279 if (x64 + static_cast<int64>(operation.paint_src_rect.x()) < 0 ||
280 x64 + static_cast<int64>(operation.paint_src_rect.right()) >
281 image_data_->width())
282 return;
283 if (y64 + static_cast<int64>(operation.paint_src_rect.y()) < 0 ||
284 y64 + static_cast<int64>(operation.paint_src_rect.bottom()) >
285 image_data_->height())
286 return;
287 operation.paint_x = top_left->x;
288 operation.paint_y = top_left->y;
289
290 queued_operations_.push_back(operation);
291 }
292
293 void Graphics2D::Scroll(const PP_Rect* clip_rect, const PP_Point* amount) {
294 QueuedOperation operation(QueuedOperation::SCROLL);
295 if (!ValidateAndConvertRect(clip_rect,
296 image_data_->width(),
297 image_data_->height(),
298 &operation.scroll_clip_rect))
299 return;
300
301 // If we're being asked to scroll by more than the clip rect size, just
302 // ignore this scroll command and say it worked.
303 int32 dx = amount->x;
304 int32 dy = amount->y;
305 if (dx <= -image_data_->width() || dx >= image_data_->width() ||
306 dy <= -image_data_->height() || dy >= image_data_->height())
307 return;
308
309 operation.scroll_dx = dx;
310 operation.scroll_dy = dy;
311
312 queued_operations_.push_back(operation);
313 }
314
315 void Graphics2D::ReplaceContents(PP_Resource image_data) {
316 scoped_refptr<ImageData> image_resource(
317 Resource::GetAs<ImageData>(image_data));
318 if (!image_resource)
319 return;
320 if (!ImageData::IsImageDataFormatSupported(image_resource->format()))
321 return;
322
323 if (image_resource->width() != image_data_->width() ||
324 image_resource->height() != image_data_->height())
325 return;
326
327 QueuedOperation operation(QueuedOperation::REPLACE);
328 operation.replace_image = image_resource;
329 queued_operations_.push_back(operation);
330 }
331
332 int32_t Graphics2D::Flush(const PP_CompletionCallback& callback) {
333 // Don't allow more than one pending flush at a time.
334 if (HasPendingFlush())
335 return PP_ERROR_INPROGRESS;
336
337 // TODO(brettw) check that the current thread is not the main one and
338 // implement blocking flushes in this case.
339 if (!callback.func)
340 return PP_ERROR_BADARGUMENT;
341
342 bool nothing_visible = true;
343 for (size_t i = 0; i < queued_operations_.size(); i++) {
344 QueuedOperation& operation = queued_operations_[i];
345 gfx::Rect op_rect;
346 switch (operation.type) {
347 case QueuedOperation::PAINT:
348 ExecutePaintImageData(operation.paint_image,
349 operation.paint_x, operation.paint_y,
350 operation.paint_src_rect,
351 &op_rect);
352 break;
353 case QueuedOperation::SCROLL:
354 ExecuteScroll(operation.scroll_clip_rect,
355 operation.scroll_dx, operation.scroll_dy,
356 &op_rect);
357 break;
358 case QueuedOperation::REPLACE:
359 ExecuteReplaceContents(operation.replace_image, &op_rect);
360 break;
361 }
362
363 // We need the rect to be in terms of the current clip rect of the plugin
364 // since that's what will actually be painted. If we issue an invalidate
365 // for a clipped-out region, WebKit will do nothing and we won't get any
366 // ViewInitiatedPaint/ViewFlushedPaint calls, leaving our callback stranded.
367 gfx::Rect visible_changed_rect;
368 if (bound_instance_ && !op_rect.IsEmpty())
369 visible_changed_rect = bound_instance_->clip().Intersect(op_rect);
370
371 if (bound_instance_ && !visible_changed_rect.IsEmpty()) {
372 if (operation.type == QueuedOperation::SCROLL) {
373 bound_instance_->ScrollRect(operation.scroll_dx, operation.scroll_dy,
374 visible_changed_rect);
375 } else {
376 bound_instance_->InvalidateRect(visible_changed_rect);
377 }
378 nothing_visible = false;
379 }
380 }
381 queued_operations_.clear();
382 flushed_any_data_ = true;
383
384 if (nothing_visible) {
385 // There's nothing visible to invalidate so just schedule the callback to
386 // execute in the next round of the message loop.
387 ScheduleOffscreenCallback(FlushCallbackData(callback));
388 } else {
389 unpainted_flush_callback_.Set(callback);
390 }
391 return PP_ERROR_WOULDBLOCK;
392 }
393
394 bool Graphics2D::ReadImageData(PP_Resource image,
395 const PP_Point* top_left) {
396 // Get and validate the image object to paint into.
397 scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image));
398 if (!image_resource)
399 return false;
400 if (!ImageData::IsImageDataFormatSupported(image_resource->format()))
401 return false; // Must be in the right format.
402
403 // Validate the bitmap position.
404 int x = top_left->x;
405 if (x < 0 ||
406 static_cast<int64>(x) + static_cast<int64>(image_resource->width()) >
407 image_data_->width())
408 return false;
409 int y = top_left->y;
410 if (y < 0 ||
411 static_cast<int64>(y) + static_cast<int64>(image_resource->height()) >
412 image_data_->height())
413 return false;
414
415 ImageDataAutoMapper auto_mapper(image_resource);
416 if (!auto_mapper.is_valid())
417 return false;
418
419 SkIRect src_irect = { x, y,
420 x + image_resource->width(),
421 y + image_resource->height() };
422 SkRect dest_rect = { SkIntToScalar(0),
423 SkIntToScalar(0),
424 SkIntToScalar(image_resource->width()),
425 SkIntToScalar(image_resource->height()) };
426
427 ImageDataAutoMapper auto_mapper2(image_data_);
428 if (image_resource->format() != image_data_->format()) {
429 // Convert the image data if the format does not match.
430 ConvertImageData(image_data_, src_irect, image_resource.get(), dest_rect);
431 } else {
432 skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas();
433
434 // We want to replace the contents of the bitmap rather than blend.
435 SkPaint paint;
436 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
437 dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(),
438 &src_irect, dest_rect, &paint);
439 }
440 return true;
441 }
442
443 bool Graphics2D::BindToInstance(PluginInstance* new_instance) {
444 if (bound_instance_ == new_instance)
445 return true; // Rebinding the same device, nothing to do.
446 if (bound_instance_ && new_instance)
447 return false; // Can't change a bound device.
448
449 if (!new_instance) {
450 // When the device is detached, we'll not get any more paint callbacks so
451 // we need to clear the list, but we still want to issue any pending
452 // callbacks to the plugin.
453 if (!unpainted_flush_callback_.is_null()) {
454 ScheduleOffscreenCallback(unpainted_flush_callback_);
455 unpainted_flush_callback_.Clear();
456 }
457 if (!painted_flush_callback_.is_null()) {
458 ScheduleOffscreenCallback(painted_flush_callback_);
459 painted_flush_callback_.Clear();
460 }
461 } else if (flushed_any_data_) {
462 // Only schedule a paint if this backing store has had any data flushed to
463 // it. This is an optimization. A "normal" plugin will first allocated a
464 // backing store, bind it, and then execute their normal painting and
465 // update loop. If binding a device always invalidated, it would mean we
466 // would get one paint for the bind, and one for the first time the plugin
467 // actually painted something. By not bothering to schedule an invalidate
468 // when an empty device is initially bound, we can save an extra paint for
469 // many plugins during the critical page initialization phase.
470 new_instance->InvalidateRect(gfx::Rect());
471 }
472
473 bound_instance_ = new_instance;
474 return true;
475 }
476
477 void Graphics2D::Paint(WebKit::WebCanvas* canvas,
478 const gfx::Rect& plugin_rect,
479 const gfx::Rect& paint_rect) {
480 ImageDataAutoMapper auto_mapper(image_data_);
481 const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap();
482
483 #if defined(OS_MACOSX)
484 SkAutoLockPixels lock(backing_bitmap);
485
486 base::mac::ScopedCFTypeRef<CGDataProviderRef> data_provider(
487 CGDataProviderCreateWithData(
488 NULL, backing_bitmap.getAddr32(0, 0),
489 backing_bitmap.rowBytes() * backing_bitmap.height(), NULL));
490 base::mac::ScopedCFTypeRef<CGImageRef> image(
491 CGImageCreate(
492 backing_bitmap.width(), backing_bitmap.height(),
493 8, 32, backing_bitmap.rowBytes(),
494 mac_util::GetSystemColorSpace(),
495 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
496 data_provider, NULL, false, kCGRenderingIntentDefault));
497
498 // Flip the transform
499 CGContextSaveGState(canvas);
500 float window_height = static_cast<float>(CGBitmapContextGetHeight(canvas));
501 CGContextTranslateCTM(canvas, 0, window_height);
502 CGContextScaleCTM(canvas, 1.0, -1.0);
503
504 CGRect bounds;
505 bounds.origin.x = plugin_rect.origin().x();
506 bounds.origin.y = window_height - plugin_rect.origin().y() -
507 backing_bitmap.height();
508 bounds.size.width = backing_bitmap.width();
509 bounds.size.height = backing_bitmap.height();
510
511 // TODO(brettw) bug 56673: do a direct memcpy instead of going through CG
512 // if the is_always_opaque_ flag is set.
513
514 CGContextDrawImage(canvas, bounds, image);
515 CGContextRestoreGState(canvas);
516 #else
517 SkPaint paint;
518 if (is_always_opaque_) {
519 // When we know the device is opaque, we can disable blending for slightly
520 // more optimized painting.
521 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
522 }
523
524 gfx::Point origin(plugin_rect.origin().x(), plugin_rect.origin().y());
525 canvas->drawBitmap(backing_bitmap,
526 SkIntToScalar(plugin_rect.origin().x()),
527 SkIntToScalar(plugin_rect.origin().y()),
528 &paint);
529 #endif
530 }
531
532 void Graphics2D::ViewInitiatedPaint() {
533 // Move any "unpainted" callback to the painted state. See
534 // |unpainted_flush_callback_| in the header for more.
535 if (!unpainted_flush_callback_.is_null()) {
536 DCHECK(painted_flush_callback_.is_null());
537 std::swap(painted_flush_callback_, unpainted_flush_callback_);
538 }
539 }
540
541 void Graphics2D::ViewFlushedPaint() {
542 // Notify any "painted" callback. See |unpainted_flush_callback_| in the
543 // header for more.
544 if (!painted_flush_callback_.is_null()) {
545 // We must clear this variable before issuing the callback. It will be
546 // common for the plugin to issue another invalidate in response to a flush
547 // callback, and we don't want to think that a callback is already pending.
548 FlushCallbackData callback;
549 std::swap(callback, painted_flush_callback_);
550 callback.Execute(PP_OK);
551 }
552 }
553
554 void Graphics2D::ExecutePaintImageData(ImageData* image,
555 int x, int y,
556 const gfx::Rect& src_rect,
557 gfx::Rect* invalidated_rect) {
558 // Ensure the source image is mapped to read from it.
559 ImageDataAutoMapper auto_mapper(image);
560 if (!auto_mapper.is_valid())
561 return;
562
563 // Portion within the source image to cut out.
564 SkIRect src_irect = { src_rect.x(), src_rect.y(),
565 src_rect.right(), src_rect.bottom() };
566
567 // Location within the backing store to copy to.
568 *invalidated_rect = src_rect;
569 invalidated_rect->Offset(x, y);
570 SkRect dest_rect = { SkIntToScalar(invalidated_rect->x()),
571 SkIntToScalar(invalidated_rect->y()),
572 SkIntToScalar(invalidated_rect->right()),
573 SkIntToScalar(invalidated_rect->bottom()) };
574
575 if (image->format() != image_data_->format()) {
576 // Convert the image data if the format does not match.
577 ConvertImageData(image, src_irect, image_data_, dest_rect);
578 } else {
579 // We're guaranteed to have a mapped canvas since we mapped it in Init().
580 skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
581
582 // We want to replace the contents of the bitmap rather than blend.
583 SkPaint paint;
584 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
585 backing_canvas->drawBitmapRect(*image->GetMappedBitmap(),
586 &src_irect, dest_rect, &paint);
587 }
588 }
589
590 void Graphics2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
591 gfx::Rect* invalidated_rect) {
592 gfx::ScrollCanvas(image_data_->mapped_canvas(),
593 clip, gfx::Point(dx, dy));
594 *invalidated_rect = clip;
595 }
596
597 void Graphics2D::ExecuteReplaceContents(ImageData* image,
598 gfx::Rect* invalidated_rect) {
599 if (image->format() != image_data_->format()) {
600 DCHECK(image->width() == image_data_->width() &&
601 image->height() == image_data_->height());
602 // Convert the image data if the format does not match.
603 SkIRect src_irect = { 0, 0, image->width(), image->height() };
604 SkRect dest_rect = { SkIntToScalar(0),
605 SkIntToScalar(0),
606 SkIntToScalar(image_data_->width()),
607 SkIntToScalar(image_data_->height()) };
608 ConvertImageData(image, src_irect, image_data_, dest_rect);
609 } else {
610 image_data_->Swap(image);
611 }
612 *invalidated_rect = gfx::Rect(0, 0,
613 image_data_->width(), image_data_->height());
614 }
615
616 void Graphics2D::ScheduleOffscreenCallback(const FlushCallbackData& callback) {
617 DCHECK(!HasPendingFlush());
618 offscreen_flush_pending_ = true;
619 MessageLoop::current()->PostTask(
620 FROM_HERE,
621 NewRunnableMethod(this,
622 &Graphics2D::ExecuteOffscreenCallback,
623 callback));
624 }
625
626 void Graphics2D::ExecuteOffscreenCallback(FlushCallbackData data) {
627 DCHECK(offscreen_flush_pending_);
628
629 // We must clear this flag before issuing the callback. It will be
630 // common for the plugin to issue another invalidate in response to a flush
631 // callback, and we don't want to think that a callback is already pending.
632 offscreen_flush_pending_ = false;
633 data.Execute(PP_OK);
634 }
635
636 bool Graphics2D::HasPendingFlush() const {
637 return !unpainted_flush_callback_.is_null() ||
638 !painted_flush_callback_.is_null() ||
639 offscreen_flush_pending_;
640 }
641
642 } // namespace pepper
OLDNEW
« no previous file with comments | « webkit/glue/plugins/pepper_graphics_2d.h ('k') | webkit/glue/plugins/pepper_graphics_3d.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698