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

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: rebase; SkPictureShader 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/SkPictureShader.h ('k') | src/core/SkShader.cpp » ('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 * 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 SK_DECLARE_STATIC_MUTEX(cachedShaderMutex);
scroggo 2014/04/11 15:51:45 Why is this static?
Dominik Grewe 2014/04/11 17:08:22 Good point. It should be a regular class member.
89 SkAutoMutexAcquire ama(cachedShaderMutex);
scroggo 2014/04/11 15:51:45 It seems like we're doing an awful lot inside this
Dominik Grewe 2014/04/11 17:08:22 We always have to lock though before we access the
90
91 if (!fCachedBitmapShader || tileScale != fCachedTileScale) {
scroggo 2014/04/11 15:51:45 Sort of tied into my last comment, if the cached s
Dominik Grewe 2014/04/11 17:08:22 I didn't even realize the setLocalMatrix below...
scroggo 2014/04/11 17:51:36 Yes. It may make more sense to make that change al
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;
101 } 104 }
102 105
103 SkMatrix shaderMatrix = this->getLocalMatrix(); 106 SkMatrix shaderMatrix = this->getLocalMatrix();
104 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); 107 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
105 fCachedShader->setLocalMatrix(shaderMatrix); 108 fCachedBitmapShader->setLocalMatrix(shaderMatrix);
106 109
107 return true; 110 fCachedBitmapShader.get()->ref();
scroggo 2014/04/11 15:51:45 Typically the caller refs the object that gets ret
Dominik Grewe 2014/04/11 17:08:22 Yes, we have to do it inside the mutex cause other
111 return fCachedBitmapShader;
108 } 112 }
109 113
110 bool SkPictureShader::setContext(const SkBitmap& device, 114 SkShader* SkPictureShader::validInternal(const SkBitmap& device, const SkPaint& paint,
111 const SkPaint& paint, 115 const SkMatrix& matrix, SkMatrix* total Inverse) const {
112 const SkMatrix& matrix) { 116 if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) {
113 if (!this->buildBitmapShader(matrix)) { 117 return NULL;
114 return false;
115 } 118 }
116 119
117 if (!this->INHERITED::setContext(device, paint, matrix)) { 120 SkShader* bitmapShader = this->buildBitmapShader(matrix);
118 return false; 121 if (!bitmapShader) {
122 return NULL;
119 } 123 }
120 124
121 SkASSERT(fCachedShader); 125 if (!bitmapShader->validContext(device, paint, matrix)) {
122 if (!fCachedShader->setContext(device, paint, matrix)) { 126 bitmapShader->unref();
123 this->INHERITED::endContext(); 127 return NULL;
124 return false;
125 } 128 }
126 129
127 return true; 130 return bitmapShader;
128 } 131 }
129 132
130 void SkPictureShader::endContext() { 133 bool SkPictureShader::validContext(const SkBitmap& device, const SkPaint& paint,
131 SkASSERT(fCachedShader); 134 const SkMatrix& matrix, SkMatrix* totalInvers e) const {
132 fCachedShader->endContext(); 135 SkAutoTUnref<SkShader> shader(this->validInternal(device, paint, matrix, tot alInverse));
133 136 return shader != NULL;
134 this->INHERITED::endContext();
135 } 137 }
136 138
137 uint32_t SkPictureShader::getFlags() { 139 SkShader::Context* SkPictureShader::createContext(const SkBitmap& device, const SkPaint& paint,
138 if (NULL != fCachedShader) { 140 const SkMatrix& matrix, void* storage) const {
139 return fCachedShader->getFlags(); 141 SkShader* bitmapShader = this->validInternal(device, paint, matrix, NULL);
142 if (!bitmapShader) {
143 return NULL;
144 }
145
146 return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext,
147 (*this, device, paint, matrix, bitmapShader));
148 }
149
150 size_t SkPictureShader::contextSize() const {
151 return sizeof(PictureShaderContext);
152 }
153
154 SkPictureShader::PictureShaderContext::PictureShaderContext(
155 const SkPictureShader& shader, const SkBitmap& device,
156 const SkPaint& paint, const SkMatrix& matrix, SkShader* bitmapShader)
157 : INHERITED(shader, device, paint, matrix)
158 , fBitmapShader(bitmapShader)
159 {
160 // TODO(dominikg): Can we avoid heap alloc here and instead put it in the sa me
161 // storage as this? The problem is that SkPicutreShader::con textSize()
162 // doesn't know the size of the bitmap shader's context.
Dominik Grewe 2014/04/11 12:39:52 Any ideas?
scroggo 2014/04/11 15:51:45 No. I guess we don't know because we don't what ty
Dominik Grewe 2014/04/11 17:08:22 Yeah, we could hard-code a maximum size, but that'
163 fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize());
164 fBitmapShaderContext = fBitmapShader->createContext(
165 device, paint, matrix, fBitmapShaderContextStorage);
166 SkASSERT(fBitmapShaderContext);
167 }
168
169 SkPictureShader::PictureShaderContext::~PictureShaderContext() {
170 fBitmapShaderContext->SkShader::Context::~Context();
171 sk_free(fBitmapShaderContextStorage);
172 }
173
174 uint32_t SkPictureShader::PictureShaderContext::getFlags() {
175 if (fBitmapShaderContext) {
scroggo 2014/04/11 15:51:45 I don't think this can ever be NULL, since it's cr
Dominik Grewe 2014/04/11 17:08:22 Done.
176 return fBitmapShaderContext->getFlags();
140 } 177 }
141 return 0; 178 return 0;
142 } 179 }
143 180
144 SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) { 181 SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc (void** ctx) {
145 if (fCachedShader) { 182 if (fBitmapShaderContext) {
scroggo 2014/04/11 15:51:45 This should never be NULL.
Dominik Grewe 2014/04/11 17:08:22 Done.
146 return fCachedShader->asAShadeProc(ctx); 183 return fBitmapShaderContext->asAShadeProc(ctx);
147 } 184 }
148 return NULL; 185 return NULL;
149 } 186 }
150 187
151 void SkPictureShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 188 void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor ds tC[], int count) {
152 SkASSERT(fCachedShader); 189 SkASSERT(fBitmapShaderContext);
153 fCachedShader->shadeSpan(x, y, dstC, count); 190 fBitmapShaderContext->shadeSpan(x, y, dstC, count);
154 } 191 }
155 192
156 void SkPictureShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { 193 void SkPictureShader::PictureShaderContext::shadeSpan16(int x, int y, uint16_t d stC[], int count) {
157 SkASSERT(fCachedShader); 194 SkASSERT(fBitmapShaderContext);
158 fCachedShader->shadeSpan16(x, y, dstC, count); 195 fBitmapShaderContext->shadeSpan16(x, y, dstC, count);
159 } 196 }
160 197
161 #ifndef SK_IGNORE_TO_STRING 198 #ifndef SK_IGNORE_TO_STRING
162 void SkPictureShader::toString(SkString* str) const { 199 void SkPictureShader::toString(SkString* str) const {
163 static const char* gTileModeName[SkShader::kTileModeCount] = { 200 static const char* gTileModeName[SkShader::kTileModeCount] = {
164 "clamp", "repeat", "mirror" 201 "clamp", "repeat", "mirror"
165 }; 202 };
166 203
167 str->appendf("PictureShader: [%d:%d] ", 204 str->appendf("PictureShader: [%d:%d] ",
168 fPicture ? fPicture->width() : 0, 205 fPicture ? fPicture->width() : 0,
169 fPicture ? fPicture->height() : 0); 206 fPicture ? fPicture->height() : 0);
170 207
171 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]); 208 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
172 209
173 this->INHERITED::toString(str); 210 this->INHERITED::toString(str);
174 } 211 }
175 #endif 212 #endif
176 213
177 #if SK_SUPPORT_GPU 214 #if SK_SUPPORT_GPU
178 GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& pai nt) const { 215 GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& pai nt) const {
179 if (!this->buildBitmapShader(context->getMatrix())) { 216 SkAutoTUnref<SkShader> bitmapShader(this->buildBitmapShader(context->getMatr ix()));
217 if (!bitmapShader) {
180 return NULL; 218 return NULL;
181 } 219 }
182 SkASSERT(fCachedShader); 220 return bitmapShader->asNewEffect(context, paint);
183 return fCachedShader->asNewEffect(context, paint);
184 } 221 }
185 #endif 222 #endif
OLDNEW
« no previous file with comments | « src/core/SkPictureShader.h ('k') | src/core/SkShader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698