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

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

Issue 246403013: Revert of Revert of 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: 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
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 validContext/createContext on our two worker shaders.
73 always let them see opaque alpha, and if the paint really 77 However, we always let them see opaque alpha, and if the paint
74 is translucent, then we apply that after the fact. 78 really 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 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->~Context();
140 fShaderContextB->~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 SkShader::Context* shaderContextA = fShaderContextA;
122 SkShader* shaderB = fShaderB; 149 SkShader::Context* shaderContextB = fShaderContextB;
123 SkXfermode* mode = fMode; 150 SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode ;
124 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); 151 unsigned scale = SkAlpha255To256(this->getPaintAlpha());
125 152
126 SkPMColor tmp[TMP_COLOR_COUNT]; 153 SkPMColor tmp[TMP_COLOR_COUNT];
127 154
128 if (NULL == mode) { // implied SRC_OVER 155 if (NULL == mode) { // implied SRC_OVER
129 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 156 // TODO: when we have a good test-case, should use SkBlitRow::Proc32
130 // for these loops 157 // for these loops
131 do { 158 do {
132 int n = count; 159 int n = count;
133 if (n > TMP_COLOR_COUNT) { 160 if (n > TMP_COLOR_COUNT) {
134 n = TMP_COLOR_COUNT; 161 n = TMP_COLOR_COUNT;
135 } 162 }
136 163
137 shaderA->shadeSpan(x, y, result, n); 164 shaderContextA->shadeSpan(x, y, result, n);
138 shaderB->shadeSpan(x, y, tmp, n); 165 shaderContextB->shadeSpan(x, y, tmp, n);
139 166
140 if (256 == scale) { 167 if (256 == scale) {
141 for (int i = 0; i < n; i++) { 168 for (int i = 0; i < n; i++) {
142 result[i] = SkPMSrcOver(tmp[i], result[i]); 169 result[i] = SkPMSrcOver(tmp[i], result[i]);
143 } 170 }
144 } else { 171 } else {
145 for (int i = 0; i < n; i++) { 172 for (int i = 0; i < n; i++) {
146 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), 173 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
147 scale); 174 scale);
148 } 175 }
149 } 176 }
150 177
151 result += n; 178 result += n;
152 x += n; 179 x += n;
153 count -= n; 180 count -= n;
154 } while (count > 0); 181 } while (count > 0);
155 } else { // use mode for the composition 182 } else { // use mode for the composition
156 do { 183 do {
157 int n = count; 184 int n = count;
158 if (n > TMP_COLOR_COUNT) { 185 if (n > TMP_COLOR_COUNT) {
159 n = TMP_COLOR_COUNT; 186 n = TMP_COLOR_COUNT;
160 } 187 }
161 188
162 shaderA->shadeSpan(x, y, result, n); 189 shaderContextA->shadeSpan(x, y, result, n);
163 shaderB->shadeSpan(x, y, tmp, n); 190 shaderContextB->shadeSpan(x, y, tmp, n);
164 mode->xfer32(result, tmp, n, NULL); 191 mode->xfer32(result, tmp, n, NULL);
165 192
166 if (256 == scale) { 193 if (256 == scale) {
167 for (int i = 0; i < n; i++) { 194 for (int i = 0; i < n; i++) {
168 result[i] = SkAlphaMulQ(result[i], scale); 195 result[i] = SkAlphaMulQ(result[i], scale);
169 } 196 }
170 } 197 }
171 198
172 result += n; 199 result += n;
173 x += n; 200 x += n;
(...skipping 11 matching lines...) Expand all
185 str->append(" ShaderB: "); 212 str->append(" ShaderB: ");
186 fShaderB->toString(str); 213 fShaderB->toString(str);
187 str->append(" Xfermode: "); 214 str->append(" Xfermode: ");
188 fMode->toString(str); 215 fMode->toString(str);
189 216
190 this->INHERITED::toString(str); 217 this->INHERITED::toString(str);
191 218
192 str->append(")"); 219 str->append(")");
193 } 220 }
194 #endif 221 #endif
OLDNEW
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698