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

Side by Side Diff: src/gpu/GrPictureUtils.cpp

Issue 504393002: Switch GPU Optimization code to SkRecord (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Update to ToT Created 6 years, 3 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/gpu/GrPictureUtils.h ('k') | src/gpu/SkGpuDevice.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 "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 }
OLDNEW
« no previous file with comments | « src/gpu/GrPictureUtils.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698