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

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: rebase & cleanup Created 6 years, 8 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,
82 if (!this->INHERITED::setContext(device, paint, matrix)) { 84 SkMatrix* totalInverse) const {
85 if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) {
83 return false; 86 return false;
84 } 87 }
85 88
86 // we preconcat our localMatrix (if any) with the device matrix 89 // we preconcat our localMatrix (if any) with the device matrix
87 // before calling our sub-shaders 90 // before calling our sub-shaders
88 91
89 SkMatrix tmpM; 92 SkMatrix tmpM;
90 93
91 tmpM.setConcat(matrix, this->getLocalMatrix()); 94 tmpM.setConcat(matrix, this->getLocalMatrix());
92 95
96 return fShaderA->validContext(device, paint, tmpM) &&
97 fShaderB->validContext(device, paint, tmpM);
98 }
99
100 SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const SkPaint& paint,
101 const SkMatrix& matrix, void* storage) const {
102 // TODO(dominikg): move this check to SkShader::createContext and the rest t o onCreateContext()?
103 if (!this->validContext(device, paint, matrix)) {
104 return NULL;
105 }
106
107 // we preconcat our localMatrix (if any) with the device matrix
108 // before calling our sub-shaders
109
110 SkMatrix tmpM;
111
112 tmpM.setConcat(matrix, this->getLocalMatrix());
113
93 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); 114 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF);
94 115
95 bool setContextA = fShaderA->setContext(device, paint, tmpM); 116 char* aStorage = (char*) storage + sizeof(ComposeShaderContext);
96 bool setContextB = fShaderB->setContext(device, paint, tmpM); 117 char* bStorage = aStorage + fShaderA->contextSize();
97 if (!setContextA || !setContextB) { 118
98 if (setContextB) { 119 SkShader::Context* contextA = fShaderA->createContext(device, paint, tmpM, a Storage);
99 fShaderB->endContext(); 120 SkShader::Context* contextB = fShaderB->createContext(device, paint, tmpM, b Storage);
100 } 121
101 else if (setContextA) { 122 // Both functions must succeed; otherwise validContext should have returned
102 fShaderA->endContext(); 123 // false.
103 } 124 SkASSERT(contextA);
104 this->INHERITED::endContext(); 125 SkASSERT(contextB);
105 return false; 126
106 } 127 return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext,
107 return true; 128 (*this, device, paint, matrix, contextA, context B));
108 } 129 }
109 130
110 void SkComposeShader::endContext() { 131 SkComposeShader::ComposeShaderContext::ComposeShaderContext(
111 fShaderB->endContext(); 132 const SkComposeShader& shader, const SkBitmap& device,
112 fShaderA->endContext(); 133 const SkPaint& paint, const SkMatrix& matrix,
113 this->INHERITED::endContext(); 134 SkShader::Context* contextA, SkShader::Context* contextB)
135 : INHERITED(shader, device, paint, matrix)
136 , fShaderContextA(contextA)
137 , fShaderContextB(contextB) {}
138
139 SkComposeShader::ComposeShaderContext::~ComposeShaderContext() {
140 fShaderContextA->SkShader::Context::~Context();
141 fShaderContextB->SkShader::Context::~Context();
114 } 142 }
115 143
116 // larger is better (fewer times we have to loop), but we shouldn't 144 // 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) 145 // take up too much stack-space (each element is 4 bytes)
118 #define TMP_COLOR_COUNT 64 146 #define TMP_COLOR_COUNT 64
119 147
120 void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { 148 void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re sult[], int count) {
121 SkShader* shaderA = fShaderA; 149 SkShader::Context* shaderContextA = fShaderContextA;
122 SkShader* shaderB = fShaderB; 150 SkShader::Context* shaderContextB = fShaderContextB;
123 SkXfermode* mode = fMode; 151 SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode ;
124 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); 152 unsigned scale = SkAlpha255To256(this->getPaintAlpha());
125 153
126 SkPMColor tmp[TMP_COLOR_COUNT]; 154 SkPMColor tmp[TMP_COLOR_COUNT];
127 155
128 if (NULL == mode) { // implied SRC_OVER 156 if (NULL == mode) { // implied SRC_OVER
129 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 157 // TODO: when we have a good test-case, should use SkBlitRow::Proc32
130 // for these loops 158 // for these loops
131 do { 159 do {
132 int n = count; 160 int n = count;
133 if (n > TMP_COLOR_COUNT) { 161 if (n > TMP_COLOR_COUNT) {
134 n = TMP_COLOR_COUNT; 162 n = TMP_COLOR_COUNT;
135 } 163 }
136 164
137 shaderA->shadeSpan(x, y, result, n); 165 shaderContextA->shadeSpan(x, y, result, n);
138 shaderB->shadeSpan(x, y, tmp, n); 166 shaderContextB->shadeSpan(x, y, tmp, n);
139 167
140 if (256 == scale) { 168 if (256 == scale) {
141 for (int i = 0; i < n; i++) { 169 for (int i = 0; i < n; i++) {
142 result[i] = SkPMSrcOver(tmp[i], result[i]); 170 result[i] = SkPMSrcOver(tmp[i], result[i]);
143 } 171 }
144 } else { 172 } else {
145 for (int i = 0; i < n; i++) { 173 for (int i = 0; i < n; i++) {
146 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), 174 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
147 scale); 175 scale);
148 } 176 }
149 } 177 }
150 178
151 result += n; 179 result += n;
152 x += n; 180 x += n;
153 count -= n; 181 count -= n;
154 } while (count > 0); 182 } while (count > 0);
155 } else { // use mode for the composition 183 } else { // use mode for the composition
156 do { 184 do {
157 int n = count; 185 int n = count;
158 if (n > TMP_COLOR_COUNT) { 186 if (n > TMP_COLOR_COUNT) {
159 n = TMP_COLOR_COUNT; 187 n = TMP_COLOR_COUNT;
160 } 188 }
161 189
162 shaderA->shadeSpan(x, y, result, n); 190 shaderContextA->shadeSpan(x, y, result, n);
163 shaderB->shadeSpan(x, y, tmp, n); 191 shaderContextB->shadeSpan(x, y, tmp, n);
164 mode->xfer32(result, tmp, n, NULL); 192 mode->xfer32(result, tmp, n, NULL);
165 193
166 if (256 == scale) { 194 if (256 == scale) {
167 for (int i = 0; i < n; i++) { 195 for (int i = 0; i < n; i++) {
168 result[i] = SkAlphaMulQ(result[i], scale); 196 result[i] = SkAlphaMulQ(result[i], scale);
169 } 197 }
170 } 198 }
171 199
172 result += n; 200 result += n;
173 x += n; 201 x += n;
(...skipping 11 matching lines...) Expand all
185 str->append(" ShaderB: "); 213 str->append(" ShaderB: ");
186 fShaderB->toString(str); 214 fShaderB->toString(str);
187 str->append(" Xfermode: "); 215 str->append(" Xfermode: ");
188 fMode->toString(str); 216 fMode->toString(str);
189 217
190 this->INHERITED::toString(str); 218 this->INHERITED::toString(str);
191 219
192 str->append(")"); 220 str->append(")");
193 } 221 }
194 #endif 222 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698