OLD | NEW |
---|---|
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 "GrPictureUtils.h" | 8 #include "GrPictureUtils.h" |
9 #include "SkCanvasPriv.h" | 9 |
10 #include "SkDevice.h" | |
11 #include "SkDraw.h" | |
12 #include "SkPaintPriv.h" | 10 #include "SkPaintPriv.h" |
13 #include "SkPictureData.h" | 11 #include "SkRecord.h" |
14 #include "SkPicturePlayback.h" | 12 #include "SkRecords.h" |
15 | 13 |
16 SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() { | 14 SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() { |
17 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::Genera teDomain(); | 15 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::Genera teDomain(); |
18 | 16 |
19 return gGPUID; | 17 return gGPUID; |
20 } | 18 } |
21 | 19 |
22 // The GrGather device performs GPU-backend-specific preprocessing on | 20 // SkRecord visitor to gather saveLayer/restore information. |
23 // a picture. The results are stored in a GrAccelData. | 21 class CollectLayers { |
24 // | |
25 // Currently the only interesting work is done in drawDevice (i.e., when a | |
26 // saveLayer is collapsed back into its parent) and, maybe, in onCreateDevice. | |
27 // All the current work could be done much more efficiently by just traversing t he | |
28 // raw op codes in the SkPicture (although we would still need to replay all the | |
29 // clip calls). | |
30 class GrGatherDevice : public SkBaseDevice { | |
31 public: | 22 public: |
32 SK_DECLARE_INST_COUNT(GrGatherDevice) | 23 CollectLayers(const SkPicture* pict, GrAccelData* accelData) |
33 | 24 : fPictureID(pict->uniqueID()) |
34 GrGatherDevice(int width, int height, SkPicturePlayback* playback, GrAccelDa ta* accelData, | 25 , fCTM(&SkMatrix::I()) |
35 int saveLayerDepth) { | 26 , fCurrentClipBounds(SkIRect::MakeXYWH(0, 0, pict->width(), pict->height ())) |
36 fPlayback = playback; | 27 , fSaveLayersInStack(0) |
37 fSaveLayerDepth = saveLayerDepth; | 28 , fAccelData(accelData) { |
38 fInfo.fValid = true; | 29 |
39 fInfo.fSize.set(width, height); | 30 if (NULL == pict->fRecord.get()) { |
40 fInfo.fPaint = NULL; | |
41 fInfo.fSaveLayerOpID = fPlayback->curOpID(); | |
42 fInfo.fRestoreOpID = 0; | |
43 fInfo.fHasNestedLayers = false; | |
44 fInfo.fIsNested = (2 == fSaveLayerDepth); | |
45 | |
46 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo. fSize.fHeight)); | |
47 fAccelData = accelData; | |
48 fAlreadyDrawn = false; | |
49 } | |
50 | |
51 virtual ~GrGatherDevice() { } | |
52 | |
53 virtual SkImageInfo imageInfo() const SK_OVERRIDE { | |
54 return fEmptyBitmap.info(); | |
55 } | |
56 | |
57 #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG | |
58 virtual void writePixels(const SkBitmap& bitmap, int x, int y, | |
59 SkCanvas::Config8888 config8888) SK_OVERRIDE { | |
60 NotSupported(); | |
61 } | |
62 #endif | |
63 virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; } | |
64 | |
65 protected: | |
66 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE { | |
67 return false; | |
68 } | |
69 virtual void clear(SkColor color) SK_OVERRIDE { | |
70 NothingToDo(); | |
71 } | |
72 virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE { | |
73 } | |
74 virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, | |
75 const SkPoint points[], const SkPaint& paint) SK_OVE RRIDE { | |
76 } | |
77 virtual void drawRect(const SkDraw& draw, const SkRect& rect, | |
78 const SkPaint& paint) SK_OVERRIDE { | |
79 } | |
80 virtual void drawOval(const SkDraw& draw, const SkRect& rect, | |
81 const SkPaint& paint) SK_OVERRIDE { | |
82 } | |
83 virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect, | |
84 const SkPaint& paint) SK_OVERRIDE { | |
85 } | |
86 virtual void drawPath(const SkDraw& draw, const SkPath& path, | |
87 const SkPaint& paint, const SkMatrix* prePathMatrix, | |
88 bool pathIsMutable) SK_OVERRIDE { | |
89 } | |
90 virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, | |
91 const SkMatrix& matrix, const SkPaint& paint) SK_OVE RRIDE { | |
92 } | |
93 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, | |
94 int x, int y, const SkPaint& paint) SK_OVERRIDE { | |
95 } | |
96 virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, | |
97 const SkRect* srcOrNull, const SkRect& dst, | |
98 const SkPaint& paint, | |
99 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE { | |
100 } | |
101 virtual void drawText(const SkDraw& draw, const void* text, size_t len, | |
102 SkScalar x, SkScalar y, | |
103 const SkPaint& paint) SK_OVERRIDE { | |
104 } | |
105 virtual void drawPosText(const SkDraw& draw, const void* text, size_t len, | |
106 const SkScalar pos[], SkScalar constY, | |
107 int scalarsPerPos, const SkPaint& paint) SK_OVERRID E { | |
108 } | |
109 virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len , | |
110 const SkPath& path, const SkMatrix* matrix, | |
111 const SkPaint& paint) SK_OVERRIDE { | |
112 } | |
113 virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vert exCount, | |
114 const SkPoint verts[], const SkPoint texs[], | |
115 const SkColor colors[], SkXfermode* xmode, | |
116 const uint16_t indices[], int indexCount, | |
117 const SkPaint& paint) SK_OVERRIDE { | |
118 } | |
119 virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, i nt y, | |
120 const SkPaint& paint) SK_OVERRIDE { | |
121 // deviceIn is the one that is being "restored" back to its parent | |
122 GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn); | |
123 | |
124 if (device->fAlreadyDrawn) { | |
125 return; | 31 return; |
126 } | 32 } |
127 | 33 |
128 device->fInfo.fRestoreOpID = fPlayback->curOpID(); | 34 for (fCurrentOp = 0; fCurrentOp < pict->fRecord->count(); ++fCurrentOp) { |
129 device->fInfo.fCTM = *draw.fMatrix; | 35 pict->fRecord->visit<void>(fCurrentOp, *this); |
130 device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX), | 36 } |
131 SkIntToScalar(-device->getOrigin().fY)) ; | 37 |
132 | 38 while (!fSaveStack.isEmpty()) { |
133 device->fInfo.fOffset = device->getOrigin(); | 39 this->popSaveBlock(); |
134 | 40 } |
135 if (NeedsDeepCopy(paint)) { | 41 } |
136 // This NULL acts as a signal that the paint was uncopyable (for now ) | 42 |
137 device->fInfo.fPaint = NULL; | 43 template <typename T> void operator()(const T& op) { |
138 device->fInfo.fValid = false; | 44 this->updateCTM(op); |
45 this->updateClipBounds(op); | |
46 this->trackSaveLayers(op); | |
47 } | |
48 | |
49 private: | |
50 | |
51 class SaveInfo { | |
52 public: | |
53 SaveInfo() { } | |
54 SaveInfo(int opIndex, bool isSaveLayer, const SkPaint* paint, const SkIR ect& bounds) | |
55 : fStartIndex(opIndex) | |
56 , fIsSaveLayer(isSaveLayer) | |
57 , fHasNestedSaveLayer(false) | |
58 , fPaint(paint) | |
59 , fBounds(bounds) { | |
60 | |
61 } | |
62 | |
63 int fStartIndex; | |
64 bool fIsSaveLayer; | |
65 bool fHasNestedSaveLayer; | |
66 const SkPaint* fPaint; | |
67 SkIRect fBounds; | |
68 }; | |
69 | |
70 uint32_t fPictureID; | |
71 unsigned int fCurrentOp; | |
72 const SkMatrix* fCTM; | |
73 SkIRect fCurrentClipBounds; | |
74 int fSaveLayersInStack; | |
75 SkTDArray<SaveInfo> fSaveStack; | |
76 GrAccelData* fAccelData; | |
77 | |
78 template <typename T> void updateCTM(const T&) { /* most ops don't change th e CTM */ } | |
79 void updateCTM(const SkRecords::Restore& op) { fCTM = &op.matrix; } | |
80 void updateCTM(const SkRecords::SetMatrix& op) { fCTM = &op.matrix; } | |
81 | |
82 template <typename T> void updateClipBounds(const T&) { /* most ops don't ch ange the clip */ } | |
83 // Each of these devBounds fields is the state of the device bounds after th e op. | |
84 // So Restore's devBounds are those bounds saved by its paired Save or SaveL ayer. | |
85 void updateClipBounds(const SkRecords::Restore& op) { fCurrentClipBounds = op.devBounds; } | |
86 void updateClipBounds(const SkRecords::ClipPath& op) { fCurrentClipBounds = op.devBounds; } | |
87 void updateClipBounds(const SkRecords::ClipRRect& op) { fCurrentClipBounds = op.devBounds; } | |
88 void updateClipBounds(const SkRecords::ClipRect& op) { fCurrentClipBounds = op.devBounds; } | |
89 void updateClipBounds(const SkRecords::ClipRegion& op) { fCurrentClipBounds = op.devBounds; } | |
90 void updateClipBounds(const SkRecords::SaveLayer& op) { | |
91 if (NULL != op.bounds) { | |
92 fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint )); | |
93 } | |
94 } | |
95 | |
96 template <typename T> void trackSaveLayers(const T& op) { | |
97 /* most ops aren't involved in saveLayers */ | |
98 } | |
99 void trackSaveLayers(const SkRecords::Save& s) { this->pushSaveBlock(); } | |
100 void trackSaveLayers(const SkRecords::SaveLayer& sl) { this->pushSaveLayerBl ock(sl.paint); } | |
101 void trackSaveLayers(const SkRecords::Restore& r) { this->popSaveBlock(); } | |
102 void trackSaveLayers(const SkRecords::DrawPicture& dp) { | |
103 // For sub-pictures, we wrap their layer information within the parent | |
104 // picture's rendering hierarchy | |
105 const GrAccelData* childData = GPUOptimize(dp.picture); | |
106 | |
107 for (int i = 0; i < childData->numSaveLayers(); ++i) { | |
108 const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i); | |
109 | |
110 this->updateStackForSaveLayer(); | |
111 | |
112 GrAccelData::SaveLayerInfo dst; | |
113 | |
114 // TODO: need to store an SkRect in GrAccelData::SaveLayerInfo? | |
115 SkRect srcRect = SkRect::MakeXYWH(SkIntToScalar(src.fOffset.fX), | |
116 SkIntToScalar(src.fOffset.fY), | |
117 SkIntToScalar(src.fSize.width()), | |
118 SkIntToScalar(src.fSize.height())) ; | |
119 SkIRect newClip(fCurrentClipBounds); | |
120 newClip.intersect(this->adjustAndMap(srcRect, dp.paint)); | |
121 | |
122 dst.fValid = true; | |
123 dst.fPictureID = dp.picture->uniqueID(); | |
124 dst.fSize = SkISize::Make(newClip.width(), newClip.height()); | |
125 dst.fOffset = SkIPoint::Make(newClip.fLeft, newClip.fTop); | |
126 dst.fOriginXform = *fCTM; | |
127 dst.fOriginXform.postConcat(src.fOriginXform); | |
128 dst.fOriginXform.postTranslate(SkIntToScalar(-newClip.fLeft), | |
129 SkIntToScalar(-newClip.fTop)); | |
130 | |
131 if (NULL == src.fPaint) { | |
132 dst.fPaint = NULL; | |
133 } else { | |
134 dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint)); | |
135 } | |
136 | |
137 dst.fSaveLayerOpID = src.fSaveLayerOpID; | |
138 dst.fRestoreOpID = src.fRestoreOpID; | |
139 dst.fHasNestedLayers = src.fHasNestedLayers; | |
140 dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested; | |
141 | |
142 fAccelData->addSaveLayerInfo(dst); | |
143 } | |
144 } | |
145 | |
146 void pushSaveBlock() { | |
147 fSaveStack.push(SaveInfo(fCurrentOp, false, NULL, SkIRect::MakeEmpty())) ; | |
148 } | |
149 | |
150 // Inform all the saveLayers already on the stack that they now have a | |
151 // nested saveLayer inside them | |
152 void updateStackForSaveLayer() { | |
153 for (int index = fSaveStack.count() - 1; index >= 0; --index) { | |
154 if (fSaveStack[index].fHasNestedSaveLayer) { | |
155 break; | |
156 } | |
157 fSaveStack[index].fHasNestedSaveLayer = true; | |
158 if (fSaveStack[index].fIsSaveLayer) { | |
159 break; | |
160 } | |
161 } | |
162 } | |
163 | |
164 void pushSaveLayerBlock(const SkPaint* paint) { | |
165 this->updateStackForSaveLayer(); | |
166 | |
167 fSaveStack.push(SaveInfo(fCurrentOp, true, paint, fCurrentClipBounds)); | |
168 ++fSaveLayersInStack; | |
169 } | |
170 | |
171 void popSaveBlock() { | |
172 if (fSaveStack.count() <= 0) { | |
173 return; | |
mtklein
2014/08/27 16:20:59
Also SkASSERT(false)?
robertphillips
2014/08/27 16:25:51
Done.
| |
174 } | |
175 | |
176 SaveInfo si; | |
177 fSaveStack.pop(&si); | |
178 | |
179 if (!si.fIsSaveLayer) { | |
180 return; | |
181 } | |
182 | |
183 --fSaveLayersInStack; | |
184 | |
185 GrAccelData::SaveLayerInfo slInfo; | |
186 | |
187 slInfo.fValid = true; | |
188 slInfo.fPictureID = fPictureID; | |
189 slInfo.fSize = SkISize::Make(si.fBounds.width(), si.fBounds.height()); | |
190 slInfo.fOffset = SkIPoint::Make(si.fBounds.fLeft, si.fBounds.fTop); | |
191 slInfo.fOriginXform = *fCTM; | |
192 slInfo.fOriginXform.postTranslate(SkIntToScalar(-si.fBounds.fLeft), | |
193 SkIntToScalar(-si.fBounds.fTop)); | |
194 | |
195 if (NULL == si.fPaint) { | |
196 slInfo.fPaint = NULL; | |
139 } else { | 197 } else { |
140 device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint)); | 198 slInfo.fPaint = SkNEW_ARGS(SkPaint, (*si.fPaint)); |
141 } | 199 } |
142 | 200 |
143 fAccelData->addSaveLayerInfo(device->fInfo); | 201 slInfo.fSaveLayerOpID = si.fStartIndex; |
144 device->fAlreadyDrawn = true; | 202 slInfo.fRestoreOpID = fCurrentOp; |
145 } | 203 slInfo.fHasNestedLayers = si.fHasNestedSaveLayer; |
146 // TODO: allow this call to return failure, or move to SkBitmapDevice only. | 204 slInfo.fIsNested = fSaveLayersInStack > 0; |
147 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE { | 205 |
148 return fEmptyBitmap; | 206 fAccelData->addSaveLayerInfo(slInfo); |
149 } | 207 } |
150 #ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG | 208 |
151 virtual bool onReadPixels(const SkBitmap& bitmap, | 209 // Returns true if rect was meaningfully adjusted for the effects of paint, |
152 int x, int y, | 210 // false if the paint could affect the rect in unknown ways. |
153 SkCanvas::Config8888 config8888) SK_OVERRIDE { | 211 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { |
154 NotSupported(); | 212 if (paint) { |
155 return false; | 213 if (paint->canComputeFastBounds()) { |
156 } | 214 *rect = paint->computeFastBounds(*rect, rect); |
157 #endif | 215 return true; |
158 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); } | 216 } |
159 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); } | 217 return false; |
160 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return fal se; } | 218 } |
161 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } | 219 return true; |
162 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImag eFilter::Context&, | 220 } |
163 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { | 221 |
164 return false; | 222 // Adjust rect for all paints that may affect its geometry, then map it to d evice space. |
165 } | 223 SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) const { |
166 | 224 // Inverted rectangles really confuse our BBHs. |
167 private: | 225 rect.sort(); |
168 // The playback object driving this rendering | 226 |
169 SkPicturePlayback *fPlayback; | 227 // Adjust the rect for its own paint. |
170 | 228 if (!AdjustForPaint(paint, &rect)) { |
171 SkBitmap fEmptyBitmap; // legacy -- need to remove | 229 // The paint could do anything to our bounds. The only safe answer is the current clip. |
172 | 230 return fCurrentClipBounds; |
173 // All information gathered during the gather process is stored here | 231 } |
174 GrAccelData* fAccelData; | 232 |
175 | 233 // Adjust rect for all the paints from the SaveLayers we're inside. |
176 // true if this device has already been drawn back to its parent(s) at least | 234 for (int i = fSaveStack.count() - 1; i >= 0; i--) { |
177 // once. | 235 if (!AdjustForPaint(fSaveStack[i].fPaint, &rect)) { |
178 bool fAlreadyDrawn; | 236 // Same deal as above. |
179 | 237 return fCurrentClipBounds; |
180 // The information regarding the saveLayer call this device represents. | 238 } |
181 GrAccelData::SaveLayerInfo fInfo; | 239 } |
182 | 240 |
183 // The depth of this device in the saveLayer stack | 241 // Map the rect back to device space. |
184 int fSaveLayerDepth; | 242 fCTM->mapRect(&rect); |
185 | 243 SkIRect devRect; |
186 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRI DE { | 244 rect.roundOut(&devRect); |
187 NotSupported(); | 245 |
188 } | 246 // Nothing can draw outside the current clip. |
189 | 247 // (Only bounded ops call into this method, so oddballs like Clear don't matter here.) |
190 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) S K_OVERRIDE { | 248 devRect.intersect(fCurrentClipBounds); |
191 // we expect to only get called via savelayer, in which case it is fine. | 249 return devRect; |
192 SkASSERT(kSaveLayer_Usage == usage); | 250 } |
193 | |
194 fInfo.fHasNestedLayers = true; | |
195 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPlaybac k, | |
196 fAccelData, fSaveLayerDepth+1)); | |
197 } | |
198 | |
199 virtual void flush() SK_OVERRIDE {} | |
200 | |
201 static void NotSupported() { | |
202 SkDEBUGFAIL("this method should never be called"); | |
203 } | |
204 | |
205 static void NothingToDo() {} | |
206 | |
207 typedef SkBaseDevice INHERITED; | |
208 }; | 251 }; |
209 | 252 |
210 // The GrGatherCanvas allows saveLayers but simplifies clipping. It is really | 253 |
211 // only intended to be used as: | 254 // GPUOptimize is only intended to be called within the context of SkGpuDevice's |
212 // | |
213 // GrGatherDevice dev(w, h, picture, accelData); | |
214 // GrGatherCanvas canvas(..., picture); | |
215 // canvas.gather(); | |
216 // | |
217 // which is all just to fill in 'accelData' | |
218 class SK_API GrGatherCanvas : public SkCanvas { | |
219 public: | |
220 GrGatherCanvas(GrGatherDevice* device) : INHERITED(device) {} | |
221 | |
222 protected: | |
223 // disable aa for speed | |
224 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE { | |
225 this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle); | |
226 } | |
227 | |
228 // for speed, just respect the bounds, and disable AA. May give us a few | |
229 // false positives and negatives. | |
230 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE { | |
231 this->updateClipConservativelyUsingBounds(path.getBounds(), op, | |
232 path.isInverseFillType()); | |
233 } | |
234 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl e) SK_OVERRIDE { | |
235 this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false); | |
236 } | |
237 | |
238 virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, | |
239 const SkPaint* paint) SK_OVERRIDE { | |
240 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->width(), pict ure->height()); | |
241 | |
242 if (NULL != picture->fData.get()) { | |
243 // Disable the BBH for the old path so all the draw calls | |
244 // will be seen. The stock SkPicture::draw method can't be | |
245 // invoked since it just uses a vanilla SkPicturePlayback. | |
246 SkPicturePlayback playback(picture); | |
247 playback.setUseBBH(false); | |
248 playback.draw(this, NULL); | |
249 } else { | |
250 // Since we know this is the SkRecord path we can just call | |
251 // SkPicture::draw. | |
252 picture->draw(this); | |
253 } | |
254 } | |
255 | |
256 private: | |
257 typedef SkCanvas INHERITED; | |
258 }; | |
259 | |
260 // GatherGPUInfo is only intended to be called within the context of SkGpuDevice 's | |
261 // EXPERIMENTAL_optimize method. | 255 // EXPERIMENTAL_optimize method. |
262 void GatherGPUInfo(const SkPicture* pict, GrAccelData* accelData) { | 256 const GrAccelData* GPUOptimize(const SkPicture* pict) { |
263 if (NULL == pict || 0 == pict->width() || 0 == pict->height()) { | 257 if (NULL == pict || 0 == pict->width() || 0 == pict->height()) { |
264 return ; | 258 return NULL; |
265 } | 259 } |
266 | 260 |
267 // BBH-based rendering doesn't re-issue many of the operations the gather | 261 SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); |
268 // process cares about (e.g., saves and restores) so it must be disabled. | 262 |
269 SkPicturePlayback playback(pict); | 263 const GrAccelData* existing = |
270 playback.setUseBBH(false); | 264 static_cast<const GrAccelData*>(pict->EXPERIMENTAL_g etAccelData(key)); |
271 | 265 if (NULL != existing) { |
272 GrGatherDevice device(pict->width(), pict->height(), &playback, accelData, 0 ); | 266 return existing; |
273 GrGatherCanvas canvas(&device); | 267 } |
274 | 268 |
275 canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()), | 269 SkAutoTUnref<GrAccelData> data(SkNEW_ARGS(GrAccelData, (key))); |
276 SkIntToScalar(pict->height())), | 270 |
277 SkRegion::kIntersect_Op, false); | 271 pict->EXPERIMENTAL_addAccelData(data); |
278 playback.draw(&canvas, NULL); | 272 |
273 CollectLayers collector(pict, data); | |
274 | |
275 return data; | |
279 } | 276 } |
OLD | NEW |