blob: 089e4219828389ab12011f77d4d69688054fc143 [file] [log] [blame]
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +00001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrPictureUtils.h"
9#include "SkDevice.h"
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000010#include "SkDraw.h"
11#include "SkPaintPriv.h"
12
13SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() {
14 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
15
16 return gGPUID;
17}
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000018
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +000019// The GrGather device performs GPU-backend-specific preprocessing on
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000020// a picture. The results are stored in a GPUAccelData.
21//
22// Currently the only interesting work is done in drawDevice (i.e., when a
23// saveLayer is collapsed back into its parent) and, maybe, in onCreateDevice.
24// All the current work could be done much more efficiently by just traversing the
25// raw op codes in the SkPicture (although we would still need to replay all the
26// clip calls).
27class GrGatherDevice : public SkBaseDevice {
28public:
29 SK_DECLARE_INST_COUNT(GrGatherDevice)
30
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000031 GrGatherDevice(int width, int height, SkPicture* picture, GPUAccelData* accelData,
32 int saveLayerDepth) {
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000033 fPicture = picture;
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000034 fSaveLayerDepth = saveLayerDepth;
35 fInfo.fValid = true;
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000036 fInfo.fSize.set(width, height);
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000037 fInfo.fPaint = NULL;
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000038 fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID();
39 fInfo.fRestoreOpID = 0;
40 fInfo.fHasNestedLayers = false;
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000041 fInfo.fIsNested = (2 == fSaveLayerDepth);
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000042
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +000043 fEmptyBitmap.setConfig(SkImageInfo::Make(fInfo.fSize.fWidth,
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000044 fInfo.fSize.fHeight,
45 kUnknown_SkColorType,
46 kIgnore_SkAlphaType));
47 fAccelData = accelData;
48 fAlreadyDrawn = false;
49 }
50
51 virtual ~GrGatherDevice() { }
52
53 virtual int width() const SK_OVERRIDE { return fInfo.fSize.width(); }
54 virtual int height() const SK_OVERRIDE { return fInfo.fSize.height(); }
55 virtual bool isOpaque() const SK_OVERRIDE { return false; }
56 virtual SkBitmap::Config config() const SK_OVERRIDE {
57 return SkBitmap::kNo_Config;
58 }
59 virtual SkImageInfo imageInfo() const SK_OVERRIDE {
60 return fEmptyBitmap.info();
61 }
62
63#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
64 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
65 SkCanvas::Config8888 config8888) SK_OVERRIDE {
66 NotSupported();
67 }
68#endif
69 virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
70
71protected:
72 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
73 return false;
74 }
75 virtual void clear(SkColor color) SK_OVERRIDE {
76 NothingToDo();
77 }
78 virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
79 }
80 virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
81 const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
82 }
83 virtual void drawRect(const SkDraw& draw, const SkRect& rect,
84 const SkPaint& paint) SK_OVERRIDE {
85 }
86 virtual void drawOval(const SkDraw& draw, const SkRect& rect,
87 const SkPaint& paint) SK_OVERRIDE {
88 }
89 virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
90 const SkPaint& paint) SK_OVERRIDE {
91 }
92 virtual void drawPath(const SkDraw& draw, const SkPath& path,
93 const SkPaint& paint, const SkMatrix* prePathMatrix,
94 bool pathIsMutable) SK_OVERRIDE {
95 }
96 virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
97 const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
98 }
99 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
100 int x, int y, const SkPaint& paint) SK_OVERRIDE {
101 }
102 virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
103 const SkRect* srcOrNull, const SkRect& dst,
104 const SkPaint& paint,
105 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
106 }
107 virtual void drawText(const SkDraw& draw, const void* text, size_t len,
108 SkScalar x, SkScalar y,
109 const SkPaint& paint) SK_OVERRIDE {
110 }
111 virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
112 const SkScalar pos[], SkScalar constY,
113 int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
114 }
115 virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
116 const SkPath& path, const SkMatrix* matrix,
117 const SkPaint& paint) SK_OVERRIDE {
118 }
119 virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
120 const SkPoint verts[], const SkPoint texs[],
121 const SkColor colors[], SkXfermode* xmode,
122 const uint16_t indices[], int indexCount,
123 const SkPaint& paint) SK_OVERRIDE {
124 }
125 virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y,
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000126 const SkPaint& paint) SK_OVERRIDE {
127 // deviceIn is the one that is being "restored" back to its parent
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000128 GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn);
129
130 if (device->fAlreadyDrawn) {
131 return;
132 }
133
134 device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID();
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000135 device->fInfo.fCTM = *draw.fMatrix;
136 device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
137 SkIntToScalar(-device->getOrigin().fY));
138
139 // We need the x & y values that will yield 'getOrigin' when transformed
140 // by 'draw.fMatrix'.
141 device->fInfo.fOffset.iset(device->getOrigin());
142
143 SkMatrix invMatrix;
144 if (draw.fMatrix->invert(&invMatrix)) {
145 invMatrix.mapPoints(&device->fInfo.fOffset, 1);
146 } else {
147 device->fInfo.fValid = false;
148 }
149
150 if (NeedsDeepCopy(paint)) {
151 // This NULL acts as a signal that the paint was uncopyable (for now)
152 device->fInfo.fPaint = NULL;
153 device->fInfo.fValid = false;
154 } else {
155 device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint));
156 }
157
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000158 fAccelData->addSaveLayerInfo(device->fInfo);
159 device->fAlreadyDrawn = true;
160 }
161 // TODO: allow this call to return failure, or move to SkBitmapDevice only.
162 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
163 return fEmptyBitmap;
164 }
165#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
166 virtual bool onReadPixels(const SkBitmap& bitmap,
167 int x, int y,
168 SkCanvas::Config8888 config8888) SK_OVERRIDE {
169 NotSupported();
170 return false;
171 }
172#endif
173 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
174 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
175 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
176 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
177 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
178 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
179 return false;
180 }
181
182private:
183 // The picture being processed
184 SkPicture *fPicture;
185
186 SkBitmap fEmptyBitmap; // legacy -- need to remove
187
188 // All information gathered during the gather process is stored here
189 GPUAccelData* fAccelData;
190
191 // true if this device has already been drawn back to its parent(s) at least
192 // once.
193 bool fAlreadyDrawn;
194
195 // The information regarding the saveLayer call this device represents.
196 GPUAccelData::SaveLayerInfo fInfo;
197
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000198 // The depth of this device in the saveLayer stack
199 int fSaveLayerDepth;
200
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000201 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
202 NotSupported();
203 }
204
205 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
206 // we expect to only get called via savelayer, in which case it is fine.
207 SkASSERT(kSaveLayer_Usage == usage);
208
209 fInfo.fHasNestedLayers = true;
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000210 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture,
211 fAccelData, fSaveLayerDepth+1));
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000212 }
213
214 virtual void flush() SK_OVERRIDE {}
215
216 static void NotSupported() {
217 SkDEBUGFAIL("this method should never be called");
218 }
219
220 static void NothingToDo() {}
221
222 typedef SkBaseDevice INHERITED;
223};
224
225// The GrGatherCanvas allows saveLayers but simplifies clipping. It is really
226// only intended to be used as:
227//
228// GrGatherDevice dev(w, h, picture, accelData);
229// GrGatherCanvas canvas(..., picture);
230// canvas.gather();
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +0000231//
232// which is all just to fill in 'accelData'
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000233class SK_API GrGatherCanvas : public SkCanvas {
234public:
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +0000235 GrGatherCanvas(GrGatherDevice* device, SkPicture* pict)
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000236 : INHERITED(device)
237 , fPicture(pict) {
238 }
239
240 void gather() {
241 if (NULL == fPicture || 0 == fPicture->width() || 0 == fPicture->height()) {
242 return;
243 }
244
245 this->clipRect(SkRect::MakeWH(SkIntToScalar(fPicture->width()),
246 SkIntToScalar(fPicture->height())),
247 SkRegion::kIntersect_Op, false);
248 this->drawPicture(*fPicture);
249 }
250
251 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE {
252 picture.draw(this);
253 }
254protected:
255 // disable aa for speed
256 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
257 this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle);
258 }
259
260 // for speed, just respect the bounds, and disable AA. May give us a few
261 // false positives and negatives.
262 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
263 this->updateClipConservativelyUsingBounds(path.getBounds(), op,
264 path.isInverseFillType());
265 }
266 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
267 this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
268 }
269
270private:
271 SkPicture* fPicture;
272
273 typedef SkCanvas INHERITED;
274};
275
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +0000276// GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
277// EXPERIMENTAL_optimize method.
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000278void GatherGPUInfo(SkPicture* pict, GPUAccelData* accelData) {
279 if (0 == pict->width() || 0 == pict->height()) {
280 return ;
281 }
282
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000283 GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0);
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000284 GrGatherCanvas canvas(&device, pict);
285
286 canvas.gather();
287}