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

Side by Side Diff: src/core/SkComposeShader.cpp

Issue 207683004: Extract most of the mutable state of SkShader into a separate Context object. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: clean up Created 6 years, 9 months 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
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkComposeShader.h" 10 #include "SkComposeShader.h"
(...skipping 27 matching lines...) Expand all
38 } 38 }
39 fMode = buffer.readXfermode(); 39 fMode = buffer.readXfermode();
40 } 40 }
41 41
42 SkComposeShader::~SkComposeShader() { 42 SkComposeShader::~SkComposeShader() {
43 SkSafeUnref(fMode); 43 SkSafeUnref(fMode);
44 fShaderB->unref(); 44 fShaderB->unref();
45 fShaderA->unref(); 45 fShaderA->unref();
46 } 46 }
47 47
48 size_t SkComposeShader::contextSize() const {
49 return sizeof(ComposeShaderContext) + fShaderA->contextSize() + fShaderB->co ntextSize();
50 }
51
48 class SkAutoAlphaRestore { 52 class SkAutoAlphaRestore {
49 public: 53 public:
50 SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { 54 SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) {
51 fAlpha = paint->getAlpha(); 55 fAlpha = paint->getAlpha();
52 fPaint = paint; 56 fPaint = paint;
53 paint->setAlpha(newAlpha); 57 paint->setAlpha(newAlpha);
54 } 58 }
55 59
56 ~SkAutoAlphaRestore() { 60 ~SkAutoAlphaRestore() {
57 fPaint->setAlpha(fAlpha); 61 fPaint->setAlpha(fAlpha);
58 } 62 }
59 private: 63 private:
60 SkPaint* fPaint; 64 SkPaint* fPaint;
61 uint8_t fAlpha; 65 uint8_t fAlpha;
62 }; 66 };
63 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) 67 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore)
64 68
65 void SkComposeShader::flatten(SkWriteBuffer& buffer) const { 69 void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
66 this->INHERITED::flatten(buffer); 70 this->INHERITED::flatten(buffer);
67 buffer.writeFlattenable(fShaderA); 71 buffer.writeFlattenable(fShaderA);
68 buffer.writeFlattenable(fShaderB); 72 buffer.writeFlattenable(fShaderB);
69 buffer.writeFlattenable(fMode); 73 buffer.writeFlattenable(fMode);
70 } 74 }
71 75
72 /* We call setContext on our two worker shaders. However, we 76 /* We call setContext on our two worker shaders. However, we
73 always let them see opaque alpha, and if the paint really 77 always let them see opaque alpha, and if the paint really
74 is translucent, then we apply that after the fact. 78 is translucent, then we apply that after the fact.
75 79
76 We need to keep the calls to setContext/endContext balanced, since if we
77 return false, our endContext() will not be called.
78 */ 80 */
79 bool SkComposeShader::setContext(const SkBitmap& device, 81 bool SkComposeShader::validContext(const SkBitmap& device,
80 const SkPaint& paint, 82 const SkPaint& paint,
81 const SkMatrix& matrix) { 83 const SkMatrix& matrix) const {
82 if (!this->INHERITED::setContext(device, paint, matrix)) { 84 if (!this->INHERITED::validContext(device, paint, matrix)) {
83 return false; 85 return false;
84 } 86 }
85 87
86 // we preconcat our localMatrix (if any) with the device matrix 88 // we preconcat our localMatrix (if any) with the device matrix
87 // before calling our sub-shaders 89 // before calling our sub-shaders
88 90
89 SkMatrix tmpM; 91 SkMatrix tmpM;
90 92
91 tmpM.setConcat(matrix, this->getLocalMatrix()); 93 tmpM.setConcat(matrix, this->getLocalMatrix());
92 94
95 return fShaderA->validContext(device, paint, tmpM) &&
96 fShaderB->validContext(device, paint, tmpM);
97 }
98
99 SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const SkPaint& paint,
100 const SkMatrix& matrix, void* storage) const {
101 // TODO: move this check to SkShader::createContext and the rest to createCo ntextImpl().
scroggo 2014/03/24 21:24:46 The general naming pattern in Skia is to name the
Dominik Grewe 2014/03/26 17:22:22 Oh yes, I forgot. But if we break the contract bet
102 if (!this->validContext(device, paint, matrix)) {
103 return NULL;
104 }
105
106 // we preconcat our localMatrix (if any) with the device matrix
107 // before calling our sub-shaders
108
109 SkMatrix tmpM;
110
111 tmpM.setConcat(matrix, this->getLocalMatrix());
112
93 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); 113 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF);
94 114
95 bool setContextA = fShaderA->setContext(device, paint, tmpM); 115 char* aStorage = (char*) storage + sizeof(ComposeShaderContext);
96 bool setContextB = fShaderB->setContext(device, paint, tmpM); 116 char* bStorage = aStorage + fShaderA->contextSize();
97 if (!setContextA || !setContextB) { 117
98 if (setContextB) { 118 SkShader::Context* contextA = fShaderA->createContext(device, paint, tmpM, a Storage);
99 fShaderB->endContext(); 119 SkShader::Context* contextB = fShaderB->createContext(device, paint, tmpM, b Storage);
100 } 120
101 else if (setContextA) { 121 // Both functions must succeed; otherwise validContext should have returned
102 fShaderA->endContext(); 122 // false.
103 } 123 SkASSERT(contextA);
104 this->INHERITED::endContext(); 124 SkASSERT(contextB);
105 return false; 125
106 } 126 return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext,
107 return true; 127 (*this, device, paint, matrix, contextA, context B));
108 } 128 }
109 129
110 void SkComposeShader::endContext() { 130 SkComposeShader::ComposeShaderContext::ComposeShaderContext(
111 fShaderB->endContext(); 131 const SkComposeShader& shader, const SkBitmap& device,
112 fShaderA->endContext(); 132 const SkPaint& paint, const SkMatrix& matrix,
113 this->INHERITED::endContext(); 133 SkShader::Context* contextA, SkShader::Context* contextB)
134 : INHERITED(shader, device, paint, matrix)
135 , fShaderContextA(contextA)
136 , fShaderContextB(contextB) {}
137
138 SkComposeShader::ComposeShaderContext::~ComposeShaderContext() {
139 fShaderContextA->SkShader::Context::~Context();
140 fShaderContextB->SkShader::Context::~Context();
114 } 141 }
115 142
116 // larger is better (fewer times we have to loop), but we shouldn't 143 // larger is better (fewer times we have to loop), but we shouldn't
117 // take up too much stack-space (each element is 4 bytes) 144 // take up too much stack-space (each element is 4 bytes)
118 #define TMP_COLOR_COUNT 64 145 #define TMP_COLOR_COUNT 64
119 146
120 void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { 147 void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re sult[], int count) {
121 SkShader* shaderA = fShaderA; 148 SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode;
scroggo 2014/03/24 21:24:46 I think we grabbed these pointers outside the loop
Dominik Grewe 2014/03/26 17:22:22 Done.
122 SkShader* shaderB = fShaderB;
123 SkXfermode* mode = fMode;
124 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); 149 unsigned scale = SkAlpha255To256(this->getPaintAlpha());
125 150
126 SkPMColor tmp[TMP_COLOR_COUNT]; 151 SkPMColor tmp[TMP_COLOR_COUNT];
127 152
128 if (NULL == mode) { // implied SRC_OVER 153 if (NULL == mode) { // implied SRC_OVER
129 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 154 // TODO: when we have a good test-case, should use SkBlitRow::Proc32
130 // for these loops 155 // for these loops
131 do { 156 do {
132 int n = count; 157 int n = count;
133 if (n > TMP_COLOR_COUNT) { 158 if (n > TMP_COLOR_COUNT) {
134 n = TMP_COLOR_COUNT; 159 n = TMP_COLOR_COUNT;
135 } 160 }
136 161
137 shaderA->shadeSpan(x, y, result, n); 162 fShaderContextA->shadeSpan(x, y, result, n);
138 shaderB->shadeSpan(x, y, tmp, n); 163 fShaderContextB->shadeSpan(x, y, tmp, n);
139 164
140 if (256 == scale) { 165 if (256 == scale) {
141 for (int i = 0; i < n; i++) { 166 for (int i = 0; i < n; i++) {
142 result[i] = SkPMSrcOver(tmp[i], result[i]); 167 result[i] = SkPMSrcOver(tmp[i], result[i]);
143 } 168 }
144 } else { 169 } else {
145 for (int i = 0; i < n; i++) { 170 for (int i = 0; i < n; i++) {
146 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), 171 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
147 scale); 172 scale);
148 } 173 }
149 } 174 }
150 175
151 result += n; 176 result += n;
152 x += n; 177 x += n;
153 count -= n; 178 count -= n;
154 } while (count > 0); 179 } while (count > 0);
155 } else { // use mode for the composition 180 } else { // use mode for the composition
156 do { 181 do {
157 int n = count; 182 int n = count;
158 if (n > TMP_COLOR_COUNT) { 183 if (n > TMP_COLOR_COUNT) {
159 n = TMP_COLOR_COUNT; 184 n = TMP_COLOR_COUNT;
160 } 185 }
161 186
162 shaderA->shadeSpan(x, y, result, n); 187 fShaderContextA->shadeSpan(x, y, result, n);
163 shaderB->shadeSpan(x, y, tmp, n); 188 fShaderContextB->shadeSpan(x, y, tmp, n);
164 mode->xfer32(result, tmp, n, NULL); 189 mode->xfer32(result, tmp, n, NULL);
165 190
166 if (256 == scale) { 191 if (256 == scale) {
167 for (int i = 0; i < n; i++) { 192 for (int i = 0; i < n; i++) {
168 result[i] = SkAlphaMulQ(result[i], scale); 193 result[i] = SkAlphaMulQ(result[i], scale);
169 } 194 }
170 } 195 }
171 196
172 result += n; 197 result += n;
173 x += n; 198 x += n;
(...skipping 11 matching lines...) Expand all
185 str->append(" ShaderB: "); 210 str->append(" ShaderB: ");
186 fShaderB->toString(str); 211 fShaderB->toString(str);
187 str->append(" Xfermode: "); 212 str->append(" Xfermode: ");
188 fMode->toString(str); 213 fMode->toString(str);
189 214
190 this->INHERITED::toString(str); 215 this->INHERITED::toString(str);
191 216
192 str->append(")"); 217 str->append(")");
193 } 218 }
194 #endif 219 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698