blob: 0b5f14c45cfd8ae4884ae7563f0b312fd31612a5 [file] [log] [blame]
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001/*
2 * Copyright 2011 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 "SkGpuDevice.h"
9
Brian Osman3b66ab62016-11-28 09:26:31 -050010#include "GrBitmapTextureMaker.h"
robertphillipsccb1b572015-05-27 11:02:55 -070011#include "GrBlurUtils.h"
kkinnunenabcfab42015-02-22 22:53:44 -080012#include "GrContext.h"
kkinnunenabcfab42015-02-22 22:53:44 -080013#include "GrGpu.h"
Brian Osman3b66ab62016-11-28 09:26:31 -050014#include "GrImageTextureMaker.h"
15#include "GrRenderTargetContextPriv.h"
bsalomon6663acf2016-05-10 09:14:17 -070016#include "GrStyle.h"
Brian Salomon199fb872017-02-06 09:41:10 -050017#include "GrSurfaceContextPriv.h"
Brian Osmane8e54582016-11-28 10:06:27 -050018#include "GrTextureAdjuster.h"
Robert Phillipse2f7d182016-12-15 09:23:05 -050019#include "GrTextureProxy.h"
egdanielbbcb38d2014-06-19 10:19:29 -070020#include "GrTracing.h"
robertphillips30d78412014-11-24 09:49:17 -080021#include "SkCanvasPriv.h"
robertphillips714712b2016-08-04 06:20:45 -070022#include "SkDraw.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000023#include "SkGlyphCache.h"
bsalomonf276ac52015-10-09 13:36:42 -070024#include "SkGr.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070025#include "SkGrPriv.h"
bsalomon1cf6f9b2015-12-08 10:53:43 -080026#include "SkImageCacherator.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000027#include "SkImageFilter.h"
senorblanco900c3672016-04-27 11:31:23 -070028#include "SkImageFilterCache.h"
Matt Sarettcb6266b2017-01-17 10:48:53 -050029#include "SkImageInfoPriv.h"
Brian Salomon6a639042016-12-14 11:08:17 -050030#include "SkImage_Base.h"
msarettc573a402016-08-02 08:05:56 -070031#include "SkLatticeIter.h"
commit-bot@chromium.org82139702014-03-10 22:53:20 +000032#include "SkMaskFilter.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000033#include "SkPathEffect.h"
commit-bot@chromium.org145d1c02014-03-16 19:46:36 +000034#include "SkPicture.h"
robertphillipsdb539902014-07-01 08:47:04 -070035#include "SkPictureData.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000036#include "SkRRect.h"
Brian Salomon6a639042016-12-14 11:08:17 -050037#include "SkRasterClip.h"
Matt Sarett03dd6d52017-01-23 12:15:09 -050038#include "SkReadPixelsRec.h"
kkinnunenabcfab42015-02-22 22:53:44 -080039#include "SkRecord.h"
robertphillips970587b2016-07-14 14:12:55 -070040#include "SkSpecialImage.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000041#include "SkStroke.h"
reed@google.com76f10a32014-02-05 15:32:21 +000042#include "SkSurface.h"
kkinnunenabcfab42015-02-22 22:53:44 -080043#include "SkSurface_Gpu.h"
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +000044#include "SkTLazy.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000045#include "SkUtils.h"
commit-bot@chromium.org559a8832014-05-30 10:08:22 +000046#include "SkVertState.h"
Brian Salomon199fb872017-02-06 09:41:10 -050047#include "SkVertices.h"
Matt Sarett03dd6d52017-01-23 12:15:09 -050048#include "SkWritePixelsRec.h"
kkinnunenabcfab42015-02-22 22:53:44 -080049#include "effects/GrBicubicEffect.h"
kkinnunenabcfab42015-02-22 22:53:44 -080050#include "effects/GrSimpleTextureEffect.h"
51#include "effects/GrTextureDomain.h"
joshualitt8e84a1e2016-02-16 11:09:25 -080052#include "text/GrTextUtils.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000053
reedf037e0b2014-10-30 11:34:15 -070054#if SK_SUPPORT_GPU
55
joshualittce894002016-01-11 13:29:31 -080056#define ASSERT_SINGLE_OWNER \
57 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->debugSingleOwner());)
58
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000059#if 0
60 extern bool (*gShouldDrawProc)();
joshualitt5531d512014-12-17 15:50:11 -080061 #define CHECK_SHOULD_DRAW(draw) \
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000062 do { \
63 if (gShouldDrawProc && !gShouldDrawProc()) return; \
joshualitt5531d512014-12-17 15:50:11 -080064 this->prepareDraw(draw); \
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000065 } while (0)
66#else
joshualitt5531d512014-12-17 15:50:11 -080067 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw)
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000068#endif
69
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000070///////////////////////////////////////////////////////////////////////////////
71
bsalomon74f681d2015-06-23 14:38:48 -070072/** Checks that the alpha type is legal and gets constructor flags. Returns false if device creation
73 should fail. */
74bool SkGpuDevice::CheckAlphaTypeAndGetFlags(
75 const SkImageInfo* info, SkGpuDevice::InitContents init, unsigned* flags) {
76 *flags = 0;
77 if (info) {
78 switch (info->alphaType()) {
79 case kPremul_SkAlphaType:
80 break;
81 case kOpaque_SkAlphaType:
82 *flags |= SkGpuDevice::kIsOpaque_Flag;
83 break;
84 default: // If it is unpremul or unknown don't try to render
85 return false;
86 }
87 }
88 if (kClear_InitContents == init) {
89 *flags |= kNeedClear_Flag;
90 }
91 return true;
92}
93
Robert Phillips9fab7e92016-11-17 12:45:04 -050094sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context,
95 sk_sp<GrRenderTargetContext> renderTargetContext,
robertphillips15c42ca2016-08-04 08:45:02 -070096 int width, int height,
97 InitContents init) {
Brian Osman11052242016-10-27 14:47:55 -040098 if (!renderTargetContext || renderTargetContext->wasAbandoned()) {
robertphillipsca6eafc2016-05-17 09:57:46 -070099 return nullptr;
100 }
101 unsigned flags;
102 if (!CheckAlphaTypeAndGetFlags(nullptr, init, &flags)) {
103 return nullptr;
104 }
Robert Phillips9fab7e92016-11-17 12:45:04 -0500105 return sk_sp<SkGpuDevice>(new SkGpuDevice(context, std::move(renderTargetContext),
106 width, height, flags));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000107}
108
robertphillips24e91282016-04-29 06:46:36 -0700109sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context, SkBudgeted budgeted,
110 const SkImageInfo& info, int sampleCount,
robertphillips7e922762016-07-26 11:38:17 -0700111 GrSurfaceOrigin origin,
robertphillips24e91282016-04-29 06:46:36 -0700112 const SkSurfaceProps* props, InitContents init) {
bsalomon74f681d2015-06-23 14:38:48 -0700113 unsigned flags;
114 if (!CheckAlphaTypeAndGetFlags(&info, init, &flags)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700115 return nullptr;
bsalomon74f681d2015-06-23 14:38:48 -0700116 }
117
Brian Osman11052242016-10-27 14:47:55 -0400118 sk_sp<GrRenderTargetContext> renderTargetContext(MakeRenderTargetContext(context, budgeted,
119 info, sampleCount,
120 origin, props));
121 if (!renderTargetContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700122 return nullptr;
bsalomon74f681d2015-06-23 14:38:48 -0700123 }
124
Robert Phillips9fab7e92016-11-17 12:45:04 -0500125 return sk_sp<SkGpuDevice>(new SkGpuDevice(context, std::move(renderTargetContext),
robertphillipsca6eafc2016-05-17 09:57:46 -0700126 info.width(), info.height(), flags));
bsalomon74f681d2015-06-23 14:38:48 -0700127}
128
Brian Osman11052242016-10-27 14:47:55 -0400129static SkImageInfo make_info(GrRenderTargetContext* context, int w, int h, bool opaque) {
reed589a39e2016-08-20 07:59:19 -0700130 SkColorType colorType;
131 if (!GrPixelConfigToColorType(context->config(), &colorType)) {
132 colorType = kUnknown_SkColorType;
133 }
134 return SkImageInfo::Make(w, h, colorType,
135 opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
Robert Phillips75a475c2017-01-13 09:18:59 -0500136 context->refColorSpace());
reed589a39e2016-08-20 07:59:19 -0700137}
138
Robert Phillips9fab7e92016-11-17 12:45:04 -0500139SkGpuDevice::SkGpuDevice(GrContext* context, sk_sp<GrRenderTargetContext> renderTargetContext,
140 int width, int height, unsigned flags)
Brian Osman11052242016-10-27 14:47:55 -0400141 : INHERITED(make_info(renderTargetContext.get(), width, height,
142 SkToBool(flags & kIsOpaque_Flag)), renderTargetContext->surfaceProps())
Robert Phillips9fab7e92016-11-17 12:45:04 -0500143 , fContext(SkRef(context))
Brian Osman11052242016-10-27 14:47:55 -0400144 , fRenderTargetContext(std::move(renderTargetContext))
reed589a39e2016-08-20 07:59:19 -0700145{
robertphillips1f3923e2016-07-21 07:17:54 -0700146 fSize.set(width, height);
bsalomon74f681d2015-06-23 14:38:48 -0700147 fOpaque = SkToBool(flags & kIsOpaque_Flag);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000148
bsalomone63ffef2016-02-05 07:17:34 -0800149 if (flags & kNeedClear_Flag) {
150 this->clearAll();
151 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000152}
153
Brian Osman11052242016-10-27 14:47:55 -0400154sk_sp<GrRenderTargetContext> SkGpuDevice::MakeRenderTargetContext(
155 GrContext* context,
156 SkBudgeted budgeted,
157 const SkImageInfo& origInfo,
158 int sampleCount,
159 GrSurfaceOrigin origin,
160 const SkSurfaceProps* surfaceProps) {
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000161 if (kUnknown_SkColorType == origInfo.colorType() ||
162 origInfo.width() < 0 || origInfo.height() < 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700163 return nullptr;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000164 }
165
bsalomonafe30052015-01-16 07:32:33 -0800166 if (!context) {
halcanary96fcdcc2015-08-27 07:41:13 -0700167 return nullptr;
bsalomonafe30052015-01-16 07:32:33 -0800168 }
169
Brian Osman0c2997b2017-01-11 16:58:42 -0500170 GrPixelConfig config = SkImageInfo2GrPixelConfig(origInfo, *context->caps());
Brian Osman11052242016-10-27 14:47:55 -0400171 return context->makeRenderTargetContext(SkBackingFit::kExact, // Why exact?
robertphillips6738c702016-07-27 12:13:51 -0700172 origInfo.width(), origInfo.height(),
Robert Phillips70b49fd2017-01-13 11:21:36 -0500173 config, origInfo.refColorSpace(), sampleCount,
robertphillips6738c702016-07-27 12:13:51 -0700174 origin, surfaceProps, budgeted);
kkinnunenabcfab42015-02-22 22:53:44 -0800175}
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000176
robertphillips970587b2016-07-14 14:12:55 -0700177sk_sp<SkSpecialImage> SkGpuDevice::filterTexture(const SkDraw& draw,
178 SkSpecialImage* srcImg,
179 int left, int top,
180 SkIPoint* offset,
181 const SkImageFilter* filter) {
182 SkASSERT(srcImg->isTextureBacked());
183 SkASSERT(filter);
184
185 SkMatrix matrix = *draw.fMatrix;
186 matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
Mike Reedfa24d342017-02-22 15:21:35 -0500187 const SkIRect clipBounds = this->devClipBounds(draw).makeOffset(-left, -top);
Hal Canary144caf52016-11-07 17:57:18 -0500188 sk_sp<SkImageFilterCache> cache(this->getImageFilterCache());
Brian Osman11052242016-10-27 14:47:55 -0400189 SkImageFilter::OutputProperties outputProperties(fRenderTargetContext->getColorSpace());
brianosman2a75e5d2016-09-22 07:15:37 -0700190 SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties);
robertphillips970587b2016-07-14 14:12:55 -0700191
192 return filter->filterImage(srcImg, ctx, offset);
193}
194
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000195///////////////////////////////////////////////////////////////////////////////
196
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000197bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
198 int x, int y) {
joshualittce894002016-01-11 13:29:31 -0800199 ASSERT_SINGLE_OWNER
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000200
Matt Sarettcb6266b2017-01-17 10:48:53 -0500201 if (!SkImageInfoValidConversion(dstInfo, this->imageInfo())) {
202 return false;
203 }
204
Matt Sarett03dd6d52017-01-23 12:15:09 -0500205 SkReadPixelsRec rec(dstInfo, dstPixels, dstRowBytes, x, y);
206 if (!rec.trim(this->width(), this->height())) {
207 return false;
208 }
209
210 return fRenderTargetContext->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000211}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000212
robertphillips1da3ecd2016-08-31 14:54:15 -0700213bool SkGpuDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
214 size_t srcRowBytes, int x, int y) {
joshualittce894002016-01-11 13:29:31 -0800215 ASSERT_SINGLE_OWNER
robertphillips1da3ecd2016-08-31 14:54:15 -0700216
Matt Sarettcb6266b2017-01-17 10:48:53 -0500217 if (!SkImageInfoValidConversion(this->imageInfo(), srcInfo)) {
218 return false;
219 }
220
Matt Sarett03dd6d52017-01-23 12:15:09 -0500221 SkWritePixelsRec rec(srcInfo, srcPixels, srcRowBytes, x, y);
222 if (!rec.trim(this->width(), this->height())) {
223 return false;
224 }
225
226 return fRenderTargetContext->writePixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000227}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000228
reed41e010c2015-06-09 12:16:53 -0700229bool SkGpuDevice::onAccessPixels(SkPixmap* pmap) {
joshualittce894002016-01-11 13:29:31 -0800230 ASSERT_SINGLE_OWNER
reed41e010c2015-06-09 12:16:53 -0700231 return false;
232}
233
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000234// call this every draw call, to ensure that the context reflects our state,
235// and not the state from some other canvas/device
joshualitt5531d512014-12-17 15:50:11 -0800236void SkGpuDevice::prepareDraw(const SkDraw& draw) {
joshualittce894002016-01-11 13:29:31 -0800237 ASSERT_SINGLE_OWNER
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000238
Mike Reedd519d482017-02-16 11:04:52 -0500239#ifdef SK_USE_DEVICE_CLIPPING
240 SkASSERT(*draw.fMatrix == this->ctm());
Mike Reedc5e641c2017-02-17 14:38:11 -0500241 fClip.reset(&this->cs(), nullptr);
Mike Reedd519d482017-02-16 11:04:52 -0500242#else
reed2c9e2002016-07-25 08:05:22 -0700243 fClip.reset(draw.fClipStack, &this->getOrigin());
Mike Reedd519d482017-02-16 11:04:52 -0500244#endif
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000245}
246
Brian Osman11052242016-10-27 14:47:55 -0400247GrRenderTargetContext* SkGpuDevice::accessRenderTargetContext() {
robertphillips175dd9b2016-04-28 14:32:04 -0700248 ASSERT_SINGLE_OWNER
Brian Osman11052242016-10-27 14:47:55 -0400249 return fRenderTargetContext.get();
robertphillips175dd9b2016-04-28 14:32:04 -0700250}
251
reed8eddfb52014-12-04 07:50:14 -0800252void SkGpuDevice::clearAll() {
joshualittce894002016-01-11 13:29:31 -0800253 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500254 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "clearAll", fContext.get());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500255
reed8eddfb52014-12-04 07:50:14 -0800256 SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500257 fRenderTargetContext->clear(&rect, 0x0, true);
reed8eddfb52014-12-04 07:50:14 -0800258}
259
Brian Osman11052242016-10-27 14:47:55 -0400260void SkGpuDevice::replaceRenderTargetContext(bool shouldRetainContent) {
joshualittce894002016-01-11 13:29:31 -0800261 ASSERT_SINGLE_OWNER
kkinnunenabcfab42015-02-22 22:53:44 -0800262
Brian Osman693a5402016-10-27 15:13:22 -0400263 SkBudgeted budgeted = fRenderTargetContext->priv().isBudgeted();
kkinnunenabcfab42015-02-22 22:53:44 -0800264
Brian Osman693a5402016-10-27 15:13:22 -0400265 sk_sp<GrRenderTargetContext> newRTC(MakeRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400266 this->context(),
267 budgeted,
268 this->imageInfo(),
269 fRenderTargetContext->numColorSamples(),
270 fRenderTargetContext->origin(),
271 &this->surfaceProps()));
Brian Osman693a5402016-10-27 15:13:22 -0400272 if (!newRTC) {
kkinnunenabcfab42015-02-22 22:53:44 -0800273 return;
274 }
275
276 if (shouldRetainContent) {
Brian Osman11052242016-10-27 14:47:55 -0400277 if (fRenderTargetContext->wasAbandoned()) {
kkinnunenabcfab42015-02-22 22:53:44 -0800278 return;
279 }
Robert Phillipsf200a902017-01-30 13:27:37 -0500280 newRTC->copy(fRenderTargetContext->asSurfaceProxy());
kkinnunenabcfab42015-02-22 22:53:44 -0800281 }
282
Brian Osman693a5402016-10-27 15:13:22 -0400283 fRenderTargetContext = newRTC;
kkinnunenabcfab42015-02-22 22:53:44 -0800284}
285
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000286///////////////////////////////////////////////////////////////////////////////
287
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000288void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800289 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -0800290 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -0500291 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPaint", fContext.get());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000292
293 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400294 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
295 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700296 return;
297 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000298
Brian Salomon82f44312017-01-11 13:42:54 -0500299 fRenderTargetContext->drawPaint(fClip, std::move(grPaint), *draw.fMatrix);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000300}
301
302// must be in SkCanvas::PointMode order
bsalomon6ade6dd2016-09-12 12:07:17 -0700303static const GrPrimitiveType gPointMode2PrimitiveType[] = {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000304 kPoints_GrPrimitiveType,
305 kLines_GrPrimitiveType,
306 kLineStrip_GrPrimitiveType
307};
308
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500309static inline bool is_int(float x) { return x == (float) sk_float_round2int(x); }
310
ethannicholas330bb952015-07-17 06:44:02 -0700311// suppress antialiasing on axis-aligned integer-coordinate lines
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500312static bool needs_antialiasing(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
313 const SkMatrix& matrix) {
ethannicholas330bb952015-07-17 06:44:02 -0700314 if (mode == SkCanvas::PointMode::kPoints_PointMode) {
315 return false;
316 }
317 if (count == 2) {
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500318 // We do not antialias horizontal or vertical lines along pixel centers, even when the ends
319 // of the line do not fully cover the first and last pixel of the line, which is slightly
320 // wrong.
321 if (!matrix.isScaleTranslate()) {
322 return true;
323 }
ethannicholas330bb952015-07-17 06:44:02 -0700324 if (pts[0].fX == pts[1].fX) {
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500325 SkScalar x = matrix.getScaleX() * pts[0].fX + matrix.getTranslateX();
326 return !is_int(x + 0.5f);
ethannicholas330bb952015-07-17 06:44:02 -0700327 }
328 if (pts[0].fY == pts[1].fY) {
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500329 SkScalar y = matrix.getScaleY() * pts[0].fY + matrix.getTranslateY();
330 return !is_int(y + 0.5f);
ethannicholas330bb952015-07-17 06:44:02 -0700331 }
332 }
333 return true;
334}
335
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000336void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
337 size_t count, const SkPoint pts[], const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800338 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500339 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPoints", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800340 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000341
342 SkScalar width = paint.getStrokeWidth();
343 if (width < 0) {
344 return;
345 }
346
commit-bot@chromium.org628ed0b2014-05-19 14:32:49 +0000347 if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
bsalomon6663acf2016-05-10 09:14:17 -0700348 GrStyle style(paint, SkPaint::kStroke_Style);
egdaniele61c4112014-06-12 10:24:21 -0700349 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400350 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
brianosman1638c0d2016-07-25 05:12:53 -0700351 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700352 return;
353 }
egdaniele61c4112014-06-12 10:24:21 -0700354 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700355 path.setIsVolatile(true);
egdaniele61c4112014-06-12 10:24:21 -0700356 path.moveTo(pts[0]);
357 path.lineTo(pts[1]);
Brian Salomon82f44312017-01-11 13:42:54 -0500358 fRenderTargetContext->drawPath(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500359 *draw.fMatrix, path, style);
egdaniele61c4112014-06-12 10:24:21 -0700360 return;
commit-bot@chromium.org628ed0b2014-05-19 14:32:49 +0000361 }
362
bsalomon6ade6dd2016-09-12 12:07:17 -0700363 SkScalar scales[2];
364 bool isHairline = (0 == width) || (1 == width && draw.fMatrix->getMinMaxScales(scales) &&
365 SkScalarNearlyEqual(scales[0], 1.f) &&
366 SkScalarNearlyEqual(scales[1], 1.f));
ethannicholas330bb952015-07-17 06:44:02 -0700367 // we only handle non-antialiased hairlines and paints without path effects or mask filters,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000368 // else we let the SkDraw call our drawPath()
bsalomon6ade6dd2016-09-12 12:07:17 -0700369 if (!isHairline || paint.getPathEffect() || paint.getMaskFilter() ||
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500370 (paint.isAntiAlias() && needs_antialiasing(mode, count, pts, *draw.fMatrix))) {
Mike Reed99330ba2017-02-22 11:01:08 -0500371 draw.drawPoints(mode, count, pts, paint, this);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000372 return;
373 }
374
bsalomon6ade6dd2016-09-12 12:07:17 -0700375 GrPrimitiveType primitiveType = gPointMode2PrimitiveType[mode];
376
377 const SkMatrix* viewMatrix = draw.fMatrix;
378#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
379 // This offsetting in device space matches the expectations of the Android framework for non-AA
380 // points and lines.
381 SkMatrix tempMatrix;
382 if (GrIsPrimTypeLines(primitiveType) || kPoints_GrPrimitiveType == primitiveType) {
383 tempMatrix = *viewMatrix;
384 static const SkScalar kOffset = 0.063f; // Just greater than 1/16.
385 tempMatrix.postTranslate(kOffset, kOffset);
386 viewMatrix = &tempMatrix;
387 }
388#endif
389
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000390 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400391 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *viewMatrix,
392 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700393 return;
394 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000395
Brian Osman11052242016-10-27 14:47:55 -0400396 fRenderTargetContext->drawVertices(fClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500397 std::move(grPaint),
Brian Osman11052242016-10-27 14:47:55 -0400398 *viewMatrix,
399 primitiveType,
400 SkToS32(count),
401 (SkPoint*)pts,
402 nullptr,
403 nullptr,
404 nullptr,
405 0);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000406}
407
408///////////////////////////////////////////////////////////////////////////////
409
robertphillipsff55b492015-11-24 07:56:59 -0800410void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800411 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500412 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRect", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800413 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000414
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000415
bsalomona7d85ba2016-07-06 11:54:59 -0700416 // A couple reasons we might need to call drawPath.
417 if (paint.getMaskFilter() || paint.getPathEffect()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000418 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700419 path.setIsVolatile(true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000420 path.addRect(rect);
Hal Canary144caf52016-11-07 17:57:18 -0500421 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillipsff55b492015-11-24 07:56:59 -0800422 fClip, path, paint,
423 *draw.fMatrix, nullptr,
Mike Reedfa24d342017-02-22 15:21:35 -0500424 this->devClipBounds(draw), true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000425 return;
426 }
427
428 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400429 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
430 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700431 return;
432 }
Mike Klein744fb732014-06-23 15:13:26 -0400433
bsalomon6663acf2016-05-10 09:14:17 -0700434 GrStyle style(paint);
Brian Salomon82f44312017-01-11 13:42:54 -0500435 fRenderTargetContext->drawRect(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
436 *draw.fMatrix, rect, &style);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000437}
438
439///////////////////////////////////////////////////////////////////////////////
440
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500441void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800442 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500443 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRRect", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800444 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000445
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000446 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400447 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
448 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700449 return;
450 }
Mike Klein744fb732014-06-23 15:13:26 -0400451
Robert Phillipsa29a9562016-10-20 09:40:55 -0400452 SkMaskFilter* mf = paint.getMaskFilter();
453 if (mf && mf->asFragmentProcessor(nullptr, nullptr, *draw.fMatrix)) {
454 mf = nullptr; // already handled in SkPaintToGrPaint
455 }
456
bsalomon6663acf2016-05-10 09:14:17 -0700457 GrStyle style(paint);
Robert Phillipsa29a9562016-10-20 09:40:55 -0400458 if (mf) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000459 // try to hit the fast path for drawing filtered round rects
460
461 SkRRect devRRect;
robertphillips9aff85a2016-08-05 07:51:29 -0700462 if (rrect.transform(*draw.fMatrix, &devRRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000463 if (devRRect.allCornersCircular()) {
464 SkRect maskRect;
Mike Reedfa24d342017-02-22 15:21:35 -0500465 if (mf->canFilterMaskGPU(devRRect, this->devClipBounds(draw),
Robert Phillipsa29a9562016-10-20 09:40:55 -0400466 *draw.fMatrix, &maskRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000467 SkIRect finalIRect;
468 maskRect.roundOut(&finalIRect);
reed1e7f5e72016-04-27 07:49:17 -0700469 if (draw.fRC->quickReject(finalIRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000470 // clipped out
471 return;
472 }
Hal Canary144caf52016-11-07 17:57:18 -0500473 if (mf->directFilterRRectMaskGPU(fContext.get(), fRenderTargetContext.get(),
Brian Salomon82f44312017-01-11 13:42:54 -0500474 std::move(grPaint), fClip, *draw.fMatrix,
Hal Canary144caf52016-11-07 17:57:18 -0500475 style.strokeRec(), rrect, devRRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000476 return;
477 }
478 }
479
480 }
481 }
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000482 }
483
Robert Phillipsa29a9562016-10-20 09:40:55 -0400484 if (mf || style.pathEffect()) {
robertphillipsff55b492015-11-24 07:56:59 -0800485 // The only mask filter the native rrect drawing code could've handle was taken
486 // care of above.
487 // A path effect will presumably transform this rrect into something else.
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000488 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700489 path.setIsVolatile(true);
robertphillips9aff85a2016-08-05 07:51:29 -0700490 path.addRRect(rrect);
Hal Canary144caf52016-11-07 17:57:18 -0500491 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillipsff55b492015-11-24 07:56:59 -0800492 fClip, path, paint,
493 *draw.fMatrix, nullptr,
Mike Reedfa24d342017-02-22 15:21:35 -0500494 this->devClipBounds(draw), true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000495 return;
496 }
Mike Klein744fb732014-06-23 15:13:26 -0400497
bsalomon6663acf2016-05-10 09:14:17 -0700498 SkASSERT(!style.pathEffect());
robertphillips514450c2015-11-24 05:36:02 -0800499
Brian Salomon82f44312017-01-11 13:42:54 -0500500 fRenderTargetContext->drawRRect(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
501 *draw.fMatrix, rrect, style);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000502}
503
robertphillipsd7706102016-02-25 09:28:08 -0800504
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000505void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
joshualitt5531d512014-12-17 15:50:11 -0800506 const SkRRect& inner, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800507 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500508 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawDRRect", fContext.get());
robertphillips0e7029e2015-11-30 05:45:06 -0800509 CHECK_SHOULD_DRAW(draw);
510
robertphillipsd7706102016-02-25 09:28:08 -0800511 if (outer.isEmpty()) {
512 return;
513 }
514
515 if (inner.isEmpty()) {
516 return this->drawRRect(draw, outer, paint);
517 }
518
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000519 SkStrokeRec stroke(paint);
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000520
robertphillips0e7029e2015-11-30 05:45:06 -0800521 if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
robertphillips00095892016-02-29 13:50:40 -0800522 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400523 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
brianosman1638c0d2016-07-25 05:12:53 -0700524 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700525 return;
526 }
robertphillips00095892016-02-29 13:50:40 -0800527
Brian Salomon82f44312017-01-11 13:42:54 -0500528 fRenderTargetContext->drawDRRect(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500529 *draw.fMatrix, outer, inner);
robertphillips00095892016-02-29 13:50:40 -0800530 return;
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000531 }
532
533 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700534 path.setIsVolatile(true);
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000535 path.addRRect(outer);
536 path.addRRect(inner);
537 path.setFillType(SkPath::kEvenOdd_FillType);
538
Hal Canary144caf52016-11-07 17:57:18 -0500539 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillips0e7029e2015-11-30 05:45:06 -0800540 fClip, path, paint,
541 *draw.fMatrix, nullptr,
Mike Reedfa24d342017-02-22 15:21:35 -0500542 this->devClipBounds(draw), true);
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000543}
544
545
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000546/////////////////////////////////////////////////////////////////////////////
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000547
msarettcc319b92016-08-25 18:07:18 -0700548void SkGpuDevice::drawRegion(const SkDraw& draw, const SkRegion& region, const SkPaint& paint) {
549 if (paint.getMaskFilter()) {
550 SkPath path;
551 region.getBoundaryPath(&path);
552 return this->drawPath(draw, path, paint, nullptr, false);
553 }
554
555 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400556 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
557 &grPaint)) {
msarettcc319b92016-08-25 18:07:18 -0700558 return;
559 }
560
Brian Salomon82f44312017-01-11 13:42:54 -0500561 fRenderTargetContext->drawRegion(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
562 *draw.fMatrix, region, GrStyle(paint));
msarettcc319b92016-08-25 18:07:18 -0700563}
564
robertphillips514450c2015-11-24 05:36:02 -0800565void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800566 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500567 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawOval", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800568 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000569
robertphillips514450c2015-11-24 05:36:02 -0800570 // Presumably the path effect warps this to something other than an oval
571 if (paint.getPathEffect()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000572 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700573 path.setIsVolatile(true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000574 path.addOval(oval);
halcanary96fcdcc2015-08-27 07:41:13 -0700575 this->drawPath(draw, path, paint, nullptr, true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000576 return;
herb11a7f7f2015-11-24 12:41:00 -0800577 }
578
robertphillips514450c2015-11-24 05:36:02 -0800579 if (paint.getMaskFilter()) {
580 // The RRect path can handle special case blurring
581 SkRRect rr = SkRRect::MakeOval(oval);
582 return this->drawRRect(draw, rr, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000583 }
584
585 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400586 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
587 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700588 return;
589 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000590
Brian Salomon82f44312017-01-11 13:42:54 -0500591 fRenderTargetContext->drawOval(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
592 *draw.fMatrix, oval, GrStyle(paint));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000593}
594
bsalomon4f3a0ca2016-08-22 13:14:26 -0700595void SkGpuDevice::drawArc(const SkDraw& draw, const SkRect& oval, SkScalar startAngle,
596 SkScalar sweepAngle, bool useCenter, const SkPaint& paint) {
597 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500598 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawArc", fContext.get());
bsalomon4f3a0ca2016-08-22 13:14:26 -0700599 CHECK_SHOULD_DRAW(draw);
600
601 if (paint.getMaskFilter()) {
602 this->INHERITED::drawArc(draw, oval, startAngle, sweepAngle, useCenter, paint);
603 return;
604 }
605 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400606 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
607 &grPaint)) {
bsalomon4f3a0ca2016-08-22 13:14:26 -0700608 return;
609 }
610
Brian Salomon82f44312017-01-11 13:42:54 -0500611 fRenderTargetContext->drawArc(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
612 *draw.fMatrix, oval, startAngle, sweepAngle, useCenter,
613 GrStyle(paint));
bsalomon4f3a0ca2016-08-22 13:14:26 -0700614}
615
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000616#include "SkMaskFilter.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000617
618///////////////////////////////////////////////////////////////////////////////
robertphillips0851d2d2016-06-02 05:21:34 -0700619void SkGpuDevice::drawStrokedLine(const SkPoint points[2],
620 const SkDraw& draw,
621 const SkPaint& origPaint) {
622 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500623 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawStrokedLine", fContext.get());
robertphillips0851d2d2016-06-02 05:21:34 -0700624 CHECK_SHOULD_DRAW(draw);
625
Brian Osman11052242016-10-27 14:47:55 -0400626 // Adding support for round capping would require a
627 // GrRenderTargetContext::fillRRectWithLocalMatrix entry point
robertphillips0851d2d2016-06-02 05:21:34 -0700628 SkASSERT(SkPaint::kRound_Cap != origPaint.getStrokeCap());
629 SkASSERT(SkPaint::kStroke_Style == origPaint.getStyle());
630 SkASSERT(!origPaint.getPathEffect());
631 SkASSERT(!origPaint.getMaskFilter());
632
633 const SkScalar halfWidth = 0.5f * origPaint.getStrokeWidth();
634 SkASSERT(halfWidth > 0);
635
636 SkVector v = points[1] - points[0];
637
638 SkScalar length = SkPoint::Normalize(&v);
639 if (!length) {
640 v.fX = 1.0f;
641 v.fY = 0.0f;
642 }
643
644 SkPaint newPaint(origPaint);
645 newPaint.setStyle(SkPaint::kFill_Style);
646
647 SkScalar xtraLength = 0.0f;
648 if (SkPaint::kButt_Cap != origPaint.getStrokeCap()) {
649 xtraLength = halfWidth;
650 }
651
652 SkPoint mid = points[0] + points[1];
653 mid.scale(0.5f);
654
655 SkRect rect = SkRect::MakeLTRB(mid.fX-halfWidth, mid.fY - 0.5f*length - xtraLength,
656 mid.fX+halfWidth, mid.fY + 0.5f*length + xtraLength);
657 SkMatrix m;
658 m.setSinCos(v.fX, -v.fY, mid.fX, mid.fY);
659
660 SkMatrix local = m;
661
662 m.postConcat(*draw.fMatrix);
663
664 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400665 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), newPaint, m, &grPaint)) {
robertphillips0851d2d2016-06-02 05:21:34 -0700666 return;
667 }
668
Brian Salomon82f44312017-01-11 13:42:54 -0500669 fRenderTargetContext->fillRectWithLocalMatrix(
670 fClip, std::move(grPaint), GrBoolToAA(newPaint.isAntiAlias()), m, rect, local);
robertphillips0851d2d2016-06-02 05:21:34 -0700671}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000672
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000673void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
674 const SkPaint& paint, const SkMatrix* prePathMatrix,
675 bool pathIsMutable) {
joshualittce894002016-01-11 13:29:31 -0800676 ASSERT_SINGLE_OWNER
robertphillipsff55b492015-11-24 07:56:59 -0800677 if (!origSrcPath.isInverseFillType() && !paint.getPathEffect() && !prePathMatrix) {
robertphillips0851d2d2016-06-02 05:21:34 -0700678 SkPoint points[2];
679 if (SkPaint::kStroke_Style == paint.getStyle() && paint.getStrokeWidth() > 0 &&
680 !paint.getMaskFilter() && SkPaint::kRound_Cap != paint.getStrokeCap() &&
681 draw.fMatrix->preservesRightAngles() && origSrcPath.isLine(points)) {
682 // Path-based stroking looks better for thin rects
683 SkScalar strokeWidth = draw.fMatrix->getMaxScale() * paint.getStrokeWidth();
robertphillipsf2204c92016-06-02 10:57:59 -0700684 if (strokeWidth >= 1.0f) {
Brian Salomon09d994e2016-12-21 11:14:46 -0500685 // Round capping support is currently disabled b.c. it would require a RRect
686 // GrDrawOp that takes a localMatrix.
robertphillips0851d2d2016-06-02 05:21:34 -0700687 this->drawStrokedLine(points, draw, paint);
688 return;
689 }
690 }
robertphillipsff55b492015-11-24 07:56:59 -0800691 bool isClosed;
692 SkRect rect;
693 if (origSrcPath.isRect(&rect, &isClosed) && isClosed) {
694 this->drawRect(draw, rect, paint);
695 return;
696 }
697 if (origSrcPath.isOval(&rect)) {
698 this->drawOval(draw, rect, paint);
699 return;
700 }
701 SkRRect rrect;
702 if (origSrcPath.isRRect(&rrect)) {
703 this->drawRRect(draw, rrect, paint);
704 return;
705 }
706 }
707
joshualitt5531d512014-12-17 15:50:11 -0800708 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -0500709 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPath", fContext.get());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000710
Hal Canary144caf52016-11-07 17:57:18 -0500711 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillipsccb1b572015-05-27 11:02:55 -0700712 fClip, origSrcPath, paint,
713 *draw.fMatrix, prePathMatrix,
Mike Reedfa24d342017-02-22 15:21:35 -0500714 this->devClipBounds(draw), pathIsMutable);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000715}
716
717static const int kBmpSmallTileSize = 1 << 10;
718
719static inline int get_tile_count(const SkIRect& srcRect, int tileSize) {
720 int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1;
721 int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1;
722 return tilesX * tilesY;
723}
724
reed85d91782015-09-10 14:33:38 -0700725static int determine_tile_size(const SkIRect& src, int maxTileSize) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000726 if (maxTileSize <= kBmpSmallTileSize) {
727 return maxTileSize;
728 }
729
730 size_t maxTileTotalTileSize = get_tile_count(src, maxTileSize);
731 size_t smallTotalTileSize = get_tile_count(src, kBmpSmallTileSize);
732
733 maxTileTotalTileSize *= maxTileSize * maxTileSize;
734 smallTotalTileSize *= kBmpSmallTileSize * kBmpSmallTileSize;
735
736 if (maxTileTotalTileSize > 2 * smallTotalTileSize) {
737 return kBmpSmallTileSize;
738 } else {
739 return maxTileSize;
740 }
741}
742
743// Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
744// pixels from the bitmap are necessary.
robertphillipse5768742016-05-13 11:20:46 -0700745static void determine_clipped_src_rect(int width, int height,
joshualitt570d2f82015-02-25 13:19:48 -0800746 const GrClip& clip,
joshualitt5531d512014-12-17 15:50:11 -0800747 const SkMatrix& viewMatrix,
bsalomone553b642016-08-17 09:02:09 -0700748 const SkMatrix& srcToDstRect,
reed85d91782015-09-10 14:33:38 -0700749 const SkISize& imageSize,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000750 const SkRect* srcRectPtr,
751 SkIRect* clippedSrcIRect) {
robertphillipse5768742016-05-13 11:20:46 -0700752 clip.getConservativeBounds(width, height, clippedSrcIRect, nullptr);
bsalomone553b642016-08-17 09:02:09 -0700753 SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect);
754 if (!inv.invert(&inv)) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000755 clippedSrcIRect->setEmpty();
756 return;
757 }
758 SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
759 inv.mapRect(&clippedSrcRect);
bsalomon49f085d2014-09-05 13:34:00 -0700760 if (srcRectPtr) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000761 if (!clippedSrcRect.intersect(*srcRectPtr)) {
762 clippedSrcIRect->setEmpty();
763 return;
764 }
765 }
766 clippedSrcRect.roundOut(clippedSrcIRect);
reed85d91782015-09-10 14:33:38 -0700767 SkIRect bmpBounds = SkIRect::MakeSize(imageSize);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000768 if (!clippedSrcIRect->intersect(bmpBounds)) {
769 clippedSrcIRect->setEmpty();
770 }
771}
772
reed85d91782015-09-10 14:33:38 -0700773bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect,
774 const SkMatrix& viewMatrix,
bsalomone553b642016-08-17 09:02:09 -0700775 const SkMatrix& srcToDstRect,
Brian Salomon514baff2016-11-17 15:17:07 -0500776 const GrSamplerParams& params,
reed85d91782015-09-10 14:33:38 -0700777 const SkRect* srcRectPtr,
778 int maxTileSize,
779 int* tileSize,
780 SkIRect* clippedSubset) const {
joshualittce894002016-01-11 13:29:31 -0800781 ASSERT_SINGLE_OWNER
reed85d91782015-09-10 14:33:38 -0700782 // if it's larger than the max tile size, then we have no choice but tiling.
783 if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) {
Brian Osman11052242016-10-27 14:47:55 -0400784 determine_clipped_src_rect(fRenderTargetContext->width(), fRenderTargetContext->height(),
785 fClip, viewMatrix, srcToDstRect, imageRect.size(), srcRectPtr,
786 clippedSubset);
reed85d91782015-09-10 14:33:38 -0700787 *tileSize = determine_tile_size(*clippedSubset, maxTileSize);
788 return true;
789 }
790
bsalomon1a1d0b82015-10-16 07:49:42 -0700791 // If the image would only produce 4 tiles of the smaller size, don't bother tiling it.
reed85d91782015-09-10 14:33:38 -0700792 const size_t area = imageRect.width() * imageRect.height();
793 if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
794 return false;
795 }
796
reed85d91782015-09-10 14:33:38 -0700797 // At this point we know we could do the draw by uploading the entire bitmap
798 // as a texture. However, if the texture would be large compared to the
799 // cache size and we don't require most of it for this draw then tile to
800 // reduce the amount of upload and cache spill.
801
802 // assumption here is that sw bitmap size is a good proxy for its size as
803 // a texture
804 size_t bmpSize = area * sizeof(SkPMColor); // assume 32bit pixels
805 size_t cacheSize;
806 fContext->getResourceCacheLimits(nullptr, &cacheSize);
807 if (bmpSize < cacheSize / 2) {
808 return false;
809 }
810
bsalomon1a1d0b82015-10-16 07:49:42 -0700811 // Figure out how much of the src we will need based on the src rect and clipping. Reject if
812 // tiling memory savings would be < 50%.
Brian Osman11052242016-10-27 14:47:55 -0400813 determine_clipped_src_rect(fRenderTargetContext->width(), fRenderTargetContext->height(), fClip,
814 viewMatrix, srcToDstRect, imageRect.size(), srcRectPtr,
815 clippedSubset);
reed85d91782015-09-10 14:33:38 -0700816 *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
817 size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) *
Brian Osmand05cdc32017-02-06 13:24:47 -0500818 kBmpSmallTileSize * kBmpSmallTileSize *
819 sizeof(SkPMColor); // assume 32bit pixels;
reed85d91782015-09-10 14:33:38 -0700820
Brian Osmand05cdc32017-02-06 13:24:47 -0500821 return usedTileBytes * 2 < bmpSize;
reed85d91782015-09-10 14:33:38 -0700822}
823
reed85d91782015-09-10 14:33:38 -0700824bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr,
825 SkCanvas::SrcRectConstraint constraint, SkFilterQuality quality,
bsalomone553b642016-08-17 09:02:09 -0700826 const SkMatrix& viewMatrix,
827 const SkMatrix& srcToDstRect) const {
joshualittce894002016-01-11 13:29:31 -0800828 ASSERT_SINGLE_OWNER
reed85d91782015-09-10 14:33:38 -0700829 // if image is explictly texture backed then just use the texture
Robert Phillips6de99042017-01-31 11:31:39 -0500830 if (image->isTextureBacked()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000831 return false;
832 }
833
Brian Salomon514baff2016-11-17 15:17:07 -0500834 GrSamplerParams params;
reed85d91782015-09-10 14:33:38 -0700835 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -0500836 GrSamplerParams::FilterMode textureFilterMode =
bsalomone553b642016-08-17 09:02:09 -0700837 GrSkFilterQualityToGrFilterMode(quality, viewMatrix, srcToDstRect, &doBicubic);
reed85d91782015-09-10 14:33:38 -0700838
839 int tileFilterPad;
840 if (doBicubic) {
841 tileFilterPad = GrBicubicEffect::kFilterTexelPad;
Brian Salomon514baff2016-11-17 15:17:07 -0500842 } else if (GrSamplerParams::kNone_FilterMode == textureFilterMode) {
reed85d91782015-09-10 14:33:38 -0700843 tileFilterPad = 0;
844 } else {
845 tileFilterPad = 1;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000846 }
reed85d91782015-09-10 14:33:38 -0700847 params.setFilterMode(textureFilterMode);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000848
bsalomon8c07b7a2015-11-02 11:36:52 -0800849 int maxTileSize = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000850
reed85d91782015-09-10 14:33:38 -0700851 // these are output, which we safely ignore, as we just want to know the predicate
852 int outTileSize;
853 SkIRect outClippedSrcRect;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000854
bsalomone553b642016-08-17 09:02:09 -0700855 return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix, srcToDstRect,
856 params, srcRectPtr, maxTileSize, &outTileSize,
857 &outClippedSrcRect);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000858}
859
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +0000860void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000861 const SkBitmap& bitmap,
862 const SkMatrix& m,
863 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800864 ASSERT_SINGLE_OWNER
bsalomonb1b01992015-11-18 10:56:08 -0800865 CHECK_SHOULD_DRAW(origDraw);
bsalomonb1b01992015-11-18 10:56:08 -0800866 SkMatrix viewMatrix;
867 viewMatrix.setConcat(*origDraw.fMatrix, m);
reedc7ec7c92016-07-25 08:29:10 -0700868
bsalomonb1b01992015-11-18 10:56:08 -0800869 int maxTileSize = fContext->caps()->maxTileSize();
870
871 // The tile code path doesn't currently support AA, so if the paint asked for aa and we could
872 // draw untiled, then we bypass checking for tiling purely for optimization reasons.
Brian Osman11052242016-10-27 14:47:55 -0400873 bool drawAA = !fRenderTargetContext->isUnifiedMultisampled() &&
bsalomonb1b01992015-11-18 10:56:08 -0800874 paint.isAntiAlias() &&
875 bitmap.width() <= maxTileSize &&
876 bitmap.height() <= maxTileSize;
877
878 bool skipTileCheck = drawAA || paint.getMaskFilter();
879
880 if (!skipTileCheck) {
881 SkRect srcRect = SkRect::MakeIWH(bitmap.width(), bitmap.height());
882 int tileSize;
883 SkIRect clippedSrcRect;
884
Brian Salomon514baff2016-11-17 15:17:07 -0500885 GrSamplerParams params;
bsalomonb1b01992015-11-18 10:56:08 -0800886 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -0500887 GrSamplerParams::FilterMode textureFilterMode =
bsalomonb1b01992015-11-18 10:56:08 -0800888 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix, SkMatrix::I(),
889 &doBicubic);
890
891 int tileFilterPad;
892
893 if (doBicubic) {
894 tileFilterPad = GrBicubicEffect::kFilterTexelPad;
Brian Salomon514baff2016-11-17 15:17:07 -0500895 } else if (GrSamplerParams::kNone_FilterMode == textureFilterMode) {
bsalomonb1b01992015-11-18 10:56:08 -0800896 tileFilterPad = 0;
897 } else {
898 tileFilterPad = 1;
899 }
900 params.setFilterMode(textureFilterMode);
901
902 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
bsalomone553b642016-08-17 09:02:09 -0700903 if (this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), viewMatrix,
904 SkMatrix::I(), params, &srcRect, maxTileSizeForFilter,
905 &tileSize, &clippedSrcRect)) {
906 this->drawTiledBitmap(bitmap, viewMatrix, SkMatrix::I(), srcRect, clippedSrcRect,
907 params, paint, SkCanvas::kStrict_SrcRectConstraint, tileSize,
908 doBicubic);
bsalomonb1b01992015-11-18 10:56:08 -0800909 return;
910 }
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +0000911 }
Hal Canary144caf52016-11-07 17:57:18 -0500912 GrBitmapTextureMaker maker(fContext.get(), bitmap);
bsalomonf1ecd212015-12-09 17:06:02 -0800913 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kStrict_SrcRectConstraint,
914 viewMatrix, fClip, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000915}
916
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000917// This method outsets 'iRect' by 'outset' all around and then clamps its extents to
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000918// 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner
919// of 'iRect' for all possible outsets/clamps.
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000920static inline void clamped_outset_with_offset(SkIRect* iRect,
921 int outset,
922 SkPoint* offset,
923 const SkIRect& clamp) {
924 iRect->outset(outset, outset);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000925
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000926 int leftClampDelta = clamp.fLeft - iRect->fLeft;
927 if (leftClampDelta > 0) {
928 offset->fX -= outset - leftClampDelta;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000929 iRect->fLeft = clamp.fLeft;
930 } else {
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000931 offset->fX -= outset;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000932 }
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000933
934 int topClampDelta = clamp.fTop - iRect->fTop;
935 if (topClampDelta > 0) {
936 offset->fY -= outset - topClampDelta;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000937 iRect->fTop = clamp.fTop;
938 } else {
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000939 offset->fY -= outset;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000940 }
941
942 if (iRect->fRight > clamp.fRight) {
943 iRect->fRight = clamp.fRight;
944 }
945 if (iRect->fBottom > clamp.fBottom) {
946 iRect->fBottom = clamp.fBottom;
947 }
948}
949
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000950// Break 'bitmap' into several tiles to draw it since it has already
951// been determined to be too large to fit in VRAM
952void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
joshualitt5531d512014-12-17 15:50:11 -0800953 const SkMatrix& viewMatrix,
bsalomone553b642016-08-17 09:02:09 -0700954 const SkMatrix& dstMatrix,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000955 const SkRect& srcRect,
956 const SkIRect& clippedSrcIRect,
Brian Salomon514baff2016-11-17 15:17:07 -0500957 const GrSamplerParams& params,
bsalomonc55271f2015-11-09 11:55:57 -0800958 const SkPaint& origPaint,
reeda5517e22015-07-14 10:54:12 -0700959 SkCanvas::SrcRectConstraint constraint,
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000960 int tileSize,
961 bool bicubic) {
joshualittce894002016-01-11 13:29:31 -0800962 ASSERT_SINGLE_OWNER
ericrk369e9372016-02-05 15:32:36 -0800963
ericrk983294f2016-04-18 09:14:00 -0700964 // This is the funnel for all paths that draw tiled bitmaps/images. Log histogram entries.
ericrk369e9372016-02-05 15:32:36 -0800965 SK_HISTOGRAM_BOOLEAN("DrawTiled", true);
ericrk983294f2016-04-18 09:14:00 -0700966 LogDrawScaleFactor(viewMatrix, origPaint.getFilterQuality());
ericrk369e9372016-02-05 15:32:36 -0800967
commit-bot@chromium.org9d5e3f12014-05-01 21:23:19 +0000968 // The following pixel lock is technically redundant, but it is desirable
969 // to lock outside of the tile loop to prevent redecoding the whole image
970 // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that
971 // is larger than the limit of the discardable memory pool.
972 SkAutoLockPixels alp(bitmap);
bsalomonc55271f2015-11-09 11:55:57 -0800973
974 const SkPaint* paint = &origPaint;
975 SkPaint tempPaint;
Brian Osman11052242016-10-27 14:47:55 -0400976 if (origPaint.isAntiAlias() && !fRenderTargetContext->isUnifiedMultisampled()) {
bsalomonc55271f2015-11-09 11:55:57 -0800977 // Drop antialiasing to avoid seams at tile boundaries.
978 tempPaint = origPaint;
979 tempPaint.setAntiAlias(false);
980 paint = &tempPaint;
981 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000982 SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
983
984 int nx = bitmap.width() / tileSize;
985 int ny = bitmap.height() / tileSize;
986 for (int x = 0; x <= nx; x++) {
987 for (int y = 0; y <= ny; y++) {
988 SkRect tileR;
989 tileR.set(SkIntToScalar(x * tileSize),
990 SkIntToScalar(y * tileSize),
991 SkIntToScalar((x + 1) * tileSize),
992 SkIntToScalar((y + 1) * tileSize));
993
994 if (!SkRect::Intersects(tileR, clippedSrcRect)) {
995 continue;
996 }
997
998 if (!tileR.intersect(srcRect)) {
999 continue;
1000 }
1001
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001002 SkIRect iTileR;
1003 tileR.roundOut(&iTileR);
bsalomone553b642016-08-17 09:02:09 -07001004 SkVector offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
1005 SkIntToScalar(iTileR.fTop));
Brian Osmana950a862017-02-06 16:48:57 -05001006 SkRect rectToDraw = tileR;
bsalomone553b642016-08-17 09:02:09 -07001007 dstMatrix.mapRect(&rectToDraw);
Brian Salomon514baff2016-11-17 15:17:07 -05001008 if (GrSamplerParams::kNone_FilterMode != params.filterMode() || bicubic) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001009 SkIRect iClampRect;
1010
reeda5517e22015-07-14 10:54:12 -07001011 if (SkCanvas::kFast_SrcRectConstraint == constraint) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001012 // In bleed mode we want to always expand the tile on all edges
1013 // but stay within the bitmap bounds
1014 iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1015 } else {
1016 // In texture-domain/clamp mode we only want to expand the
1017 // tile on edges interior to "srcRect" (i.e., we want to
1018 // not bleed across the original clamped edges)
1019 srcRect.roundOut(&iClampRect);
1020 }
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +00001021 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1;
1022 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001023 }
1024
bsalomone553b642016-08-17 09:02:09 -07001025 SkBitmap tmpB;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001026 if (bitmap.extractSubset(&tmpB, iTileR)) {
1027 // now offset it to make it "local" to our tmp bitmap
1028 tileR.offset(-offset.fX, -offset.fY);
bsalomonb1b01992015-11-18 10:56:08 -08001029 // de-optimized this determination
1030 bool needsTextureDomain = true;
bsalomone553b642016-08-17 09:02:09 -07001031 this->drawBitmapTile(tmpB,
1032 viewMatrix,
1033 rectToDraw,
1034 tileR,
Robert Phillipse14d3052017-02-15 13:18:21 -05001035 params,
bsalomone553b642016-08-17 09:02:09 -07001036 *paint,
1037 constraint,
1038 bicubic,
1039 needsTextureDomain);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001040 }
1041 }
1042 }
1043}
1044
bsalomone553b642016-08-17 09:02:09 -07001045void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
1046 const SkMatrix& viewMatrix,
1047 const SkRect& dstRect,
1048 const SkRect& srcRect,
Brian Salomon514baff2016-11-17 15:17:07 -05001049 const GrSamplerParams& params,
bsalomone553b642016-08-17 09:02:09 -07001050 const SkPaint& paint,
1051 SkCanvas::SrcRectConstraint constraint,
1052 bool bicubic,
1053 bool needsTextureDomain) {
bsalomon9c586542015-11-02 12:33:21 -08001054 // We should have already handled bitmaps larger than the max texture size.
1055 SkASSERT(bitmap.width() <= fContext->caps()->maxTextureSize() &&
1056 bitmap.height() <= fContext->caps()->maxTextureSize());
reedc7ec7c92016-07-25 08:29:10 -07001057 // We should be respecting the max tile size by the time we get here.
1058 SkASSERT(bitmap.width() <= fContext->caps()->maxTileSize() &&
1059 bitmap.height() <= fContext->caps()->maxTileSize());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001060
Robert Phillipse14d3052017-02-15 13:18:21 -05001061 SkASSERT(SkShader::kClamp_TileMode == params.getTileModeX() &&
1062 SkShader::kClamp_TileMode == params.getTileModeY());
1063
Robert Phillips67c18d62017-01-20 12:44:06 -05001064 sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext.get(), bitmap,
Robert Phillipse14d3052017-02-15 13:18:21 -05001065 params, nullptr);
halcanary96fcdcc2015-08-27 07:41:13 -07001066 if (nullptr == texture) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001067 return;
1068 }
brianosman500bb3e2016-07-22 10:33:07 -07001069 sk_sp<GrColorSpaceXform> colorSpaceXform =
Brian Osman11052242016-10-27 14:47:55 -04001070 GrColorSpaceXform::Make(bitmap.colorSpace(), fRenderTargetContext->getColorSpace());
bsalomone553b642016-08-17 09:02:09 -07001071
bsalomone553b642016-08-17 09:02:09 -07001072 // Compute a matrix that maps the rect we will draw to the src rect.
Robert Phillipse14d3052017-02-15 13:18:21 -05001073 const SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect,
1074 SkMatrix::kFill_ScaleToFit);
joshualitt5f10b5c2015-07-09 10:24:35 -07001075
1076 // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
1077 // the rest from the SkPaint.
bungeman06ca8ec2016-06-09 08:01:03 -07001078 sk_sp<GrFragmentProcessor> fp;
joshualitt5f10b5c2015-07-09 10:24:35 -07001079
reeda5517e22015-07-14 10:54:12 -07001080 if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001081 // Use a constrained texture domain to avoid color bleeding
bsalomone553b642016-08-17 09:02:09 -07001082 SkRect domain;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001083 if (srcRect.width() > SK_Scalar1) {
Robert Phillipse98234f2017-01-09 14:23:59 -05001084 domain.fLeft = srcRect.fLeft + 0.5f;
1085 domain.fRight = srcRect.fRight - 0.5f;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001086 } else {
Robert Phillipse98234f2017-01-09 14:23:59 -05001087 domain.fLeft = domain.fRight = srcRect.centerX();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001088 }
1089 if (srcRect.height() > SK_Scalar1) {
Robert Phillipse98234f2017-01-09 14:23:59 -05001090 domain.fTop = srcRect.fTop + 0.5f;
1091 domain.fBottom = srcRect.fBottom - 0.5f;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001092 } else {
Robert Phillipse98234f2017-01-09 14:23:59 -05001093 domain.fTop = domain.fBottom = srcRect.centerY();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001094 }
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +00001095 if (bicubic) {
reedc7ec7c92016-07-25 08:29:10 -07001096 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix,
bsalomone553b642016-08-17 09:02:09 -07001097 domain);
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +00001098 } else {
reedc7ec7c92016-07-25 08:29:10 -07001099 fp = GrTextureDomainEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix,
bsalomone553b642016-08-17 09:02:09 -07001100 domain, GrTextureDomain::kClamp_Mode,
brianosman54f30c12016-07-18 10:53:52 -07001101 params.filterMode());
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +00001102 }
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +00001103 } else if (bicubic) {
Brian Salomon514baff2016-11-17 15:17:07 -05001104 SkASSERT(GrSamplerParams::kNone_FilterMode == params.filterMode());
commit-bot@chromium.orgbc91fd72013-12-10 12:53:39 +00001105 SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTileModeY() };
reedc7ec7c92016-07-25 08:29:10 -07001106 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix, tileModes);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001107 } else {
reedc7ec7c92016-07-25 08:29:10 -07001108 fp = GrSimpleTextureEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix, params);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001109 }
1110
joshualitt33a5fce2015-11-18 13:28:51 -08001111 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -04001112 if (!SkPaintToGrPaintWithTexture(this->context(), fRenderTargetContext.get(), paint, viewMatrix,
brianosman8fe485b2016-07-25 12:31:51 -07001113 std::move(fp), kAlpha_8_SkColorType == bitmap.colorType(),
1114 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -07001115 return;
1116 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001117
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001118 // Coverage-based AA would cause seams between tiles.
1119 GrAA aa = GrBoolToAA(paint.isAntiAlias() &&
1120 fRenderTargetContext->isStencilBufferMultisampled());
Brian Salomon82f44312017-01-11 13:42:54 -05001121 fRenderTargetContext->drawRect(fClip, std::move(grPaint), aa, viewMatrix, dstRect);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001122}
1123
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001124void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
1125 int left, int top, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001126 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -08001127 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001128 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSprite", fContext.get());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001129
robertphillips970587b2016-07-14 14:12:55 -07001130 if (fContext->abandoned()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001131 return;
1132 }
1133
Robert Phillipse14d3052017-02-15 13:18:21 -05001134 sk_sp<SkSpecialImage> srcImg = this->makeSpecial(bitmap);
1135 if (!srcImg) {
1136 return;
joshualitt5f5a8d72015-02-25 14:09:45 -08001137 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001138
robertphillips970587b2016-07-14 14:12:55 -07001139 this->drawSpecial(draw, srcImg.get(), left, top, paint);
1140}
1141
1142
Mike Kleine54c75f2016-10-13 14:18:09 -04001143void SkGpuDevice::drawSpecial(const SkDraw& draw,
robertphillips970587b2016-07-14 14:12:55 -07001144 SkSpecialImage* special1,
1145 int left, int top,
1146 const SkPaint& paint) {
robertphillips1b5f9682016-07-15 08:01:12 -07001147 ASSERT_SINGLE_OWNER
1148 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001149 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpecial", fContext.get());
robertphillips970587b2016-07-14 14:12:55 -07001150
1151 SkIPoint offset = { 0, 0 };
1152
1153 sk_sp<SkSpecialImage> result;
1154 if (paint.getImageFilter()) {
1155 result = this->filterTexture(draw, special1, left, top,
1156 &offset,
1157 paint.getImageFilter());
1158 if (!result) {
1159 return;
1160 }
1161 } else {
1162 result = sk_ref_sp(special1);
1163 }
1164
1165 SkASSERT(result->isTextureBacked());
Robert Phillips2c6d2bf2017-02-21 10:19:29 -05001166 sk_sp<GrTextureProxy> proxy = result->asTextureProxyRef(this->context());
Robert Phillips8e1c4e62017-02-19 12:27:01 -05001167 if (!proxy) {
Robert Phillips833dcf42016-11-18 08:44:13 -05001168 return;
1169 }
robertphillips970587b2016-07-14 14:12:55 -07001170
Robert Phillips8e1c4e62017-02-19 12:27:01 -05001171 const GrPixelConfig config = proxy->config();
1172
robertphillips970587b2016-07-14 14:12:55 -07001173 SkPaint tmpUnfiltered(paint);
1174 tmpUnfiltered.setImageFilter(nullptr);
1175
brianosman77320db2016-09-07 08:09:10 -07001176 sk_sp<GrColorSpaceXform> colorSpaceXform =
Brian Osman11052242016-10-27 14:47:55 -04001177 GrColorSpaceXform::Make(result->getColorSpace(), fRenderTargetContext->getColorSpace());
Robert Phillips2c6d2bf2017-02-21 10:19:29 -05001178
1179 sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(this->context(),
Robert Phillips8e1c4e62017-02-19 12:27:01 -05001180 std::move(proxy),
brianosman77320db2016-09-07 08:09:10 -07001181 std::move(colorSpaceXform),
brianosman54f30c12016-07-18 10:53:52 -07001182 SkMatrix::I()));
Robert Phillips8e1c4e62017-02-19 12:27:01 -05001183 if (GrPixelConfigIsAlphaOnly(config)) {
Brian Salomon22af73f2017-01-26 11:25:12 -05001184 fp = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
bsalomonf1b7a1d2015-09-28 06:26:28 -07001185 } else {
bungeman06ca8ec2016-06-09 08:01:03 -07001186 fp = GrFragmentProcessor::MulOutputByInputAlpha(std::move(fp));
bsalomonf1b7a1d2015-09-28 06:26:28 -07001187 }
Robert Phillips8e1c4e62017-02-19 12:27:01 -05001188
1189 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -04001190 if (!SkPaintToGrPaintReplaceShader(this->context(), fRenderTargetContext.get(), tmpUnfiltered,
brianosman8fe485b2016-07-25 12:31:51 -07001191 std::move(fp), &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -07001192 return;
1193 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001194
robertphillips970587b2016-07-14 14:12:55 -07001195 const SkIRect& subset = result->subset();
1196
Brian Salomon82f44312017-01-11 13:42:54 -05001197 fRenderTargetContext->fillRectToRect(
1198 fClip,
1199 std::move(grPaint),
1200 GrBoolToAA(paint.isAntiAlias()),
1201 SkMatrix::I(),
1202 SkRect::Make(SkIRect::MakeXYWH(
1203 left + offset.fX, top + offset.fY, subset.width(), subset.height())),
Robert Phillips67c18d62017-01-20 12:44:06 -05001204 SkRect::Make(subset));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001205}
1206
bsalomonb1b01992015-11-18 10:56:08 -08001207void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
1208 const SkRect* src, const SkRect& origDst,
reed562fe472015-07-28 07:35:14 -07001209 const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
joshualittce894002016-01-11 13:29:31 -08001210 ASSERT_SINGLE_OWNER
lsalzman973ed242016-01-14 13:06:41 -08001211 CHECK_SHOULD_DRAW(draw);
reedc7ec7c92016-07-25 08:29:10 -07001212
bsalomonb1b01992015-11-18 10:56:08 -08001213 // The src rect is inferred to be the bmp bounds if not provided. Otherwise, the src rect must
1214 // be clipped to the bmp bounds. To determine tiling parameters we need the filter mode which
1215 // in turn requires knowing the src-to-dst mapping. If the src was clipped to the bmp bounds
1216 // then we use the src-to-dst mapping to compute a new clipped dst rect.
1217 const SkRect* dst = &origDst;
1218 const SkRect bmpBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001219 // Compute matrix from the two rectangles
bsalomonb1b01992015-11-18 10:56:08 -08001220 if (!src) {
1221 src = &bmpBounds;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001222 }
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +00001223
bsalomonb1b01992015-11-18 10:56:08 -08001224 SkMatrix srcToDstMatrix;
1225 if (!srcToDstMatrix.setRectToRect(*src, *dst, SkMatrix::kFill_ScaleToFit)) {
1226 return;
1227 }
1228 SkRect tmpSrc, tmpDst;
1229 if (src != &bmpBounds) {
1230 if (!bmpBounds.contains(*src)) {
1231 tmpSrc = *src;
1232 if (!tmpSrc.intersect(bmpBounds)) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001233 return; // nothing to draw
1234 }
bsalomonb1b01992015-11-18 10:56:08 -08001235 src = &tmpSrc;
1236 srcToDstMatrix.mapRect(&tmpDst, *src);
1237 dst = &tmpDst;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001238 }
1239 }
1240
bsalomonb1b01992015-11-18 10:56:08 -08001241 int maxTileSize = fContext->caps()->maxTileSize();
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +00001242
bsalomonb1b01992015-11-18 10:56:08 -08001243 // The tile code path doesn't currently support AA, so if the paint asked for aa and we could
1244 // draw untiled, then we bypass checking for tiling purely for optimization reasons.
Brian Osman11052242016-10-27 14:47:55 -04001245 bool drawAA = !fRenderTargetContext->isUnifiedMultisampled() &&
bsalomonb1b01992015-11-18 10:56:08 -08001246 paint.isAntiAlias() &&
1247 bitmap.width() <= maxTileSize &&
1248 bitmap.height() <= maxTileSize;
1249
1250 bool skipTileCheck = drawAA || paint.getMaskFilter();
1251
1252 if (!skipTileCheck) {
1253 int tileSize;
1254 SkIRect clippedSrcRect;
1255
Brian Salomon514baff2016-11-17 15:17:07 -05001256 GrSamplerParams params;
bsalomonb1b01992015-11-18 10:56:08 -08001257 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -05001258 GrSamplerParams::FilterMode textureFilterMode =
bsalomonb1b01992015-11-18 10:56:08 -08001259 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMatrix, srcToDstMatrix,
1260 &doBicubic);
1261
1262 int tileFilterPad;
1263
1264 if (doBicubic) {
1265 tileFilterPad = GrBicubicEffect::kFilterTexelPad;
Brian Salomon514baff2016-11-17 15:17:07 -05001266 } else if (GrSamplerParams::kNone_FilterMode == textureFilterMode) {
bsalomonb1b01992015-11-18 10:56:08 -08001267 tileFilterPad = 0;
1268 } else {
1269 tileFilterPad = 1;
1270 }
1271 params.setFilterMode(textureFilterMode);
1272
1273 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
bsalomone553b642016-08-17 09:02:09 -07001274 if (this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), *draw.fMatrix,
1275 srcToDstMatrix, params, src, maxTileSizeForFilter, &tileSize,
1276 &clippedSrcRect)) {
1277 this->drawTiledBitmap(bitmap, *draw.fMatrix, srcToDstMatrix, *src, clippedSrcRect,
1278 params, paint, constraint, tileSize, doBicubic);
bsalomonb1b01992015-11-18 10:56:08 -08001279 return;
1280 }
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +00001281 }
Hal Canary144caf52016-11-07 17:57:18 -05001282 GrBitmapTextureMaker maker(fContext.get(), bitmap);
bsalomonf1ecd212015-12-09 17:06:02 -08001283 this->drawTextureProducer(&maker, src, dst, constraint, *draw.fMatrix, fClip, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001284}
1285
robertphillips6451a0c2016-07-18 08:31:31 -07001286sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) {
Robert Phillipse14d3052017-02-15 13:18:21 -05001287 // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's
1288 // semantics). Since this is cached we would have to bake the fit into the cache key though.
1289 sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(fContext.get(), bitmap);
1290 if (!proxy) {
robertphillips6451a0c2016-07-18 08:31:31 -07001291 return nullptr;
1292 }
1293
Robert Phillipse14d3052017-02-15 13:18:21 -05001294 const SkIRect rect = SkIRect::MakeWH(proxy->width(), proxy->height());
robertphillips6451a0c2016-07-18 08:31:31 -07001295
Robert Phillipse14d3052017-02-15 13:18:21 -05001296 // GrMakeCachedBitmapProxy creates a tight copy of 'bitmap' so we don't have to subset
1297 // the special image
1298 return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
1299 rect,
1300 bitmap.getGenerationID(),
1301 std::move(proxy),
1302 bitmap.refColorSpace(),
1303 &this->surfaceProps());
robertphillips6451a0c2016-07-18 08:31:31 -07001304}
1305
reede51c3562016-07-19 14:33:20 -07001306sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkImage* image) {
robertphillips6451a0c2016-07-18 08:31:31 -07001307 SkPixmap pm;
1308 if (image->isTextureBacked()) {
Robert Phillips6de99042017-01-31 11:31:39 -05001309 sk_sp<GrTextureProxy> proxy = as_IB(image)->asTextureProxyRef();
robertphillips6451a0c2016-07-18 08:31:31 -07001310
Robert Phillips6de99042017-01-31 11:31:39 -05001311 return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
1312 SkIRect::MakeWH(image->width(), image->height()),
1313 image->uniqueID(),
1314 std::move(proxy),
1315 as_IB(image)->onImageInfo().refColorSpace(),
1316 &this->surfaceProps());
robertphillips6451a0c2016-07-18 08:31:31 -07001317 } else if (image->peekPixels(&pm)) {
1318 SkBitmap bm;
1319
1320 bm.installPixels(pm);
1321 return this->makeSpecial(bm);
1322 } else {
1323 return nullptr;
1324 }
1325}
1326
1327sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
Robert Phillips63c67462017-02-15 14:19:01 -05001328 sk_sp<GrTextureProxy> proxy(this->accessRenderTargetContext()->asTextureProxyRef());
1329 if (!proxy) {
robertphillips04d62182016-07-15 12:21:33 -07001330 // When the device doesn't have a texture, we create a temporary texture.
1331 // TODO: we should actually only copy the portion of the source needed to apply the image
1332 // filter
Robert Phillips63c67462017-02-15 14:19:01 -05001333 proxy = GrSurfaceProxy::Copy(fContext.get(),
1334 this->accessRenderTargetContext()->asSurfaceProxy(),
1335 SkBudgeted::kYes);
1336 if (!proxy) {
robertphillips04d62182016-07-15 12:21:33 -07001337 return nullptr;
1338 }
robertphillips1b5f9682016-07-15 08:01:12 -07001339 }
1340
1341 const SkImageInfo ii = this->imageInfo();
1342 const SkIRect srcRect = SkIRect::MakeWH(ii.width(), ii.height());
1343
Robert Phillipse2f7d182016-12-15 09:23:05 -05001344 return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
1345 srcRect,
1346 kNeedNewImageUniqueID_SpecialImage,
Robert Phillips63c67462017-02-15 14:19:01 -05001347 std::move(proxy),
Robert Phillips70b49fd2017-01-13 11:21:36 -05001348 ii.refColorSpace(),
Robert Phillipse2f7d182016-12-15 09:23:05 -05001349 &this->surfaceProps());
robertphillips1b5f9682016-07-15 08:01:12 -07001350}
1351
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001352void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
robertphillips1b5f9682016-07-15 08:01:12 -07001353 int left, int top, const SkPaint& paint) {
reedcf5c8462016-07-20 12:28:40 -07001354 SkASSERT(!paint.getImageFilter());
1355
joshualittce894002016-01-11 13:29:31 -08001356 ASSERT_SINGLE_OWNER
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001357 // clear of the source device must occur before CHECK_SHOULD_DRAW
Hal Canary144caf52016-11-07 17:57:18 -05001358 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawDevice", fContext.get());
kkinnunen2e4414e2015-02-19 07:20:40 -08001359
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001360 // drawDevice is defined to be in device coords.
joshualitt5531d512014-12-17 15:50:11 -08001361 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001362
robertphillips1b5f9682016-07-15 08:01:12 -07001363 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
robertphillips6451a0c2016-07-18 08:31:31 -07001364 sk_sp<SkSpecialImage> srcImg(dev->snapSpecial());
robertphillips1b5f9682016-07-15 08:01:12 -07001365 if (!srcImg) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001366 return;
1367 }
1368
robertphillips1b5f9682016-07-15 08:01:12 -07001369 this->drawSpecial(draw, srcImg.get(), left, top, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001370}
1371
reeda85d4d02015-05-06 12:56:48 -07001372void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
1373 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001374 ASSERT_SINGLE_OWNER
bsalomon1cf6f9b2015-12-08 10:53:43 -08001375 SkMatrix viewMatrix = *draw.fMatrix;
1376 viewMatrix.preTranslate(x, y);
reed2d5b7142016-08-17 11:12:33 -07001377 uint32_t pinnedUniqueID;
1378 if (sk_sp<GrTexture> tex = as_IB(image)->refPinnedTexture(&pinnedUniqueID)) {
bsalomonc55271f2015-11-09 11:55:57 -08001379 CHECK_SHOULD_DRAW(draw);
brianosman5814b8a2016-08-18 06:43:03 -07001380 GrTextureAdjuster adjuster(tex.get(), image->alphaType(), image->bounds(), pinnedUniqueID,
reed2d5b7142016-08-17 11:12:33 -07001381 as_IB(image)->onImageInfo().colorSpace());
bsalomonf1ecd212015-12-09 17:06:02 -08001382 this->drawTextureProducer(&adjuster, nullptr, nullptr, SkCanvas::kFast_SrcRectConstraint,
1383 viewMatrix, fClip, paint);
bsalomonc55271f2015-11-09 11:55:57 -08001384 return;
reed85d91782015-09-10 14:33:38 -07001385 } else {
bsalomon1cf6f9b2015-12-08 10:53:43 -08001386 SkBitmap bm;
reed85d91782015-09-10 14:33:38 -07001387 if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstraint,
bsalomone553b642016-08-17 09:02:09 -07001388 paint.getFilterQuality(), *draw.fMatrix, SkMatrix::I())) {
reed85d91782015-09-10 14:33:38 -07001389 // only support tiling as bitmap at the moment, so force raster-version
Brian Osman61624f02016-12-09 14:51:59 -05001390 if (!as_IB(image)->getROPixels(&bm, fRenderTargetContext->getColorSpace())) {
reed85d91782015-09-10 14:33:38 -07001391 return;
1392 }
bsalomon1cf6f9b2015-12-08 10:53:43 -08001393 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
1394 } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
1395 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001396 GrImageTextureMaker maker(fContext.get(), cacher, image, SkImage::kAllow_CachingHint);
bsalomonf1ecd212015-12-09 17:06:02 -08001397 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kFast_SrcRectConstraint,
1398 viewMatrix, fClip, paint);
Brian Osman61624f02016-12-09 14:51:59 -05001399 } else if (as_IB(image)->getROPixels(&bm, fRenderTargetContext->getColorSpace())) {
bsalomon1cf6f9b2015-12-08 10:53:43 -08001400 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
reed85d91782015-09-10 14:33:38 -07001401 }
reeda85d4d02015-05-06 12:56:48 -07001402 }
1403}
1404
1405void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
reeda5517e22015-07-14 10:54:12 -07001406 const SkRect& dst, const SkPaint& paint,
1407 SkCanvas::SrcRectConstraint constraint) {
joshualittce894002016-01-11 13:29:31 -08001408 ASSERT_SINGLE_OWNER
reed2d5b7142016-08-17 11:12:33 -07001409 uint32_t pinnedUniqueID;
1410 if (sk_sp<GrTexture> tex = as_IB(image)->refPinnedTexture(&pinnedUniqueID)) {
bsalomonc55271f2015-11-09 11:55:57 -08001411 CHECK_SHOULD_DRAW(draw);
brianosman5814b8a2016-08-18 06:43:03 -07001412 GrTextureAdjuster adjuster(tex.get(), image->alphaType(), image->bounds(), pinnedUniqueID,
reed2d5b7142016-08-17 11:12:33 -07001413 as_IB(image)->onImageInfo().colorSpace());
bsalomonf1ecd212015-12-09 17:06:02 -08001414 this->drawTextureProducer(&adjuster, src, &dst, constraint, *draw.fMatrix, fClip, paint);
bsalomonc55271f2015-11-09 11:55:57 -08001415 return;
1416 }
1417 SkBitmap bm;
bsalomone553b642016-08-17 09:02:09 -07001418 SkMatrix srcToDstRect;
1419 srcToDstRect.setRectToRect((src ? *src : SkRect::MakeIWH(image->width(), image->height())),
1420 dst, SkMatrix::kFill_ScaleToFit);
1421 if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), *draw.fMatrix,
1422 srcToDstRect)) {
bsalomonc55271f2015-11-09 11:55:57 -08001423 // only support tiling as bitmap at the moment, so force raster-version
Brian Osman61624f02016-12-09 14:51:59 -05001424 if (!as_IB(image)->getROPixels(&bm, fRenderTargetContext->getColorSpace())) {
bsalomonc55271f2015-11-09 11:55:57 -08001425 return;
1426 }
bsalomon1cf6f9b2015-12-08 10:53:43 -08001427 this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
1428 } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
1429 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001430 GrImageTextureMaker maker(fContext.get(), cacher, image, SkImage::kAllow_CachingHint);
bsalomonf1ecd212015-12-09 17:06:02 -08001431 this->drawTextureProducer(&maker, src, &dst, constraint, *draw.fMatrix, fClip, paint);
Brian Osman61624f02016-12-09 14:51:59 -05001432 } else if (as_IB(image)->getROPixels(&bm, fRenderTargetContext->getColorSpace())) {
bsalomon1cf6f9b2015-12-08 10:53:43 -08001433 this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
reeda85d4d02015-05-06 12:56:48 -07001434 }
bsalomon1cf6f9b2015-12-08 10:53:43 -08001435}
1436
bsalomonf1ecd212015-12-09 17:06:02 -08001437void SkGpuDevice::drawProducerNine(const SkDraw& draw, GrTextureProducer* producer,
bsalomon2bbd0c62015-12-09 12:50:56 -08001438 const SkIRect& center, const SkRect& dst, const SkPaint& paint) {
Hal Canary144caf52016-11-07 17:57:18 -05001439 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerNine", fContext.get());
joshualitt33a5fce2015-11-18 13:28:51 -08001440
joshualitt33a5fce2015-11-18 13:28:51 -08001441 CHECK_SHOULD_DRAW(draw);
1442
joshualittedb36442015-11-19 14:29:30 -08001443 bool useFallback = paint.getMaskFilter() || paint.isAntiAlias() ||
Brian Osman11052242016-10-27 14:47:55 -04001444 fRenderTargetContext->isUnifiedMultisampled();
joshualitt33a5fce2015-11-18 13:28:51 -08001445 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -05001446 GrSamplerParams::FilterMode textureFilterMode =
bsalomon2bbd0c62015-12-09 12:50:56 -08001447 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMatrix, SkMatrix::I(),
1448 &doBicubic);
Brian Salomon514baff2016-11-17 15:17:07 -05001449 if (useFallback || doBicubic || GrSamplerParams::kNone_FilterMode != textureFilterMode) {
msarettc573a402016-08-02 08:05:56 -07001450 SkLatticeIter iter(producer->width(), producer->height(), center, dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001451
1452 SkRect srcR, dstR;
1453 while (iter.next(&srcR, &dstR)) {
erikchen9a1ed5d2016-02-10 16:32:34 -08001454 this->drawTextureProducer(producer, &srcR, &dstR, SkCanvas::kStrict_SrcRectConstraint,
bsalomonf1ecd212015-12-09 17:06:02 -08001455 *draw.fMatrix, fClip, paint);
joshualitt33a5fce2015-11-18 13:28:51 -08001456 }
1457 return;
1458 }
1459
Brian Salomon514baff2016-11-17 15:17:07 -05001460 static const GrSamplerParams::FilterMode kMode = GrSamplerParams::kNone_FilterMode;
bungeman06ca8ec2016-06-09 08:01:03 -07001461 sk_sp<GrFragmentProcessor> fp(
bsalomon2bbd0c62015-12-09 12:50:56 -08001462 producer->createFragmentProcessor(SkMatrix::I(),
1463 SkRect::MakeIWH(producer->width(), producer->height()),
1464 GrTextureProducer::kNo_FilterConstraint, true,
Brian Osman61624f02016-12-09 14:51:59 -05001465 &kMode, fRenderTargetContext->getColorSpace()));
joshualitt33a5fce2015-11-18 13:28:51 -08001466 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -04001467 if (!SkPaintToGrPaintWithTexture(this->context(), fRenderTargetContext.get(), paint,
1468 *draw.fMatrix, std::move(fp), producer->isAlphaOnly(),
1469 &grPaint)) {
joshualitt33a5fce2015-11-18 13:28:51 -08001470 return;
1471 }
1472
msarett10e3d9b2016-08-18 15:46:03 -07001473 std::unique_ptr<SkLatticeIter> iter(
1474 new SkLatticeIter(producer->width(), producer->height(), center, dst));
Brian Salomon82f44312017-01-11 13:42:54 -05001475 fRenderTargetContext->drawImageLattice(fClip, std::move(grPaint), *draw.fMatrix,
1476 producer->width(), producer->height(), std::move(iter),
1477 dst);
bsalomon2bbd0c62015-12-09 12:50:56 -08001478}
1479
1480void SkGpuDevice::drawImageNine(const SkDraw& draw, const SkImage* image,
1481 const SkIRect& center, const SkRect& dst, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001482 ASSERT_SINGLE_OWNER
reed2d5b7142016-08-17 11:12:33 -07001483 uint32_t pinnedUniqueID;
1484 if (sk_sp<GrTexture> tex = as_IB(image)->refPinnedTexture(&pinnedUniqueID)) {
1485 CHECK_SHOULD_DRAW(draw);
brianosman5814b8a2016-08-18 06:43:03 -07001486 GrTextureAdjuster adjuster(tex.get(), image->alphaType(), image->bounds(), pinnedUniqueID,
reed2d5b7142016-08-17 11:12:33 -07001487 as_IB(image)->onImageInfo().colorSpace());
bsalomonf1ecd212015-12-09 17:06:02 -08001488 this->drawProducerNine(draw, &adjuster, center, dst, paint);
bsalomon2bbd0c62015-12-09 12:50:56 -08001489 } else {
1490 SkBitmap bm;
1491 if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
Hal Canary144caf52016-11-07 17:57:18 -05001492 GrImageTextureMaker maker(fContext.get(), cacher, image, SkImage::kAllow_CachingHint);
bsalomonf1ecd212015-12-09 17:06:02 -08001493 this->drawProducerNine(draw, &maker, center, dst, paint);
Brian Osman61624f02016-12-09 14:51:59 -05001494 } else if (as_IB(image)->getROPixels(&bm, fRenderTargetContext->getColorSpace())) {
bsalomon2bbd0c62015-12-09 12:50:56 -08001495 this->drawBitmapNine(draw, bm, center, dst, paint);
1496 }
1497 }
1498}
1499
1500void SkGpuDevice::drawBitmapNine(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect& center,
1501 const SkRect& dst, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001502 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -05001503 GrBitmapTextureMaker maker(fContext.get(), bitmap);
reedc7ec7c92016-07-25 08:29:10 -07001504 this->drawProducerNine(draw, &maker, center, dst, paint);
joshualitt33a5fce2015-11-18 13:28:51 -08001505}
1506
msarett10e3d9b2016-08-18 15:46:03 -07001507void SkGpuDevice::drawProducerLattice(const SkDraw& draw, GrTextureProducer* producer,
1508 const SkCanvas::Lattice& lattice, const SkRect& dst,
1509 const SkPaint& paint) {
Hal Canary144caf52016-11-07 17:57:18 -05001510 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerLattice", fContext.get());
msarett10e3d9b2016-08-18 15:46:03 -07001511
1512 CHECK_SHOULD_DRAW(draw);
1513
Brian Salomon514baff2016-11-17 15:17:07 -05001514 static const GrSamplerParams::FilterMode kMode = GrSamplerParams::kNone_FilterMode;
msarett10e3d9b2016-08-18 15:46:03 -07001515 sk_sp<GrFragmentProcessor> fp(
1516 producer->createFragmentProcessor(SkMatrix::I(),
1517 SkRect::MakeIWH(producer->width(), producer->height()),
1518 GrTextureProducer::kNo_FilterConstraint, true,
Brian Osman61624f02016-12-09 14:51:59 -05001519 &kMode, fRenderTargetContext->getColorSpace()));
msarett10e3d9b2016-08-18 15:46:03 -07001520 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -04001521 if (!SkPaintToGrPaintWithTexture(this->context(), fRenderTargetContext.get(), paint,
1522 *draw.fMatrix, std::move(fp), producer->isAlphaOnly(),
1523 &grPaint)) {
msarett10e3d9b2016-08-18 15:46:03 -07001524 return;
1525 }
1526
1527 std::unique_ptr<SkLatticeIter> iter(
msarett71df2d72016-09-30 12:41:42 -07001528 new SkLatticeIter(lattice, dst));
Brian Salomon82f44312017-01-11 13:42:54 -05001529 fRenderTargetContext->drawImageLattice(fClip, std::move(grPaint), *draw.fMatrix,
1530 producer->width(), producer->height(), std::move(iter),
1531 dst);
msarett10e3d9b2016-08-18 15:46:03 -07001532}
1533
1534void SkGpuDevice::drawImageLattice(const SkDraw& draw, const SkImage* image,
1535 const SkCanvas::Lattice& lattice, const SkRect& dst,
1536 const SkPaint& paint) {
1537 ASSERT_SINGLE_OWNER
1538 uint32_t pinnedUniqueID;
1539 if (sk_sp<GrTexture> tex = as_IB(image)->refPinnedTexture(&pinnedUniqueID)) {
1540 CHECK_SHOULD_DRAW(draw);
1541 GrTextureAdjuster adjuster(tex.get(), image->alphaType(), image->bounds(), pinnedUniqueID,
1542 as_IB(image)->onImageInfo().colorSpace());
1543 this->drawProducerLattice(draw, &adjuster, lattice, dst, paint);
1544 } else {
1545 SkBitmap bm;
1546 if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
Hal Canary144caf52016-11-07 17:57:18 -05001547 GrImageTextureMaker maker(fContext.get(), cacher, image, SkImage::kAllow_CachingHint);
msarett10e3d9b2016-08-18 15:46:03 -07001548 this->drawProducerLattice(draw, &maker, lattice, dst, paint);
Brian Osman61624f02016-12-09 14:51:59 -05001549 } else if (as_IB(image)->getROPixels(&bm, fRenderTargetContext->getColorSpace())) {
msarett10e3d9b2016-08-18 15:46:03 -07001550 this->drawBitmapLattice(draw, bm, lattice, dst, paint);
1551 }
1552 }
1553}
1554
1555void SkGpuDevice::drawBitmapLattice(const SkDraw& draw, const SkBitmap& bitmap,
1556 const SkCanvas::Lattice& lattice, const SkRect& dst,
1557 const SkPaint& paint) {
1558 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -05001559 GrBitmapTextureMaker maker(fContext.get(), bitmap);
msarett10e3d9b2016-08-18 15:46:03 -07001560 this->drawProducerLattice(draw, &maker, lattice, dst, paint);
1561}
1562
Brian Salomon199fb872017-02-06 09:41:10 -05001563bool init_vertices_paint(const SkPaint& skPaint, const SkMatrix& matrix, SkBlendMode bmode,
1564 bool hasTexs, bool hasColors, GrRenderTargetContext* rtc,
1565 GrPaint* grPaint) {
1566 GrContext* context = rtc->surfPriv().getContext();
1567 if (hasTexs && skPaint.getShader()) {
1568 if (hasColors) {
1569 // When there are texs and colors the shader and colors are combined using bmode.
1570 return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, matrix, bmode, false,
1571 grPaint);
1572 } else {
1573 // We have a shader, but no colors to blend it against.
1574 return SkPaintToGrPaint(context, rtc, skPaint, matrix, grPaint);
1575 }
1576 } else {
1577 if (hasColors) {
1578 // We have colors, but either have no shader or no texture coords (which implies that
1579 // we should ignore the shader).
1580 return SkPaintToGrPaintWithPrimitiveColor(context, rtc, skPaint, grPaint);
1581 } else {
1582 // No colors and no shaders. Just draw with the paint color.
1583 return (!SkPaintToGrPaintNoShader(context, rtc, skPaint, grPaint));
1584 }
1585 }
1586}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001587
1588void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
1589 int vertexCount, const SkPoint vertices[],
1590 const SkPoint texs[], const SkColor colors[],
Mike Reedfaba3712016-11-03 14:45:31 -04001591 SkBlendMode bmode,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001592 const uint16_t indices[], int indexCount,
1593 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001594 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -08001595 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001596 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVertices", fContext.get());
mtklein533eb782014-08-27 10:39:42 -07001597
halcanary96fcdcc2015-08-27 07:41:13 -07001598 // If both textures and vertex-colors are nullptr, strokes hairlines with the paint's color.
1599 if ((nullptr == texs || nullptr == paint.getShader()) && nullptr == colors) {
mtklein533eb782014-08-27 10:39:42 -07001600
halcanary96fcdcc2015-08-27 07:41:13 -07001601 texs = nullptr;
mtklein533eb782014-08-27 10:39:42 -07001602
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001603 SkPaint copy(paint);
1604 copy.setStyle(SkPaint::kStroke_Style);
1605 copy.setStrokeWidth(0);
mtklein533eb782014-08-27 10:39:42 -07001606
bsalomonf1b7a1d2015-09-28 06:26:28 -07001607 GrPaint grPaint;
dandov32a311b2014-07-15 19:46:26 -07001608 // we ignore the shader if texs is null.
Brian Osman11052242016-10-27 14:47:55 -04001609 if (!SkPaintToGrPaintNoShader(this->context(), fRenderTargetContext.get(), copy,
1610 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -07001611 return;
1612 }
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001613
dandov32a311b2014-07-15 19:46:26 -07001614 int triangleCount = 0;
halcanary96fcdcc2015-08-27 07:41:13 -07001615 int n = (nullptr == indices) ? vertexCount : indexCount;
dandov32a311b2014-07-15 19:46:26 -07001616 switch (vmode) {
1617 case SkCanvas::kTriangles_VertexMode:
bsalomona098dd42014-08-06 11:01:44 -07001618 triangleCount = n / 3;
dandov32a311b2014-07-15 19:46:26 -07001619 break;
1620 case SkCanvas::kTriangleStrip_VertexMode:
1621 case SkCanvas::kTriangleFan_VertexMode:
bsalomona098dd42014-08-06 11:01:44 -07001622 triangleCount = n - 2;
dandov32a311b2014-07-15 19:46:26 -07001623 break;
1624 }
mtklein533eb782014-08-27 10:39:42 -07001625
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001626 VertState state(vertexCount, indices, indexCount);
1627 VertState::Proc vertProc = state.chooseProc(vmode);
mtklein533eb782014-08-27 10:39:42 -07001628
dandov32a311b2014-07-15 19:46:26 -07001629 //number of indices for lines per triangle with kLines
1630 indexCount = triangleCount * 6;
mtklein533eb782014-08-27 10:39:42 -07001631
Ben Wagner7ecc5962016-11-02 17:07:33 -04001632 std::unique_ptr<uint16_t[]> lineIndices(new uint16_t[indexCount]);
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001633 int i = 0;
1634 while (vertProc(&state)) {
bsalomonf1b7a1d2015-09-28 06:26:28 -07001635 lineIndices[i] = state.f0;
1636 lineIndices[i + 1] = state.f1;
1637 lineIndices[i + 2] = state.f1;
1638 lineIndices[i + 3] = state.f2;
1639 lineIndices[i + 4] = state.f2;
1640 lineIndices[i + 5] = state.f0;
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001641 i += 6;
1642 }
Brian Osman11052242016-10-27 14:47:55 -04001643 fRenderTargetContext->drawVertices(fClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001644 std::move(grPaint),
Brian Osman11052242016-10-27 14:47:55 -04001645 *draw.fMatrix,
1646 kLines_GrPrimitiveType,
1647 vertexCount,
1648 vertices,
1649 texs,
1650 colors,
1651 lineIndices.get(),
1652 indexCount);
bsalomonf1b7a1d2015-09-28 06:26:28 -07001653 return;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001654 }
1655
Brian Salomon199fb872017-02-06 09:41:10 -05001656 GrPrimitiveType primType = SkVertexModeToGrPrimitiveType(vmode);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001657
bsalomonf1b7a1d2015-09-28 06:26:28 -07001658 GrPaint grPaint;
Brian Salomon199fb872017-02-06 09:41:10 -05001659 if (!init_vertices_paint(paint, *draw.fMatrix, bmode, SkToBool(texs), SkToBool(colors),
1660 fRenderTargetContext.get(), &grPaint)) {
1661 return;
bsalomonf1b7a1d2015-09-28 06:26:28 -07001662 }
Brian Osman11052242016-10-27 14:47:55 -04001663 fRenderTargetContext->drawVertices(fClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001664 std::move(grPaint),
Brian Osman11052242016-10-27 14:47:55 -04001665 *draw.fMatrix,
1666 primType,
1667 vertexCount,
1668 vertices,
1669 texs,
1670 colors,
1671 indices,
Brian Salomon3de0aee2017-01-29 09:34:17 -05001672 indexCount,
1673 GrRenderTargetContext::ColorArrayType::kSkColor);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001674}
1675
Brian Salomon199fb872017-02-06 09:41:10 -05001676void SkGpuDevice::drawVerticesObject(const SkDraw& draw, sk_sp<SkVertices> vertices,
1677 SkBlendMode mode, const SkPaint& paint, uint32_t flags) {
1678 ASSERT_SINGLE_OWNER
1679 CHECK_SHOULD_DRAW(draw);
1680 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVerticesObject", fContext.get());
1681
1682 SkASSERT(vertices);
1683 GrPaint grPaint;
1684 bool hasColors = vertices->hasColors() && !(SkCanvas::kIgnoreColors_VerticesFlag & flags);
1685 bool hasTexs = vertices->hasTexCoords() & !(SkCanvas::kIgnoreTexCoords_VerticesFlag & flags);
1686 if (!hasTexs && !hasColors) {
1687 // The dreaded wireframe mode. Fallback to drawVertices and go so slooooooow.
1688 this->drawVertices(draw, vertices->mode(), vertices->vertexCount(), vertices->positions(),
1689 nullptr, nullptr, mode, vertices->indices(), vertices->indexCount(),
1690 paint);
1691 }
1692 if (!init_vertices_paint(paint, *draw.fMatrix, mode, hasTexs, hasColors,
1693 fRenderTargetContext.get(), &grPaint)) {
1694 return;
1695 }
1696 fRenderTargetContext->drawVertices(fClip, std::move(grPaint), *draw.fMatrix,
1697 std::move(vertices), flags);
1698}
1699
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001700///////////////////////////////////////////////////////////////////////////////
1701
jvanverth31ff7622015-08-07 10:09:28 -07001702void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
reedca109532015-06-25 16:25:25 -07001703 const SkRect texRect[], const SkColor colors[], int count,
Mike Reedfaba3712016-11-03 14:45:31 -04001704 SkBlendMode mode, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001705 ASSERT_SINGLE_OWNER
reedca109532015-06-25 16:25:25 -07001706 if (paint.isAntiAlias()) {
jvanverth31ff7622015-08-07 10:09:28 -07001707 this->INHERITED::drawAtlas(draw, atlas, xform, texRect, colors, count, mode, paint);
reedca109532015-06-25 16:25:25 -07001708 return;
1709 }
1710
jvanverth31ff7622015-08-07 10:09:28 -07001711 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001712 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext.get());
herb11a7f7f2015-11-24 12:41:00 -08001713
reedca109532015-06-25 16:25:25 -07001714 SkPaint p(paint);
reed5671c5b2016-03-09 14:47:34 -08001715 p.setShader(atlas->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
reedca109532015-06-25 16:25:25 -07001716
jvanverth31ff7622015-08-07 10:09:28 -07001717 GrPaint grPaint;
robertphillips29ccdf82015-07-24 10:20:45 -07001718 if (colors) {
Brian Osman11052242016-10-27 14:47:55 -04001719 if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), p,
Mike Reed7d954ad2016-10-28 15:42:34 -04001720 *draw.fMatrix, (SkBlendMode)mode, true, &grPaint)) {
bsalomonf1b7a1d2015-09-28 06:26:28 -07001721 return;
1722 }
1723 } else {
Brian Osman11052242016-10-27 14:47:55 -04001724 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), p, *draw.fMatrix,
1725 &grPaint)) {
jvanverth31ff7622015-08-07 10:09:28 -07001726 return;
robertphillips29ccdf82015-07-24 10:20:45 -07001727 }
1728 }
bsalomonf1b7a1d2015-09-28 06:26:28 -07001729
1730 SkDEBUGCODE(this->validate();)
Brian Salomon82f44312017-01-11 13:42:54 -05001731 fRenderTargetContext->drawAtlas(fClip, std::move(grPaint), *draw.fMatrix, count, xform, texRect,
1732 colors);
reedca109532015-06-25 16:25:25 -07001733}
1734
1735///////////////////////////////////////////////////////////////////////////////
1736
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001737void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
joshualitt5531d512014-12-17 15:50:11 -08001738 size_t byteLength, SkScalar x, SkScalar y,
1739 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001740 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -08001741 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001742 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext.get());
jvanverth8c27a182014-10-14 08:45:50 -07001743 SkDEBUGCODE(this->validate();)
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +00001744
Brian Salomon6f1d36c2017-01-13 12:02:17 -05001745 fRenderTargetContext->drawText(fClip, paint, *draw.fMatrix,
Mike Reedfa24d342017-02-22 15:21:35 -05001746 (const char*)text, byteLength, x, y, this->devClipBounds(draw));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001747}
1748
fmalita05c4a432014-09-29 06:29:53 -07001749void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteLength,
1750 const SkScalar pos[], int scalarsPerPos,
1751 const SkPoint& offset, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001752 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -05001753 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPosText", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -08001754 CHECK_SHOULD_DRAW(draw);
jvanverth8c27a182014-10-14 08:45:50 -07001755 SkDEBUGCODE(this->validate();)
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +00001756
Brian Salomon6f1d36c2017-01-13 12:02:17 -05001757 fRenderTargetContext->drawPosText(fClip, paint, *draw.fMatrix,
Brian Salomon82f44312017-01-11 13:42:54 -05001758 (const char*)text, byteLength, pos, scalarsPerPos, offset,
Mike Reedfa24d342017-02-22 15:21:35 -05001759 this->devClipBounds(draw));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001760}
1761
joshualitt9c328182015-03-23 08:13:04 -07001762void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y,
1763 const SkPaint& paint, SkDrawFilter* drawFilter) {
joshualittce894002016-01-11 13:29:31 -08001764 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -05001765 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawTextBlob", fContext.get());
joshualitt9c328182015-03-23 08:13:04 -07001766 CHECK_SHOULD_DRAW(draw);
1767
1768 SkDEBUGCODE(this->validate();)
1769
Brian Osman11052242016-10-27 14:47:55 -04001770 fRenderTargetContext->drawTextBlob(fClip, paint, *draw.fMatrix,
Mike Reedfa24d342017-02-22 15:21:35 -05001771 blob, x, y, drawFilter, this->devClipBounds(draw));
joshualitt9c328182015-03-23 08:13:04 -07001772}
1773
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001774///////////////////////////////////////////////////////////////////////////////
1775
reedb2db8982014-11-13 12:41:02 -08001776bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const {
joshualitt8e84a1e2016-02-16 11:09:25 -08001777 return GrTextUtils::ShouldDisableLCD(paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001778}
1779
1780void SkGpuDevice::flush() {
joshualittce894002016-01-11 13:29:31 -08001781 ASSERT_SINGLE_OWNER
joshualittbc907352016-01-13 06:45:40 -08001782
Brian Osman11052242016-10-27 14:47:55 -04001783 fRenderTargetContext->prepareForExternalIO();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001784}
1785
1786///////////////////////////////////////////////////////////////////////////////
1787
reed76033be2015-03-14 10:54:31 -07001788SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
joshualittce894002016-01-11 13:29:31 -08001789 ASSERT_SINGLE_OWNER
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001790
robertphillipsca6eafc2016-05-17 09:57:46 -07001791 SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001792
robertphillipsca6eafc2016-05-17 09:57:46 -07001793 // layers are never drawn in repeat modes, so we can request an approx
hcm4396fa52014-10-27 21:43:30 -07001794 // match and ignore any padding.
robertphillipsca6eafc2016-05-17 09:57:46 -07001795 SkBackingFit fit = kNever_TileUsage == cinfo.fTileUsage ? SkBackingFit::kApprox
1796 : SkBackingFit::kExact;
bsalomonafe30052015-01-16 07:32:33 -08001797
Brian Osman11052242016-10-27 14:47:55 -04001798 sk_sp<GrRenderTargetContext> rtc(fContext->makeRenderTargetContext(
1799 fit,
1800 cinfo.fInfo.width(), cinfo.fInfo.height(),
1801 fRenderTargetContext->config(),
Robert Phillips75a475c2017-01-13 09:18:59 -05001802 fRenderTargetContext->refColorSpace(),
Brian Osman11052242016-10-27 14:47:55 -04001803 fRenderTargetContext->desc().fSampleCnt,
1804 kDefault_GrSurfaceOrigin,
1805 &props));
1806 if (!rtc) {
Mike Kleine54c75f2016-10-13 14:18:09 -04001807 return nullptr;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001808 }
robertphillipsca6eafc2016-05-17 09:57:46 -07001809
1810 // Skia's convention is to only clear a device if it is non-opaque.
1811 InitContents init = cinfo.fInfo.isOpaque() ? kUninit_InitContents : kClear_InitContents;
1812
Robert Phillips9fab7e92016-11-17 12:45:04 -05001813 return SkGpuDevice::Make(fContext.get(), std::move(rtc),
1814 cinfo.fInfo.width(), cinfo.fInfo.height(), init).release();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001815}
1816
reede8f30622016-03-23 18:59:25 -07001817sk_sp<SkSurface> SkGpuDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
joshualittce894002016-01-11 13:29:31 -08001818 ASSERT_SINGLE_OWNER
bsalomonafe30052015-01-16 07:32:33 -08001819 // TODO: Change the signature of newSurface to take a budgeted parameter.
bsalomon5ec26ae2016-02-25 08:33:02 -08001820 static const SkBudgeted kBudgeted = SkBudgeted::kNo;
Hal Canary144caf52016-11-07 17:57:18 -05001821 return SkSurface::MakeRenderTarget(fContext.get(), kBudgeted, info,
Brian Osman11052242016-10-27 14:47:55 -04001822 fRenderTargetContext->desc().fSampleCnt,
1823 fRenderTargetContext->origin(), &props);
reed@google.com76f10a32014-02-05 15:32:21 +00001824}
1825
senorblanco900c3672016-04-27 11:31:23 -07001826SkImageFilterCache* SkGpuDevice::getImageFilterCache() {
joshualittce894002016-01-11 13:29:31 -08001827 ASSERT_SINGLE_OWNER
senorblanco55b6d8b2014-07-30 11:26:46 -07001828 // We always return a transient cache, so it is freed after each
1829 // filter traversal.
brianosman04a44d02016-09-21 09:46:57 -07001830 return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
senorblanco55b6d8b2014-07-30 11:26:46 -07001831}
reedf037e0b2014-10-30 11:34:15 -07001832
1833#endif