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

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

Issue 198193005: Work (in progress) to make SkShader immutable. (Closed) Base URL: https://skia.googlesource.com/skia.git@shaderGenerator
Patch Set: 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::shaderImplSize() const {
49 return sizeof(ComposeImpl) + fShaderA->shaderImplSize()
50 + fShaderB->shaderImplSize();
51 }
52
48 class SkAutoAlphaRestore { 53 class SkAutoAlphaRestore {
49 public: 54 public:
50 SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { 55 SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) {
51 fAlpha = paint->getAlpha(); 56 fAlpha = paint->getAlpha();
52 fPaint = paint; 57 fPaint = paint;
53 paint->setAlpha(newAlpha); 58 paint->setAlpha(newAlpha);
54 } 59 }
55 60
56 ~SkAutoAlphaRestore() { 61 ~SkAutoAlphaRestore() {
57 fPaint->setAlpha(fAlpha); 62 fPaint->setAlpha(fAlpha);
58 } 63 }
59 private: 64 private:
60 SkPaint* fPaint; 65 SkPaint* fPaint;
61 uint8_t fAlpha; 66 uint8_t fAlpha;
62 }; 67 };
63 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) 68 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore)
64 69
65 void SkComposeShader::flatten(SkWriteBuffer& buffer) const { 70 void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
66 this->INHERITED::flatten(buffer); 71 this->INHERITED::flatten(buffer);
67 buffer.writeFlattenable(fShaderA); 72 buffer.writeFlattenable(fShaderA);
68 buffer.writeFlattenable(fShaderB); 73 buffer.writeFlattenable(fShaderB);
69 buffer.writeFlattenable(fMode); 74 buffer.writeFlattenable(fMode);
70 } 75 }
71 76
72 /* We call setContext on our two worker shaders. However, we 77 /* We call setContext on our two worker shaders. However, we
73 always let them see opaque alpha, and if the paint really 78 always let them see opaque alpha, and if the paint really
74 is translucent, then we apply that after the fact. 79 is translucent, then we apply that after the fact.
75 80
76 We need to keep the calls to setContext/endContext balanced, since if we
77 return false, our endContext() will not be called.
78 */ 81 */
79 bool SkComposeShader::setContext(const SkBitmap& device, 82 bool SkComposeShader::validContext(const SkBitmap& device,
80 const SkPaint& paint, 83 const SkPaint& paint,
81 const SkMatrix& matrix) { 84 const SkMatrix& matrix) {
82 if (!this->INHERITED::setContext(device, paint, matrix)) { 85 if (!this->INHERITED::validContext(device, paint, matrix)) {
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 SkShaderGenerator::ShaderImpl* SkComposeShader::createShaderImpl(
101 const SkBitmap& device, const SkPaint& paint,
102 const SkMatrix& matrix, void* storage) const
103 {
104 SkASSERT(this->validContext(device, paint, matrix));
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(ComposeImpl);
96 bool setContextB = fShaderB->setContext(device, paint, tmpM); 116 char* bStorage = aStorage + fShaderA->shaderImplSize();
97 if (!setContextA || !setContextB) { 117
98 if (setContextB) { 118 ShaderImpl* implA = fShaderA->createShaderImpl(device, paint, matrix,
99 fShaderB->endContext(); 119 aStorage);
100 } 120 ShaderImpl* implB = fShaderB->createShaderImpl(device, paint, matrix,
101 else if (setContextA) { 121 bStorage);
102 fShaderA->endContext(); 122
103 } 123 // Both functions must succeed; otherwise validContext should have returned
104 this->INHERITED::endContext(); 124 // false.
105 return false; 125 SkASSERT(implA);
106 } 126 SkASSERT(implB);
107 return true; 127
128 return SkNEW_PLACEMENT_ARGS(storage, ComposeImpl,
129 (*this, device, paint, matrix, implA, implB));
108 } 130 }
109 131
110 void SkComposeShader::endContext() { 132 SkComposeShader::ComposeImpl::ComposeImpl(const SkComposeShader& shader,
111 fShaderB->endContext(); 133 const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix,
112 fShaderA->endContext(); 134 ShaderImpl* shaderImplA, ShaderImpl* shaderImplB)
113 this->INHERITED::endContext(); 135 : INHERITED(shader, device, paint, matrix)
136 , fShaderImplA(shaderImplA)
137 , fShaderImplB(shaderImplB) {}
138
139 void SkComposeShader::ComposeImpl::~ComposeImpl() {
140 fShaderImplA->~ShaderImpl();
141 fShaderImplB->~ShaderImpl();
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::shadeSpan(int x, int y, SkPMColor result[], int count) {
121 SkShader* shaderA = fShaderA; 149 SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode;
122 SkShader* shaderB = fShaderB;
123 SkXfermode* mode = fMode;
124 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); 150 unsigned scale = SkAlpha255To256(this->getPaintAlpha());
125 151
126 SkPMColor tmp[TMP_COLOR_COUNT]; 152 SkPMColor tmp[TMP_COLOR_COUNT];
127 153
128 if (NULL == mode) { // implied SRC_OVER 154 if (NULL == mode) { // implied SRC_OVER
129 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 155 // TODO: when we have a good test-case, should use SkBlitRow::Proc32
130 // for these loops 156 // for these loops
131 do { 157 do {
132 int n = count; 158 int n = count;
133 if (n > TMP_COLOR_COUNT) { 159 if (n > TMP_COLOR_COUNT) {
134 n = TMP_COLOR_COUNT; 160 n = TMP_COLOR_COUNT;
135 } 161 }
136 162
137 shaderA->shadeSpan(x, y, result, n); 163 fShaderImplA->shadeSpan(x, y, result, n);
138 shaderB->shadeSpan(x, y, tmp, n); 164 fShaderImplB->shadeSpan(x, y, tmp, n);
139 165
140 if (256 == scale) { 166 if (256 == scale) {
141 for (int i = 0; i < n; i++) { 167 for (int i = 0; i < n; i++) {
142 result[i] = SkPMSrcOver(tmp[i], result[i]); 168 result[i] = SkPMSrcOver(tmp[i], result[i]);
143 } 169 }
144 } else { 170 } else {
145 for (int i = 0; i < n; i++) { 171 for (int i = 0; i < n; i++) {
146 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), 172 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
147 scale); 173 scale);
148 } 174 }
149 } 175 }
150 176
151 result += n; 177 result += n;
152 x += n; 178 x += n;
153 count -= n; 179 count -= n;
154 } while (count > 0); 180 } while (count > 0);
155 } else { // use mode for the composition 181 } else { // use mode for the composition
156 do { 182 do {
157 int n = count; 183 int n = count;
158 if (n > TMP_COLOR_COUNT) { 184 if (n > TMP_COLOR_COUNT) {
159 n = TMP_COLOR_COUNT; 185 n = TMP_COLOR_COUNT;
160 } 186 }
161 187
162 shaderA->shadeSpan(x, y, result, n); 188 fShaderImplA->shadeSpan(x, y, result, n);
163 shaderB->shadeSpan(x, y, tmp, n); 189 fShaderImplB->shadeSpan(x, y, tmp, n);
164 mode->xfer32(result, tmp, n, NULL); 190 mode->xfer32(result, tmp, n, NULL);
165 191
166 if (256 == scale) { 192 if (256 == scale) {
167 for (int i = 0; i < n; i++) { 193 for (int i = 0; i < n; i++) {
168 result[i] = SkAlphaMulQ(result[i], scale); 194 result[i] = SkAlphaMulQ(result[i], scale);
169 } 195 }
170 } 196 }
171 197
172 result += n; 198 result += n;
173 x += n; 199 x += n;
(...skipping 11 matching lines...) Expand all
185 str->append(" ShaderB: "); 211 str->append(" ShaderB: ");
186 fShaderB->toString(str); 212 fShaderB->toString(str);
187 str->append(" Xfermode: "); 213 str->append(" Xfermode: ");
188 fMode->toString(str); 214 fMode->toString(str);
189 215
190 this->INHERITED::toString(str); 216 this->INHERITED::toString(str);
191 217
192 str->append(")"); 218 str->append(")");
193 } 219 }
194 #endif 220 #endif
OLDNEW
« no previous file with comments | « src/core/SkBlitter_RGB16.cpp ('k') | src/core/SkCoreBlitters.h » ('j') | src/core/SkShader.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698