1 | /* |
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 "src/gpu/GrSWMaskHelper.h" |
9 | |
10 | #include "include/gpu/GrRecordingContext.h" |
11 | #include "src/core/SkMatrixProvider.h" |
12 | #include "src/gpu/GrBitmapTextureMaker.h" |
13 | #include "src/gpu/GrCaps.h" |
14 | #include "src/gpu/GrProxyProvider.h" |
15 | #include "src/gpu/GrRecordingContextPriv.h" |
16 | #include "src/gpu/GrSurfaceContext.h" |
17 | #include "src/gpu/GrTextureProxy.h" |
18 | #include "src/gpu/geometry/GrStyledShape.h" |
19 | |
20 | /* |
21 | * Convert a boolean operation into a transfer mode code |
22 | */ |
23 | static SkBlendMode op_to_mode(SkRegion::Op op) { |
24 | |
25 | static const SkBlendMode modeMap[] = { |
26 | SkBlendMode::kDstOut, // kDifference_Op |
27 | SkBlendMode::kModulate, // kIntersect_Op |
28 | SkBlendMode::kSrcOver, // kUnion_Op |
29 | SkBlendMode::kXor, // kXOR_Op |
30 | SkBlendMode::kClear, // kReverseDifference_Op |
31 | SkBlendMode::kSrc, // kReplace_Op |
32 | }; |
33 | |
34 | return modeMap[op]; |
35 | } |
36 | |
37 | static SkPaint get_paint(SkRegion::Op op, GrAA aa, uint8_t alpha) { |
38 | SkPaint paint; |
39 | paint.setBlendMode(op_to_mode(op)); |
40 | paint.setAntiAlias(GrAA::kYes == aa); |
41 | // SkPaint's color is unpremul so this will produce alpha in every channel. |
42 | paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); |
43 | return paint; |
44 | } |
45 | |
46 | /** |
47 | * Draw a single rect element of the clip stack into the accumulation bitmap |
48 | */ |
49 | void GrSWMaskHelper::drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA aa, |
50 | uint8_t alpha) { |
51 | SkMatrix translatedMatrix = matrix; |
52 | translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); |
53 | SkSimpleMatrixProvider matrixProvider(translatedMatrix); |
54 | fDraw.fMatrixProvider = &matrixProvider; |
55 | |
56 | fDraw.drawRect(rect, get_paint(op, aa, alpha)); |
57 | } |
58 | |
59 | void GrSWMaskHelper::drawRRect(const SkRRect& rrect, const SkMatrix& matrix, SkRegion::Op op, |
60 | GrAA aa, uint8_t alpha) { |
61 | SkMatrix translatedMatrix = matrix; |
62 | translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); |
63 | SkSimpleMatrixProvider matrixProvider(translatedMatrix); |
64 | fDraw.fMatrixProvider = &matrixProvider; |
65 | |
66 | fDraw.drawRRect(rrect, get_paint(op, aa, alpha)); |
67 | } |
68 | |
69 | /** |
70 | * Draw a single path element of the clip stack into the accumulation bitmap |
71 | */ |
72 | void GrSWMaskHelper::drawShape(const GrStyledShape& shape, const SkMatrix& matrix, SkRegion::Op op, |
73 | GrAA aa, uint8_t alpha) { |
74 | SkPaint paint = get_paint(op, aa, alpha); |
75 | paint.setPathEffect(shape.style().refPathEffect()); |
76 | shape.style().strokeRec().applyToPaint(&paint); |
77 | |
78 | SkMatrix translatedMatrix = matrix; |
79 | translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); |
80 | SkSimpleMatrixProvider matrixProvider(translatedMatrix); |
81 | fDraw.fMatrixProvider = &matrixProvider; |
82 | |
83 | SkPath path; |
84 | shape.asPath(&path); |
85 | if (SkRegion::kReplace_Op == op && 0xFF == alpha) { |
86 | SkASSERT(0xFF == paint.getAlpha()); |
87 | fDraw.drawPathCoverage(path, paint); |
88 | } else { |
89 | fDraw.drawPath(path, paint); |
90 | } |
91 | } |
92 | |
93 | void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkRegion::Op op, |
94 | GrAA aa, uint8_t alpha) { |
95 | SkPaint paint = get_paint(op, aa, alpha); |
96 | |
97 | SkMatrix translatedMatrix = matrix; |
98 | translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); |
99 | SkSimpleMatrixProvider matrixProvider(translatedMatrix); |
100 | fDraw.fMatrixProvider = &matrixProvider; |
101 | |
102 | if (shape.inverted()) { |
103 | if (shape.isEmpty() || shape.isLine() || shape.isPoint()) { |
104 | // These shapes are empty for simple fills, so when inverted, cover everything |
105 | fDraw.drawPaint(paint); |
106 | return; |
107 | } |
108 | // Else fall through to the draw method using asPath(), which will toggle fill type properly |
109 | } else if (shape.isEmpty() || shape.isLine() || shape.isPoint()) { |
110 | // Do nothing, these shapes do not cover any pixels for simple fills |
111 | return; |
112 | } else if (shape.isRect()) { |
113 | fDraw.drawRect(shape.rect(), paint); |
114 | return; |
115 | } else if (shape.isRRect()) { |
116 | fDraw.drawRRect(shape.rrect(), paint); |
117 | return; |
118 | } |
119 | |
120 | // A complex, or inverse-filled shape, so go through drawPath. |
121 | SkPath path; |
122 | shape.asPath(&path); |
123 | if (SkRegion::kReplace_Op == op && 0xFF == alpha) { |
124 | SkASSERT(0xFF == paint.getAlpha()); |
125 | fDraw.drawPathCoverage(path, paint); |
126 | } else { |
127 | fDraw.drawPath(path, paint); |
128 | } |
129 | } |
130 | |
131 | bool GrSWMaskHelper::init(const SkIRect& resultBounds) { |
132 | // We will need to translate draws so the bound's UL corner is at the origin |
133 | fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)}; |
134 | SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height()); |
135 | |
136 | const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height()); |
137 | if (!fPixels->tryAlloc(bmImageInfo)) { |
138 | return false; |
139 | } |
140 | fPixels->erase(0); |
141 | |
142 | fDraw.fDst = *fPixels; |
143 | fRasterClip.setRect(bounds); |
144 | fDraw.fRC = &fRasterClip; |
145 | return true; |
146 | } |
147 | |
148 | GrSurfaceProxyView GrSWMaskHelper::toTextureView(GrRecordingContext* context, SkBackingFit fit) { |
149 | SkImageInfo ii = SkImageInfo::MakeA8(fPixels->width(), fPixels->height()); |
150 | size_t rowBytes = fPixels->rowBytes(); |
151 | |
152 | SkBitmap bitmap; |
153 | SkAssertResult(bitmap.installPixels(ii, fPixels->detachPixels(), rowBytes, |
154 | [](void* addr, void* context) { sk_free(addr); }, |
155 | nullptr)); |
156 | bitmap.setImmutable(); |
157 | |
158 | GrBitmapTextureMaker maker(context, bitmap, fit); |
159 | return maker.view(GrMipmapped::kNo); |
160 | } |
161 | |