blob: 2f21a67d2430f0574b36d13f1ab01691072898e4 [file] [log] [blame]
robertphillips@google.com58b20212012-06-27 20:44:52 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrSWMaskHelper.h"
Brian Osmanf9810662017-08-30 10:02:10 -04009
robertphillips976f5f02016-06-03 10:59:20 -070010#include "GrContext.h"
Robert Phillipse305cc1f2016-12-14 12:19:05 -050011#include "GrContextPriv.h"
Robert Phillipscb7b8312018-04-20 11:49:51 -040012#include "GrProxyProvider.h"
bsalomon8acedde2016-06-24 10:42:16 -070013#include "GrShape.h"
Robert Phillipse305cc1f2016-12-14 12:19:05 -050014#include "GrSurfaceContext.h"
15#include "GrTextureProxy.h"
robertphillips@google.com58b20212012-06-27 20:44:52 +000016
robertphillips@google.com58b20212012-06-27 20:44:52 +000017/*
18 * Convert a boolean operation into a transfer mode code
19 */
reed374772b2016-10-05 17:33:02 -070020static SkBlendMode op_to_mode(SkRegion::Op op) {
robertphillips@google.com58b20212012-06-27 20:44:52 +000021
reed374772b2016-10-05 17:33:02 -070022 static const SkBlendMode modeMap[] = {
23 SkBlendMode::kDstOut, // kDifference_Op
24 SkBlendMode::kModulate, // kIntersect_Op
25 SkBlendMode::kSrcOver, // kUnion_Op
26 SkBlendMode::kXor, // kXOR_Op
27 SkBlendMode::kClear, // kReverseDifference_Op
28 SkBlendMode::kSrc, // kReplace_Op
robertphillips@google.com58b20212012-06-27 20:44:52 +000029 };
30
31 return modeMap[op];
32}
33
robertphillips@google.com58b20212012-06-27 20:44:52 +000034/**
35 * Draw a single rect element of the clip stack into the accumulation bitmap
36 */
Brian Salomon74077562017-08-30 13:55:35 -040037void GrSWMaskHelper::drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA aa,
38 uint8_t alpha) {
robertphillips@google.com58b20212012-06-27 20:44:52 +000039 SkPaint paint;
reed374772b2016-10-05 17:33:02 -070040 paint.setBlendMode(op_to_mode(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -050041 paint.setAntiAlias(GrAA::kYes == aa);
robertphillips@google.com366f1c62012-06-29 21:38:47 +000042 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
robertphillips@google.com58b20212012-06-27 20:44:52 +000043
Brian Salomon74077562017-08-30 13:55:35 -040044 SkMatrix translatedMatrix = matrix;
45 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);
46 fDraw.fMatrix = &translatedMatrix;
47
robertphillips@google.com366f1c62012-06-29 21:38:47 +000048 fDraw.drawRect(rect, paint);
robertphillips@google.com58b20212012-06-27 20:44:52 +000049}
50
51/**
52 * Draw a single path element of the clip stack into the accumulation bitmap
53 */
Brian Salomon74077562017-08-30 13:55:35 -040054void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkRegion::Op op,
55 GrAA aa, uint8_t alpha) {
robertphillips@google.com58b20212012-06-27 20:44:52 +000056 SkPaint paint;
Robert Phillipsf809c1e2017-01-13 11:02:42 -050057 paint.setPathEffect(shape.style().refPathEffect());
bsalomon8acedde2016-06-24 10:42:16 -070058 shape.style().strokeRec().applyToPaint(&paint);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -050059 paint.setAntiAlias(GrAA::kYes == aa);
reed@google.com84e922b2013-11-04 20:57:36 +000060
Brian Salomon74077562017-08-30 13:55:35 -040061 SkMatrix translatedMatrix = matrix;
62 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);
63 fDraw.fMatrix = &translatedMatrix;
64
bsalomon8acedde2016-06-24 10:42:16 -070065 SkPath path;
66 shape.asPath(&path);
reed@google.com126f7f52013-11-07 16:06:53 +000067 if (SkRegion::kReplace_Op == op && 0xFF == alpha) {
68 SkASSERT(0xFF == paint.getAlpha());
robertphillips98377402016-05-13 05:47:23 -070069 fDraw.drawPathCoverage(path, paint);
reed@google.com126f7f52013-11-07 16:06:53 +000070 } else {
reed374772b2016-10-05 17:33:02 -070071 paint.setBlendMode(op_to_mode(op));
reed@google.com126f7f52013-11-07 16:06:53 +000072 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
robertphillips98377402016-05-13 05:47:23 -070073 fDraw.drawPath(path, paint);
reed@google.com126f7f52013-11-07 16:06:53 +000074 }
Brian Salomon74077562017-08-30 13:55:35 -040075};
robertphillips@google.com58b20212012-06-27 20:44:52 +000076
Brian Salomon74077562017-08-30 13:55:35 -040077bool GrSWMaskHelper::init(const SkIRect& resultBounds) {
78 // We will need to translate draws so the bound's UL corner is at the origin
79 fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)};
robertphillips98377402016-05-13 05:47:23 -070080 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height());
krajcevski25a67bc2014-07-29 11:44:26 -070081
robertphillips98377402016-05-13 05:47:23 -070082 const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height());
Brian Osmanf9810662017-08-30 10:02:10 -040083 if (!fPixels->tryAlloc(bmImageInfo)) {
robertphillips98377402016-05-13 05:47:23 -070084 return false;
krajcevskib8ccc2f2014-08-07 08:15:14 -070085 }
Brian Osmanf9810662017-08-30 10:02:10 -040086 fPixels->erase(0);
krajcevskib8ccc2f2014-08-07 08:15:14 -070087
Brian Osmanf9810662017-08-30 10:02:10 -040088 fDraw.fDst = *fPixels;
robertphillips@google.com58b20212012-06-27 20:44:52 +000089 fRasterClip.setRect(bounds);
reed41e010c2015-06-09 12:16:53 -070090 fDraw.fRC = &fRasterClip;
robertphillips@google.com58b20212012-06-27 20:44:52 +000091 return true;
92}
93
Robert Phillipsd3749482017-03-14 09:17:43 -040094sk_sp<GrTextureProxy> GrSWMaskHelper::toTextureProxy(GrContext* context, SkBackingFit fit) {
Robert Phillipscb7b8312018-04-20 11:49:51 -040095 SkImageInfo ii = SkImageInfo::MakeA8(fPixels->width(), fPixels->height());
96 size_t rowBytes = fPixels->rowBytes();
krajcevskifb4f5cb2014-06-12 09:20:38 -070097
Robert Phillipscb7b8312018-04-20 11:49:51 -040098 sk_sp<SkData> data = fPixels->detachPixelsAsData();
99 if (!data) {
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500100 return nullptr;
bsalomon39ef7fb2016-09-21 11:16:05 -0700101 }
robertphillips@google.com58b20212012-06-27 20:44:52 +0000102
Robert Phillipscb7b8312018-04-20 11:49:51 -0400103 sk_sp<SkImage> img = SkImage::MakeRasterData(ii, std::move(data), rowBytes);
104 if (!img) {
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500105 return nullptr;
106 }
cblumeed828002016-02-16 13:00:01 -0800107
Chris Daltond004e0b2018-09-27 09:28:03 -0600108 // TODO: http://skbug.com/8422: Although this fixes http://skbug.com/8351, it seems like these
109 // should just participate in the normal allocation process and not need the pending IO flag.
110 auto surfaceFlags = GrInternalSurfaceFlags::kNone;
Robert Phillips9da87e02019-02-04 13:26:26 -0500111 if (!context->priv().resourceProvider()) {
Chris Daltond004e0b2018-09-27 09:28:03 -0600112 // In DDL mode, this texture proxy will be instantiated at flush time, therfore it cannot
113 // have pending IO.
114 surfaceFlags |= GrInternalSurfaceFlags::kNoPendingIO;
115 }
Kevin Lubicka96ec092018-12-17 11:08:36 -0500116 auto clearFlag = kNone_GrSurfaceFlags;
117 // In a WASM build on Firefox, we see warnings like
118 // WebGL warning: texSubImage2D: This operation requires zeroing texture data. This is slow.
119 // WebGL warning: texSubImage2D: Texture has not been initialized prior to a partial upload,
120 // forcing the browser to clear it. This may be slow.
121 // Setting the initial clear seems to make those warnings go away and offers a substantial
122 // boost in performance in Firefox. Chrome sees a more modest increase.
123#if IS_WEBGL==1
124 clearFlag = kPerformInitialClear_GrSurfaceFlag;
125#endif
Robert Phillips9da87e02019-02-04 13:26:26 -0500126 return context->priv().proxyProvider()->createTextureProxy(
Kevin Lubicka96ec092018-12-17 11:08:36 -0500127 std::move(img), clearFlag, 1, SkBudgeted::kYes, fit, surfaceFlags);
robertphillips@google.com58b20212012-06-27 20:44:52 +0000128}