OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |