OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkGpuDevice.h" | 8 #include "SkGpuDevice.h" |
9 | 9 |
10 #include "effects/GrBicubicEffect.h" | 10 #include "effects/GrBicubicEffect.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 #include "SkTLazy.h" | 41 #include "SkTLazy.h" |
42 #include "SkUtils.h" | 42 #include "SkUtils.h" |
43 #include "SkVertState.h" | 43 #include "SkVertState.h" |
44 #include "SkXfermode.h" | 44 #include "SkXfermode.h" |
45 #include "SkErrorInternals.h" | 45 #include "SkErrorInternals.h" |
46 | 46 |
47 #if SK_SUPPORT_GPU | 47 #if SK_SUPPORT_GPU |
48 | 48 |
49 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 }; | 49 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 }; |
50 | 50 |
51 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1 | |
52 | |
53 #if 0 | 51 #if 0 |
54 extern bool (*gShouldDrawProc)(); | 52 extern bool (*gShouldDrawProc)(); |
55 #define CHECK_SHOULD_DRAW(draw) \ | 53 #define CHECK_SHOULD_DRAW(draw) \ |
56 do { \ | 54 do { \ |
57 if (gShouldDrawProc && !gShouldDrawProc()) return; \ | 55 if (gShouldDrawProc && !gShouldDrawProc()) return; \ |
58 this->prepareDraw(draw); \ | 56 this->prepareDraw(draw); \ |
59 } while (0) | 57 } while (0) |
60 #else | 58 #else |
61 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw) | 59 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw) |
62 #endif | 60 #endif |
63 | 61 |
64 // This constant represents the screen alignment criterion in texels for | 62 // This constant represents the screen alignment criterion in texels for |
65 // requiring texture domain clamping to prevent color bleeding when drawing | 63 // requiring texture domain clamping to prevent color bleeding when drawing |
66 // a sub region of a larger source image. | 64 // a sub region of a larger source image. |
67 #define COLOR_BLEED_TOLERANCE 0.001f | 65 #define COLOR_BLEED_TOLERANCE 0.001f |
68 | 66 |
69 #define DO_DEFERRED_CLEAR() \ | 67 #define DO_DEFERRED_CLEAR() \ |
70 do { \ | 68 do { \ |
71 if (fFlags & kNeedClear_Flag) { \ | 69 if (fNeedClear) { \ |
72 this->clearAll(); \ | 70 this->clearAll(); \ |
73 } \ | 71 } \ |
74 } while (false) \ | 72 } while (false) \ |
75 | 73 |
76 /////////////////////////////////////////////////////////////////////////////// | 74 /////////////////////////////////////////////////////////////////////////////// |
77 | 75 |
78 #define CHECK_FOR_ANNOTATION(paint) \ | 76 #define CHECK_FOR_ANNOTATION(paint) \ |
79 do { if (paint.getAnnotation()) { return; } } while (0) | 77 do { if (paint.getAnnotation()) { return; } } while (0) |
80 | 78 |
81 /////////////////////////////////////////////////////////////////////////////// | 79 /////////////////////////////////////////////////////////////////////////////// |
82 | 80 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 | 115 |
118 struct GrSkDrawProcs : public SkDrawProcs { | 116 struct GrSkDrawProcs : public SkDrawProcs { |
119 public: | 117 public: |
120 GrContext* fContext; | 118 GrContext* fContext; |
121 GrTextContext* fTextContext; | 119 GrTextContext* fTextContext; |
122 GrFontScaler* fFontScaler; // cached in the skia glyphcache | 120 GrFontScaler* fFontScaler; // cached in the skia glyphcache |
123 }; | 121 }; |
124 | 122 |
125 /////////////////////////////////////////////////////////////////////////////// | 123 /////////////////////////////////////////////////////////////////////////////// |
126 | 124 |
127 SkGpuDevice* SkGpuDevice::Create(GrSurface* surface, const SkSurfaceProps& props
, unsigned flags) { | 125 SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props
, unsigned flags) { |
128 SkASSERT(surface); | 126 if (!rt || rt->wasDestroyed()) { |
129 if (NULL == surface->asRenderTarget() || surface->wasDestroyed()) { | |
130 return NULL; | 127 return NULL; |
131 } | 128 } |
132 return SkNEW_ARGS(SkGpuDevice, (surface, props, flags)); | 129 return SkNEW_ARGS(SkGpuDevice, (rt, props, flags)); |
133 } | 130 } |
134 | 131 |
135 static SkDeviceProperties surfaceprops_to_deviceprops(const SkSurfaceProps& prop
s) { | 132 static SkDeviceProperties surfaceprops_to_deviceprops(const SkSurfaceProps* prop
s) { |
136 return SkDeviceProperties(props.pixelGeometry()); | 133 if (props) { |
| 134 return SkDeviceProperties(props->pixelGeometry()); |
| 135 } else { |
| 136 return SkDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType); |
| 137 } |
137 } | 138 } |
138 | 139 |
139 SkGpuDevice::SkGpuDevice(GrSurface* surface, const SkSurfaceProps& props, unsign
ed flags) | 140 static SkSurfaceProps copy_or_default_props(const SkSurfaceProps* props) { |
| 141 if (props) { |
| 142 return SkSurfaceProps(*props); |
| 143 } else { |
| 144 return SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType); |
| 145 } |
| 146 } |
| 147 |
| 148 SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsign
ed flags) |
140 : INHERITED(surfaceprops_to_deviceprops(props)) | 149 : INHERITED(surfaceprops_to_deviceprops(props)) |
| 150 , fSurfaceProps(copy_or_default_props(props)) |
141 { | 151 { |
142 fDrawProcs = NULL; | 152 fDrawProcs = NULL; |
143 | 153 |
144 fContext = SkRef(surface->getContext()); | 154 fContext = SkRef(rt->getContext()); |
| 155 fNeedClear = flags & kNeedClear_Flag; |
145 | 156 |
146 fFlags = flags; | 157 fRenderTarget = SkRef(rt); |
147 | 158 |
148 fRenderTarget = SkRef(surface->asRenderTarget()); | 159 SkImageInfo info = rt->surfacePriv().info(); |
149 | 160 SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt)); |
150 SkImageInfo info = surface->surfacePriv().info(); | |
151 SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, surface)); | |
152 fLegacyBitmap.setInfo(info); | 161 fLegacyBitmap.setInfo(info); |
153 fLegacyBitmap.setPixelRef(pr)->unref(); | 162 fLegacyBitmap.setPixelRef(pr)->unref(); |
154 | 163 |
155 bool useDFT = SkToBool(flags & kDFText_Flag); | 164 bool useDFT = props && props->isUseDistanceFieldFonts(); |
156 fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProp
erties(), useDFT); | 165 fTextContext = this->context()->createTextContext(fRenderTarget, this->getLe
akyProperties(), |
| 166 useDFT); |
157 } | 167 } |
158 | 168 |
159 SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo
, | 169 SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkSurface::Budgeted budgete
d, |
160 const SkSurfaceProps& props, int sampleCount) { | 170 const SkImageInfo& origInfo, int sampleCount, |
| 171 const SkSurfaceProps* props, unsigned flags) { |
161 if (kUnknown_SkColorType == origInfo.colorType() || | 172 if (kUnknown_SkColorType == origInfo.colorType() || |
162 origInfo.width() < 0 || origInfo.height() < 0) { | 173 origInfo.width() < 0 || origInfo.height() < 0) { |
163 return NULL; | 174 return NULL; |
164 } | 175 } |
165 | 176 |
| 177 if (!context) { |
| 178 return NULL; |
| 179 } |
| 180 |
166 SkColorType ct = origInfo.colorType(); | 181 SkColorType ct = origInfo.colorType(); |
167 SkAlphaType at = origInfo.alphaType(); | 182 SkAlphaType at = origInfo.alphaType(); |
168 // TODO: perhaps we can loosen this check now that colortype is more detaile
d | |
169 // e.g. can we support both RGBA and BGRA here? | |
170 if (kRGB_565_SkColorType == ct) { | 183 if (kRGB_565_SkColorType == ct) { |
171 at = kOpaque_SkAlphaType; // force this setting | 184 at = kOpaque_SkAlphaType; // force this setting |
172 } else { | 185 } else if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) { |
| 186 // Fall back from whatever ct was to default of kRGBA or kBGRA which is
aliased as kN32 |
173 ct = kN32_SkColorType; | 187 ct = kN32_SkColorType; |
174 if (kOpaque_SkAlphaType != at) { | 188 } |
175 at = kPremul_SkAlphaType; // force this setting | 189 if (kOpaque_SkAlphaType != at) { |
176 } | 190 at = kPremul_SkAlphaType; // force this setting |
177 } | 191 } |
178 const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height
(), ct, at); | 192 const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height
(), ct, at); |
179 | 193 |
180 GrSurfaceDesc desc; | 194 GrSurfaceDesc desc; |
181 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 195 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
182 desc.fWidth = info.width(); | 196 desc.fWidth = info.width(); |
183 desc.fHeight = info.height(); | 197 desc.fHeight = info.height(); |
184 desc.fConfig = SkImageInfo2GrPixelConfig(info); | 198 desc.fConfig = SkImageInfo2GrPixelConfig(info); |
185 desc.fSampleCnt = sampleCount; | 199 desc.fSampleCnt = sampleCount; |
186 | 200 |
187 SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0
)); | 201 SkAutoTUnref<GrTexture> texture; |
188 if (!texture.get()) { | 202 if (SkSurface::kYes_Budgeted == budgeted) { |
| 203 texture.reset(context->refScratchTexture(desc, GrContext::kExact_Scratch
TexMatch)); |
| 204 } else { |
| 205 texture.reset(context->createUncachedTexture(desc, NULL, 0)); |
| 206 } |
| 207 |
| 208 if (!texture) { |
189 return NULL; | 209 return NULL; |
190 } | 210 } |
191 | 211 |
192 return SkNEW_ARGS(SkGpuDevice, (texture.get(), props)); | 212 return SkNEW_ARGS(SkGpuDevice, (texture->asRenderTarget(), props, flags)); |
193 } | 213 } |
194 | 214 |
195 SkGpuDevice::~SkGpuDevice() { | 215 SkGpuDevice::~SkGpuDevice() { |
196 if (fDrawProcs) { | 216 if (fDrawProcs) { |
197 delete fDrawProcs; | 217 delete fDrawProcs; |
198 } | 218 } |
199 | 219 |
200 delete fTextContext; | 220 delete fTextContext; |
201 | 221 |
202 // The GrContext takes a ref on the target. We don't want to cause the rende
r | 222 // The GrContext takes a ref on the target. We don't want to cause the rende
r |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 GrRenderTarget* SkGpuDevice::accessRenderTarget() { | 308 GrRenderTarget* SkGpuDevice::accessRenderTarget() { |
289 DO_DEFERRED_CLEAR(); | 309 DO_DEFERRED_CLEAR(); |
290 return fRenderTarget; | 310 return fRenderTarget; |
291 } | 311 } |
292 | 312 |
293 void SkGpuDevice::clearAll() { | 313 void SkGpuDevice::clearAll() { |
294 GrColor color = 0; | 314 GrColor color = 0; |
295 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clearAll", fContext); | 315 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clearAll", fContext); |
296 SkIRect rect = SkIRect::MakeWH(this->width(), this->height()); | 316 SkIRect rect = SkIRect::MakeWH(this->width(), this->height()); |
297 fContext->clear(&rect, color, true, fRenderTarget); | 317 fContext->clear(&rect, color, true, fRenderTarget); |
298 fFlags &= ~kNeedClear_Flag; | 318 fNeedClear = false; |
299 } | 319 } |
300 | 320 |
301 /////////////////////////////////////////////////////////////////////////////// | 321 /////////////////////////////////////////////////////////////////////////////// |
302 | 322 |
303 SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch); | 323 SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch); |
304 SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch); | 324 SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch); |
305 SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch); | 325 SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch); |
306 SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch); | 326 SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch); |
307 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4, | 327 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4, |
308 shader_type_mismatch); | 328 shader_type_mismatch); |
(...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 dstSize.fHeight = tmpDst.height(); | 1530 dstSize.fHeight = tmpDst.height(); |
1511 | 1531 |
1512 this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, flags); | 1532 this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, flags); |
1513 } | 1533 } |
1514 | 1534 |
1515 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, | 1535 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, |
1516 int x, int y, const SkPaint& paint) { | 1536 int x, int y, const SkPaint& paint) { |
1517 // clear of the source device must occur before CHECK_SHOULD_DRAW | 1537 // clear of the source device must occur before CHECK_SHOULD_DRAW |
1518 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext); | 1538 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext); |
1519 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); | 1539 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); |
1520 if (dev->fFlags & kNeedClear_Flag) { | 1540 if (fNeedClear) { |
1521 // TODO: could check here whether we really need to draw at all | 1541 // TODO: could check here whether we really need to draw at all |
1522 dev->clearAll(); | 1542 dev->clearAll(); |
1523 } | 1543 } |
1524 | 1544 |
1525 // drawDevice is defined to be in device coords. | 1545 // drawDevice is defined to be in device coords. |
1526 CHECK_SHOULD_DRAW(draw); | 1546 CHECK_SHOULD_DRAW(draw); |
1527 | 1547 |
1528 GrRenderTarget* devRT = dev->accessRenderTarget(); | 1548 GrRenderTarget* devRT = dev->accessRenderTarget(); |
1529 GrTexture* devTex; | 1549 GrTexture* devTex; |
1530 if (NULL == (devTex = devRT->asTexture())) { | 1550 if (NULL == (devTex = devRT->asTexture())) { |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1793 GrSurfaceDesc desc; | 1813 GrSurfaceDesc desc; |
1794 desc.fConfig = fRenderTarget->config(); | 1814 desc.fConfig = fRenderTarget->config(); |
1795 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 1815 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
1796 desc.fWidth = cinfo.fInfo.width(); | 1816 desc.fWidth = cinfo.fInfo.width(); |
1797 desc.fHeight = cinfo.fInfo.height(); | 1817 desc.fHeight = cinfo.fInfo.height(); |
1798 desc.fSampleCnt = fRenderTarget->numSamples(); | 1818 desc.fSampleCnt = fRenderTarget->numSamples(); |
1799 | 1819 |
1800 SkAutoTUnref<GrTexture> texture; | 1820 SkAutoTUnref<GrTexture> texture; |
1801 // Skia's convention is to only clear a device if it is non-opaque. | 1821 // Skia's convention is to only clear a device if it is non-opaque. |
1802 unsigned flags = cinfo.fInfo.isOpaque() ? 0 : kNeedClear_Flag; | 1822 unsigned flags = cinfo.fInfo.isOpaque() ? 0 : kNeedClear_Flag; |
1803 // If we're using distance field text, enable in the new device | |
1804 flags |= (fFlags & kDFText_Flag) ? kDFText_Flag : 0; | |
1805 | 1823 |
1806 #if CACHE_COMPATIBLE_DEVICE_TEXTURES | |
1807 // layers are never draw in repeat modes, so we can request an approx | 1824 // layers are never draw in repeat modes, so we can request an approx |
1808 // match and ignore any padding. | 1825 // match and ignore any padding. |
1809 const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == cinfo.fUsage)
? | 1826 const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == cinfo.fUsage)
? |
1810 GrContext::kApprox_ScratchTexMat
ch : | 1827 GrContext::kApprox_ScratchTexMat
ch : |
1811 GrContext::kExact_ScratchTexMatc
h; | 1828 GrContext::kExact_ScratchTexMatc
h; |
1812 texture.reset(fContext->refScratchTexture(desc, match)); | 1829 texture.reset(fContext->refScratchTexture(desc, match)); |
1813 #else | 1830 |
1814 texture.reset(fContext->createUncachedTexture(desc, NULL, 0)); | 1831 if (texture) { |
1815 #endif | 1832 SkSurfaceProps props(fSurfaceProps.flags(), cinfo.fPixelGeometry); |
1816 if (texture.get()) { | 1833 return SkGpuDevice::Create(texture->asRenderTarget(), &props, flags); |
1817 return SkGpuDevice::Create(texture, SkSurfaceProps(0, cinfo.fPixelGeomet
ry), flags); | |
1818 } else { | 1834 } else { |
1819 SkDebugf("---- failed to create compatible device texture [%d %d]\n", | 1835 SkDebugf("---- failed to create compatible device texture [%d %d]\n", |
1820 cinfo.fInfo.width(), cinfo.fInfo.height()); | 1836 cinfo.fInfo.width(), cinfo.fInfo.height()); |
1821 return NULL; | 1837 return NULL; |
1822 } | 1838 } |
1823 } | 1839 } |
1824 | 1840 |
1825 SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps
& props) { | 1841 SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps
& props) { |
1826 return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples(
), &props); | 1842 // TODO: Change the signature of newSurface to take a budgeted parameter. |
| 1843 static const SkSurface::Budgeted kBudgeted = SkSurface::kNo_Budgeted; |
| 1844 return SkSurface::NewRenderTarget(fContext, kBudgeted, info, fRenderTarget->
numSamples(), |
| 1845 &props); |
1827 } | 1846 } |
1828 | 1847 |
1829 bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
* mainPicture, | 1848 bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
* mainPicture, |
1830 const SkMatrix* matrix, const SkPaint
* paint) { | 1849 const SkMatrix* matrix, const SkPaint
* paint) { |
1831 #ifndef SK_IGNORE_GPU_LAYER_HOISTING | 1850 #ifndef SK_IGNORE_GPU_LAYER_HOISTING |
1832 // todo: should handle this natively | 1851 // todo: should handle this natively |
1833 if (paint) { | 1852 if (paint) { |
1834 return false; | 1853 return false; |
1835 } | 1854 } |
1836 | 1855 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1885 #endif | 1904 #endif |
1886 } | 1905 } |
1887 | 1906 |
1888 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { | 1907 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { |
1889 // We always return a transient cache, so it is freed after each | 1908 // We always return a transient cache, so it is freed after each |
1890 // filter traversal. | 1909 // filter traversal. |
1891 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); | 1910 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); |
1892 } | 1911 } |
1893 | 1912 |
1894 #endif | 1913 #endif |
OLD | NEW |