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

Side by Side Diff: src/core/SkPictureShader.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: fCachedLocalMatrix 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 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPictureShader.h" 8 #include "SkPictureShader.h"
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 this->INHERITED::flatten(buffer); 48 this->INHERITED::flatten(buffer);
49 49
50 buffer.write32(fTmx); 50 buffer.write32(fTmx);
51 buffer.write32(fTmy); 51 buffer.write32(fTmy);
52 buffer.writeBool(NULL != fPicture); 52 buffer.writeBool(NULL != fPicture);
53 if (fPicture) { 53 if (fPicture) {
54 fPicture->flatten(buffer); 54 fPicture->flatten(buffer);
55 } 55 }
56 } 56 }
57 57
58 bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { 58 SkShader* SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const {
59 if (!fPicture || (0 == fPicture->width() && 0 == fPicture->height())) { 59 if (!fPicture || (0 == fPicture->width() && 0 == fPicture->height())) {
60 return false; 60 return NULL;
61 } 61 }
62 62
63 SkMatrix m; 63 SkMatrix m;
64 if (this->hasLocalMatrix()) { 64 if (this->hasLocalMatrix()) {
65 m.setConcat(matrix, this->getLocalMatrix()); 65 m.setConcat(matrix, this->getLocalMatrix());
66 } else { 66 } else {
67 m = matrix; 67 m = matrix;
68 } 68 }
69 69
70 // Use a rotation-invariant scale 70 // Use a rotation-invariant scale
71 SkPoint scale; 71 SkPoint scale;
72 if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) { 72 if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) {
73 // Decomposition failed, use an approximation. 73 // Decomposition failed, use an approximation.
74 scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m. getSkewX()), 74 scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m. getSkewX()),
75 SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m. getSkewY())); 75 SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m. getSkewY()));
76 } 76 }
77 SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height()); 77 SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height());
78 78
79 SkISize tileSize = scaledSize.toRound(); 79 SkISize tileSize = scaledSize.toRound();
80 if (tileSize.isEmpty()) { 80 if (tileSize.isEmpty()) {
81 return false; 81 return NULL;
82 } 82 }
83 83
84 // The actual scale, compensating for rounding. 84 // The actual scale, compensating for rounding.
85 SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture-> width(), 85 SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture-> width(),
86 SkIntToScalar(tileSize.height()) / fPicture- >height()); 86 SkIntToScalar(tileSize.height()) / fPicture- >height());
87 87
88 if (!fCachedShader || tileScale != fCachedTileScale) { 88 SkAutoMutexAcquire ama(fCachedBitmapShaderMutex);
89
90 if (!fCachedBitmapShader || tileScale != fCachedTileScale ||
91 this->getLocalMatrix() != fCachedLocalMatrix) {
89 SkBitmap bm; 92 SkBitmap bm;
90 if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) { 93 if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) {
91 return false; 94 return NULL;
92 } 95 }
93 bm.eraseColor(SK_ColorTRANSPARENT); 96 bm.eraseColor(SK_ColorTRANSPARENT);
94 97
95 SkCanvas canvas(bm); 98 SkCanvas canvas(bm);
96 canvas.scale(tileScale.width(), tileScale.height()); 99 canvas.scale(tileScale.width(), tileScale.height());
97 canvas.drawPicture(*fPicture); 100 canvas.drawPicture(*fPicture);
98 101
99 fCachedShader.reset(CreateBitmapShader(bm, fTmx, fTmy)); 102 fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy));
100 fCachedTileScale = tileScale; 103 fCachedTileScale = tileScale;
104 fCachedLocalMatrix = this->getLocalMatrix();
105
106 SkMatrix shaderMatrix = this->getLocalMatrix();
107 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
108 fCachedBitmapShader->setLocalMatrix(shaderMatrix);
101 } 109 }
102 110
103 SkMatrix shaderMatrix = this->getLocalMatrix(); 111 // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
104 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); 112 // Otherwise, the object pointed to may have already been overwritten on a d ifferent thread.
105 fCachedShader->setLocalMatrix(shaderMatrix); 113 fCachedBitmapShader.get()->ref();
106 114 return fCachedBitmapShader;
107 return true;
108 } 115 }
109 116
110 bool SkPictureShader::setContext(const SkBitmap& device, 117 SkShader* SkPictureShader::validInternal(const SkBitmap& device, const SkPaint& paint,
111 const SkPaint& paint, 118 const SkMatrix& matrix, SkMatrix* total Inverse) const {
112 const SkMatrix& matrix) { 119 if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) {
113 if (!this->buildBitmapShader(matrix)) { 120 return NULL;
114 return false;
115 } 121 }
116 122
117 if (!this->INHERITED::setContext(device, paint, matrix)) { 123 SkShader* bitmapShader = this->buildBitmapShader(matrix);
118 return false; 124 if (!bitmapShader) {
125 return NULL;
119 } 126 }
120 127
121 SkASSERT(fCachedShader); 128 if (!bitmapShader->validContext(device, paint, matrix)) {
122 if (!fCachedShader->setContext(device, paint, matrix)) { 129 bitmapShader->unref();
123 this->INHERITED::endContext(); 130 return NULL;
124 return false;
125 } 131 }
126 132
127 return true; 133 return bitmapShader;
128 } 134 }
129 135
130 void SkPictureShader::endContext() { 136 bool SkPictureShader::validContext(const SkBitmap& device, const SkPaint& paint,
131 SkASSERT(fCachedShader); 137 const SkMatrix& matrix, SkMatrix* totalInvers e) const {
132 fCachedShader->endContext(); 138 SkAutoTUnref<SkShader> shader(this->validInternal(device, paint, matrix, tot alInverse));
133 139 return shader != NULL;
134 this->INHERITED::endContext();
135 } 140 }
136 141
137 uint32_t SkPictureShader::getFlags() { 142 SkShader::Context* SkPictureShader::createContext(const SkBitmap& device, const SkPaint& paint,
138 if (NULL != fCachedShader) { 143 const SkMatrix& matrix, void* storage) const {
139 return fCachedShader->getFlags(); 144 SkShader* bitmapShader = this->validInternal(device, paint, matrix, NULL);
145 if (!bitmapShader) {
146 return NULL;
140 } 147 }
141 return 0; 148
149 return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext,
150 (*this, device, paint, matrix, bitmapShader));
142 } 151 }
143 152
144 SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) { 153 size_t SkPictureShader::contextSize() const {
145 if (fCachedShader) { 154 return sizeof(PictureShaderContext);
146 return fCachedShader->asAShadeProc(ctx);
147 }
148 return NULL;
149 } 155 }
150 156
151 void SkPictureShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 157 SkPictureShader::PictureShaderContext::PictureShaderContext(
152 SkASSERT(fCachedShader); 158 const SkPictureShader& shader, const SkBitmap& device,
153 fCachedShader->shadeSpan(x, y, dstC, count); 159 const SkPaint& paint, const SkMatrix& matrix, SkShader* bitmapShader)
160 : INHERITED(shader, device, paint, matrix)
161 , fBitmapShader(bitmapShader)
162 {
163 SkASSERT(fBitmapShader);
164 fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize());
165 fBitmapShaderContext = fBitmapShader->createContext(
166 device, paint, matrix, fBitmapShaderContextStorage);
167 SkASSERT(fBitmapShaderContext);
154 } 168 }
155 169
156 void SkPictureShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { 170 SkPictureShader::PictureShaderContext::~PictureShaderContext() {
157 SkASSERT(fCachedShader); 171 fBitmapShaderContext->SkShader::Context::~Context();
158 fCachedShader->shadeSpan16(x, y, dstC, count); 172 sk_free(fBitmapShaderContextStorage);
173 }
174
175 uint32_t SkPictureShader::PictureShaderContext::getFlags() const {
176 return fBitmapShaderContext->getFlags();
177 }
178
179 SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc (void** ctx) {
180 return fBitmapShaderContext->asAShadeProc(ctx);
181 }
182
183 void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor ds tC[], int count) {
184 SkASSERT(fBitmapShaderContext);
185 fBitmapShaderContext->shadeSpan(x, y, dstC, count);
186 }
187
188 void SkPictureShader::PictureShaderContext::shadeSpan16(int x, int y, uint16_t d stC[], int count) {
189 SkASSERT(fBitmapShaderContext);
190 fBitmapShaderContext->shadeSpan16(x, y, dstC, count);
159 } 191 }
160 192
161 #ifndef SK_IGNORE_TO_STRING 193 #ifndef SK_IGNORE_TO_STRING
162 void SkPictureShader::toString(SkString* str) const { 194 void SkPictureShader::toString(SkString* str) const {
163 static const char* gTileModeName[SkShader::kTileModeCount] = { 195 static const char* gTileModeName[SkShader::kTileModeCount] = {
164 "clamp", "repeat", "mirror" 196 "clamp", "repeat", "mirror"
165 }; 197 };
166 198
167 str->appendf("PictureShader: [%d:%d] ", 199 str->appendf("PictureShader: [%d:%d] ",
168 fPicture ? fPicture->width() : 0, 200 fPicture ? fPicture->width() : 0,
169 fPicture ? fPicture->height() : 0); 201 fPicture ? fPicture->height() : 0);
170 202
171 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]); 203 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
172 204
173 this->INHERITED::toString(str); 205 this->INHERITED::toString(str);
174 } 206 }
175 #endif 207 #endif
176 208
177 #if SK_SUPPORT_GPU 209 #if SK_SUPPORT_GPU
178 GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& pai nt) const { 210 GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& pai nt) const {
179 if (!this->buildBitmapShader(context->getMatrix())) { 211 SkAutoTUnref<SkShader> bitmapShader(this->buildBitmapShader(context->getMatr ix()));
212 if (!bitmapShader) {
180 return NULL; 213 return NULL;
181 } 214 }
182 SkASSERT(fCachedShader); 215 return bitmapShader->asNewEffect(context, paint);
183 return fCachedShader->asNewEffect(context, paint);
184 } 216 }
185 #endif 217 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698