| 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 |