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 SkASSERT(false); |
| 174 return; |
| 175 } |
| 176 |
| 177 SaveInfo si; |
| 178 fSaveStack.pop(&si); |
| 179 |
| 180 if (!si.fIsSaveLayer) { |
| 181 return; |
| 182 } |
| 183 |
| 184 --fSaveLayersInStack; |
| 185 |
| 186 GrAccelData::SaveLayerInfo slInfo; |
| 187 |
| 188 slInfo.fValid = true; |
| 189 slInfo.fPictureID = fPictureID; |
| 190 slInfo.fSize = SkISize::Make(si.fBounds.width(), si.fBounds.height()); |
| 191 slInfo.fOffset = SkIPoint::Make(si.fBounds.fLeft, si.fBounds.fTop); |
| 192 slInfo.fOriginXform = *fCTM; |
| 193 slInfo.fOriginXform.postTranslate(SkIntToScalar(-si.fBounds.fLeft), |
| 194 SkIntToScalar(-si.fBounds.fTop)); |
| 195 |
| 196 if (NULL == si.fPaint) { |
| 197 slInfo.fPaint = NULL; |
139 } else { | 198 } else { |
140 device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint)); | 199 slInfo.fPaint = SkNEW_ARGS(SkPaint, (*si.fPaint)); |
141 } | 200 } |
142 | 201 |
143 fAccelData->addSaveLayerInfo(device->fInfo); | 202 slInfo.fSaveLayerOpID = si.fStartIndex; |
144 device->fAlreadyDrawn = true; | 203 slInfo.fRestoreOpID = fCurrentOp; |
145 } | 204 slInfo.fHasNestedLayers = si.fHasNestedSaveLayer; |
146 // TODO: allow this call to return failure, or move to SkBitmapDevice only. | 205 slInfo.fIsNested = fSaveLayersInStack > 0; |
147 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE { | 206 |
148 return fEmptyBitmap; | 207 fAccelData->addSaveLayerInfo(slInfo); |
149 } | 208 } |
150 #ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG | 209 |
151 virtual bool onReadPixels(const SkBitmap& bitmap, | 210 // Returns true if rect was meaningfully adjusted for the effects of paint, |
152 int x, int y, | 211 // false if the paint could affect the rect in unknown ways. |
153 SkCanvas::Config8888 config8888) SK_OVERRIDE { | 212 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { |
154 NotSupported(); | 213 if (paint) { |
155 return false; | 214 if (paint->canComputeFastBounds()) { |
156 } | 215 *rect = paint->computeFastBounds(*rect, rect); |
157 #endif | 216 return true; |
158 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); } | 217 } |
159 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); } | 218 return false; |
160 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return fal
se; } | 219 } |
161 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return
false; } | 220 return true; |
162 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImag
eFilter::Context&, | 221 } |
163 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { | 222 |
164 return false; | 223 // Adjust rect for all paints that may affect its geometry, then map it to d
evice space. |
165 } | 224 SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) const { |
166 | 225 // Inverted rectangles really confuse our BBHs. |
167 private: | 226 rect.sort(); |
168 // The playback object driving this rendering | 227 |
169 SkPicturePlayback *fPlayback; | 228 // Adjust the rect for its own paint. |
170 | 229 if (!AdjustForPaint(paint, &rect)) { |
171 SkBitmap fEmptyBitmap; // legacy -- need to remove | 230 // The paint could do anything to our bounds. The only safe answer
is the current clip. |
172 | 231 return fCurrentClipBounds; |
173 // All information gathered during the gather process is stored here | 232 } |
174 GrAccelData* fAccelData; | 233 |
175 | 234 // 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 | 235 for (int i = fSaveStack.count() - 1; i >= 0; i--) { |
177 // once. | 236 if (!AdjustForPaint(fSaveStack[i].fPaint, &rect)) { |
178 bool fAlreadyDrawn; | 237 // Same deal as above. |
179 | 238 return fCurrentClipBounds; |
180 // The information regarding the saveLayer call this device represents. | 239 } |
181 GrAccelData::SaveLayerInfo fInfo; | 240 } |
182 | 241 |
183 // The depth of this device in the saveLayer stack | 242 // Map the rect back to device space. |
184 int fSaveLayerDepth; | 243 fCTM->mapRect(&rect); |
185 | 244 SkIRect devRect; |
186 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRI
DE { | 245 rect.roundOut(&devRect); |
187 NotSupported(); | 246 |
188 } | 247 // Nothing can draw outside the current clip. |
189 | 248 // (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 { | 249 devRect.intersect(fCurrentClipBounds); |
191 // we expect to only get called via savelayer, in which case it is fine. | 250 return devRect; |
192 SkASSERT(kSaveLayer_Usage == usage); | 251 } |
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 }; | 252 }; |
209 | 253 |
210 // The GrGatherCanvas allows saveLayers but simplifies clipping. It is really | 254 |
211 // only intended to be used as: | 255 // 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. | 256 // EXPERIMENTAL_optimize method. |
262 void GatherGPUInfo(const SkPicture* pict, GrAccelData* accelData) { | 257 const GrAccelData* GPUOptimize(const SkPicture* pict) { |
263 if (NULL == pict || 0 == pict->width() || 0 == pict->height()) { | 258 if (NULL == pict || 0 == pict->width() || 0 == pict->height()) { |
264 return ; | 259 return NULL; |
265 } | 260 } |
266 | 261 |
267 // BBH-based rendering doesn't re-issue many of the operations the gather | 262 SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); |
268 // process cares about (e.g., saves and restores) so it must be disabled. | 263 |
269 SkPicturePlayback playback(pict); | 264 const GrAccelData* existing = |
270 playback.setUseBBH(false); | 265 static_cast<const GrAccelData*>(pict->EXPERIMENTAL_g
etAccelData(key)); |
271 | 266 if (NULL != existing) { |
272 GrGatherDevice device(pict->width(), pict->height(), &playback, accelData, 0
); | 267 return existing; |
273 GrGatherCanvas canvas(&device); | 268 } |
274 | 269 |
275 canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()), | 270 SkAutoTUnref<GrAccelData> data(SkNEW_ARGS(GrAccelData, (key))); |
276 SkIntToScalar(pict->height())), | 271 |
277 SkRegion::kIntersect_Op, false); | 272 pict->EXPERIMENTAL_addAccelData(data); |
278 playback.draw(&canvas, NULL); | 273 |
| 274 CollectLayers collector(pict, data); |
| 275 |
| 276 return data; |
279 } | 277 } |
OLD | NEW |