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

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

Powered by Google App Engine
This is Rietveld 408576698