2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrPictureUtils.h"
11 #include "SkPaintPriv.h"
12 #include "SkPicturePlayback.h"
14 SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() {
15 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
20 // The GrGather device performs GPU-backend-specific preprocessing on
21 // a picture. The results are stored in a GPUAccelData.
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
28 class GrGatherDevice : public SkBaseDevice {
30 SK_DECLARE_INST_COUNT(GrGatherDevice)
32 GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData* accelData,
35 fSaveLayerDepth = saveLayerDepth;
37 fInfo.fSize.set(width, height);
39 fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID();
40 fInfo.fRestoreOpID = 0;
41 fInfo.fHasNestedLayers = false;
42 fInfo.fIsNested = (2 == fSaveLayerDepth);
44 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.fSize.fHeight));
45 fAccelData = accelData;
46 fAlreadyDrawn = false;
49 virtual ~GrGatherDevice() { }
51 virtual SkImageInfo imageInfo() const SK_OVERRIDE {
52 return fEmptyBitmap.info();
55 #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
56 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
57 SkCanvas::Config8888 config8888) SK_OVERRIDE {
61 virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
64 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
67 virtual void clear(SkColor color) SK_OVERRIDE {
70 virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
72 virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
73 const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
75 virtual void drawRect(const SkDraw& draw, const SkRect& rect,
76 const SkPaint& paint) SK_OVERRIDE {
78 virtual void drawOval(const SkDraw& draw, const SkRect& rect,
79 const SkPaint& paint) SK_OVERRIDE {
81 virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
82 const SkPaint& paint) SK_OVERRIDE {
84 virtual void drawPath(const SkDraw& draw, const SkPath& path,
85 const SkPaint& paint, const SkMatrix* prePathMatrix,
86 bool pathIsMutable) SK_OVERRIDE {
88 virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
89 const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
91 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
92 int x, int y, const SkPaint& paint) SK_OVERRIDE {
94 virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
95 const SkRect* srcOrNull, const SkRect& dst,
97 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
99 virtual void drawText(const SkDraw& draw, const void* text, size_t len,
100 SkScalar x, SkScalar y,
101 const SkPaint& paint) SK_OVERRIDE {
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 {
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 {
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 {
117 virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y,
118 const SkPaint& paint) SK_OVERRIDE {
119 // deviceIn is the one that is being "restored" back to its parent
120 GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn);
122 if (device->fAlreadyDrawn) {
126 device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID();
127 device->fInfo.fCTM = *draw.fMatrix;
128 device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
129 SkIntToScalar(-device->getOrigin().fY));
131 device->fInfo.fOffset = device->getOrigin();
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;
138 device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint));
141 fAccelData->addSaveLayerInfo(device->fInfo);
142 device->fAlreadyDrawn = true;
144 // TODO: allow this call to return failure, or move to SkBitmapDevice only.
145 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
148 #ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
149 virtual bool onReadPixels(const SkBitmap& bitmap,
151 SkCanvas::Config8888 config8888) SK_OVERRIDE {
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 {
166 // The picture being processed
167 const SkPicture *fPicture;
169 SkBitmap fEmptyBitmap; // legacy -- need to remove
171 // All information gathered during the gather process is stored here
172 GPUAccelData* fAccelData;
174 // true if this device has already been drawn back to its parent(s) at least
178 // The information regarding the saveLayer call this device represents.
179 GPUAccelData::SaveLayerInfo fInfo;
181 // The depth of this device in the saveLayer stack
184 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
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);
192 fInfo.fHasNestedLayers = true;
193 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture,
194 fAccelData, fSaveLayerDepth+1));
197 virtual void flush() SK_OVERRIDE {}
199 static void NotSupported() {
200 SkDEBUGFAIL("this method should never be called");
203 static void NothingToDo() {}
205 typedef SkBaseDevice INHERITED;
208 // The GrGatherCanvas allows saveLayers but simplifies clipping. It is really
209 // only intended to be used as:
211 // GrGatherDevice dev(w, h, picture, accelData);
212 // GrGatherCanvas canvas(..., picture);
215 // which is all just to fill in 'accelData'
216 class SK_API GrGatherCanvas : public SkCanvas {
218 GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict)
224 if (NULL == fPicture || 0 == fPicture->width() || 0 == fPicture->height()) {
228 this->clipRect(SkRect::MakeWH(SkIntToScalar(fPicture->width()),
229 SkIntToScalar(fPicture->height())),
230 SkRegion::kIntersect_Op, false);
231 this->drawPicture(fPicture);
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);
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());
246 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
247 this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
250 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.
253 if (NULL != picture->fPlayback) {
254 picture->fPlayback->setUseBBH(false);
257 if (NULL != picture->fPlayback) {
258 picture->fPlayback->setUseBBH(true);
263 const SkPicture* fPicture;
265 typedef SkCanvas INHERITED;
268 // GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
269 // EXPERIMENTAL_optimize method.
270 void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) {
271 if (0 == pict->width() || 0 == pict->height()) {
275 GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0);
276 GrGatherCanvas canvas(&device, pict);