OLD | NEW |
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 "SkDevice.h" | 9 #include "SkDevice.h" |
10 #include "SkDraw.h" | 10 #include "SkDraw.h" |
11 #include "SkPaintPriv.h" | 11 #include "SkPaintPriv.h" |
12 #include "SkPictureData.h" | 12 #include "SkPictureData.h" |
| 13 #include "SkPicturePlayback.h" |
13 | 14 |
14 SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() { | 15 SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() { |
15 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::Genera
teDomain(); | 16 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::Genera
teDomain(); |
16 | 17 |
17 return gGPUID; | 18 return gGPUID; |
18 } | 19 } |
19 | 20 |
20 // The GrGather device performs GPU-backend-specific preprocessing on | 21 // The GrGather device performs GPU-backend-specific preprocessing on |
21 // a picture. The results are stored in a GPUAccelData. | 22 // a picture. The results are stored in a GPUAccelData. |
22 // | 23 // |
23 // Currently the only interesting work is done in drawDevice (i.e., when a | 24 // 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 // 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 t
he | 26 // All the current work could be done much more efficiently by just traversing t
he |
26 // raw op codes in the SkPicture (although we would still need to replay all the | 27 // raw op codes in the SkPicture (although we would still need to replay all the |
27 // clip calls). | 28 // clip calls). |
28 class GrGatherDevice : public SkBaseDevice { | 29 class GrGatherDevice : public SkBaseDevice { |
29 public: | 30 public: |
30 SK_DECLARE_INST_COUNT(GrGatherDevice) | 31 SK_DECLARE_INST_COUNT(GrGatherDevice) |
31 | 32 |
32 GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData
* accelData, | 33 GrGatherDevice(int width, int height, SkPicturePlayback* playback, GPUAccelD
ata* accelData, |
33 int saveLayerDepth) { | 34 int saveLayerDepth) { |
34 fPicture = picture; | 35 fPlayback = playback; |
35 fSaveLayerDepth = saveLayerDepth; | 36 fSaveLayerDepth = saveLayerDepth; |
36 fInfo.fValid = true; | 37 fInfo.fValid = true; |
37 fInfo.fSize.set(width, height); | 38 fInfo.fSize.set(width, height); |
38 fInfo.fPaint = NULL; | 39 fInfo.fPaint = NULL; |
39 fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID(); | 40 fInfo.fSaveLayerOpID = fPlayback->curOpID(); |
40 fInfo.fRestoreOpID = 0; | 41 fInfo.fRestoreOpID = 0; |
41 fInfo.fHasNestedLayers = false; | 42 fInfo.fHasNestedLayers = false; |
42 fInfo.fIsNested = (2 == fSaveLayerDepth); | 43 fInfo.fIsNested = (2 == fSaveLayerDepth); |
43 | 44 |
44 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.
fSize.fHeight)); | 45 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.
fSize.fHeight)); |
45 fAccelData = accelData; | 46 fAccelData = accelData; |
46 fAlreadyDrawn = false; | 47 fAlreadyDrawn = false; |
47 } | 48 } |
48 | 49 |
49 virtual ~GrGatherDevice() { } | 50 virtual ~GrGatherDevice() { } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 117 } |
117 virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, i
nt y, | 118 virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, i
nt y, |
118 const SkPaint& paint) SK_OVERRIDE { | 119 const SkPaint& paint) SK_OVERRIDE { |
119 // deviceIn is the one that is being "restored" back to its parent | 120 // deviceIn is the one that is being "restored" back to its parent |
120 GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn); | 121 GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn); |
121 | 122 |
122 if (device->fAlreadyDrawn) { | 123 if (device->fAlreadyDrawn) { |
123 return; | 124 return; |
124 } | 125 } |
125 | 126 |
126 device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID(); | 127 device->fInfo.fRestoreOpID = fPlayback->curOpID(); |
127 device->fInfo.fCTM = *draw.fMatrix; | 128 device->fInfo.fCTM = *draw.fMatrix; |
128 device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX), | 129 device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX), |
129 SkIntToScalar(-device->getOrigin().fY))
; | 130 SkIntToScalar(-device->getOrigin().fY))
; |
130 | 131 |
131 device->fInfo.fOffset = device->getOrigin(); | 132 device->fInfo.fOffset = device->getOrigin(); |
132 | 133 |
133 if (NeedsDeepCopy(paint)) { | 134 if (NeedsDeepCopy(paint)) { |
134 // This NULL acts as a signal that the paint was uncopyable (for now
) | 135 // This NULL acts as a signal that the paint was uncopyable (for now
) |
135 device->fInfo.fPaint = NULL; | 136 device->fInfo.fPaint = NULL; |
136 device->fInfo.fValid = false; | 137 device->fInfo.fValid = false; |
(...skipping 19 matching lines...) Expand all Loading... |
156 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); } | 157 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); } |
157 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); } | 158 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); } |
158 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return fal
se; } | 159 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return fal
se; } |
159 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return
false; } | 160 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return
false; } |
160 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImag
eFilter::Context&, | 161 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImag
eFilter::Context&, |
161 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { | 162 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { |
162 return false; | 163 return false; |
163 } | 164 } |
164 | 165 |
165 private: | 166 private: |
166 // The picture being processed | 167 // The playback object driving this rendering |
167 const SkPicture *fPicture; | 168 SkPicturePlayback *fPlayback; |
168 | 169 |
169 SkBitmap fEmptyBitmap; // legacy -- need to remove | 170 SkBitmap fEmptyBitmap; // legacy -- need to remove |
170 | 171 |
171 // All information gathered during the gather process is stored here | 172 // All information gathered during the gather process is stored here |
172 GPUAccelData* fAccelData; | 173 GPUAccelData* fAccelData; |
173 | 174 |
174 // true if this device has already been drawn back to its parent(s) at least | 175 // true if this device has already been drawn back to its parent(s) at least |
175 // once. | 176 // once. |
176 bool fAlreadyDrawn; | 177 bool fAlreadyDrawn; |
177 | 178 |
178 // The information regarding the saveLayer call this device represents. | 179 // The information regarding the saveLayer call this device represents. |
179 GPUAccelData::SaveLayerInfo fInfo; | 180 GPUAccelData::SaveLayerInfo fInfo; |
180 | 181 |
181 // The depth of this device in the saveLayer stack | 182 // The depth of this device in the saveLayer stack |
182 int fSaveLayerDepth; | 183 int fSaveLayerDepth; |
183 | 184 |
184 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRI
DE { | 185 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRI
DE { |
185 NotSupported(); | 186 NotSupported(); |
186 } | 187 } |
187 | 188 |
188 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) S
K_OVERRIDE { | 189 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) S
K_OVERRIDE { |
189 // we expect to only get called via savelayer, in which case it is fine. | 190 // we expect to only get called via savelayer, in which case it is fine. |
190 SkASSERT(kSaveLayer_Usage == usage); | 191 SkASSERT(kSaveLayer_Usage == usage); |
191 | 192 |
192 fInfo.fHasNestedLayers = true; | 193 fInfo.fHasNestedLayers = true; |
193 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture
, | 194 return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPlaybac
k, |
194 fAccelData, fSaveLayerDepth+1)); | 195 fAccelData, fSaveLayerDepth+1)); |
195 } | 196 } |
196 | 197 |
197 virtual void flush() SK_OVERRIDE {} | 198 virtual void flush() SK_OVERRIDE {} |
198 | 199 |
199 static void NotSupported() { | 200 static void NotSupported() { |
200 SkDEBUGFAIL("this method should never be called"); | 201 SkDEBUGFAIL("this method should never be called"); |
201 } | 202 } |
202 | 203 |
203 static void NothingToDo() {} | 204 static void NothingToDo() {} |
204 | 205 |
205 typedef SkBaseDevice INHERITED; | 206 typedef SkBaseDevice INHERITED; |
206 }; | 207 }; |
207 | 208 |
208 // The GrGatherCanvas allows saveLayers but simplifies clipping. It is really | 209 // The GrGatherCanvas allows saveLayers but simplifies clipping. It is really |
209 // only intended to be used as: | 210 // only intended to be used as: |
210 // | 211 // |
211 // GrGatherDevice dev(w, h, picture, accelData); | 212 // GrGatherDevice dev(w, h, picture, accelData); |
212 // GrGatherCanvas canvas(..., picture); | 213 // GrGatherCanvas canvas(..., picture); |
213 // canvas.gather(); | 214 // canvas.gather(); |
214 // | 215 // |
215 // which is all just to fill in 'accelData' | 216 // which is all just to fill in 'accelData' |
216 class SK_API GrGatherCanvas : public SkCanvas { | 217 class SK_API GrGatherCanvas : public SkCanvas { |
217 public: | 218 public: |
218 GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict) | 219 GrGatherCanvas(GrGatherDevice* device) : INHERITED(device) {} |
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 | 220 |
234 protected: | 221 protected: |
235 // disable aa for speed | 222 // disable aa for speed |
236 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle)
SK_OVERRIDE { | 223 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle)
SK_OVERRIDE { |
237 this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle); | 224 this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle); |
238 } | 225 } |
239 | 226 |
240 // for speed, just respect the bounds, and disable AA. May give us a few | 227 // for speed, just respect the bounds, and disable AA. May give us a few |
241 // false positives and negatives. | 228 // false positives and negatives. |
242 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle)
SK_OVERRIDE { | 229 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle)
SK_OVERRIDE { |
243 this->updateClipConservativelyUsingBounds(path.getBounds(), op, | 230 this->updateClipConservativelyUsingBounds(path.getBounds(), op, |
244 path.isInverseFillType()); | 231 path.isInverseFillType()); |
245 } | 232 } |
246 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl
e) SK_OVERRIDE { | 233 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl
e) SK_OVERRIDE { |
247 this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false); | 234 this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false); |
248 } | 235 } |
249 | 236 |
250 virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE { | 237 virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE { |
251 // BBH-based rendering doesn't re-issue many of the operations the gathe
r | |
252 // process cares about (e.g., saves and restores) so it must be disabled
. | |
253 if (NULL != picture->fData.get()) { | 238 if (NULL != picture->fData.get()) { |
254 picture->fData->setUseBBH(false); | 239 // Disable the BBH for the old path so all the draw calls |
255 } | 240 // will be seen. The stock SkPicture::draw method can't be |
256 picture->draw(this); | 241 // invoked since it just uses a vanilla SkPicturePlayback. |
257 if (NULL != picture->fData.get()) { | 242 SkPicturePlayback playback(picture); |
258 picture->fData->setUseBBH(true); | 243 playback.setUseBBH(false); |
| 244 playback.draw(this, NULL); |
| 245 } else { |
| 246 // Since we know this is the SkRecord path we can just call |
| 247 // SkPicture::draw. |
| 248 picture->draw(this); |
259 } | 249 } |
260 } | 250 } |
261 | 251 |
262 private: | 252 private: |
263 const SkPicture* fPicture; | |
264 | |
265 typedef SkCanvas INHERITED; | 253 typedef SkCanvas INHERITED; |
266 }; | 254 }; |
267 | 255 |
268 // GatherGPUInfo is only intended to be called within the context of SkGpuDevice
's | 256 // GatherGPUInfo is only intended to be called within the context of SkGpuDevice
's |
269 // EXPERIMENTAL_optimize method. | 257 // EXPERIMENTAL_optimize method. |
270 void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) { | 258 void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) { |
271 if (0 == pict->width() || 0 == pict->height()) { | 259 if (NULL == pict || 0 == pict->width() || 0 == pict->height()) { |
272 return ; | 260 return ; |
273 } | 261 } |
274 | 262 |
275 GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0); | 263 // BBH-based rendering doesn't re-issue many of the operations the gather |
276 GrGatherCanvas canvas(&device, pict); | 264 // process cares about (e.g., saves and restores) so it must be disabled. |
| 265 SkPicturePlayback playback(pict); |
| 266 playback.setUseBBH(false); |
277 | 267 |
278 canvas.gather(); | 268 GrGatherDevice device(pict->width(), pict->height(), &playback, accelData, 0
); |
| 269 GrGatherCanvas canvas(&device); |
| 270 |
| 271 canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()), |
| 272 SkIntToScalar(pict->height())), |
| 273 SkRegion::kIntersect_Op, false); |
| 274 playback.draw(&canvas, NULL); |
279 } | 275 } |
OLD | NEW |