OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkGpuDevice.h" | 8 #include "SkGpuDevice.h" |
9 | 9 |
10 #include "effects/GrBicubicEffect.h" | 10 #include "effects/GrBicubicEffect.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 #include "SkErrorInternals.h" | 45 #include "SkErrorInternals.h" |
46 | 46 |
47 #if SK_SUPPORT_GPU | 47 #if SK_SUPPORT_GPU |
48 | 48 |
49 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 }; | 49 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 }; |
50 | 50 |
51 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1 | 51 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1 |
52 | 52 |
53 #if 0 | 53 #if 0 |
54 extern bool (*gShouldDrawProc)(); | 54 extern bool (*gShouldDrawProc)(); |
55 #define CHECK_SHOULD_DRAW(draw, forceI) \ | 55 #define CHECK_SHOULD_DRAW(draw) \ |
56 do { \ | 56 do { \ |
57 if (gShouldDrawProc && !gShouldDrawProc()) return; \ | 57 if (gShouldDrawProc && !gShouldDrawProc()) return; \ |
58 this->prepareDraw(draw, forceI); \ | 58 this->prepareDraw(draw); \ |
59 } while (0) | 59 } while (0) |
60 #else | 60 #else |
61 #define CHECK_SHOULD_DRAW(draw, forceI) this->prepareDraw(draw, forceI) | 61 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw) |
62 #endif | 62 #endif |
63 | 63 |
64 // This constant represents the screen alignment criterion in texels for | 64 // This constant represents the screen alignment criterion in texels for |
65 // requiring texture domain clamping to prevent color bleeding when drawing | 65 // requiring texture domain clamping to prevent color bleeding when drawing |
66 // a sub region of a larger source image. | 66 // a sub region of a larger source image. |
67 #define COLOR_BLEED_TOLERANCE 0.001f | 67 #define COLOR_BLEED_TOLERANCE 0.001f |
68 | 68 |
69 #define DO_DEFERRED_CLEAR() \ | 69 #define DO_DEFERRED_CLEAR() \ |
70 do { \ | 70 do { \ |
71 if (fFlags & kNeedClear_Flag) { \ | 71 if (fFlags & kNeedClear_Flag) { \ |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 fClipData.fClipStack = canvas->getClipStack(); | 264 fClipData.fClipStack = canvas->getClipStack(); |
265 } | 265 } |
266 | 266 |
267 void SkGpuDevice::onDetachFromCanvas() { | 267 void SkGpuDevice::onDetachFromCanvas() { |
268 INHERITED::onDetachFromCanvas(); | 268 INHERITED::onDetachFromCanvas(); |
269 fClipData.fClipStack = NULL; | 269 fClipData.fClipStack = NULL; |
270 } | 270 } |
271 | 271 |
272 // call this every draw call, to ensure that the context reflects our state, | 272 // call this every draw call, to ensure that the context reflects our state, |
273 // and not the state from some other canvas/device | 273 // and not the state from some other canvas/device |
274 void SkGpuDevice::prepareDraw(const SkDraw& draw, bool forceIdentity) { | 274 void SkGpuDevice::prepareDraw(const SkDraw& draw) { |
275 SkASSERT(fClipData.fClipStack); | 275 SkASSERT(fClipData.fClipStack); |
276 | 276 |
277 fContext->setRenderTarget(fRenderTarget); | 277 fContext->setRenderTarget(fRenderTarget); |
278 | 278 |
279 SkASSERT(draw.fClipStack && draw.fClipStack == fClipData.fClipStack); | 279 SkASSERT(draw.fClipStack && draw.fClipStack == fClipData.fClipStack); |
280 | 280 |
281 if (forceIdentity) { | |
282 fContext->setIdentityMatrix(); | |
283 } else { | |
284 fContext->setMatrix(*draw.fMatrix); | |
285 } | |
286 fClipData.fOrigin = this->getOrigin(); | 281 fClipData.fOrigin = this->getOrigin(); |
287 | 282 |
288 fContext->setClip(&fClipData); | 283 fContext->setClip(&fClipData); |
289 | 284 |
290 DO_DEFERRED_CLEAR(); | 285 DO_DEFERRED_CLEAR(); |
291 } | 286 } |
292 | 287 |
293 GrRenderTarget* SkGpuDevice::accessRenderTarget() { | 288 GrRenderTarget* SkGpuDevice::accessRenderTarget() { |
294 DO_DEFERRED_CLEAR(); | 289 DO_DEFERRED_CLEAR(); |
295 return fRenderTarget; | 290 return fRenderTarget; |
(...skipping 16 matching lines...) Expand all Loading... |
312 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4, | 307 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4, |
313 shader_type_mismatch); | 308 shader_type_mismatch); |
314 SK_COMPILE_ASSERT(SkShader::kTwoPointConical_BitmapType == 5, | 309 SK_COMPILE_ASSERT(SkShader::kTwoPointConical_BitmapType == 5, |
315 shader_type_mismatch); | 310 shader_type_mismatch); |
316 SK_COMPILE_ASSERT(SkShader::kLinear_BitmapType == 6, shader_type_mismatch); | 311 SK_COMPILE_ASSERT(SkShader::kLinear_BitmapType == 6, shader_type_mismatch); |
317 SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 6, shader_type_mismatch); | 312 SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 6, shader_type_mismatch); |
318 | 313 |
319 /////////////////////////////////////////////////////////////////////////////// | 314 /////////////////////////////////////////////////////////////////////////////// |
320 | 315 |
321 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { | 316 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { |
322 CHECK_SHOULD_DRAW(draw, false); | 317 CHECK_SHOULD_DRAW(draw); |
323 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext); | 318 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext); |
324 | 319 |
325 GrPaint grPaint; | 320 GrPaint grPaint; |
326 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 321 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
327 | 322 |
328 fContext->drawPaint(grPaint); | 323 fContext->drawPaint(grPaint, *draw.fMatrix); |
329 } | 324 } |
330 | 325 |
331 // must be in SkCanvas::PointMode order | 326 // must be in SkCanvas::PointMode order |
332 static const GrPrimitiveType gPointMode2PrimtiveType[] = { | 327 static const GrPrimitiveType gPointMode2PrimtiveType[] = { |
333 kPoints_GrPrimitiveType, | 328 kPoints_GrPrimitiveType, |
334 kLines_GrPrimitiveType, | 329 kLines_GrPrimitiveType, |
335 kLineStrip_GrPrimitiveType | 330 kLineStrip_GrPrimitiveType |
336 }; | 331 }; |
337 | 332 |
338 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, | 333 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, |
339 size_t count, const SkPoint pts[], const SkPaint& p
aint) { | 334 size_t count, const SkPoint pts[], const SkPaint& p
aint) { |
340 CHECK_FOR_ANNOTATION(paint); | 335 CHECK_FOR_ANNOTATION(paint); |
341 CHECK_SHOULD_DRAW(draw, false); | 336 CHECK_SHOULD_DRAW(draw); |
342 | 337 |
343 SkScalar width = paint.getStrokeWidth(); | 338 SkScalar width = paint.getStrokeWidth(); |
344 if (width < 0) { | 339 if (width < 0) { |
345 return; | 340 return; |
346 } | 341 } |
347 | 342 |
348 if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mod
e) { | 343 if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mod
e) { |
349 GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style); | 344 GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style); |
350 GrPaint grPaint; | 345 GrPaint grPaint; |
351 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 346 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPa
int); |
352 SkPath path; | 347 SkPath path; |
353 path.setIsVolatile(true); | 348 path.setIsVolatile(true); |
354 path.moveTo(pts[0]); | 349 path.moveTo(pts[0]); |
355 path.lineTo(pts[1]); | 350 path.lineTo(pts[1]); |
356 fContext->drawPath(grPaint, path, strokeInfo); | 351 fContext->drawPath(grPaint, *draw.fMatrix, path, strokeInfo); |
357 return; | 352 return; |
358 } | 353 } |
359 | 354 |
360 // we only handle hairlines and paints without path effects or mask filters, | 355 // we only handle hairlines and paints without path effects or mask filters, |
361 // else we let the SkDraw call our drawPath() | 356 // else we let the SkDraw call our drawPath() |
362 if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) { | 357 if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) { |
363 draw.drawPoints(mode, count, pts, paint, true); | 358 draw.drawPoints(mode, count, pts, paint, true); |
364 return; | 359 return; |
365 } | 360 } |
366 | 361 |
367 GrPaint grPaint; | 362 GrPaint grPaint; |
368 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 363 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
369 | 364 |
370 fContext->drawVertices(grPaint, | 365 fContext->drawVertices(grPaint, |
| 366 *draw.fMatrix, |
371 gPointMode2PrimtiveType[mode], | 367 gPointMode2PrimtiveType[mode], |
372 SkToS32(count), | 368 SkToS32(count), |
373 (SkPoint*)pts, | 369 (SkPoint*)pts, |
374 NULL, | 370 NULL, |
375 NULL, | 371 NULL, |
376 NULL, | 372 NULL, |
377 0); | 373 0); |
378 } | 374 } |
379 | 375 |
380 /////////////////////////////////////////////////////////////////////////////// | 376 /////////////////////////////////////////////////////////////////////////////// |
381 | 377 |
382 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, | 378 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, |
383 const SkPaint& paint) { | 379 const SkPaint& paint) { |
384 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRect", fContext); | 380 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRect", fContext); |
385 | 381 |
386 CHECK_FOR_ANNOTATION(paint); | 382 CHECK_FOR_ANNOTATION(paint); |
387 CHECK_SHOULD_DRAW(draw, false); | 383 CHECK_SHOULD_DRAW(draw); |
388 | 384 |
389 bool doStroke = paint.getStyle() != SkPaint::kFill_Style; | 385 bool doStroke = paint.getStyle() != SkPaint::kFill_Style; |
390 SkScalar width = paint.getStrokeWidth(); | 386 SkScalar width = paint.getStrokeWidth(); |
391 | 387 |
392 /* | 388 /* |
393 We have special code for hairline strokes, miter-strokes, bevel-stroke | 389 We have special code for hairline strokes, miter-strokes, bevel-stroke |
394 and fills. Anything else we just call our path code. | 390 and fills. Anything else we just call our path code. |
395 */ | 391 */ |
396 bool usePath = doStroke && width > 0 && | 392 bool usePath = doStroke && width > 0 && |
397 (paint.getStrokeJoin() == SkPaint::kRound_Join || | 393 (paint.getStrokeJoin() == SkPaint::kRound_Join || |
398 (paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmp
ty())); | 394 (paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmp
ty())); |
399 // another two reasons we might need to call drawPath... | 395 // another two reasons we might need to call drawPath... |
400 | 396 |
401 if (paint.getMaskFilter()) { | 397 if (paint.getMaskFilter()) { |
402 usePath = true; | 398 usePath = true; |
403 } | 399 } |
404 | 400 |
405 if (!usePath && paint.isAntiAlias() && !fContext->getMatrix().rectStaysRect(
)) { | 401 if (!usePath && paint.isAntiAlias() && !draw.fMatrix->rectStaysRect()) { |
406 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT) | 402 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT) |
407 if (doStroke) { | 403 if (doStroke) { |
408 #endif | 404 #endif |
409 usePath = true; | 405 usePath = true; |
410 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT) | 406 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT) |
411 } else { | 407 } else { |
412 usePath = !fContext->getMatrix().preservesRightAngles(); | 408 usePath = !draw.fMatrix->preservesRightAngles(); |
413 } | 409 } |
414 #endif | 410 #endif |
415 } | 411 } |
416 // until we can both stroke and fill rectangles | 412 // until we can both stroke and fill rectangles |
417 if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) { | 413 if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) { |
418 usePath = true; | 414 usePath = true; |
419 } | 415 } |
420 | 416 |
421 GrStrokeInfo strokeInfo(paint); | 417 GrStrokeInfo strokeInfo(paint); |
422 | 418 |
423 const SkPathEffect* pe = paint.getPathEffect(); | 419 const SkPathEffect* pe = paint.getPathEffect(); |
424 if (!usePath && pe && !strokeInfo.isDashed()) { | 420 if (!usePath && pe && !strokeInfo.isDashed()) { |
425 usePath = true; | 421 usePath = true; |
426 } | 422 } |
427 | 423 |
428 if (usePath) { | 424 if (usePath) { |
429 SkPath path; | 425 SkPath path; |
430 path.setIsVolatile(true); | 426 path.setIsVolatile(true); |
431 path.addRect(rect); | 427 path.addRect(rect); |
432 this->drawPath(draw, path, paint, NULL, true); | 428 this->drawPath(draw, path, paint, NULL, true); |
433 return; | 429 return; |
434 } | 430 } |
435 | 431 |
436 GrPaint grPaint; | 432 GrPaint grPaint; |
437 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 433 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
438 | 434 |
439 fContext->drawRect(grPaint, rect, &strokeInfo); | 435 fContext->drawRect(grPaint, *draw.fMatrix, rect, &strokeInfo); |
440 } | 436 } |
441 | 437 |
442 /////////////////////////////////////////////////////////////////////////////// | 438 /////////////////////////////////////////////////////////////////////////////// |
443 | 439 |
444 void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect, | 440 void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect, |
445 const SkPaint& paint) { | 441 const SkPaint& paint) { |
446 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRRect", fContext); | 442 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRRect", fContext); |
447 CHECK_FOR_ANNOTATION(paint); | 443 CHECK_FOR_ANNOTATION(paint); |
448 CHECK_SHOULD_DRAW(draw, false); | 444 CHECK_SHOULD_DRAW(draw); |
449 | 445 |
450 GrPaint grPaint; | 446 GrPaint grPaint; |
451 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 447 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
452 | 448 |
453 GrStrokeInfo strokeInfo(paint); | 449 GrStrokeInfo strokeInfo(paint); |
454 if (paint.getMaskFilter()) { | 450 if (paint.getMaskFilter()) { |
455 // try to hit the fast path for drawing filtered round rects | 451 // try to hit the fast path for drawing filtered round rects |
456 | 452 |
457 SkRRect devRRect; | 453 SkRRect devRRect; |
458 if (rect.transform(fContext->getMatrix(), &devRRect)) { | 454 if (rect.transform(*draw.fMatrix, &devRRect)) { |
459 if (devRRect.allCornersCircular()) { | 455 if (devRRect.allCornersCircular()) { |
460 SkRect maskRect; | 456 SkRect maskRect; |
461 if (paint.getMaskFilter()->canFilterMaskGPU(devRRect.rect(), | 457 if (paint.getMaskFilter()->canFilterMaskGPU(devRRect.rect(), |
462 draw.fClip->getBounds(), | 458 draw.fClip->getBound
s(), |
463 fContext->getMatrix(), | 459 *draw.fMatrix, |
464 &maskRect)) { | 460 &maskRect)) { |
465 SkIRect finalIRect; | 461 SkIRect finalIRect; |
466 maskRect.roundOut(&finalIRect); | 462 maskRect.roundOut(&finalIRect); |
467 if (draw.fClip->quickReject(finalIRect)) { | 463 if (draw.fClip->quickReject(finalIRect)) { |
468 // clipped out | 464 // clipped out |
469 return; | 465 return; |
470 } | 466 } |
471 if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext
, &grPaint, | 467 if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext
, &grPaint, |
| 468 *draw.fM
atrix, |
472 strokeIn
fo.getStrokeRec(), | 469 strokeIn
fo.getStrokeRec(), |
473 devRRect
)) { | 470 devRRect
)) { |
474 return; | 471 return; |
475 } | 472 } |
476 } | 473 } |
477 | 474 |
478 } | 475 } |
479 } | 476 } |
480 | 477 |
481 } | 478 } |
(...skipping 11 matching lines...) Expand all Loading... |
493 | 490 |
494 | 491 |
495 if (usePath) { | 492 if (usePath) { |
496 SkPath path; | 493 SkPath path; |
497 path.setIsVolatile(true); | 494 path.setIsVolatile(true); |
498 path.addRRect(rect); | 495 path.addRRect(rect); |
499 this->drawPath(draw, path, paint, NULL, true); | 496 this->drawPath(draw, path, paint, NULL, true); |
500 return; | 497 return; |
501 } | 498 } |
502 | 499 |
503 fContext->drawRRect(grPaint, rect, strokeInfo); | 500 fContext->drawRRect(grPaint, *draw.fMatrix, rect, strokeInfo); |
504 } | 501 } |
505 | 502 |
506 void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, | 503 void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, |
507 const SkRRect& inner, const SkPaint& paint) { | 504 const SkRRect& inner, const SkPaint& paint) { |
508 SkStrokeRec stroke(paint); | 505 SkStrokeRec stroke(paint); |
509 if (stroke.isFillStyle()) { | 506 if (stroke.isFillStyle()) { |
510 | 507 |
511 CHECK_FOR_ANNOTATION(paint); | 508 CHECK_FOR_ANNOTATION(paint); |
512 CHECK_SHOULD_DRAW(draw, false); | 509 CHECK_SHOULD_DRAW(draw); |
513 | 510 |
514 GrPaint grPaint; | 511 GrPaint grPaint; |
515 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 512 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPa
int); |
516 | 513 |
517 if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) { | 514 if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) { |
518 fContext->drawDRRect(grPaint, outer, inner); | 515 fContext->drawDRRect(grPaint, *draw.fMatrix, outer, inner); |
519 return; | 516 return; |
520 } | 517 } |
521 } | 518 } |
522 | 519 |
523 SkPath path; | 520 SkPath path; |
524 path.setIsVolatile(true); | 521 path.setIsVolatile(true); |
525 path.addRRect(outer); | 522 path.addRRect(outer); |
526 path.addRRect(inner); | 523 path.addRRect(inner); |
527 path.setFillType(SkPath::kEvenOdd_FillType); | 524 path.setFillType(SkPath::kEvenOdd_FillType); |
528 | 525 |
529 this->drawPath(draw, path, paint, NULL, true); | 526 this->drawPath(draw, path, paint, NULL, true); |
530 } | 527 } |
531 | 528 |
532 | 529 |
533 ///////////////////////////////////////////////////////////////////////////// | 530 ///////////////////////////////////////////////////////////////////////////// |
534 | 531 |
535 void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, | 532 void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, |
536 const SkPaint& paint) { | 533 const SkPaint& paint) { |
537 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawOval", fContext); | 534 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawOval", fContext); |
538 CHECK_FOR_ANNOTATION(paint); | 535 CHECK_FOR_ANNOTATION(paint); |
539 CHECK_SHOULD_DRAW(draw, false); | 536 CHECK_SHOULD_DRAW(draw); |
540 | 537 |
541 GrStrokeInfo strokeInfo(paint); | 538 GrStrokeInfo strokeInfo(paint); |
542 | 539 |
543 bool usePath = false; | 540 bool usePath = false; |
544 // some basic reasons we might need to call drawPath... | 541 // some basic reasons we might need to call drawPath... |
545 if (paint.getMaskFilter()) { | 542 if (paint.getMaskFilter()) { |
546 usePath = true; | 543 usePath = true; |
547 } else { | 544 } else { |
548 const SkPathEffect* pe = paint.getPathEffect(); | 545 const SkPathEffect* pe = paint.getPathEffect(); |
549 if (pe && !strokeInfo.isDashed()) { | 546 if (pe && !strokeInfo.isDashed()) { |
550 usePath = true; | 547 usePath = true; |
551 } | 548 } |
552 } | 549 } |
553 | 550 |
554 if (usePath) { | 551 if (usePath) { |
555 SkPath path; | 552 SkPath path; |
556 path.setIsVolatile(true); | 553 path.setIsVolatile(true); |
557 path.addOval(oval); | 554 path.addOval(oval); |
558 this->drawPath(draw, path, paint, NULL, true); | 555 this->drawPath(draw, path, paint, NULL, true); |
559 return; | 556 return; |
560 } | 557 } |
561 | 558 |
562 GrPaint grPaint; | 559 GrPaint grPaint; |
563 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 560 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
564 | 561 |
565 fContext->drawOval(grPaint, oval, strokeInfo); | 562 fContext->drawOval(grPaint, *draw.fMatrix, oval, strokeInfo); |
566 } | 563 } |
567 | 564 |
568 #include "SkMaskFilter.h" | 565 #include "SkMaskFilter.h" |
569 | 566 |
570 /////////////////////////////////////////////////////////////////////////////// | 567 /////////////////////////////////////////////////////////////////////////////// |
571 | 568 |
572 // helpers for applying mask filters | 569 // helpers for applying mask filters |
573 namespace { | 570 namespace { |
574 | 571 |
575 // Draw a mask using the supplied paint. Since the coverage/geometry | 572 // Draw a mask using the supplied paint. Since the coverage/geometry |
576 // is already burnt into the mask this boils down to a rect draw. | 573 // is already burnt into the mask this boils down to a rect draw. |
577 // Return true if the mask was successfully drawn. | 574 // Return true if the mask was successfully drawn. |
578 bool draw_mask(GrContext* context, const SkRect& maskRect, | 575 bool draw_mask(GrContext* context, const SkMatrix& viewMatrix, const SkRect& mas
kRect, |
579 GrPaint* grp, GrTexture* mask) { | 576 GrPaint* grp, GrTexture* mask) { |
580 GrContext::AutoMatrix am; | 577 if (!grp->localCoordChangeInverse(viewMatrix)) { |
581 if (!am.setIdentity(context, grp)) { | |
582 return false; | 578 return false; |
583 } | 579 } |
584 | 580 |
585 SkMatrix matrix; | 581 SkMatrix matrix; |
586 matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop); | 582 matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop); |
587 matrix.postIDiv(mask->width(), mask->height()); | 583 matrix.postIDiv(mask->width(), mask->height()); |
588 | 584 |
589 grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix))->unre
f(); | 585 grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix))->unre
f(); |
590 context->drawRect(*grp, maskRect); | 586 context->drawRect(*grp, SkMatrix::I(), maskRect); |
591 return true; | 587 return true; |
592 } | 588 } |
593 | 589 |
594 bool draw_with_mask_filter(GrContext* context, const SkPath& devPath, | 590 bool draw_with_mask_filter(GrContext* context, const SkMatrix& viewMatrix, const
SkPath& devPath, |
595 SkMaskFilter* filter, const SkRegion& clip, | 591 SkMaskFilter* filter, const SkRegion& clip, |
596 GrPaint* grp, SkPaint::Style style) { | 592 GrPaint* grp, SkPaint::Style style) { |
597 SkMask srcM, dstM; | 593 SkMask srcM, dstM; |
598 | 594 |
599 if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), filter, &context->getMat
rix(), &srcM, | 595 if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), filter, &viewMatrix, &sr
cM, |
600 SkMask::kComputeBoundsAndRenderImage_CreateMode, sty
le)) { | 596 SkMask::kComputeBoundsAndRenderImage_CreateMode, sty
le)) { |
601 return false; | 597 return false; |
602 } | 598 } |
603 SkAutoMaskFreeImage autoSrc(srcM.fImage); | 599 SkAutoMaskFreeImage autoSrc(srcM.fImage); |
604 | 600 |
605 if (!filter->filterMask(&dstM, srcM, context->getMatrix(), NULL)) { | 601 if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) { |
606 return false; | 602 return false; |
607 } | 603 } |
608 // this will free-up dstM when we're done (allocated in filterMask()) | 604 // this will free-up dstM when we're done (allocated in filterMask()) |
609 SkAutoMaskFreeImage autoDst(dstM.fImage); | 605 SkAutoMaskFreeImage autoDst(dstM.fImage); |
610 | 606 |
611 if (clip.quickReject(dstM.fBounds)) { | 607 if (clip.quickReject(dstM.fBounds)) { |
612 return false; | 608 return false; |
613 } | 609 } |
614 | 610 |
615 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using | 611 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using |
616 // the current clip (and identity matrix) and GrPaint settings | 612 // the current clip (and identity matrix) and GrPaint settings |
617 GrSurfaceDesc desc; | 613 GrSurfaceDesc desc; |
618 desc.fWidth = dstM.fBounds.width(); | 614 desc.fWidth = dstM.fBounds.width(); |
619 desc.fHeight = dstM.fBounds.height(); | 615 desc.fHeight = dstM.fBounds.height(); |
620 desc.fConfig = kAlpha_8_GrPixelConfig; | 616 desc.fConfig = kAlpha_8_GrPixelConfig; |
621 | 617 |
622 SkAutoTUnref<GrTexture> texture( | 618 SkAutoTUnref<GrTexture> texture( |
623 context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch)); | 619 context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch)); |
624 if (!texture) { | 620 if (!texture) { |
625 return false; | 621 return false; |
626 } | 622 } |
627 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, | 623 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, |
628 dstM.fImage, dstM.fRowBytes); | 624 dstM.fImage, dstM.fRowBytes); |
629 | 625 |
630 SkRect maskRect = SkRect::Make(dstM.fBounds); | 626 SkRect maskRect = SkRect::Make(dstM.fBounds); |
631 | 627 |
632 return draw_mask(context, maskRect, grp, texture); | 628 return draw_mask(context, viewMatrix, maskRect, grp, texture); |
633 } | 629 } |
634 | 630 |
635 // Create a mask of 'devPath' and place the result in 'mask'. | 631 // Create a mask of 'devPath' and place the result in 'mask'. |
636 GrTexture* create_mask_GPU(GrContext* context, | 632 GrTexture* create_mask_GPU(GrContext* context, |
637 const SkRect& maskRect, | 633 const SkRect& maskRect, |
638 const SkPath& devPath, | 634 const SkPath& devPath, |
639 const GrStrokeInfo& strokeInfo, | 635 const GrStrokeInfo& strokeInfo, |
640 bool doAA, | 636 bool doAA, |
641 int sampleCnt) { | 637 int sampleCnt) { |
642 GrSurfaceDesc desc; | 638 GrSurfaceDesc desc; |
(...skipping 27 matching lines...) Expand all Loading... |
670 tempPaint.setAntiAlias(true); | 666 tempPaint.setAntiAlias(true); |
671 // AA uses the "coverage" stages on GrDrawTarget. Coverage with a dst | 667 // AA uses the "coverage" stages on GrDrawTarget. Coverage with a dst |
672 // blend coeff of zero requires dual source blending support in order | 668 // blend coeff of zero requires dual source blending support in order |
673 // to properly blend partially covered pixels. This means the AA | 669 // to properly blend partially covered pixels. This means the AA |
674 // code path may not be taken. So we use a dst blend coeff of ISA. We | 670 // code path may not be taken. So we use a dst blend coeff of ISA. We |
675 // could special case AA draws to a dst surface with known alpha=0 to | 671 // could special case AA draws to a dst surface with known alpha=0 to |
676 // use a zero dst coeff when dual source blending isn't available. | 672 // use a zero dst coeff when dual source blending isn't available. |
677 tempPaint.setPorterDuffXPFactory(kOne_GrBlendCoeff, kISC_GrBlendCoeff); | 673 tempPaint.setPorterDuffXPFactory(kOne_GrBlendCoeff, kISC_GrBlendCoeff); |
678 } | 674 } |
679 | 675 |
680 GrContext::AutoMatrix am; | |
681 | |
682 // Draw the mask into maskTexture with the path's top-left at the origin usi
ng tempPaint. | 676 // Draw the mask into maskTexture with the path's top-left at the origin usi
ng tempPaint. |
683 SkMatrix translate; | 677 SkMatrix translate; |
684 translate.setTranslate(-maskRect.fLeft, -maskRect.fTop); | 678 translate.setTranslate(-maskRect.fLeft, -maskRect.fTop); |
685 am.set(context, translate); | 679 context->drawPath(tempPaint, translate, devPath, strokeInfo); |
686 context->drawPath(tempPaint, devPath, strokeInfo); | |
687 return mask; | 680 return mask; |
688 } | 681 } |
689 | 682 |
690 SkBitmap wrap_texture(GrTexture* texture) { | 683 SkBitmap wrap_texture(GrTexture* texture) { |
691 SkBitmap result; | 684 SkBitmap result; |
692 result.setInfo(texture->surfacePriv().info()); | 685 result.setInfo(texture->surfacePriv().info()); |
693 result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unre
f(); | 686 result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unre
f(); |
694 return result; | 687 return result; |
695 } | 688 } |
696 | 689 |
697 }; | 690 }; |
698 | 691 |
699 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, | 692 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, |
700 const SkPaint& paint, const SkMatrix* prePathMatrix, | 693 const SkPaint& paint, const SkMatrix* prePathMatrix, |
701 bool pathIsMutable) { | 694 bool pathIsMutable) { |
702 CHECK_FOR_ANNOTATION(paint); | 695 CHECK_FOR_ANNOTATION(paint); |
703 CHECK_SHOULD_DRAW(draw, false); | 696 CHECK_SHOULD_DRAW(draw); |
704 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext); | 697 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext); |
705 | 698 |
706 SkASSERT(!pathIsMutable || origSrcPath.isVolatile()); | 699 SkASSERT(!pathIsMutable || origSrcPath.isVolatile()); |
707 | 700 |
708 GrPaint grPaint; | 701 GrPaint grPaint; |
709 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 702 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
710 | 703 |
711 // If we have a prematrix, apply it to the path, optimizing for the case | 704 // If we have a prematrix, apply it to the path, optimizing for the case |
712 // where the original path can in fact be modified in place (even though | 705 // where the original path can in fact be modified in place (even though |
713 // its parameter type is const). | 706 // its parameter type is const). |
714 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath); | 707 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath); |
715 SkTLazy<SkPath> tmpPath; | 708 SkTLazy<SkPath> tmpPath; |
716 SkTLazy<SkPath> effectPath; | 709 SkTLazy<SkPath> effectPath; |
717 | 710 |
718 if (prePathMatrix) { | 711 if (prePathMatrix) { |
719 SkPath* result = pathPtr; | 712 SkPath* result = pathPtr; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 } | 746 } |
754 } | 747 } |
755 | 748 |
756 // avoid possibly allocating a new path in transform if we can | 749 // avoid possibly allocating a new path in transform if we can |
757 SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init(); | 750 SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init(); |
758 if (!pathIsMutable) { | 751 if (!pathIsMutable) { |
759 devPathPtr->setIsVolatile(true); | 752 devPathPtr->setIsVolatile(true); |
760 } | 753 } |
761 | 754 |
762 // transform the path into device space | 755 // transform the path into device space |
763 pathPtr->transform(fContext->getMatrix(), devPathPtr); | 756 pathPtr->transform(*draw.fMatrix, devPathPtr); |
764 | 757 |
765 SkRect maskRect; | 758 SkRect maskRect; |
766 if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(), | 759 if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(), |
767 draw.fClip->getBounds(), | 760 draw.fClip->getBounds(), |
768 fContext->getMatrix(), | 761 *draw.fMatrix, |
769 &maskRect)) { | 762 &maskRect)) { |
770 // The context's matrix may change while creating the mask, so save
the CTM here to | 763 // The context's matrix may change while creating the mask, so save
the CTM here to |
771 // pass to filterMaskGPU. | 764 // pass to filterMaskGPU. |
772 const SkMatrix ctm = fContext->getMatrix(); | 765 const SkMatrix ctm = *draw.fMatrix; |
773 | 766 |
774 SkIRect finalIRect; | 767 SkIRect finalIRect; |
775 maskRect.roundOut(&finalIRect); | 768 maskRect.roundOut(&finalIRect); |
776 if (draw.fClip->quickReject(finalIRect)) { | 769 if (draw.fClip->quickReject(finalIRect)) { |
777 // clipped out | 770 // clipped out |
778 return; | 771 return; |
779 } | 772 } |
780 | 773 |
781 if (paint.getMaskFilter()->directFilterMaskGPU(fContext, &grPaint, | 774 if (paint.getMaskFilter()->directFilterMaskGPU(fContext, &grPaint, *
draw.fMatrix, |
782 stroke, *devPathPtr))
{ | 775 stroke, *devPathPtr))
{ |
783 // the mask filter was able to draw itself directly, so there's
nothing | 776 // the mask filter was able to draw itself directly, so there's
nothing |
784 // left to do. | 777 // left to do. |
785 return; | 778 return; |
786 } | 779 } |
787 | 780 |
788 | 781 |
789 SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext, maskRect, *de
vPathPtr, | 782 SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext, maskRect, *de
vPathPtr, |
790 strokeInfo, grPaint.isA
ntiAlias(), | 783 strokeInfo, grPaint.isA
ntiAlias(), |
791 fRenderTarget->numSampl
es())); | 784 fRenderTarget->numSampl
es())); |
792 if (mask) { | 785 if (mask) { |
793 GrTexture* filtered; | 786 GrTexture* filtered; |
794 | 787 |
795 if (paint.getMaskFilter()->filterMaskGPU(mask, ctm, maskRect, &f
iltered, true)) { | 788 if (paint.getMaskFilter()->filterMaskGPU(mask, ctm, maskRect, &f
iltered, true)) { |
796 // filterMaskGPU gives us ownership of a ref to the result | 789 // filterMaskGPU gives us ownership of a ref to the result |
797 SkAutoTUnref<GrTexture> atu(filtered); | 790 SkAutoTUnref<GrTexture> atu(filtered); |
798 if (draw_mask(fContext, maskRect, &grPaint, filtered)) { | 791 if (draw_mask(fContext, *draw.fMatrix, maskRect, &grPaint, f
iltered)) { |
799 // This path is completely drawn | 792 // This path is completely drawn |
800 return; | 793 return; |
801 } | 794 } |
802 } | 795 } |
803 } | 796 } |
804 } | 797 } |
805 | 798 |
806 // draw the mask on the CPU - this is a fallthrough path in case the | 799 // draw the mask on the CPU - this is a fallthrough path in case the |
807 // GPU path fails | 800 // GPU path fails |
808 SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style
: | 801 SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style
: |
809 SkPaint::kFill_Style; | 802 SkPaint::kFill_Style; |
810 draw_with_mask_filter(fContext, *devPathPtr, paint.getMaskFilter(), | 803 draw_with_mask_filter(fContext, *draw.fMatrix, *devPathPtr, paint.getMas
kFilter(), |
811 *draw.fClip, &grPaint, style); | 804 *draw.fClip, &grPaint, style); |
812 return; | 805 return; |
813 } | 806 } |
814 | 807 |
815 fContext->drawPath(grPaint, *pathPtr, strokeInfo); | 808 fContext->drawPath(grPaint, *draw.fMatrix, *pathPtr, strokeInfo); |
816 } | 809 } |
817 | 810 |
818 static const int kBmpSmallTileSize = 1 << 10; | 811 static const int kBmpSmallTileSize = 1 << 10; |
819 | 812 |
820 static inline int get_tile_count(const SkIRect& srcRect, int tileSize) { | 813 static inline int get_tile_count(const SkIRect& srcRect, int tileSize) { |
821 int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1; | 814 int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1; |
822 int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1; | 815 int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1; |
823 return tilesX * tilesY; | 816 return tilesX * tilesY; |
824 } | 817 } |
825 | 818 |
(...skipping 11 matching lines...) Expand all Loading... |
837 if (maxTileTotalTileSize > 2 * smallTotalTileSize) { | 830 if (maxTileTotalTileSize > 2 * smallTotalTileSize) { |
838 return kBmpSmallTileSize; | 831 return kBmpSmallTileSize; |
839 } else { | 832 } else { |
840 return maxTileSize; | 833 return maxTileSize; |
841 } | 834 } |
842 } | 835 } |
843 | 836 |
844 // Given a bitmap, an optional src rect, and a context with a clip and matrix de
termine what | 837 // Given a bitmap, an optional src rect, and a context with a clip and matrix de
termine what |
845 // pixels from the bitmap are necessary. | 838 // pixels from the bitmap are necessary. |
846 static void determine_clipped_src_rect(const GrContext* context, | 839 static void determine_clipped_src_rect(const GrContext* context, |
| 840 const SkMatrix& viewMatrix, |
847 const SkBitmap& bitmap, | 841 const SkBitmap& bitmap, |
848 const SkRect* srcRectPtr, | 842 const SkRect* srcRectPtr, |
849 SkIRect* clippedSrcIRect) { | 843 SkIRect* clippedSrcIRect) { |
850 const GrClipData* clip = context->getClip(); | 844 const GrClipData* clip = context->getClip(); |
851 clip->getConservativeBounds(context->getRenderTarget(), clippedSrcIRect, NUL
L); | 845 clip->getConservativeBounds(context->getRenderTarget(), clippedSrcIRect, NUL
L); |
852 SkMatrix inv; | 846 SkMatrix inv; |
853 if (!context->getMatrix().invert(&inv)) { | 847 if (!viewMatrix.invert(&inv)) { |
854 clippedSrcIRect->setEmpty(); | 848 clippedSrcIRect->setEmpty(); |
855 return; | 849 return; |
856 } | 850 } |
857 SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect); | 851 SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect); |
858 inv.mapRect(&clippedSrcRect); | 852 inv.mapRect(&clippedSrcRect); |
859 if (srcRectPtr) { | 853 if (srcRectPtr) { |
860 // we've setup src space 0,0 to map to the top left of the src rect. | 854 // we've setup src space 0,0 to map to the top left of the src rect. |
861 clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop); | 855 clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop); |
862 if (!clippedSrcRect.intersect(*srcRectPtr)) { | 856 if (!clippedSrcRect.intersect(*srcRectPtr)) { |
863 clippedSrcIRect->setEmpty(); | 857 clippedSrcIRect->setEmpty(); |
864 return; | 858 return; |
865 } | 859 } |
866 } | 860 } |
867 clippedSrcRect.roundOut(clippedSrcIRect); | 861 clippedSrcRect.roundOut(clippedSrcIRect); |
868 SkIRect bmpBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height()); | 862 SkIRect bmpBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height()); |
869 if (!clippedSrcIRect->intersect(bmpBounds)) { | 863 if (!clippedSrcIRect->intersect(bmpBounds)) { |
870 clippedSrcIRect->setEmpty(); | 864 clippedSrcIRect->setEmpty(); |
871 } | 865 } |
872 } | 866 } |
873 | 867 |
874 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap, | 868 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap, |
| 869 const SkMatrix& viewMatrix, |
875 const GrTextureParams& params, | 870 const GrTextureParams& params, |
876 const SkRect* srcRectPtr, | 871 const SkRect* srcRectPtr, |
877 int maxTileSize, | 872 int maxTileSize, |
878 int* tileSize, | 873 int* tileSize, |
879 SkIRect* clippedSrcRect) const { | 874 SkIRect* clippedSrcRect) const { |
880 // if bitmap is explictly texture backed then just use the texture | 875 // if bitmap is explictly texture backed then just use the texture |
881 if (bitmap.getTexture()) { | 876 if (bitmap.getTexture()) { |
882 return false; | 877 return false; |
883 } | 878 } |
884 | 879 |
885 // if it's larger than the max tile size, then we have no choice but tiling. | 880 // if it's larger than the max tile size, then we have no choice but tiling. |
886 if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) { | 881 if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) { |
887 determine_clipped_src_rect(fContext, bitmap, srcRectPtr, clippedSrcRect)
; | 882 determine_clipped_src_rect(fContext, viewMatrix, bitmap, srcRectPtr, cli
ppedSrcRect); |
888 *tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize); | 883 *tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize); |
889 return true; | 884 return true; |
890 } | 885 } |
891 | 886 |
892 if (bitmap.width() * bitmap.height() < 4 * kBmpSmallTileSize * kBmpSmallTile
Size) { | 887 if (bitmap.width() * bitmap.height() < 4 * kBmpSmallTileSize * kBmpSmallTile
Size) { |
893 return false; | 888 return false; |
894 } | 889 } |
895 | 890 |
896 // if the entire texture is already in our cache then no reason to tile it | 891 // if the entire texture is already in our cache then no reason to tile it |
897 if (GrIsBitmapInCache(fContext, bitmap, ¶ms)) { | 892 if (GrIsBitmapInCache(fContext, bitmap, ¶ms)) { |
898 return false; | 893 return false; |
899 } | 894 } |
900 | 895 |
901 // At this point we know we could do the draw by uploading the entire bitmap | 896 // At this point we know we could do the draw by uploading the entire bitmap |
902 // as a texture. However, if the texture would be large compared to the | 897 // as a texture. However, if the texture would be large compared to the |
903 // cache size and we don't require most of it for this draw then tile to | 898 // cache size and we don't require most of it for this draw then tile to |
904 // reduce the amount of upload and cache spill. | 899 // reduce the amount of upload and cache spill. |
905 | 900 |
906 // assumption here is that sw bitmap size is a good proxy for its size as | 901 // assumption here is that sw bitmap size is a good proxy for its size as |
907 // a texture | 902 // a texture |
908 size_t bmpSize = bitmap.getSize(); | 903 size_t bmpSize = bitmap.getSize(); |
909 size_t cacheSize; | 904 size_t cacheSize; |
910 fContext->getResourceCacheLimits(NULL, &cacheSize); | 905 fContext->getResourceCacheLimits(NULL, &cacheSize); |
911 if (bmpSize < cacheSize / 2) { | 906 if (bmpSize < cacheSize / 2) { |
912 return false; | 907 return false; |
913 } | 908 } |
914 | 909 |
915 // Figure out how much of the src we will need based on the src rect and cli
pping. | 910 // Figure out how much of the src we will need based on the src rect and cli
pping. |
916 determine_clipped_src_rect(fContext, bitmap, srcRectPtr, clippedSrcRect); | 911 determine_clipped_src_rect(fContext, viewMatrix, bitmap, srcRectPtr, clipped
SrcRect); |
917 *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max
sized tile. | 912 *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max
sized tile. |
918 size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) * | 913 size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) * |
919 kBmpSmallTileSize * kBmpSmallTileSize; | 914 kBmpSmallTileSize * kBmpSmallTileSize; |
920 | 915 |
921 return usedTileBytes < 2 * bmpSize; | 916 return usedTileBytes < 2 * bmpSize; |
922 } | 917 } |
923 | 918 |
924 void SkGpuDevice::drawBitmap(const SkDraw& origDraw, | 919 void SkGpuDevice::drawBitmap(const SkDraw& origDraw, |
925 const SkBitmap& bitmap, | 920 const SkBitmap& bitmap, |
926 const SkMatrix& m, | 921 const SkMatrix& m, |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 } | 1029 } |
1035 return needsTextureDomain; | 1030 return needsTextureDomain; |
1036 } | 1031 } |
1037 | 1032 |
1038 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, | 1033 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, |
1039 const SkBitmap& bitmap, | 1034 const SkBitmap& bitmap, |
1040 const SkRect* srcRectPtr, | 1035 const SkRect* srcRectPtr, |
1041 const SkSize* dstSizePtr, | 1036 const SkSize* dstSizePtr, |
1042 const SkPaint& paint, | 1037 const SkPaint& paint, |
1043 SkCanvas::DrawBitmapRectFlags flags) { | 1038 SkCanvas::DrawBitmapRectFlags flags) { |
1044 CHECK_SHOULD_DRAW(draw, false); | 1039 CHECK_SHOULD_DRAW(draw); |
1045 | 1040 |
1046 SkRect srcRect; | 1041 SkRect srcRect; |
1047 SkSize dstSize; | 1042 SkSize dstSize; |
1048 // If there is no src rect, or the src rect contains the entire bitmap then
we're effectively | 1043 // If there is no src rect, or the src rect contains the entire bitmap then
we're effectively |
1049 // in the (easier) bleed case, so update flags. | 1044 // in the (easier) bleed case, so update flags. |
1050 if (NULL == srcRectPtr) { | 1045 if (NULL == srcRectPtr) { |
1051 SkScalar w = SkIntToScalar(bitmap.width()); | 1046 SkScalar w = SkIntToScalar(bitmap.width()); |
1052 SkScalar h = SkIntToScalar(bitmap.height()); | 1047 SkScalar h = SkIntToScalar(bitmap.height()); |
1053 dstSize.fWidth = w; | 1048 dstSize.fWidth = w; |
1054 dstSize.fHeight = h; | 1049 dstSize.fHeight = h; |
(...skipping 15 matching lines...) Expand all Loading... |
1070 // anti-aliased edges, we work around that for now by drawing directly | 1065 // anti-aliased edges, we work around that for now by drawing directly |
1071 // if the image size exceeds maximum texture size. | 1066 // if the image size exceeds maximum texture size. |
1072 int maxTextureSize = fContext->getMaxTextureSize(); | 1067 int maxTextureSize = fContext->getMaxTextureSize(); |
1073 bool directDraw = fRenderTarget->isMultisampled() || | 1068 bool directDraw = fRenderTarget->isMultisampled() || |
1074 !paint.isAntiAlias() || | 1069 !paint.isAntiAlias() || |
1075 bitmap.width() > maxTextureSize || | 1070 bitmap.width() > maxTextureSize || |
1076 bitmap.height() > maxTextureSize; | 1071 bitmap.height() > maxTextureSize; |
1077 | 1072 |
1078 // we check whether dst rect are pixel aligned | 1073 // we check whether dst rect are pixel aligned |
1079 if (!directDraw) { | 1074 if (!directDraw) { |
1080 bool staysRect = fContext->getMatrix().rectStaysRect(); | 1075 bool staysRect = draw.fMatrix->rectStaysRect(); |
1081 | 1076 |
1082 if (staysRect) { | 1077 if (staysRect) { |
1083 SkRect rect; | 1078 SkRect rect; |
1084 SkRect dstRect = SkRect::MakeXYWH(0, 0, dstSize.fWidth, dstSize.fHei
ght); | 1079 SkRect dstRect = SkRect::MakeXYWH(0, 0, dstSize.fWidth, dstSize.fHei
ght); |
1085 fContext->getMatrix().mapRect(&rect, dstRect); | 1080 draw.fMatrix->mapRect(&rect, dstRect); |
1086 const SkScalar *scalars = rect.asScalars(); | 1081 const SkScalar *scalars = rect.asScalars(); |
1087 bool isDstPixelAligned = true; | 1082 bool isDstPixelAligned = true; |
1088 for (int i = 0; i < 4; i++) { | 1083 for (int i = 0; i < 4; i++) { |
1089 if (!SkScalarIsInt(scalars[i])) { | 1084 if (!SkScalarIsInt(scalars[i])) { |
1090 isDstPixelAligned = false; | 1085 isDstPixelAligned = false; |
1091 break; | 1086 break; |
1092 } | 1087 } |
1093 } | 1088 } |
1094 | 1089 |
1095 if (isDstPixelAligned) | 1090 if (isDstPixelAligned) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 this->drawRect(draw, dstRect, paintWithShader); | 1133 this->drawRect(draw, dstRect, paintWithShader); |
1139 | 1134 |
1140 return; | 1135 return; |
1141 } | 1136 } |
1142 | 1137 |
1143 // If there is no mask filter than it is OK to handle the src rect -> dst re
ct scaling using | 1138 // If there is no mask filter than it is OK to handle the src rect -> dst re
ct scaling using |
1144 // the view matrix rather than a local matrix. | 1139 // the view matrix rather than a local matrix. |
1145 SkMatrix m; | 1140 SkMatrix m; |
1146 m.setScale(dstSize.fWidth / srcRect.width(), | 1141 m.setScale(dstSize.fWidth / srcRect.width(), |
1147 dstSize.fHeight / srcRect.height()); | 1142 dstSize.fHeight / srcRect.height()); |
1148 fContext->concatMatrix(m); | 1143 SkMatrix viewM = *draw.fMatrix; |
| 1144 viewM.preConcat(m); |
1149 | 1145 |
1150 GrTextureParams params; | 1146 GrTextureParams params; |
1151 SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); | 1147 SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); |
1152 GrTextureParams::FilterMode textureFilterMode; | 1148 GrTextureParams::FilterMode textureFilterMode; |
1153 | 1149 |
1154 bool doBicubic = false; | 1150 bool doBicubic = false; |
1155 | 1151 |
1156 switch(paintFilterLevel) { | 1152 switch(paintFilterLevel) { |
1157 case SkPaint::kNone_FilterLevel: | 1153 case SkPaint::kNone_FilterLevel: |
1158 textureFilterMode = GrTextureParams::kNone_FilterMode; | 1154 textureFilterMode = GrTextureParams::kNone_FilterMode; |
1159 break; | 1155 break; |
1160 case SkPaint::kLow_FilterLevel: | 1156 case SkPaint::kLow_FilterLevel: |
1161 textureFilterMode = GrTextureParams::kBilerp_FilterMode; | 1157 textureFilterMode = GrTextureParams::kBilerp_FilterMode; |
1162 break; | 1158 break; |
1163 case SkPaint::kMedium_FilterLevel: | 1159 case SkPaint::kMedium_FilterLevel: |
1164 if (fContext->getMatrix().getMinScale() < SK_Scalar1) { | 1160 if (viewM.getMinScale() < SK_Scalar1) { |
1165 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 1161 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
1166 } else { | 1162 } else { |
1167 // Don't trigger MIP level generation unnecessarily. | 1163 // Don't trigger MIP level generation unnecessarily. |
1168 textureFilterMode = GrTextureParams::kBilerp_FilterMode; | 1164 textureFilterMode = GrTextureParams::kBilerp_FilterMode; |
1169 } | 1165 } |
1170 break; | 1166 break; |
1171 case SkPaint::kHigh_FilterLevel: | 1167 case SkPaint::kHigh_FilterLevel: |
1172 // Minification can look bad with the bicubic effect. | 1168 // Minification can look bad with the bicubic effect. |
1173 doBicubic = | 1169 doBicubic = |
1174 GrBicubicEffect::ShouldUseBicubic(fContext->getMatrix(), &textur
eFilterMode); | 1170 GrBicubicEffect::ShouldUseBicubic(viewM, &textureFilterMode); |
1175 break; | 1171 break; |
1176 default: | 1172 default: |
1177 SkErrorInternals::SetError( kInvalidPaint_SkError, | 1173 SkErrorInternals::SetError( kInvalidPaint_SkError, |
1178 "Sorry, I don't understand the filtering
" | 1174 "Sorry, I don't understand the filtering
" |
1179 "mode you asked for. Falling back to " | 1175 "mode you asked for. Falling back to " |
1180 "MIPMaps."); | 1176 "MIPMaps."); |
1181 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 1177 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
1182 break; | 1178 break; |
1183 } | 1179 } |
1184 | 1180 |
1185 int tileFilterPad; | 1181 int tileFilterPad; |
1186 if (doBicubic) { | 1182 if (doBicubic) { |
1187 tileFilterPad = GrBicubicEffect::kFilterTexelPad; | 1183 tileFilterPad = GrBicubicEffect::kFilterTexelPad; |
1188 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { | 1184 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { |
1189 tileFilterPad = 0; | 1185 tileFilterPad = 0; |
1190 } else { | 1186 } else { |
1191 tileFilterPad = 1; | 1187 tileFilterPad = 1; |
1192 } | 1188 } |
1193 params.setFilterMode(textureFilterMode); | 1189 params.setFilterMode(textureFilterMode); |
1194 | 1190 |
1195 int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad; | 1191 int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad; |
1196 int tileSize; | 1192 int tileSize; |
1197 | 1193 |
1198 SkIRect clippedSrcRect; | 1194 SkIRect clippedSrcRect; |
1199 if (this->shouldTileBitmap(bitmap, params, srcRectPtr, maxTileSize, &tileSiz
e, | 1195 if (this->shouldTileBitmap(bitmap, viewM, params, srcRectPtr, maxTileSize, &
tileSize, |
1200 &clippedSrcRect)) { | 1196 &clippedSrcRect)) { |
1201 this->drawTiledBitmap(bitmap, srcRect, clippedSrcRect, params, paint, fl
ags, tileSize, | 1197 this->drawTiledBitmap(bitmap, viewM, srcRect, clippedSrcRect, params, pa
int, flags, |
1202 doBicubic); | 1198 tileSize, doBicubic); |
1203 } else { | 1199 } else { |
1204 // take the simple case | 1200 // take the simple case |
1205 bool needsTextureDomain = needs_texture_domain(bitmap, | 1201 bool needsTextureDomain = needs_texture_domain(bitmap, |
1206 srcRect, | 1202 srcRect, |
1207 params, | 1203 params, |
1208 fContext->getMatrix(), | 1204 viewM, |
1209 doBicubic); | 1205 doBicubic); |
1210 this->internalDrawBitmap(bitmap, | 1206 this->internalDrawBitmap(bitmap, |
| 1207 viewM, |
1211 srcRect, | 1208 srcRect, |
1212 params, | 1209 params, |
1213 paint, | 1210 paint, |
1214 flags, | 1211 flags, |
1215 doBicubic, | 1212 doBicubic, |
1216 needsTextureDomain); | 1213 needsTextureDomain); |
1217 } | 1214 } |
1218 } | 1215 } |
1219 | 1216 |
1220 // Break 'bitmap' into several tiles to draw it since it has already | 1217 // Break 'bitmap' into several tiles to draw it since it has already |
1221 // been determined to be too large to fit in VRAM | 1218 // been determined to be too large to fit in VRAM |
1222 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, | 1219 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, |
| 1220 const SkMatrix& viewMatrix, |
1223 const SkRect& srcRect, | 1221 const SkRect& srcRect, |
1224 const SkIRect& clippedSrcIRect, | 1222 const SkIRect& clippedSrcIRect, |
1225 const GrTextureParams& params, | 1223 const GrTextureParams& params, |
1226 const SkPaint& paint, | 1224 const SkPaint& paint, |
1227 SkCanvas::DrawBitmapRectFlags flags, | 1225 SkCanvas::DrawBitmapRectFlags flags, |
1228 int tileSize, | 1226 int tileSize, |
1229 bool bicubic) { | 1227 bool bicubic) { |
1230 // The following pixel lock is technically redundant, but it is desirable | 1228 // The following pixel lock is technically redundant, but it is desirable |
1231 // to lock outside of the tile loop to prevent redecoding the whole image | 1229 // to lock outside of the tile loop to prevent redecoding the whole image |
1232 // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that | 1230 // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that |
(...skipping 19 matching lines...) Expand all Loading... |
1252 continue; | 1250 continue; |
1253 } | 1251 } |
1254 | 1252 |
1255 SkBitmap tmpB; | 1253 SkBitmap tmpB; |
1256 SkIRect iTileR; | 1254 SkIRect iTileR; |
1257 tileR.roundOut(&iTileR); | 1255 tileR.roundOut(&iTileR); |
1258 SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft), | 1256 SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft), |
1259 SkIntToScalar(iTileR.fTop)); | 1257 SkIntToScalar(iTileR.fTop)); |
1260 | 1258 |
1261 // Adjust the context matrix to draw at the right x,y in device spac
e | 1259 // Adjust the context matrix to draw at the right x,y in device spac
e |
| 1260 SkMatrix viewM = viewMatrix; |
1262 SkMatrix tmpM; | 1261 SkMatrix tmpM; |
1263 GrContext::AutoMatrix am; | |
1264 tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTo
p); | 1262 tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTo
p); |
1265 am.setPreConcat(fContext, tmpM); | 1263 viewM.preConcat(tmpM); |
1266 | 1264 |
1267 if (GrTextureParams::kNone_FilterMode != params.filterMode() || bicu
bic) { | 1265 if (GrTextureParams::kNone_FilterMode != params.filterMode() || bicu
bic) { |
1268 SkIRect iClampRect; | 1266 SkIRect iClampRect; |
1269 | 1267 |
1270 if (SkCanvas::kBleed_DrawBitmapRectFlag & flags) { | 1268 if (SkCanvas::kBleed_DrawBitmapRectFlag & flags) { |
1271 // In bleed mode we want to always expand the tile on all ed
ges | 1269 // In bleed mode we want to always expand the tile on all ed
ges |
1272 // but stay within the bitmap bounds | 1270 // but stay within the bitmap bounds |
1273 iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height()
); | 1271 iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height()
); |
1274 } else { | 1272 } else { |
1275 // In texture-domain/clamp mode we only want to expand the | 1273 // In texture-domain/clamp mode we only want to expand the |
1276 // tile on edges interior to "srcRect" (i.e., we want to | 1274 // tile on edges interior to "srcRect" (i.e., we want to |
1277 // not bleed across the original clamped edges) | 1275 // not bleed across the original clamped edges) |
1278 srcRect.roundOut(&iClampRect); | 1276 srcRect.roundOut(&iClampRect); |
1279 } | 1277 } |
1280 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; | 1278 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; |
1281 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect)
; | 1279 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect)
; |
1282 } | 1280 } |
1283 | 1281 |
1284 if (bitmap.extractSubset(&tmpB, iTileR)) { | 1282 if (bitmap.extractSubset(&tmpB, iTileR)) { |
1285 // now offset it to make it "local" to our tmp bitmap | 1283 // now offset it to make it "local" to our tmp bitmap |
1286 tileR.offset(-offset.fX, -offset.fY); | 1284 tileR.offset(-offset.fX, -offset.fY); |
1287 GrTextureParams paramsTemp = params; | 1285 GrTextureParams paramsTemp = params; |
1288 bool needsTextureDomain = needs_texture_domain(bitmap, | 1286 bool needsTextureDomain = needs_texture_domain(bitmap, |
1289 srcRect, | 1287 srcRect, |
1290 paramsTemp, | 1288 paramsTemp, |
1291 fContext->getMatr
ix(), | 1289 viewM, |
1292 bicubic); | 1290 bicubic); |
1293 this->internalDrawBitmap(tmpB, | 1291 this->internalDrawBitmap(tmpB, |
| 1292 viewM, |
1294 tileR, | 1293 tileR, |
1295 paramsTemp, | 1294 paramsTemp, |
1296 paint, | 1295 paint, |
1297 flags, | 1296 flags, |
1298 bicubic, | 1297 bicubic, |
1299 needsTextureDomain); | 1298 needsTextureDomain); |
1300 } | 1299 } |
1301 } | 1300 } |
1302 } | 1301 } |
1303 } | 1302 } |
1304 | 1303 |
1305 | 1304 |
1306 /* | 1305 /* |
1307 * This is called by drawBitmap(), which has to handle images that may be too | 1306 * This is called by drawBitmap(), which has to handle images that may be too |
1308 * large to be represented by a single texture. | 1307 * large to be represented by a single texture. |
1309 * | 1308 * |
1310 * internalDrawBitmap assumes that the specified bitmap will fit in a texture | 1309 * internalDrawBitmap assumes that the specified bitmap will fit in a texture |
1311 * and that non-texture portion of the GrPaint has already been setup. | 1310 * and that non-texture portion of the GrPaint has already been setup. |
1312 */ | 1311 */ |
1313 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, | 1312 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
| 1313 const SkMatrix& viewMatrix, |
1314 const SkRect& srcRect, | 1314 const SkRect& srcRect, |
1315 const GrTextureParams& params, | 1315 const GrTextureParams& params, |
1316 const SkPaint& paint, | 1316 const SkPaint& paint, |
1317 SkCanvas::DrawBitmapRectFlags flags, | 1317 SkCanvas::DrawBitmapRectFlags flags, |
1318 bool bicubic, | 1318 bool bicubic, |
1319 bool needsTextureDomain) { | 1319 bool needsTextureDomain) { |
1320 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && | 1320 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && |
1321 bitmap.height() <= fContext->getMaxTextureSize()); | 1321 bitmap.height() <= fContext->getMaxTextureSize()); |
1322 | 1322 |
1323 GrTexture* texture; | 1323 GrTexture* texture; |
(...skipping 28 matching lines...) Expand all Loading... |
1352 top = paintRect.top() + border; | 1352 top = paintRect.top() + border; |
1353 bottom = paintRect.bottom() - border; | 1353 bottom = paintRect.bottom() - border; |
1354 } else { | 1354 } else { |
1355 top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom()); | 1355 top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom()); |
1356 } | 1356 } |
1357 textureDomain.setLTRB(left, top, right, bottom); | 1357 textureDomain.setLTRB(left, top, right, bottom); |
1358 if (bicubic) { | 1358 if (bicubic) { |
1359 fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), textureDoma
in)); | 1359 fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), textureDoma
in)); |
1360 } else { | 1360 } else { |
1361 fp.reset(GrTextureDomainEffect::Create(texture, | 1361 fp.reset(GrTextureDomainEffect::Create(texture, |
1362 SkMatrix::I(), | 1362 SkMatrix::I(), |
1363 textureDomain, | 1363 textureDomain, |
1364 GrTextureDomain::kClamp_M
ode, | 1364 GrTextureDomain::kClamp_Mode, |
1365 params.filterMode())); | 1365 params.filterMode())); |
1366 } | 1366 } |
1367 } else if (bicubic) { | 1367 } else if (bicubic) { |
1368 SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode()); | 1368 SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode()); |
1369 SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTil
eModeY() }; | 1369 SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTil
eModeY() }; |
1370 fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), tileModes)); | 1370 fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), tileModes)); |
1371 } else { | 1371 } else { |
1372 fp.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params)); | 1372 fp.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params)); |
1373 } | 1373 } |
1374 | 1374 |
1375 // Construct a GrPaint by setting the bitmap texture as the first effect and
then configuring | 1375 // Construct a GrPaint by setting the bitmap texture as the first effect and
then configuring |
1376 // the rest from the SkPaint. | 1376 // the rest from the SkPaint. |
1377 GrPaint grPaint; | 1377 GrPaint grPaint; |
1378 grPaint.addColorProcessor(fp); | 1378 grPaint.addColorProcessor(fp); |
1379 bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType()); | 1379 bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType()); |
1380 GrColor paintColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()
) : | 1380 GrColor paintColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()
) : |
1381 SkColor2GrColor(paint.getColor()); | 1381 SkColor2GrColor(paint.getColor()); |
1382 SkPaint2GrPaintNoShader(this->context(), paint, paintColor, false, &grPaint)
; | 1382 SkPaint2GrPaintNoShader(this->context(), paint, paintColor, false, &grPaint)
; |
1383 | 1383 |
1384 fContext->drawRectToRect(grPaint, dstRect, paintRect); | 1384 fContext->drawRectToRect(grPaint, viewMatrix, dstRect, paintRect); |
1385 } | 1385 } |
1386 | 1386 |
1387 bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture, | 1387 bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture, |
1388 const SkImageFilter* filter, | 1388 const SkImageFilter* filter, |
1389 const SkImageFilter::Context& ctx, | 1389 const SkImageFilter::Context& ctx, |
1390 SkBitmap* result, SkIPoint* offset) { | 1390 SkBitmap* result, SkIPoint* offset) { |
1391 SkASSERT(filter); | 1391 SkASSERT(filter); |
1392 | 1392 |
1393 // FIXME: plumb actual surface props such that we don't have to lie about th
e flags here | 1393 // FIXME: plumb actual surface props such that we don't have to lie about th
e flags here |
1394 // (https://code.google.com/p/skia/issues/detail?id=3148). | 1394 // (https://code.google.com/p/skia/issues/detail?id=3148). |
1395 SkDeviceImageFilterProxy proxy(this, SkSurfaceProps(0, getLeakyProperties().
pixelGeometry())); | 1395 SkDeviceImageFilterProxy proxy(this, SkSurfaceProps(0, getLeakyProperties().
pixelGeometry())); |
1396 | 1396 |
1397 if (filter->canFilterImageGPU()) { | 1397 if (filter->canFilterImageGPU()) { |
1398 // Save the render target and set it to NULL, so we don't accidentally d
raw to it in the | 1398 // Save the render target and set it to NULL, so we don't accidentally d
raw to it in the |
1399 // filter. Also set the clip wide open and the matrix to identity. | 1399 // filter. Also set the clip wide open and the matrix to identity. |
1400 GrContext::AutoWideOpenIdentityDraw awo(context, NULL); | 1400 GrContext::AutoWideOpenIdentityDraw awo(context, NULL); |
1401 return filter->filterImageGPU(&proxy, wrap_texture(texture), ctx, result
, offset); | 1401 return filter->filterImageGPU(&proxy, wrap_texture(texture), ctx, result
, offset); |
1402 } else { | 1402 } else { |
1403 return false; | 1403 return false; |
1404 } | 1404 } |
1405 } | 1405 } |
1406 | 1406 |
1407 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, | 1407 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, |
1408 int left, int top, const SkPaint& paint) { | 1408 int left, int top, const SkPaint& paint) { |
1409 // drawSprite is defined to be in device coords. | 1409 // drawSprite is defined to be in device coords. |
1410 CHECK_SHOULD_DRAW(draw, true); | 1410 CHECK_SHOULD_DRAW(draw); |
1411 | 1411 |
1412 SkAutoLockPixels alp(bitmap, !bitmap.getTexture()); | 1412 SkAutoLockPixels alp(bitmap, !bitmap.getTexture()); |
1413 if (!bitmap.getTexture() && !bitmap.readyToDraw()) { | 1413 if (!bitmap.getTexture() && !bitmap.readyToDraw()) { |
1414 return; | 1414 return; |
1415 } | 1415 } |
1416 | 1416 |
1417 int w = bitmap.width(); | 1417 int w = bitmap.width(); |
1418 int h = bitmap.height(); | 1418 int h = bitmap.height(); |
1419 | 1419 |
1420 GrTexture* texture; | 1420 GrTexture* texture; |
(...skipping 25 matching lines...) Expand all Loading... |
1446 } | 1446 } |
1447 } | 1447 } |
1448 | 1448 |
1449 GrPaint grPaint; | 1449 GrPaint grPaint; |
1450 grPaint.addColorTextureProcessor(texture, SkMatrix::I()); | 1450 grPaint.addColorTextureProcessor(texture, SkMatrix::I()); |
1451 | 1451 |
1452 SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColorJustAlpha(pai
nt.getColor()), | 1452 SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColorJustAlpha(pai
nt.getColor()), |
1453 false, &grPaint); | 1453 false, &grPaint); |
1454 | 1454 |
1455 fContext->drawRectToRect(grPaint, | 1455 fContext->drawRectToRect(grPaint, |
| 1456 SkMatrix::I(), |
1456 SkRect::MakeXYWH(SkIntToScalar(left), | 1457 SkRect::MakeXYWH(SkIntToScalar(left), |
1457 SkIntToScalar(top), | 1458 SkIntToScalar(top), |
1458 SkIntToScalar(w), | 1459 SkIntToScalar(w), |
1459 SkIntToScalar(h)), | 1460 SkIntToScalar(h)), |
1460 SkRect::MakeXYWH(0, | 1461 SkRect::MakeXYWH(0, |
1461 0, | 1462 0, |
1462 SK_Scalar1 * w / texture->width(), | 1463 SK_Scalar1 * w / texture->width(), |
1463 SK_Scalar1 * h / texture->height()
)); | 1464 SK_Scalar1 * h / texture->height()
)); |
1464 } | 1465 } |
1465 | 1466 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1513 int x, int y, const SkPaint& paint) { | 1514 int x, int y, const SkPaint& paint) { |
1514 // clear of the source device must occur before CHECK_SHOULD_DRAW | 1515 // clear of the source device must occur before CHECK_SHOULD_DRAW |
1515 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext); | 1516 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext); |
1516 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); | 1517 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); |
1517 if (dev->fFlags & kNeedClear_Flag) { | 1518 if (dev->fFlags & kNeedClear_Flag) { |
1518 // TODO: could check here whether we really need to draw at all | 1519 // TODO: could check here whether we really need to draw at all |
1519 dev->clearAll(); | 1520 dev->clearAll(); |
1520 } | 1521 } |
1521 | 1522 |
1522 // drawDevice is defined to be in device coords. | 1523 // drawDevice is defined to be in device coords. |
1523 CHECK_SHOULD_DRAW(draw, true); | 1524 CHECK_SHOULD_DRAW(draw); |
1524 | 1525 |
1525 GrRenderTarget* devRT = dev->accessRenderTarget(); | 1526 GrRenderTarget* devRT = dev->accessRenderTarget(); |
1526 GrTexture* devTex; | 1527 GrTexture* devTex; |
1527 if (NULL == (devTex = devRT->asTexture())) { | 1528 if (NULL == (devTex = devRT->asTexture())) { |
1528 return; | 1529 return; |
1529 } | 1530 } |
1530 | 1531 |
1531 const SkImageInfo ii = dev->imageInfo(); | 1532 const SkImageInfo ii = dev->imageInfo(); |
1532 int w = ii.width(); | 1533 int w = ii.width(); |
1533 int h = ii.height(); | 1534 int h = ii.height(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1566 SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x), | 1567 SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x), |
1567 SkIntToScalar(y), | 1568 SkIntToScalar(y), |
1568 SkIntToScalar(w), | 1569 SkIntToScalar(w), |
1569 SkIntToScalar(h)); | 1570 SkIntToScalar(h)); |
1570 | 1571 |
1571 // The device being drawn may not fill up its texture (e.g. saveLayer uses a
pproximate | 1572 // The device being drawn may not fill up its texture (e.g. saveLayer uses a
pproximate |
1572 // scratch texture). | 1573 // scratch texture). |
1573 SkRect srcRect = SkRect::MakeWH(SK_Scalar1 * w / devTex->width(), | 1574 SkRect srcRect = SkRect::MakeWH(SK_Scalar1 * w / devTex->width(), |
1574 SK_Scalar1 * h / devTex->height()); | 1575 SK_Scalar1 * h / devTex->height()); |
1575 | 1576 |
1576 fContext->drawRectToRect(grPaint, dstRect, srcRect); | 1577 fContext->drawRectToRect(grPaint, SkMatrix::I(), dstRect, srcRect); |
1577 } | 1578 } |
1578 | 1579 |
1579 bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) { | 1580 bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) { |
1580 return filter->canFilterImageGPU(); | 1581 return filter->canFilterImageGPU(); |
1581 } | 1582 } |
1582 | 1583 |
1583 bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src, | 1584 bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src, |
1584 const SkImageFilter::Context& ctx, | 1585 const SkImageFilter::Context& ctx, |
1585 SkBitmap* result, SkIPoint* offset) { | 1586 SkBitmap* result, SkIPoint* offset) { |
1586 // want explicitly our impl, so guard against a subclass of us overriding it | 1587 // want explicitly our impl, so guard against a subclass of us overriding it |
(...skipping 22 matching lines...) Expand all Loading... |
1609 kTriangleStrip_GrPrimitiveType, | 1610 kTriangleStrip_GrPrimitiveType, |
1610 kTriangleFan_GrPrimitiveType, | 1611 kTriangleFan_GrPrimitiveType, |
1611 }; | 1612 }; |
1612 | 1613 |
1613 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, | 1614 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, |
1614 int vertexCount, const SkPoint vertices[], | 1615 int vertexCount, const SkPoint vertices[], |
1615 const SkPoint texs[], const SkColor colors[], | 1616 const SkPoint texs[], const SkColor colors[], |
1616 SkXfermode* xmode, | 1617 SkXfermode* xmode, |
1617 const uint16_t indices[], int indexCount, | 1618 const uint16_t indices[], int indexCount, |
1618 const SkPaint& paint) { | 1619 const SkPaint& paint) { |
1619 CHECK_SHOULD_DRAW(draw, false); | 1620 CHECK_SHOULD_DRAW(draw); |
1620 | |
1621 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawVertices", fContext); | 1621 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawVertices", fContext); |
1622 | 1622 |
1623 const uint16_t* outIndices; | 1623 const uint16_t* outIndices; |
1624 SkAutoTDeleteArray<uint16_t> outAlloc(NULL); | 1624 SkAutoTDeleteArray<uint16_t> outAlloc(NULL); |
1625 GrPrimitiveType primType; | 1625 GrPrimitiveType primType; |
1626 GrPaint grPaint; | 1626 GrPaint grPaint; |
1627 | 1627 |
1628 // If both textures and vertex-colors are NULL, strokes hairlines with the p
aint's color. | 1628 // If both textures and vertex-colors are NULL, strokes hairlines with the p
aint's color. |
1629 if ((NULL == texs || NULL == paint.getShader()) && NULL == colors) { | 1629 if ((NULL == texs || NULL == paint.getShader()) && NULL == colors) { |
1630 | 1630 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 i += 6; | 1671 i += 6; |
1672 } | 1672 } |
1673 } else { | 1673 } else { |
1674 outIndices = indices; | 1674 outIndices = indices; |
1675 primType = gVertexMode2PrimitiveType[vmode]; | 1675 primType = gVertexMode2PrimitiveType[vmode]; |
1676 | 1676 |
1677 if (NULL == texs || NULL == paint.getShader()) { | 1677 if (NULL == texs || NULL == paint.getShader()) { |
1678 SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColor(pain
t.getColor()), | 1678 SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColor(pain
t.getColor()), |
1679 NULL == colors, &grPaint); | 1679 NULL == colors, &grPaint); |
1680 } else { | 1680 } else { |
1681 SkPaint2GrPaintShader(this->context(), paint, NULL == colors, &grPai
nt); | 1681 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, NULL ==
colors, &grPaint); |
1682 } | 1682 } |
1683 } | 1683 } |
1684 | 1684 |
1685 #if 0 | 1685 #if 0 |
1686 if (xmode && texs && colors) { | 1686 if (xmode && texs && colors) { |
1687 if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) { | 1687 if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) { |
1688 SkDebugf("Unsupported vertex-color/texture xfer mode.\n"); | 1688 SkDebugf("Unsupported vertex-color/texture xfer mode.\n"); |
1689 return; | 1689 return; |
1690 } | 1690 } |
1691 } | 1691 } |
1692 #endif | 1692 #endif |
1693 | 1693 |
1694 SkAutoSTMalloc<128, GrColor> convertedColors(0); | 1694 SkAutoSTMalloc<128, GrColor> convertedColors(0); |
1695 if (colors) { | 1695 if (colors) { |
1696 // need to convert byte order and from non-PM to PM | 1696 // need to convert byte order and from non-PM to PM |
1697 convertedColors.reset(vertexCount); | 1697 convertedColors.reset(vertexCount); |
1698 SkColor color; | 1698 SkColor color; |
1699 for (int i = 0; i < vertexCount; ++i) { | 1699 for (int i = 0; i < vertexCount; ++i) { |
1700 color = colors[i]; | 1700 color = colors[i]; |
1701 if (paint.getAlpha() != 255) { | 1701 if (paint.getAlpha() != 255) { |
1702 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color),
paint.getAlpha())); | 1702 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color),
paint.getAlpha())); |
1703 } | 1703 } |
1704 convertedColors[i] = SkColor2GrColor(color); | 1704 convertedColors[i] = SkColor2GrColor(color); |
1705 } | 1705 } |
1706 colors = convertedColors.get(); | 1706 colors = convertedColors.get(); |
1707 } | 1707 } |
1708 fContext->drawVertices(grPaint, | 1708 fContext->drawVertices(grPaint, |
| 1709 *draw.fMatrix, |
1709 primType, | 1710 primType, |
1710 vertexCount, | 1711 vertexCount, |
1711 vertices, | 1712 vertices, |
1712 texs, | 1713 texs, |
1713 colors, | 1714 colors, |
1714 outIndices, | 1715 outIndices, |
1715 indexCount); | 1716 indexCount); |
1716 } | 1717 } |
1717 | 1718 |
1718 /////////////////////////////////////////////////////////////////////////////// | 1719 /////////////////////////////////////////////////////////////////////////////// |
1719 | 1720 |
1720 void SkGpuDevice::drawText(const SkDraw& draw, const void* text, | 1721 void SkGpuDevice::drawText(const SkDraw& draw, const void* text, |
1721 size_t byteLength, SkScalar x, SkScalar y, | 1722 size_t byteLength, SkScalar x, SkScalar y, |
1722 const SkPaint& paint) { | 1723 const SkPaint& paint) { |
1723 CHECK_SHOULD_DRAW(draw, false); | 1724 CHECK_SHOULD_DRAW(draw); |
1724 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext); | 1725 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext); |
1725 | 1726 |
1726 GrPaint grPaint; | 1727 GrPaint grPaint; |
1727 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 1728 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
1728 | 1729 |
1729 SkDEBUGCODE(this->validate();) | 1730 SkDEBUGCODE(this->validate();) |
1730 | 1731 |
1731 if (!fTextContext->drawText(grPaint, paint, (const char *)text, byteLength,
x, y)) { | 1732 if (!fTextContext->drawText(grPaint, paint, *draw.fMatrix, (const char *)tex
t, byteLength, x, |
| 1733 y)) { |
1732 // this will just call our drawPath() | 1734 // this will just call our drawPath() |
1733 draw.drawText_asPaths((const char*)text, byteLength, x, y, paint); | 1735 draw.drawText_asPaths((const char*)text, byteLength, x, y, paint); |
1734 } | 1736 } |
1735 } | 1737 } |
1736 | 1738 |
1737 void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL
ength, | 1739 void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL
ength, |
1738 const SkScalar pos[], int scalarsPerPos, | 1740 const SkScalar pos[], int scalarsPerPos, |
1739 const SkPoint& offset, const SkPaint& paint) { | 1741 const SkPoint& offset, const SkPaint& paint) { |
1740 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPosText", fContext); | 1742 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPosText", fContext); |
1741 CHECK_SHOULD_DRAW(draw, false); | 1743 CHECK_SHOULD_DRAW(draw); |
1742 | 1744 |
1743 GrPaint grPaint; | 1745 GrPaint grPaint; |
1744 SkPaint2GrPaintShader(this->context(), paint, true, &grPaint); | 1746 SkPaint2GrPaintShader(this->context(), paint, *draw.fMatrix, true, &grPaint)
; |
1745 | 1747 |
1746 SkDEBUGCODE(this->validate();) | 1748 SkDEBUGCODE(this->validate();) |
1747 | 1749 |
1748 if (!fTextContext->drawPosText(grPaint, paint, (const char *)text, byteLengt
h, pos, | 1750 if (!fTextContext->drawPosText(grPaint, paint, *draw.fMatrix, (const char *)
text, byteLength, |
1749 scalarsPerPos, offset)) { | 1751 pos, scalarsPerPos, offset)) { |
1750 // this will just call our drawPath() | 1752 // this will just call our drawPath() |
1751 draw.drawPosText_asPaths((const char*)text, byteLength, pos, scalarsPerP
os, offset, paint); | 1753 draw.drawPosText_asPaths((const char*)text, byteLength, pos, scalarsPerP
os, offset, paint); |
1752 } | 1754 } |
1753 } | 1755 } |
1754 | 1756 |
1755 void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text, | 1757 void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text, |
1756 size_t len, const SkPath& path, | 1758 size_t len, const SkPath& path, |
1757 const SkMatrix* m, const SkPaint& paint) { | 1759 const SkMatrix* m, const SkPaint& paint) { |
1758 CHECK_SHOULD_DRAW(draw, false); | 1760 CHECK_SHOULD_DRAW(draw); |
1759 | 1761 |
1760 SkASSERT(draw.fDevice == this); | 1762 SkASSERT(draw.fDevice == this); |
1761 draw.drawTextOnPath((const char*)text, len, path, m, paint); | 1763 draw.drawTextOnPath((const char*)text, len, path, m, paint); |
1762 } | 1764 } |
1763 | 1765 |
1764 /////////////////////////////////////////////////////////////////////////////// | 1766 /////////////////////////////////////////////////////////////////////////////// |
1765 | 1767 |
1766 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const { | 1768 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const { |
1767 if (paint.getShader() || | 1769 if (paint.getShader() || |
1768 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode) || | 1770 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode) || |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1881 #endif | 1883 #endif |
1882 } | 1884 } |
1883 | 1885 |
1884 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { | 1886 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { |
1885 // We always return a transient cache, so it is freed after each | 1887 // We always return a transient cache, so it is freed after each |
1886 // filter traversal. | 1888 // filter traversal. |
1887 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); | 1889 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); |
1888 } | 1890 } |
1889 | 1891 |
1890 #endif | 1892 #endif |
OLD | NEW |