blob: 4da9e3ceabb272c004bcce01a5a4f0c428490e1b [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"
robertphillipsdb539902014-07-01 08:47:04 -070012#include "SkPictureData.h"
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000013
14SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() {
15 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
16
17 return gGPUID;
18}
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000019
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +000020// The GrGather device performs GPU-backend-specific preprocessing on
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000021// a picture. The results are stored in a GPUAccelData.
22//
23// Currently the only interesting work is done in drawDevice (i.e., when a
24// saveLayer is collapsed back into its parent) and, maybe, in onCreateDevice.
25// All the current work could be done much more efficiently by just traversing the
26// raw op codes in the SkPicture (although we would still need to replay all the
27// clip calls).
28class GrGatherDevice : public SkBaseDevice {
29public:
30 SK_DECLARE_INST_COUNT(GrGatherDevice)
31
robertphillips9b14f262014-06-04 05:40:44 -070032 GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData* accelData,
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000033 int saveLayerDepth) {
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000034 fPicture = picture;
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000035 fSaveLayerDepth = saveLayerDepth;
36 fInfo.fValid = true;
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000037 fInfo.fSize.set(width, height);
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000038 fInfo.fPaint = NULL;
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000039 fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID();
40 fInfo.fRestoreOpID = 0;
41 fInfo.fHasNestedLayers = false;
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +000042 fInfo.fIsNested = (2 == fSaveLayerDepth);
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000043
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +000044 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.fSize.fHeight));
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000045 fAccelData = accelData;
46 fAlreadyDrawn = false;
47 }
48
49 virtual ~GrGatherDevice() { }
50
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +000051 virtual SkImageInfo imageInfo() const SK_OVERRIDE {
52 return fEmptyBitmap.info();
53 }
54
55#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
56 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
57 SkCanvas::Config8888 config8888) SK_OVERRIDE {
58 NotSupported();
59 }
60#endif
61 virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
62
63protected:
64 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
65 return false;
66 }
67 virtual void clear(SkColor color) SK_OVERRIDE {
68 NothingToDo();
69 }
70 virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
71 }
72 virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
73 const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
74 }
75 virtual void drawRect(const SkDraw& draw, const SkRect& rect,
76 const SkPaint& paint) SK_OVERRIDE {
77 }
78 virtual void drawOval(const SkDraw& draw, const SkRect& rect,
79 const SkPaint& paint) SK_OVERRIDE {
80 }
81 virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
82 const SkPaint& paint) SK_OVERRIDE {
83 }
84 virtual void drawPath(const SkDraw& draw, const SkPath& path,
85 const SkPaint& paint, const SkMatrix* prePathMatrix,
86 bool pathIsMutable) SK_OVERRIDE {
87 }
88 virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
89 const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
90 }
91 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
92 int x, int y, const SkPaint& paint) SK_OVERRIDE {
93 }
94 virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
95 const SkRect* srcOrNull, const SkRect& dst,
96 const SkPaint& paint,
97 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
98 }
99 virtual void drawText(const SkDraw& draw, const void* text, size_t len,
100 SkScalar x, SkScalar y,
101 const SkPaint& paint) SK_OVERRIDE {
102 }
103 virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
104 const SkScalar pos[], SkScalar constY,
105 int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
106 }
107 virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
108 const SkPath& path, const SkMatrix* matrix,
109 const SkPaint& paint) SK_OVERRIDE {
110 }
111 virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
112 const SkPoint verts[], const SkPoint texs[],
113 const SkColor colors[], SkXfermode* xmode,
114 const uint16_t indices[], int indexCount,
115 const SkPaint& paint) SK_OVERRIDE {
116 }
117 virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y,
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000118 const SkPaint& paint) SK_OVERRIDE {
119 // deviceIn is the one that is being "restored" back to its parent
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000120 GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn);
121
122 if (device->fAlreadyDrawn) {
123 return;
124 }
125
126 device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID();
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000127 device->fInfo.fCTM = *draw.fMatrix;
128 device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
129 SkIntToScalar(-device->getOrigin().fY));
130
commit-bot@chromium.orgf97d65d2014-05-08 23:24:05 +0000131 device->fInfo.fOffset = device->getOrigin();
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000132
133 if (NeedsDeepCopy(paint)) {
134 // This NULL acts as a signal that the paint was uncopyable (for now)
135 device->fInfo.fPaint = NULL;
136 device->fInfo.fValid = false;
137 } else {
138 device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint));
139 }
140
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000141 fAccelData->addSaveLayerInfo(device->fInfo);
142 device->fAlreadyDrawn = true;
143 }
144 // TODO: allow this call to return failure, or move to SkBitmapDevice only.
145 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
146 return fEmptyBitmap;
147 }
148#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
149 virtual bool onReadPixels(const SkBitmap& bitmap,
150 int x, int y,
151 SkCanvas::Config8888 config8888) SK_OVERRIDE {
152 NotSupported();
153 return false;
154 }
155#endif
156 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
157 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
158 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
159 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
160 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
161 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
162 return false;
163 }
164
165private:
166 // The picture being processed
robertphillips9b14f262014-06-04 05:40:44 -0700167 const SkPicture *fPicture;
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000168
169 SkBitmap fEmptyBitmap; // legacy -- need to remove
170
171 // All information gathered during the gather process is stored here
172 GPUAccelData* fAccelData;
173
174 // true if this device has already been drawn back to its parent(s) at least
175 // once.
176 bool fAlreadyDrawn;
177
178 // The information regarding the saveLayer call this device represents.
179 GPUAccelData::SaveLayerInfo fInfo;
180
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000181 // The depth of this device in the saveLayer stack
182 int fSaveLayerDepth;
183
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000184 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
185 NotSupported();
186 }
187
188 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
189 // we expect to only get called via savelayer, in which case it is fine.
190 SkASSERT(kSaveLayer_Usage == usage);
191
192 fInfo.fHasNestedLayers = true;
skia.committer@gmail.coma5b068c2014-05-07 03:04:15 +0000193 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture,
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000194 fAccelData, fSaveLayerDepth+1));
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000195 }
196
197 virtual void flush() SK_OVERRIDE {}
198
199 static void NotSupported() {
200 SkDEBUGFAIL("this method should never be called");
201 }
202
203 static void NothingToDo() {}
204
205 typedef SkBaseDevice INHERITED;
206};
207
208// The GrGatherCanvas allows saveLayers but simplifies clipping. It is really
209// only intended to be used as:
210//
211// GrGatherDevice dev(w, h, picture, accelData);
212// GrGatherCanvas canvas(..., picture);
213// canvas.gather();
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +0000214//
215// which is all just to fill in 'accelData'
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000216class SK_API GrGatherCanvas : public SkCanvas {
217public:
robertphillips9b14f262014-06-04 05:40:44 -0700218 GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict)
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000219 : INHERITED(device)
220 , fPicture(pict) {
221 }
222
223 void gather() {
224 if (NULL == fPicture || 0 == fPicture->width() || 0 == fPicture->height()) {
225 return;
226 }
227
228 this->clipRect(SkRect::MakeWH(SkIntToScalar(fPicture->width()),
229 SkIntToScalar(fPicture->height())),
230 SkRegion::kIntersect_Op, false);
robertphillips9b14f262014-06-04 05:40:44 -0700231 this->drawPicture(fPicture);
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000232 }
233
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000234protected:
235 // disable aa for speed
236 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
237 this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle);
238 }
239
240 // for speed, just respect the bounds, and disable AA. May give us a few
241 // false positives and negatives.
242 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
243 this->updateClipConservativelyUsingBounds(path.getBounds(), op,
244 path.isInverseFillType());
245 }
246 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
247 this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
248 }
249
robertphillips9b14f262014-06-04 05:40:44 -0700250 virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE {
251 // BBH-based rendering doesn't re-issue many of the operations the gather
252 // process cares about (e.g., saves and restores) so it must be disabled.
robertphillipsdb539902014-07-01 08:47:04 -0700253 if (NULL != picture->fData.get()) {
254 picture->fData->setUseBBH(false);
robertphillips9b14f262014-06-04 05:40:44 -0700255 }
256 picture->draw(this);
robertphillipsdb539902014-07-01 08:47:04 -0700257 if (NULL != picture->fData.get()) {
258 picture->fData->setUseBBH(true);
robertphillips9b14f262014-06-04 05:40:44 -0700259 }
260 }
261
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000262private:
robertphillips9b14f262014-06-04 05:40:44 -0700263 const SkPicture* fPicture;
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000264
265 typedef SkCanvas INHERITED;
266};
267
skia.committer@gmail.com2c48ee82014-04-01 03:07:47 +0000268// GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
269// EXPERIMENTAL_optimize method.
robertphillips9b14f262014-06-04 05:40:44 -0700270void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) {
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000271 if (0 == pict->width() || 0 == pict->height()) {
272 return ;
273 }
274
commit-bot@chromium.org0205aba2014-05-06 12:02:22 +0000275 GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0);
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000276 GrGatherCanvas canvas(&device, pict);
277
278 canvas.gather();
279}