1 /* 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" 10 #include "SkDraw.h" 11 #include "SkPaintPriv.h" 12 #include "SkPicturePlayback.h" 13 14 SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() { 15 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain(); 16 17 return gGPUID; 18 } 19 20 // The GrGather device performs GPU-backend-specific preprocessing on 21 // 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). 28 class GrGatherDevice : public SkBaseDevice { 29 public: 30 SK_DECLARE_INST_COUNT(GrGatherDevice) 31 32 GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData* accelData, 33 int saveLayerDepth) { 34 fPicture = picture; 35 fSaveLayerDepth = saveLayerDepth; 36 fInfo.fValid = true; 37 fInfo.fSize.set(width, height); 38 fInfo.fPaint = NULL; 39 fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID(); 40 fInfo.fRestoreOpID = 0; 41 fInfo.fHasNestedLayers = false; 42 fInfo.fIsNested = (2 == fSaveLayerDepth); 43 44 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.fSize.fHeight)); 45 fAccelData = accelData; 46 fAlreadyDrawn = false; 47 } 48 49 virtual ~GrGatherDevice() { } 50 51 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 63 protected: 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, 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); 121 122 if (device->fAlreadyDrawn) { 123 return; 124 } 125 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)); 130 131 device->fInfo.fOffset = device->getOrigin(); 132 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 141 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 165 private: 166 // The picture being processed 167 const SkPicture *fPicture; 168 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 181 // The depth of this device in the saveLayer stack 182 int fSaveLayerDepth; 183 184 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; 193 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture, 194 fAccelData, fSaveLayerDepth+1)); 195 } 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(); 214 // 215 // which is all just to fill in 'accelData' 216 class SK_API GrGatherCanvas : public SkCanvas { 217 public: 218 GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict) 219 : 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); 231 this->drawPicture(fPicture); 232 } 233 234 protected: 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 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); 255 } 256 picture->draw(this); 257 if (NULL != picture->fPlayback) { 258 picture->fPlayback->setUseBBH(true); 259 } 260 } 261 262 private: 263 const SkPicture* fPicture; 264 265 typedef SkCanvas INHERITED; 266 }; 267 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()) { 272 return ; 273 } 274 275 GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0); 276 GrGatherCanvas canvas(&device, pict); 277 278 canvas.gather(); 279 } 280