blob: 1dec0f6371c913e0768c314b8d4751c5c98171d0 [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 Osmane8e54582016-11-28 10:06:27 -050017#include "GrTextureAdjuster.h"
Robert Phillipse2f7d182016-12-15 09:23:05 -050018#include "GrTextureProxy.h"
egdanielbbcb38d2014-06-19 10:19:29 -070019#include "GrTracing.h"
robertphillips714712b2016-08-04 06:20:45 -070020
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"
kkinnunenabcfab42015-02-22 22:53:44 -080038#include "SkRecord.h"
robertphillips970587b2016-07-14 14:12:55 -070039#include "SkSpecialImage.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000040#include "SkStroke.h"
reed@google.com76f10a32014-02-05 15:32:21 +000041#include "SkSurface.h"
kkinnunenabcfab42015-02-22 22:53:44 -080042#include "SkSurface_Gpu.h"
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +000043#include "SkTLazy.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000044#include "SkUtils.h"
commit-bot@chromium.org559a8832014-05-30 10:08:22 +000045#include "SkVertState.h"
kkinnunenabcfab42015-02-22 22:53:44 -080046#include "effects/GrBicubicEffect.h"
kkinnunenabcfab42015-02-22 22:53:44 -080047#include "effects/GrSimpleTextureEffect.h"
48#include "effects/GrTextureDomain.h"
joshualitt8e84a1e2016-02-16 11:09:25 -080049#include "text/GrTextUtils.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000050
reedf037e0b2014-10-30 11:34:15 -070051#if SK_SUPPORT_GPU
52
joshualittce894002016-01-11 13:29:31 -080053#define ASSERT_SINGLE_OWNER \
54 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->debugSingleOwner());)
55
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000056#if 0
57 extern bool (*gShouldDrawProc)();
joshualitt5531d512014-12-17 15:50:11 -080058 #define CHECK_SHOULD_DRAW(draw) \
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000059 do { \
60 if (gShouldDrawProc && !gShouldDrawProc()) return; \
joshualitt5531d512014-12-17 15:50:11 -080061 this->prepareDraw(draw); \
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000062 } while (0)
63#else
joshualitt5531d512014-12-17 15:50:11 -080064 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw)
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000065#endif
66
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +000067///////////////////////////////////////////////////////////////////////////////
68
bsalomon74f681d2015-06-23 14:38:48 -070069/** Checks that the alpha type is legal and gets constructor flags. Returns false if device creation
70 should fail. */
71bool SkGpuDevice::CheckAlphaTypeAndGetFlags(
72 const SkImageInfo* info, SkGpuDevice::InitContents init, unsigned* flags) {
73 *flags = 0;
74 if (info) {
75 switch (info->alphaType()) {
76 case kPremul_SkAlphaType:
77 break;
78 case kOpaque_SkAlphaType:
79 *flags |= SkGpuDevice::kIsOpaque_Flag;
80 break;
81 default: // If it is unpremul or unknown don't try to render
82 return false;
83 }
84 }
85 if (kClear_InitContents == init) {
86 *flags |= kNeedClear_Flag;
87 }
88 return true;
89}
90
Robert Phillips9fab7e92016-11-17 12:45:04 -050091sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context,
92 sk_sp<GrRenderTargetContext> renderTargetContext,
robertphillips15c42ca2016-08-04 08:45:02 -070093 int width, int height,
94 InitContents init) {
Brian Osman11052242016-10-27 14:47:55 -040095 if (!renderTargetContext || renderTargetContext->wasAbandoned()) {
robertphillipsca6eafc2016-05-17 09:57:46 -070096 return nullptr;
97 }
98 unsigned flags;
99 if (!CheckAlphaTypeAndGetFlags(nullptr, init, &flags)) {
100 return nullptr;
101 }
Robert Phillips9fab7e92016-11-17 12:45:04 -0500102 return sk_sp<SkGpuDevice>(new SkGpuDevice(context, std::move(renderTargetContext),
103 width, height, flags));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000104}
105
robertphillips24e91282016-04-29 06:46:36 -0700106sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context, SkBudgeted budgeted,
107 const SkImageInfo& info, int sampleCount,
robertphillips7e922762016-07-26 11:38:17 -0700108 GrSurfaceOrigin origin,
robertphillips24e91282016-04-29 06:46:36 -0700109 const SkSurfaceProps* props, InitContents init) {
bsalomon74f681d2015-06-23 14:38:48 -0700110 unsigned flags;
111 if (!CheckAlphaTypeAndGetFlags(&info, init, &flags)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700112 return nullptr;
bsalomon74f681d2015-06-23 14:38:48 -0700113 }
114
Brian Osman11052242016-10-27 14:47:55 -0400115 sk_sp<GrRenderTargetContext> renderTargetContext(MakeRenderTargetContext(context, budgeted,
116 info, sampleCount,
117 origin, props));
118 if (!renderTargetContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700119 return nullptr;
bsalomon74f681d2015-06-23 14:38:48 -0700120 }
121
Robert Phillips9fab7e92016-11-17 12:45:04 -0500122 return sk_sp<SkGpuDevice>(new SkGpuDevice(context, std::move(renderTargetContext),
robertphillipsca6eafc2016-05-17 09:57:46 -0700123 info.width(), info.height(), flags));
bsalomon74f681d2015-06-23 14:38:48 -0700124}
125
Brian Osman11052242016-10-27 14:47:55 -0400126static SkImageInfo make_info(GrRenderTargetContext* context, int w, int h, bool opaque) {
reed589a39e2016-08-20 07:59:19 -0700127 SkColorType colorType;
128 if (!GrPixelConfigToColorType(context->config(), &colorType)) {
129 colorType = kUnknown_SkColorType;
130 }
131 return SkImageInfo::Make(w, h, colorType,
132 opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
Robert Phillips75a475c2017-01-13 09:18:59 -0500133 context->refColorSpace());
reed589a39e2016-08-20 07:59:19 -0700134}
135
Robert Phillips9fab7e92016-11-17 12:45:04 -0500136SkGpuDevice::SkGpuDevice(GrContext* context, sk_sp<GrRenderTargetContext> renderTargetContext,
137 int width, int height, unsigned flags)
Brian Osman11052242016-10-27 14:47:55 -0400138 : INHERITED(make_info(renderTargetContext.get(), width, height,
139 SkToBool(flags & kIsOpaque_Flag)), renderTargetContext->surfaceProps())
Robert Phillips9fab7e92016-11-17 12:45:04 -0500140 , fContext(SkRef(context))
Brian Osman11052242016-10-27 14:47:55 -0400141 , fRenderTargetContext(std::move(renderTargetContext))
reed589a39e2016-08-20 07:59:19 -0700142{
robertphillips1f3923e2016-07-21 07:17:54 -0700143 fSize.set(width, height);
bsalomon74f681d2015-06-23 14:38:48 -0700144 fOpaque = SkToBool(flags & kIsOpaque_Flag);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000145
bsalomone63ffef2016-02-05 07:17:34 -0800146 if (flags & kNeedClear_Flag) {
147 this->clearAll();
148 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000149}
150
Brian Osman11052242016-10-27 14:47:55 -0400151sk_sp<GrRenderTargetContext> SkGpuDevice::MakeRenderTargetContext(
152 GrContext* context,
153 SkBudgeted budgeted,
154 const SkImageInfo& origInfo,
155 int sampleCount,
156 GrSurfaceOrigin origin,
157 const SkSurfaceProps* surfaceProps) {
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000158 if (kUnknown_SkColorType == origInfo.colorType() ||
159 origInfo.width() < 0 || origInfo.height() < 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700160 return nullptr;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000161 }
162
bsalomonafe30052015-01-16 07:32:33 -0800163 if (!context) {
halcanary96fcdcc2015-08-27 07:41:13 -0700164 return nullptr;
bsalomonafe30052015-01-16 07:32:33 -0800165 }
166
Brian Osman0c2997b2017-01-11 16:58:42 -0500167 GrPixelConfig config = SkImageInfo2GrPixelConfig(origInfo, *context->caps());
Brian Osman11052242016-10-27 14:47:55 -0400168 return context->makeRenderTargetContext(SkBackingFit::kExact, // Why exact?
robertphillips6738c702016-07-27 12:13:51 -0700169 origInfo.width(), origInfo.height(),
Robert Phillips70b49fd2017-01-13 11:21:36 -0500170 config, origInfo.refColorSpace(), sampleCount,
robertphillips6738c702016-07-27 12:13:51 -0700171 origin, surfaceProps, budgeted);
kkinnunenabcfab42015-02-22 22:53:44 -0800172}
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000173
robertphillips970587b2016-07-14 14:12:55 -0700174sk_sp<SkSpecialImage> SkGpuDevice::filterTexture(const SkDraw& draw,
175 SkSpecialImage* srcImg,
176 int left, int top,
177 SkIPoint* offset,
178 const SkImageFilter* filter) {
179 SkASSERT(srcImg->isTextureBacked());
180 SkASSERT(filter);
181
182 SkMatrix matrix = *draw.fMatrix;
183 matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
184 const SkIRect clipBounds = draw.fRC->getBounds().makeOffset(-left, -top);
Hal Canary144caf52016-11-07 17:57:18 -0500185 sk_sp<SkImageFilterCache> cache(this->getImageFilterCache());
Brian Osman11052242016-10-27 14:47:55 -0400186 SkImageFilter::OutputProperties outputProperties(fRenderTargetContext->getColorSpace());
brianosman2a75e5d2016-09-22 07:15:37 -0700187 SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties);
robertphillips970587b2016-07-14 14:12:55 -0700188
189 return filter->filterImage(srcImg, ctx, offset);
190}
191
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000192///////////////////////////////////////////////////////////////////////////////
193
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000194bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
195 int x, int y) {
joshualittce894002016-01-11 13:29:31 -0800196 ASSERT_SINGLE_OWNER
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000197
Matt Sarettcb6266b2017-01-17 10:48:53 -0500198 if (!SkImageInfoValidConversion(dstInfo, this->imageInfo())) {
199 return false;
200 }
201
Brian Osman11052242016-10-27 14:47:55 -0400202 return fRenderTargetContext->readPixels(dstInfo, dstPixels, dstRowBytes, x, y);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000203}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000204
robertphillips1da3ecd2016-08-31 14:54:15 -0700205bool SkGpuDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
206 size_t srcRowBytes, int x, int y) {
joshualittce894002016-01-11 13:29:31 -0800207 ASSERT_SINGLE_OWNER
robertphillips1da3ecd2016-08-31 14:54:15 -0700208
Matt Sarettcb6266b2017-01-17 10:48:53 -0500209 if (!SkImageInfoValidConversion(this->imageInfo(), srcInfo)) {
210 return false;
211 }
212
Brian Osman11052242016-10-27 14:47:55 -0400213 return fRenderTargetContext->writePixels(srcInfo, srcPixels, srcRowBytes, x, y);
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000214}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000215
reed41e010c2015-06-09 12:16:53 -0700216bool SkGpuDevice::onAccessPixels(SkPixmap* pmap) {
joshualittce894002016-01-11 13:29:31 -0800217 ASSERT_SINGLE_OWNER
reed41e010c2015-06-09 12:16:53 -0700218 return false;
219}
220
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000221// call this every draw call, to ensure that the context reflects our state,
222// and not the state from some other canvas/device
joshualitt5531d512014-12-17 15:50:11 -0800223void SkGpuDevice::prepareDraw(const SkDraw& draw) {
joshualittce894002016-01-11 13:29:31 -0800224 ASSERT_SINGLE_OWNER
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000225
reed2c9e2002016-07-25 08:05:22 -0700226 fClip.reset(draw.fClipStack, &this->getOrigin());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000227}
228
Brian Osman11052242016-10-27 14:47:55 -0400229GrRenderTargetContext* SkGpuDevice::accessRenderTargetContext() {
robertphillips175dd9b2016-04-28 14:32:04 -0700230 ASSERT_SINGLE_OWNER
Brian Osman11052242016-10-27 14:47:55 -0400231 return fRenderTargetContext.get();
robertphillips175dd9b2016-04-28 14:32:04 -0700232}
233
reed8eddfb52014-12-04 07:50:14 -0800234void SkGpuDevice::clearAll() {
joshualittce894002016-01-11 13:29:31 -0800235 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500236 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "clearAll", fContext.get());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500237
reed8eddfb52014-12-04 07:50:14 -0800238 SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500239 fRenderTargetContext->clear(&rect, 0x0, true);
reed8eddfb52014-12-04 07:50:14 -0800240}
241
Brian Osman11052242016-10-27 14:47:55 -0400242void SkGpuDevice::replaceRenderTargetContext(bool shouldRetainContent) {
joshualittce894002016-01-11 13:29:31 -0800243 ASSERT_SINGLE_OWNER
kkinnunenabcfab42015-02-22 22:53:44 -0800244
Brian Osman693a5402016-10-27 15:13:22 -0400245 SkBudgeted budgeted = fRenderTargetContext->priv().isBudgeted();
kkinnunenabcfab42015-02-22 22:53:44 -0800246
Brian Osman693a5402016-10-27 15:13:22 -0400247 sk_sp<GrRenderTargetContext> newRTC(MakeRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400248 this->context(),
249 budgeted,
250 this->imageInfo(),
251 fRenderTargetContext->numColorSamples(),
252 fRenderTargetContext->origin(),
253 &this->surfaceProps()));
Brian Osman693a5402016-10-27 15:13:22 -0400254 if (!newRTC) {
kkinnunenabcfab42015-02-22 22:53:44 -0800255 return;
256 }
257
258 if (shouldRetainContent) {
Brian Osman11052242016-10-27 14:47:55 -0400259 if (fRenderTargetContext->wasAbandoned()) {
kkinnunenabcfab42015-02-22 22:53:44 -0800260 return;
261 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500262 newRTC->copy(fRenderTargetContext->asDeferredSurface());
kkinnunenabcfab42015-02-22 22:53:44 -0800263 }
264
Brian Osman693a5402016-10-27 15:13:22 -0400265 fRenderTargetContext = newRTC;
kkinnunenabcfab42015-02-22 22:53:44 -0800266}
267
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000268///////////////////////////////////////////////////////////////////////////////
269
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000270void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800271 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -0800272 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -0500273 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPaint", fContext.get());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000274
275 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400276 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
277 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700278 return;
279 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000280
Brian Salomon82f44312017-01-11 13:42:54 -0500281 fRenderTargetContext->drawPaint(fClip, std::move(grPaint), *draw.fMatrix);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000282}
283
284// must be in SkCanvas::PointMode order
bsalomon6ade6dd2016-09-12 12:07:17 -0700285static const GrPrimitiveType gPointMode2PrimitiveType[] = {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000286 kPoints_GrPrimitiveType,
287 kLines_GrPrimitiveType,
288 kLineStrip_GrPrimitiveType
289};
290
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500291static inline bool is_int(float x) { return x == (float) sk_float_round2int(x); }
292
ethannicholas330bb952015-07-17 06:44:02 -0700293// suppress antialiasing on axis-aligned integer-coordinate lines
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500294static bool needs_antialiasing(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
295 const SkMatrix& matrix) {
ethannicholas330bb952015-07-17 06:44:02 -0700296 if (mode == SkCanvas::PointMode::kPoints_PointMode) {
297 return false;
298 }
299 if (count == 2) {
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500300 // We do not antialias horizontal or vertical lines along pixel centers, even when the ends
301 // of the line do not fully cover the first and last pixel of the line, which is slightly
302 // wrong.
303 if (!matrix.isScaleTranslate()) {
304 return true;
305 }
ethannicholas330bb952015-07-17 06:44:02 -0700306 if (pts[0].fX == pts[1].fX) {
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500307 SkScalar x = matrix.getScaleX() * pts[0].fX + matrix.getTranslateX();
308 return !is_int(x + 0.5f);
ethannicholas330bb952015-07-17 06:44:02 -0700309 }
310 if (pts[0].fY == pts[1].fY) {
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500311 SkScalar y = matrix.getScaleY() * pts[0].fY + matrix.getTranslateY();
312 return !is_int(y + 0.5f);
ethannicholas330bb952015-07-17 06:44:02 -0700313 }
314 }
315 return true;
316}
317
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000318void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
319 size_t count, const SkPoint pts[], const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800320 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500321 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPoints", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800322 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000323
324 SkScalar width = paint.getStrokeWidth();
325 if (width < 0) {
326 return;
327 }
328
commit-bot@chromium.org628ed0b2014-05-19 14:32:49 +0000329 if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
bsalomon6663acf2016-05-10 09:14:17 -0700330 GrStyle style(paint, SkPaint::kStroke_Style);
egdaniele61c4112014-06-12 10:24:21 -0700331 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400332 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
brianosman1638c0d2016-07-25 05:12:53 -0700333 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700334 return;
335 }
egdaniele61c4112014-06-12 10:24:21 -0700336 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700337 path.setIsVolatile(true);
egdaniele61c4112014-06-12 10:24:21 -0700338 path.moveTo(pts[0]);
339 path.lineTo(pts[1]);
Brian Salomon82f44312017-01-11 13:42:54 -0500340 fRenderTargetContext->drawPath(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500341 *draw.fMatrix, path, style);
egdaniele61c4112014-06-12 10:24:21 -0700342 return;
commit-bot@chromium.org628ed0b2014-05-19 14:32:49 +0000343 }
344
bsalomon6ade6dd2016-09-12 12:07:17 -0700345 SkScalar scales[2];
346 bool isHairline = (0 == width) || (1 == width && draw.fMatrix->getMinMaxScales(scales) &&
347 SkScalarNearlyEqual(scales[0], 1.f) &&
348 SkScalarNearlyEqual(scales[1], 1.f));
ethannicholas330bb952015-07-17 06:44:02 -0700349 // we only handle non-antialiased hairlines and paints without path effects or mask filters,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000350 // else we let the SkDraw call our drawPath()
bsalomon6ade6dd2016-09-12 12:07:17 -0700351 if (!isHairline || paint.getPathEffect() || paint.getMaskFilter() ||
Brian Salomonbd72f5a2016-12-06 16:52:24 -0500352 (paint.isAntiAlias() && needs_antialiasing(mode, count, pts, *draw.fMatrix))) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000353 draw.drawPoints(mode, count, pts, paint, true);
354 return;
355 }
356
bsalomon6ade6dd2016-09-12 12:07:17 -0700357 GrPrimitiveType primitiveType = gPointMode2PrimitiveType[mode];
358
359 const SkMatrix* viewMatrix = draw.fMatrix;
360#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
361 // This offsetting in device space matches the expectations of the Android framework for non-AA
362 // points and lines.
363 SkMatrix tempMatrix;
364 if (GrIsPrimTypeLines(primitiveType) || kPoints_GrPrimitiveType == primitiveType) {
365 tempMatrix = *viewMatrix;
366 static const SkScalar kOffset = 0.063f; // Just greater than 1/16.
367 tempMatrix.postTranslate(kOffset, kOffset);
368 viewMatrix = &tempMatrix;
369 }
370#endif
371
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000372 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400373 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *viewMatrix,
374 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700375 return;
376 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000377
Brian Osman11052242016-10-27 14:47:55 -0400378 fRenderTargetContext->drawVertices(fClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500379 std::move(grPaint),
Brian Osman11052242016-10-27 14:47:55 -0400380 *viewMatrix,
381 primitiveType,
382 SkToS32(count),
383 (SkPoint*)pts,
384 nullptr,
385 nullptr,
386 nullptr,
387 0);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000388}
389
390///////////////////////////////////////////////////////////////////////////////
391
robertphillipsff55b492015-11-24 07:56:59 -0800392void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800393 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500394 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRect", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800395 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000396
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000397
bsalomona7d85ba2016-07-06 11:54:59 -0700398 // A couple reasons we might need to call drawPath.
399 if (paint.getMaskFilter() || paint.getPathEffect()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000400 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700401 path.setIsVolatile(true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000402 path.addRect(rect);
Hal Canary144caf52016-11-07 17:57:18 -0500403 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillipsff55b492015-11-24 07:56:59 -0800404 fClip, path, paint,
405 *draw.fMatrix, nullptr,
reed1e7f5e72016-04-27 07:49:17 -0700406 draw.fRC->getBounds(), true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000407 return;
408 }
409
410 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400411 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
412 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700413 return;
414 }
Mike Klein744fb732014-06-23 15:13:26 -0400415
bsalomon6663acf2016-05-10 09:14:17 -0700416 GrStyle style(paint);
Brian Salomon82f44312017-01-11 13:42:54 -0500417 fRenderTargetContext->drawRect(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
418 *draw.fMatrix, rect, &style);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000419}
420
421///////////////////////////////////////////////////////////////////////////////
422
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500423void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800424 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500425 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRRect", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800426 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000427
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000428 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
Robert Phillipsa29a9562016-10-20 09:40:55 -0400434 SkMaskFilter* mf = paint.getMaskFilter();
435 if (mf && mf->asFragmentProcessor(nullptr, nullptr, *draw.fMatrix)) {
436 mf = nullptr; // already handled in SkPaintToGrPaint
437 }
438
bsalomon6663acf2016-05-10 09:14:17 -0700439 GrStyle style(paint);
Robert Phillipsa29a9562016-10-20 09:40:55 -0400440 if (mf) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000441 // try to hit the fast path for drawing filtered round rects
442
443 SkRRect devRRect;
robertphillips9aff85a2016-08-05 07:51:29 -0700444 if (rrect.transform(*draw.fMatrix, &devRRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000445 if (devRRect.allCornersCircular()) {
446 SkRect maskRect;
Robert Phillipsa29a9562016-10-20 09:40:55 -0400447 if (mf->canFilterMaskGPU(devRRect, draw.fRC->getBounds(),
448 *draw.fMatrix, &maskRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000449 SkIRect finalIRect;
450 maskRect.roundOut(&finalIRect);
reed1e7f5e72016-04-27 07:49:17 -0700451 if (draw.fRC->quickReject(finalIRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000452 // clipped out
453 return;
454 }
Hal Canary144caf52016-11-07 17:57:18 -0500455 if (mf->directFilterRRectMaskGPU(fContext.get(), fRenderTargetContext.get(),
Brian Salomon82f44312017-01-11 13:42:54 -0500456 std::move(grPaint), fClip, *draw.fMatrix,
Hal Canary144caf52016-11-07 17:57:18 -0500457 style.strokeRec(), rrect, devRRect)) {
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000458 return;
459 }
460 }
461
462 }
463 }
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000464 }
465
Robert Phillipsa29a9562016-10-20 09:40:55 -0400466 if (mf || style.pathEffect()) {
robertphillipsff55b492015-11-24 07:56:59 -0800467 // The only mask filter the native rrect drawing code could've handle was taken
468 // care of above.
469 // A path effect will presumably transform this rrect into something else.
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000470 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700471 path.setIsVolatile(true);
robertphillips9aff85a2016-08-05 07:51:29 -0700472 path.addRRect(rrect);
Hal Canary144caf52016-11-07 17:57:18 -0500473 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillipsff55b492015-11-24 07:56:59 -0800474 fClip, path, paint,
475 *draw.fMatrix, nullptr,
reed1e7f5e72016-04-27 07:49:17 -0700476 draw.fRC->getBounds(), true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000477 return;
478 }
Mike Klein744fb732014-06-23 15:13:26 -0400479
bsalomon6663acf2016-05-10 09:14:17 -0700480 SkASSERT(!style.pathEffect());
robertphillips514450c2015-11-24 05:36:02 -0800481
Brian Salomon82f44312017-01-11 13:42:54 -0500482 fRenderTargetContext->drawRRect(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
483 *draw.fMatrix, rrect, style);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000484}
485
robertphillipsd7706102016-02-25 09:28:08 -0800486
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000487void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
joshualitt5531d512014-12-17 15:50:11 -0800488 const SkRRect& inner, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800489 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500490 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawDRRect", fContext.get());
robertphillips0e7029e2015-11-30 05:45:06 -0800491 CHECK_SHOULD_DRAW(draw);
492
robertphillipsd7706102016-02-25 09:28:08 -0800493 if (outer.isEmpty()) {
494 return;
495 }
496
497 if (inner.isEmpty()) {
498 return this->drawRRect(draw, outer, paint);
499 }
500
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000501 SkStrokeRec stroke(paint);
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000502
robertphillips0e7029e2015-11-30 05:45:06 -0800503 if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
robertphillips00095892016-02-29 13:50:40 -0800504 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400505 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
brianosman1638c0d2016-07-25 05:12:53 -0700506 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700507 return;
508 }
robertphillips00095892016-02-29 13:50:40 -0800509
Brian Salomon82f44312017-01-11 13:42:54 -0500510 fRenderTargetContext->drawDRRect(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500511 *draw.fMatrix, outer, inner);
robertphillips00095892016-02-29 13:50:40 -0800512 return;
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000513 }
514
515 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700516 path.setIsVolatile(true);
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000517 path.addRRect(outer);
518 path.addRRect(inner);
519 path.setFillType(SkPath::kEvenOdd_FillType);
520
Hal Canary144caf52016-11-07 17:57:18 -0500521 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillips0e7029e2015-11-30 05:45:06 -0800522 fClip, path, paint,
523 *draw.fMatrix, nullptr,
reed1e7f5e72016-04-27 07:49:17 -0700524 draw.fRC->getBounds(), true);
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000525}
526
527
commit-bot@chromium.org82139702014-03-10 22:53:20 +0000528/////////////////////////////////////////////////////////////////////////////
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000529
msarettcc319b92016-08-25 18:07:18 -0700530void SkGpuDevice::drawRegion(const SkDraw& draw, const SkRegion& region, const SkPaint& paint) {
531 if (paint.getMaskFilter()) {
532 SkPath path;
533 region.getBoundaryPath(&path);
534 return this->drawPath(draw, path, paint, nullptr, false);
535 }
536
537 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400538 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
539 &grPaint)) {
msarettcc319b92016-08-25 18:07:18 -0700540 return;
541 }
542
Brian Salomon82f44312017-01-11 13:42:54 -0500543 fRenderTargetContext->drawRegion(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
544 *draw.fMatrix, region, GrStyle(paint));
msarettcc319b92016-08-25 18:07:18 -0700545}
546
robertphillips514450c2015-11-24 05:36:02 -0800547void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800548 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500549 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawOval", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -0800550 CHECK_SHOULD_DRAW(draw);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000551
robertphillips514450c2015-11-24 05:36:02 -0800552 // Presumably the path effect warps this to something other than an oval
553 if (paint.getPathEffect()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000554 SkPath path;
jvanverthb3eb6872014-10-24 07:12:51 -0700555 path.setIsVolatile(true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000556 path.addOval(oval);
halcanary96fcdcc2015-08-27 07:41:13 -0700557 this->drawPath(draw, path, paint, nullptr, true);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000558 return;
herb11a7f7f2015-11-24 12:41:00 -0800559 }
560
robertphillips514450c2015-11-24 05:36:02 -0800561 if (paint.getMaskFilter()) {
562 // The RRect path can handle special case blurring
563 SkRRect rr = SkRRect::MakeOval(oval);
564 return this->drawRRect(draw, rr, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000565 }
566
567 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400568 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
569 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700570 return;
571 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000572
Brian Salomon82f44312017-01-11 13:42:54 -0500573 fRenderTargetContext->drawOval(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
574 *draw.fMatrix, oval, GrStyle(paint));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000575}
576
bsalomon4f3a0ca2016-08-22 13:14:26 -0700577void SkGpuDevice::drawArc(const SkDraw& draw, const SkRect& oval, SkScalar startAngle,
578 SkScalar sweepAngle, bool useCenter, const SkPaint& paint) {
579 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500580 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawArc", fContext.get());
bsalomon4f3a0ca2016-08-22 13:14:26 -0700581 CHECK_SHOULD_DRAW(draw);
582
583 if (paint.getMaskFilter()) {
584 this->INHERITED::drawArc(draw, oval, startAngle, sweepAngle, useCenter, paint);
585 return;
586 }
587 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400588 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
589 &grPaint)) {
bsalomon4f3a0ca2016-08-22 13:14:26 -0700590 return;
591 }
592
Brian Salomon82f44312017-01-11 13:42:54 -0500593 fRenderTargetContext->drawArc(fClip, std::move(grPaint), GrBoolToAA(paint.isAntiAlias()),
594 *draw.fMatrix, oval, startAngle, sweepAngle, useCenter,
595 GrStyle(paint));
bsalomon4f3a0ca2016-08-22 13:14:26 -0700596}
597
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000598#include "SkMaskFilter.h"
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000599
600///////////////////////////////////////////////////////////////////////////////
robertphillips0851d2d2016-06-02 05:21:34 -0700601void SkGpuDevice::drawStrokedLine(const SkPoint points[2],
602 const SkDraw& draw,
603 const SkPaint& origPaint) {
604 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -0500605 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawStrokedLine", fContext.get());
robertphillips0851d2d2016-06-02 05:21:34 -0700606 CHECK_SHOULD_DRAW(draw);
607
Brian Osman11052242016-10-27 14:47:55 -0400608 // Adding support for round capping would require a
609 // GrRenderTargetContext::fillRRectWithLocalMatrix entry point
robertphillips0851d2d2016-06-02 05:21:34 -0700610 SkASSERT(SkPaint::kRound_Cap != origPaint.getStrokeCap());
611 SkASSERT(SkPaint::kStroke_Style == origPaint.getStyle());
612 SkASSERT(!origPaint.getPathEffect());
613 SkASSERT(!origPaint.getMaskFilter());
614
615 const SkScalar halfWidth = 0.5f * origPaint.getStrokeWidth();
616 SkASSERT(halfWidth > 0);
617
618 SkVector v = points[1] - points[0];
619
620 SkScalar length = SkPoint::Normalize(&v);
621 if (!length) {
622 v.fX = 1.0f;
623 v.fY = 0.0f;
624 }
625
626 SkPaint newPaint(origPaint);
627 newPaint.setStyle(SkPaint::kFill_Style);
628
629 SkScalar xtraLength = 0.0f;
630 if (SkPaint::kButt_Cap != origPaint.getStrokeCap()) {
631 xtraLength = halfWidth;
632 }
633
634 SkPoint mid = points[0] + points[1];
635 mid.scale(0.5f);
636
637 SkRect rect = SkRect::MakeLTRB(mid.fX-halfWidth, mid.fY - 0.5f*length - xtraLength,
638 mid.fX+halfWidth, mid.fY + 0.5f*length + xtraLength);
639 SkMatrix m;
640 m.setSinCos(v.fX, -v.fY, mid.fX, mid.fY);
641
642 SkMatrix local = m;
643
644 m.postConcat(*draw.fMatrix);
645
646 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400647 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), newPaint, m, &grPaint)) {
robertphillips0851d2d2016-06-02 05:21:34 -0700648 return;
649 }
650
Brian Salomon82f44312017-01-11 13:42:54 -0500651 fRenderTargetContext->fillRectWithLocalMatrix(
652 fClip, std::move(grPaint), GrBoolToAA(newPaint.isAntiAlias()), m, rect, local);
robertphillips0851d2d2016-06-02 05:21:34 -0700653}
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000654
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000655void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
656 const SkPaint& paint, const SkMatrix* prePathMatrix,
657 bool pathIsMutable) {
joshualittce894002016-01-11 13:29:31 -0800658 ASSERT_SINGLE_OWNER
robertphillipsff55b492015-11-24 07:56:59 -0800659 if (!origSrcPath.isInverseFillType() && !paint.getPathEffect() && !prePathMatrix) {
robertphillips0851d2d2016-06-02 05:21:34 -0700660 SkPoint points[2];
661 if (SkPaint::kStroke_Style == paint.getStyle() && paint.getStrokeWidth() > 0 &&
662 !paint.getMaskFilter() && SkPaint::kRound_Cap != paint.getStrokeCap() &&
663 draw.fMatrix->preservesRightAngles() && origSrcPath.isLine(points)) {
664 // Path-based stroking looks better for thin rects
665 SkScalar strokeWidth = draw.fMatrix->getMaxScale() * paint.getStrokeWidth();
robertphillipsf2204c92016-06-02 10:57:59 -0700666 if (strokeWidth >= 1.0f) {
Brian Salomon09d994e2016-12-21 11:14:46 -0500667 // Round capping support is currently disabled b.c. it would require a RRect
668 // GrDrawOp that takes a localMatrix.
robertphillips0851d2d2016-06-02 05:21:34 -0700669 this->drawStrokedLine(points, draw, paint);
670 return;
671 }
672 }
robertphillipsff55b492015-11-24 07:56:59 -0800673 bool isClosed;
674 SkRect rect;
675 if (origSrcPath.isRect(&rect, &isClosed) && isClosed) {
676 this->drawRect(draw, rect, paint);
677 return;
678 }
679 if (origSrcPath.isOval(&rect)) {
680 this->drawOval(draw, rect, paint);
681 return;
682 }
683 SkRRect rrect;
684 if (origSrcPath.isRRect(&rrect)) {
685 this->drawRRect(draw, rrect, paint);
686 return;
687 }
688 }
689
joshualitt5531d512014-12-17 15:50:11 -0800690 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -0500691 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPath", fContext.get());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000692
Hal Canary144caf52016-11-07 17:57:18 -0500693 GrBlurUtils::drawPathWithMaskFilter(fContext.get(), fRenderTargetContext.get(),
robertphillipsccb1b572015-05-27 11:02:55 -0700694 fClip, origSrcPath, paint,
695 *draw.fMatrix, prePathMatrix,
reed1e7f5e72016-04-27 07:49:17 -0700696 draw.fRC->getBounds(), pathIsMutable);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000697}
698
699static const int kBmpSmallTileSize = 1 << 10;
700
701static inline int get_tile_count(const SkIRect& srcRect, int tileSize) {
702 int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1;
703 int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1;
704 return tilesX * tilesY;
705}
706
reed85d91782015-09-10 14:33:38 -0700707static int determine_tile_size(const SkIRect& src, int maxTileSize) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000708 if (maxTileSize <= kBmpSmallTileSize) {
709 return maxTileSize;
710 }
711
712 size_t maxTileTotalTileSize = get_tile_count(src, maxTileSize);
713 size_t smallTotalTileSize = get_tile_count(src, kBmpSmallTileSize);
714
715 maxTileTotalTileSize *= maxTileSize * maxTileSize;
716 smallTotalTileSize *= kBmpSmallTileSize * kBmpSmallTileSize;
717
718 if (maxTileTotalTileSize > 2 * smallTotalTileSize) {
719 return kBmpSmallTileSize;
720 } else {
721 return maxTileSize;
722 }
723}
724
725// Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
726// pixels from the bitmap are necessary.
robertphillipse5768742016-05-13 11:20:46 -0700727static void determine_clipped_src_rect(int width, int height,
joshualitt570d2f82015-02-25 13:19:48 -0800728 const GrClip& clip,
joshualitt5531d512014-12-17 15:50:11 -0800729 const SkMatrix& viewMatrix,
bsalomone553b642016-08-17 09:02:09 -0700730 const SkMatrix& srcToDstRect,
reed85d91782015-09-10 14:33:38 -0700731 const SkISize& imageSize,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000732 const SkRect* srcRectPtr,
733 SkIRect* clippedSrcIRect) {
robertphillipse5768742016-05-13 11:20:46 -0700734 clip.getConservativeBounds(width, height, clippedSrcIRect, nullptr);
bsalomone553b642016-08-17 09:02:09 -0700735 SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect);
736 if (!inv.invert(&inv)) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000737 clippedSrcIRect->setEmpty();
738 return;
739 }
740 SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
741 inv.mapRect(&clippedSrcRect);
bsalomon49f085d2014-09-05 13:34:00 -0700742 if (srcRectPtr) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000743 if (!clippedSrcRect.intersect(*srcRectPtr)) {
744 clippedSrcIRect->setEmpty();
745 return;
746 }
747 }
748 clippedSrcRect.roundOut(clippedSrcIRect);
reed85d91782015-09-10 14:33:38 -0700749 SkIRect bmpBounds = SkIRect::MakeSize(imageSize);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000750 if (!clippedSrcIRect->intersect(bmpBounds)) {
751 clippedSrcIRect->setEmpty();
752 }
753}
754
reed85d91782015-09-10 14:33:38 -0700755bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect,
756 const SkMatrix& viewMatrix,
bsalomone553b642016-08-17 09:02:09 -0700757 const SkMatrix& srcToDstRect,
Brian Salomon514baff2016-11-17 15:17:07 -0500758 const GrSamplerParams& params,
reed85d91782015-09-10 14:33:38 -0700759 const SkRect* srcRectPtr,
760 int maxTileSize,
761 int* tileSize,
762 SkIRect* clippedSubset) const {
joshualittce894002016-01-11 13:29:31 -0800763 ASSERT_SINGLE_OWNER
reed85d91782015-09-10 14:33:38 -0700764 // if it's larger than the max tile size, then we have no choice but tiling.
765 if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) {
Brian Osman11052242016-10-27 14:47:55 -0400766 determine_clipped_src_rect(fRenderTargetContext->width(), fRenderTargetContext->height(),
767 fClip, viewMatrix, srcToDstRect, imageRect.size(), srcRectPtr,
768 clippedSubset);
reed85d91782015-09-10 14:33:38 -0700769 *tileSize = determine_tile_size(*clippedSubset, maxTileSize);
770 return true;
771 }
772
bsalomon1a1d0b82015-10-16 07:49:42 -0700773 // If the image would only produce 4 tiles of the smaller size, don't bother tiling it.
reed85d91782015-09-10 14:33:38 -0700774 const size_t area = imageRect.width() * imageRect.height();
775 if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
776 return false;
777 }
778
reed85d91782015-09-10 14:33:38 -0700779 // At this point we know we could do the draw by uploading the entire bitmap
780 // as a texture. However, if the texture would be large compared to the
781 // cache size and we don't require most of it for this draw then tile to
782 // reduce the amount of upload and cache spill.
783
784 // assumption here is that sw bitmap size is a good proxy for its size as
785 // a texture
786 size_t bmpSize = area * sizeof(SkPMColor); // assume 32bit pixels
787 size_t cacheSize;
788 fContext->getResourceCacheLimits(nullptr, &cacheSize);
789 if (bmpSize < cacheSize / 2) {
790 return false;
791 }
792
bsalomon1a1d0b82015-10-16 07:49:42 -0700793 // Figure out how much of the src we will need based on the src rect and clipping. Reject if
794 // tiling memory savings would be < 50%.
Brian Osman11052242016-10-27 14:47:55 -0400795 determine_clipped_src_rect(fRenderTargetContext->width(), fRenderTargetContext->height(), fClip,
796 viewMatrix, srcToDstRect, imageRect.size(), srcRectPtr,
797 clippedSubset);
reed85d91782015-09-10 14:33:38 -0700798 *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
799 size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) *
800 kBmpSmallTileSize * kBmpSmallTileSize;
801
802 return usedTileBytes < 2 * bmpSize;
803}
804
reed85d91782015-09-10 14:33:38 -0700805bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr,
806 SkCanvas::SrcRectConstraint constraint, SkFilterQuality quality,
bsalomone553b642016-08-17 09:02:09 -0700807 const SkMatrix& viewMatrix,
808 const SkMatrix& srcToDstRect) const {
joshualittce894002016-01-11 13:29:31 -0800809 ASSERT_SINGLE_OWNER
reed85d91782015-09-10 14:33:38 -0700810 // if image is explictly texture backed then just use the texture
811 if (as_IB(image)->peekTexture()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000812 return false;
813 }
814
Brian Salomon514baff2016-11-17 15:17:07 -0500815 GrSamplerParams params;
reed85d91782015-09-10 14:33:38 -0700816 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -0500817 GrSamplerParams::FilterMode textureFilterMode =
bsalomone553b642016-08-17 09:02:09 -0700818 GrSkFilterQualityToGrFilterMode(quality, viewMatrix, srcToDstRect, &doBicubic);
reed85d91782015-09-10 14:33:38 -0700819
820 int tileFilterPad;
821 if (doBicubic) {
822 tileFilterPad = GrBicubicEffect::kFilterTexelPad;
Brian Salomon514baff2016-11-17 15:17:07 -0500823 } else if (GrSamplerParams::kNone_FilterMode == textureFilterMode) {
reed85d91782015-09-10 14:33:38 -0700824 tileFilterPad = 0;
825 } else {
826 tileFilterPad = 1;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000827 }
reed85d91782015-09-10 14:33:38 -0700828 params.setFilterMode(textureFilterMode);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000829
bsalomon8c07b7a2015-11-02 11:36:52 -0800830 int maxTileSize = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000831
reed85d91782015-09-10 14:33:38 -0700832 // these are output, which we safely ignore, as we just want to know the predicate
833 int outTileSize;
834 SkIRect outClippedSrcRect;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000835
bsalomone553b642016-08-17 09:02:09 -0700836 return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix, srcToDstRect,
837 params, srcRectPtr, maxTileSize, &outTileSize,
838 &outClippedSrcRect);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000839}
840
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +0000841void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000842 const SkBitmap& bitmap,
843 const SkMatrix& m,
844 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -0800845 ASSERT_SINGLE_OWNER
bsalomonb1b01992015-11-18 10:56:08 -0800846 CHECK_SHOULD_DRAW(origDraw);
bsalomonb1b01992015-11-18 10:56:08 -0800847 SkMatrix viewMatrix;
848 viewMatrix.setConcat(*origDraw.fMatrix, m);
reedc7ec7c92016-07-25 08:29:10 -0700849
bsalomonb1b01992015-11-18 10:56:08 -0800850 int maxTileSize = fContext->caps()->maxTileSize();
851
852 // The tile code path doesn't currently support AA, so if the paint asked for aa and we could
853 // draw untiled, then we bypass checking for tiling purely for optimization reasons.
Brian Osman11052242016-10-27 14:47:55 -0400854 bool drawAA = !fRenderTargetContext->isUnifiedMultisampled() &&
bsalomonb1b01992015-11-18 10:56:08 -0800855 paint.isAntiAlias() &&
856 bitmap.width() <= maxTileSize &&
857 bitmap.height() <= maxTileSize;
858
859 bool skipTileCheck = drawAA || paint.getMaskFilter();
860
861 if (!skipTileCheck) {
862 SkRect srcRect = SkRect::MakeIWH(bitmap.width(), bitmap.height());
863 int tileSize;
864 SkIRect clippedSrcRect;
865
Brian Salomon514baff2016-11-17 15:17:07 -0500866 GrSamplerParams params;
bsalomonb1b01992015-11-18 10:56:08 -0800867 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -0500868 GrSamplerParams::FilterMode textureFilterMode =
bsalomonb1b01992015-11-18 10:56:08 -0800869 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix, SkMatrix::I(),
870 &doBicubic);
871
872 int tileFilterPad;
873
874 if (doBicubic) {
875 tileFilterPad = GrBicubicEffect::kFilterTexelPad;
Brian Salomon514baff2016-11-17 15:17:07 -0500876 } else if (GrSamplerParams::kNone_FilterMode == textureFilterMode) {
bsalomonb1b01992015-11-18 10:56:08 -0800877 tileFilterPad = 0;
878 } else {
879 tileFilterPad = 1;
880 }
881 params.setFilterMode(textureFilterMode);
882
883 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
bsalomone553b642016-08-17 09:02:09 -0700884 if (this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), viewMatrix,
885 SkMatrix::I(), params, &srcRect, maxTileSizeForFilter,
886 &tileSize, &clippedSrcRect)) {
887 this->drawTiledBitmap(bitmap, viewMatrix, SkMatrix::I(), srcRect, clippedSrcRect,
888 params, paint, SkCanvas::kStrict_SrcRectConstraint, tileSize,
889 doBicubic);
bsalomonb1b01992015-11-18 10:56:08 -0800890 return;
891 }
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +0000892 }
Hal Canary144caf52016-11-07 17:57:18 -0500893 GrBitmapTextureMaker maker(fContext.get(), bitmap);
bsalomonf1ecd212015-12-09 17:06:02 -0800894 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kStrict_SrcRectConstraint,
895 viewMatrix, fClip, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000896}
897
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000898// This method outsets 'iRect' by 'outset' all around and then clamps its extents to
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000899// 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner
900// of 'iRect' for all possible outsets/clamps.
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000901static inline void clamped_outset_with_offset(SkIRect* iRect,
902 int outset,
903 SkPoint* offset,
904 const SkIRect& clamp) {
905 iRect->outset(outset, outset);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000906
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000907 int leftClampDelta = clamp.fLeft - iRect->fLeft;
908 if (leftClampDelta > 0) {
909 offset->fX -= outset - leftClampDelta;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000910 iRect->fLeft = clamp.fLeft;
911 } else {
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000912 offset->fX -= outset;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000913 }
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000914
915 int topClampDelta = clamp.fTop - iRect->fTop;
916 if (topClampDelta > 0) {
917 offset->fY -= outset - topClampDelta;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000918 iRect->fTop = clamp.fTop;
919 } else {
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000920 offset->fY -= outset;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000921 }
922
923 if (iRect->fRight > clamp.fRight) {
924 iRect->fRight = clamp.fRight;
925 }
926 if (iRect->fBottom > clamp.fBottom) {
927 iRect->fBottom = clamp.fBottom;
928 }
929}
930
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000931// Break 'bitmap' into several tiles to draw it since it has already
932// been determined to be too large to fit in VRAM
933void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
joshualitt5531d512014-12-17 15:50:11 -0800934 const SkMatrix& viewMatrix,
bsalomone553b642016-08-17 09:02:09 -0700935 const SkMatrix& dstMatrix,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000936 const SkRect& srcRect,
937 const SkIRect& clippedSrcIRect,
Brian Salomon514baff2016-11-17 15:17:07 -0500938 const GrSamplerParams& params,
bsalomonc55271f2015-11-09 11:55:57 -0800939 const SkPaint& origPaint,
reeda5517e22015-07-14 10:54:12 -0700940 SkCanvas::SrcRectConstraint constraint,
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +0000941 int tileSize,
942 bool bicubic) {
joshualittce894002016-01-11 13:29:31 -0800943 ASSERT_SINGLE_OWNER
ericrk369e9372016-02-05 15:32:36 -0800944
ericrk983294f2016-04-18 09:14:00 -0700945 // This is the funnel for all paths that draw tiled bitmaps/images. Log histogram entries.
ericrk369e9372016-02-05 15:32:36 -0800946 SK_HISTOGRAM_BOOLEAN("DrawTiled", true);
ericrk983294f2016-04-18 09:14:00 -0700947 LogDrawScaleFactor(viewMatrix, origPaint.getFilterQuality());
ericrk369e9372016-02-05 15:32:36 -0800948
commit-bot@chromium.org9d5e3f12014-05-01 21:23:19 +0000949 // The following pixel lock is technically redundant, but it is desirable
950 // to lock outside of the tile loop to prevent redecoding the whole image
951 // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that
952 // is larger than the limit of the discardable memory pool.
953 SkAutoLockPixels alp(bitmap);
bsalomonc55271f2015-11-09 11:55:57 -0800954
955 const SkPaint* paint = &origPaint;
956 SkPaint tempPaint;
Brian Osman11052242016-10-27 14:47:55 -0400957 if (origPaint.isAntiAlias() && !fRenderTargetContext->isUnifiedMultisampled()) {
bsalomonc55271f2015-11-09 11:55:57 -0800958 // Drop antialiasing to avoid seams at tile boundaries.
959 tempPaint = origPaint;
960 tempPaint.setAntiAlias(false);
961 paint = &tempPaint;
962 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000963 SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
964
965 int nx = bitmap.width() / tileSize;
966 int ny = bitmap.height() / tileSize;
967 for (int x = 0; x <= nx; x++) {
968 for (int y = 0; y <= ny; y++) {
969 SkRect tileR;
970 tileR.set(SkIntToScalar(x * tileSize),
971 SkIntToScalar(y * tileSize),
972 SkIntToScalar((x + 1) * tileSize),
973 SkIntToScalar((y + 1) * tileSize));
974
975 if (!SkRect::Intersects(tileR, clippedSrcRect)) {
976 continue;
977 }
978
979 if (!tileR.intersect(srcRect)) {
980 continue;
981 }
982
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000983 SkIRect iTileR;
984 tileR.roundOut(&iTileR);
bsalomone553b642016-08-17 09:02:09 -0700985 SkVector offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
986 SkIntToScalar(iTileR.fTop));
987 SkRect rectToDraw = SkRect::MakeXYWH(offset.fX, offset.fY,
988 tileR.width(), tileR.height());
989 dstMatrix.mapRect(&rectToDraw);
Brian Salomon514baff2016-11-17 15:17:07 -0500990 if (GrSamplerParams::kNone_FilterMode != params.filterMode() || bicubic) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000991 SkIRect iClampRect;
992
reeda5517e22015-07-14 10:54:12 -0700993 if (SkCanvas::kFast_SrcRectConstraint == constraint) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000994 // In bleed mode we want to always expand the tile on all edges
995 // but stay within the bitmap bounds
996 iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height());
997 } else {
998 // In texture-domain/clamp mode we only want to expand the
999 // tile on edges interior to "srcRect" (i.e., we want to
1000 // not bleed across the original clamped edges)
1001 srcRect.roundOut(&iClampRect);
1002 }
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +00001003 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1;
1004 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001005 }
1006
bsalomone553b642016-08-17 09:02:09 -07001007 SkBitmap tmpB;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001008 if (bitmap.extractSubset(&tmpB, iTileR)) {
1009 // now offset it to make it "local" to our tmp bitmap
1010 tileR.offset(-offset.fX, -offset.fY);
Brian Salomon514baff2016-11-17 15:17:07 -05001011 GrSamplerParams paramsTemp = params;
bsalomonb1b01992015-11-18 10:56:08 -08001012 // de-optimized this determination
1013 bool needsTextureDomain = true;
bsalomone553b642016-08-17 09:02:09 -07001014 this->drawBitmapTile(tmpB,
1015 viewMatrix,
1016 rectToDraw,
1017 tileR,
1018 paramsTemp,
1019 *paint,
1020 constraint,
1021 bicubic,
1022 needsTextureDomain);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001023 }
1024 }
1025 }
1026}
1027
bsalomone553b642016-08-17 09:02:09 -07001028void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
1029 const SkMatrix& viewMatrix,
1030 const SkRect& dstRect,
1031 const SkRect& srcRect,
Brian Salomon514baff2016-11-17 15:17:07 -05001032 const GrSamplerParams& params,
bsalomone553b642016-08-17 09:02:09 -07001033 const SkPaint& paint,
1034 SkCanvas::SrcRectConstraint constraint,
1035 bool bicubic,
1036 bool needsTextureDomain) {
bsalomon9c586542015-11-02 12:33:21 -08001037 // We should have already handled bitmaps larger than the max texture size.
1038 SkASSERT(bitmap.width() <= fContext->caps()->maxTextureSize() &&
1039 bitmap.height() <= fContext->caps()->maxTextureSize());
reedc7ec7c92016-07-25 08:29:10 -07001040 // We should be respecting the max tile size by the time we get here.
1041 SkASSERT(bitmap.width() <= fContext->caps()->maxTileSize() &&
1042 bitmap.height() <= fContext->caps()->maxTileSize());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001043
Brian Osman61624f02016-12-09 14:51:59 -05001044 sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext.get(), bitmap, params);
halcanary96fcdcc2015-08-27 07:41:13 -07001045 if (nullptr == texture) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001046 return;
1047 }
brianosman500bb3e2016-07-22 10:33:07 -07001048 sk_sp<GrColorSpaceXform> colorSpaceXform =
Brian Osman11052242016-10-27 14:47:55 -04001049 GrColorSpaceXform::Make(bitmap.colorSpace(), fRenderTargetContext->getColorSpace());
bsalomone553b642016-08-17 09:02:09 -07001050
1051 SkScalar iw = 1.f / texture->width();
1052 SkScalar ih = 1.f / texture->height();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001053
egdaniel79da63f2015-10-09 10:55:16 -07001054 SkMatrix texMatrix;
bsalomone553b642016-08-17 09:02:09 -07001055 // Compute a matrix that maps the rect we will draw to the src rect.
Brian Salomond93f4a42016-11-14 14:41:58 -05001056 texMatrix.setRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
bsalomone553b642016-08-17 09:02:09 -07001057 texMatrix.postScale(iw, ih);
joshualitt5f10b5c2015-07-09 10:24:35 -07001058
1059 // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
1060 // the rest from the SkPaint.
bungeman06ca8ec2016-06-09 08:01:03 -07001061 sk_sp<GrFragmentProcessor> fp;
joshualitt5f10b5c2015-07-09 10:24:35 -07001062
reeda5517e22015-07-14 10:54:12 -07001063 if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001064 // Use a constrained texture domain to avoid color bleeding
bsalomone553b642016-08-17 09:02:09 -07001065 SkRect domain;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001066 if (srcRect.width() > SK_Scalar1) {
Robert Phillipse98234f2017-01-09 14:23:59 -05001067 domain.fLeft = srcRect.fLeft + 0.5f;
1068 domain.fRight = srcRect.fRight - 0.5f;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001069 } else {
Robert Phillipse98234f2017-01-09 14:23:59 -05001070 domain.fLeft = domain.fRight = srcRect.centerX();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001071 }
1072 if (srcRect.height() > SK_Scalar1) {
Robert Phillipse98234f2017-01-09 14:23:59 -05001073 domain.fTop = srcRect.fTop + 0.5f;
1074 domain.fBottom = srcRect.fBottom - 0.5f;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001075 } else {
Robert Phillipse98234f2017-01-09 14:23:59 -05001076 domain.fTop = domain.fBottom = srcRect.centerY();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001077 }
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +00001078 if (bicubic) {
reedc7ec7c92016-07-25 08:29:10 -07001079 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix,
bsalomone553b642016-08-17 09:02:09 -07001080 domain);
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +00001081 } else {
reedc7ec7c92016-07-25 08:29:10 -07001082 fp = GrTextureDomainEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix,
bsalomone553b642016-08-17 09:02:09 -07001083 domain, GrTextureDomain::kClamp_Mode,
brianosman54f30c12016-07-18 10:53:52 -07001084 params.filterMode());
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +00001085 }
commit-bot@chromium.orgdec61502013-12-02 22:22:35 +00001086 } else if (bicubic) {
Brian Salomon514baff2016-11-17 15:17:07 -05001087 SkASSERT(GrSamplerParams::kNone_FilterMode == params.filterMode());
commit-bot@chromium.orgbc91fd72013-12-10 12:53:39 +00001088 SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTileModeY() };
reedc7ec7c92016-07-25 08:29:10 -07001089 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix, tileModes);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001090 } else {
reedc7ec7c92016-07-25 08:29:10 -07001091 fp = GrSimpleTextureEffect::Make(texture.get(), std::move(colorSpaceXform), texMatrix, params);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001092 }
1093
joshualitt33a5fce2015-11-18 13:28:51 -08001094 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -04001095 if (!SkPaintToGrPaintWithTexture(this->context(), fRenderTargetContext.get(), paint, viewMatrix,
brianosman8fe485b2016-07-25 12:31:51 -07001096 std::move(fp), kAlpha_8_SkColorType == bitmap.colorType(),
1097 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -07001098 return;
1099 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001100
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001101 // Coverage-based AA would cause seams between tiles.
1102 GrAA aa = GrBoolToAA(paint.isAntiAlias() &&
1103 fRenderTargetContext->isStencilBufferMultisampled());
Brian Salomon82f44312017-01-11 13:42:54 -05001104 fRenderTargetContext->drawRect(fClip, std::move(grPaint), aa, viewMatrix, dstRect);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001105}
1106
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001107void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
1108 int left, int top, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001109 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -08001110 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001111 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSprite", fContext.get());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001112
robertphillips970587b2016-07-14 14:12:55 -07001113 if (fContext->abandoned()) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001114 return;
1115 }
1116
reedc7ec7c92016-07-25 08:29:10 -07001117 sk_sp<GrTexture> texture;
1118 {
robertphillips970587b2016-07-14 14:12:55 -07001119 SkAutoLockPixels alp(bitmap, true);
1120 if (!bitmap.readyToDraw()) {
1121 return;
1122 }
1123
1124 // draw sprite neither filters nor tiles.
Brian Osman7b8400d2016-11-08 17:08:54 -05001125 texture.reset(
Brian Osman61624f02016-12-09 14:51:59 -05001126 GrRefCachedBitmapTexture(fContext.get(), bitmap, GrSamplerParams::ClampNoFilter()));
robertphillips970587b2016-07-14 14:12:55 -07001127 if (!texture) {
1128 return;
1129 }
joshualitt5f5a8d72015-02-25 14:09:45 -08001130 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001131
robertphillips970587b2016-07-14 14:12:55 -07001132 SkIRect srcRect = SkIRect::MakeXYWH(bitmap.pixelRefOrigin().fX,
1133 bitmap.pixelRefOrigin().fY,
1134 bitmap.width(),
1135 bitmap.height());
bsalomonf1b7a1d2015-09-28 06:26:28 -07001136
robertphillips970587b2016-07-14 14:12:55 -07001137 sk_sp<SkSpecialImage> srcImg(SkSpecialImage::MakeFromGpu(srcRect,
1138 bitmap.getGenerationID(),
brianosmanafbf71d2016-07-21 07:15:37 -07001139 std::move(texture),
Robert Phillips70b49fd2017-01-13 11:21:36 -05001140 bitmap.refColorSpace(),
robertphillips1b5f9682016-07-15 08:01:12 -07001141 &this->surfaceProps()));
robertphillips970587b2016-07-14 14:12:55 -07001142
1143 this->drawSpecial(draw, srcImg.get(), left, top, paint);
1144}
1145
1146
Mike Kleine54c75f2016-10-13 14:18:09 -04001147void SkGpuDevice::drawSpecial(const SkDraw& draw,
robertphillips970587b2016-07-14 14:12:55 -07001148 SkSpecialImage* special1,
1149 int left, int top,
1150 const SkPaint& paint) {
robertphillips1b5f9682016-07-15 08:01:12 -07001151 ASSERT_SINGLE_OWNER
1152 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001153 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpecial", fContext.get());
robertphillips970587b2016-07-14 14:12:55 -07001154
1155 SkIPoint offset = { 0, 0 };
1156
1157 sk_sp<SkSpecialImage> result;
1158 if (paint.getImageFilter()) {
1159 result = this->filterTexture(draw, special1, left, top,
1160 &offset,
1161 paint.getImageFilter());
1162 if (!result) {
1163 return;
1164 }
1165 } else {
1166 result = sk_ref_sp(special1);
1167 }
1168
1169 SkASSERT(result->isTextureBacked());
Hal Canary144caf52016-11-07 17:57:18 -05001170 sk_sp<GrTexture> texture = result->asTextureRef(fContext.get());
Robert Phillips833dcf42016-11-18 08:44:13 -05001171 if (!texture) {
1172 return;
1173 }
robertphillips970587b2016-07-14 14:12:55 -07001174
1175 SkPaint tmpUnfiltered(paint);
1176 tmpUnfiltered.setImageFilter(nullptr);
1177
brianosman77320db2016-09-07 08:09:10 -07001178 sk_sp<GrColorSpaceXform> colorSpaceXform =
Brian Osman11052242016-10-27 14:47:55 -04001179 GrColorSpaceXform::Make(result->getColorSpace(), fRenderTargetContext->getColorSpace());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001180 GrPaint grPaint;
brianosman77320db2016-09-07 08:09:10 -07001181 sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture.get(),
1182 std::move(colorSpaceXform),
brianosman54f30c12016-07-18 10:53:52 -07001183 SkMatrix::I()));
robertphillips1b5f9682016-07-15 08:01:12 -07001184 if (GrPixelConfigIsAlphaOnly(texture->config())) {
bungeman06ca8ec2016-06-09 08:01:03 -07001185 fp = GrFragmentProcessor::MulOutputByInputUnpremulColor(std::move(fp));
bsalomonf1b7a1d2015-09-28 06:26:28 -07001186 } else {
bungeman06ca8ec2016-06-09 08:01:03 -07001187 fp = GrFragmentProcessor::MulOutputByInputAlpha(std::move(fp));
bsalomonf1b7a1d2015-09-28 06:26:28 -07001188 }
Brian Osman11052242016-10-27 14:47:55 -04001189 if (!SkPaintToGrPaintReplaceShader(this->context(), fRenderTargetContext.get(), tmpUnfiltered,
brianosman8fe485b2016-07-25 12:31:51 -07001190 std::move(fp), &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -07001191 return;
1192 }
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001193
robertphillips970587b2016-07-14 14:12:55 -07001194 const SkIRect& subset = result->subset();
1195
Brian Salomon82f44312017-01-11 13:42:54 -05001196 fRenderTargetContext->fillRectToRect(
1197 fClip,
1198 std::move(grPaint),
1199 GrBoolToAA(paint.isAntiAlias()),
1200 SkMatrix::I(),
1201 SkRect::Make(SkIRect::MakeXYWH(
1202 left + offset.fX, top + offset.fY, subset.width(), subset.height())),
1203 SkRect::MakeXYWH(SkIntToScalar(subset.fLeft) / texture->width(),
1204 SkIntToScalar(subset.fTop) / texture->height(),
1205 SkIntToScalar(subset.width()) / texture->width(),
1206 SkIntToScalar(subset.height()) / texture->height()));
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001207}
1208
bsalomonb1b01992015-11-18 10:56:08 -08001209void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
1210 const SkRect* src, const SkRect& origDst,
reed562fe472015-07-28 07:35:14 -07001211 const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
joshualittce894002016-01-11 13:29:31 -08001212 ASSERT_SINGLE_OWNER
lsalzman973ed242016-01-14 13:06:41 -08001213 CHECK_SHOULD_DRAW(draw);
reedc7ec7c92016-07-25 08:29:10 -07001214
bsalomonb1b01992015-11-18 10:56:08 -08001215 // The src rect is inferred to be the bmp bounds if not provided. Otherwise, the src rect must
1216 // be clipped to the bmp bounds. To determine tiling parameters we need the filter mode which
1217 // in turn requires knowing the src-to-dst mapping. If the src was clipped to the bmp bounds
1218 // then we use the src-to-dst mapping to compute a new clipped dst rect.
1219 const SkRect* dst = &origDst;
1220 const SkRect bmpBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001221 // Compute matrix from the two rectangles
bsalomonb1b01992015-11-18 10:56:08 -08001222 if (!src) {
1223 src = &bmpBounds;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001224 }
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +00001225
bsalomonb1b01992015-11-18 10:56:08 -08001226 SkMatrix srcToDstMatrix;
1227 if (!srcToDstMatrix.setRectToRect(*src, *dst, SkMatrix::kFill_ScaleToFit)) {
1228 return;
1229 }
1230 SkRect tmpSrc, tmpDst;
1231 if (src != &bmpBounds) {
1232 if (!bmpBounds.contains(*src)) {
1233 tmpSrc = *src;
1234 if (!tmpSrc.intersect(bmpBounds)) {
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001235 return; // nothing to draw
1236 }
bsalomonb1b01992015-11-18 10:56:08 -08001237 src = &tmpSrc;
1238 srcToDstMatrix.mapRect(&tmpDst, *src);
1239 dst = &tmpDst;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001240 }
1241 }
1242
bsalomonb1b01992015-11-18 10:56:08 -08001243 int maxTileSize = fContext->caps()->maxTileSize();
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +00001244
bsalomonb1b01992015-11-18 10:56:08 -08001245 // The tile code path doesn't currently support AA, so if the paint asked for aa and we could
1246 // draw untiled, then we bypass checking for tiling purely for optimization reasons.
Brian Osman11052242016-10-27 14:47:55 -04001247 bool drawAA = !fRenderTargetContext->isUnifiedMultisampled() &&
bsalomonb1b01992015-11-18 10:56:08 -08001248 paint.isAntiAlias() &&
1249 bitmap.width() <= maxTileSize &&
1250 bitmap.height() <= maxTileSize;
1251
1252 bool skipTileCheck = drawAA || paint.getMaskFilter();
1253
1254 if (!skipTileCheck) {
1255 int tileSize;
1256 SkIRect clippedSrcRect;
1257
Brian Salomon514baff2016-11-17 15:17:07 -05001258 GrSamplerParams params;
bsalomonb1b01992015-11-18 10:56:08 -08001259 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -05001260 GrSamplerParams::FilterMode textureFilterMode =
bsalomonb1b01992015-11-18 10:56:08 -08001261 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMatrix, srcToDstMatrix,
1262 &doBicubic);
1263
1264 int tileFilterPad;
1265
1266 if (doBicubic) {
1267 tileFilterPad = GrBicubicEffect::kFilterTexelPad;
Brian Salomon514baff2016-11-17 15:17:07 -05001268 } else if (GrSamplerParams::kNone_FilterMode == textureFilterMode) {
bsalomonb1b01992015-11-18 10:56:08 -08001269 tileFilterPad = 0;
1270 } else {
1271 tileFilterPad = 1;
1272 }
1273 params.setFilterMode(textureFilterMode);
1274
1275 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFilterPad;
bsalomone553b642016-08-17 09:02:09 -07001276 if (this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), *draw.fMatrix,
1277 srcToDstMatrix, params, src, maxTileSizeForFilter, &tileSize,
1278 &clippedSrcRect)) {
1279 this->drawTiledBitmap(bitmap, *draw.fMatrix, srcToDstMatrix, *src, clippedSrcRect,
1280 params, paint, constraint, tileSize, doBicubic);
bsalomonb1b01992015-11-18 10:56:08 -08001281 return;
1282 }
commit-bot@chromium.orga7d89c82014-01-13 14:47:00 +00001283 }
Hal Canary144caf52016-11-07 17:57:18 -05001284 GrBitmapTextureMaker maker(fContext.get(), bitmap);
bsalomonf1ecd212015-12-09 17:06:02 -08001285 this->drawTextureProducer(&maker, src, dst, constraint, *draw.fMatrix, fClip, paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001286}
1287
robertphillips6451a0c2016-07-18 08:31:31 -07001288sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) {
robertphillips6451a0c2016-07-18 08:31:31 -07001289 SkAutoLockPixels alp(bitmap, true);
1290 if (!bitmap.readyToDraw()) {
1291 return nullptr;
1292 }
1293
Brian Osman7b8400d2016-11-08 17:08:54 -05001294 sk_sp<GrTexture> texture =
Brian Osman61624f02016-12-09 14:51:59 -05001295 GrMakeCachedBitmapTexture(fContext.get(), bitmap, GrSamplerParams::ClampNoFilter());
robertphillips6451a0c2016-07-18 08:31:31 -07001296 if (!texture) {
1297 return nullptr;
1298 }
1299
1300 return SkSpecialImage::MakeFromGpu(bitmap.bounds(),
1301 bitmap.getGenerationID(),
reedc7ec7c92016-07-25 08:29:10 -07001302 texture,
Robert Phillips70b49fd2017-01-13 11:21:36 -05001303 bitmap.refColorSpace(),
robertphillips6451a0c2016-07-18 08:31:31 -07001304 &this->surfaceProps());
1305}
1306
reede51c3562016-07-19 14:33:20 -07001307sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkImage* image) {
robertphillips6451a0c2016-07-18 08:31:31 -07001308 SkPixmap pm;
1309 if (image->isTextureBacked()) {
1310 GrTexture* texture = as_IB(image)->peekTexture();
1311
1312 return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(image->width(), image->height()),
1313 image->uniqueID(),
brianosmanafbf71d2016-07-21 07:15:37 -07001314 sk_ref_sp(texture),
Robert Phillips70b49fd2017-01-13 11:21:36 -05001315 as_IB(image)->onImageInfo().refColorSpace(),
robertphillips6451a0c2016-07-18 08:31:31 -07001316 &this->surfaceProps());
1317 } 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 Phillipse2f7d182016-12-15 09:23:05 -05001328 sk_sp<GrSurfaceProxy> sProxy(sk_ref_sp(this->accessRenderTargetContext()->asDeferredTexture()));
1329 if (!sProxy) {
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 Phillipse2f7d182016-12-15 09:23:05 -05001333 sProxy = GrSurfaceProxy::Copy(fContext.get(),
1334 this->accessRenderTargetContext()->asDeferredSurface(),
1335 SkBudgeted::kYes);
1336 if (!sProxy) {
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,
1347 sProxy,
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
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001563///////////////////////////////////////////////////////////////////////////////
1564
1565// must be in SkCanvas::VertexMode order
1566static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
1567 kTriangles_GrPrimitiveType,
1568 kTriangleStrip_GrPrimitiveType,
1569 kTriangleFan_GrPrimitiveType,
1570};
1571
1572void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
1573 int vertexCount, const SkPoint vertices[],
1574 const SkPoint texs[], const SkColor colors[],
Mike Reedfaba3712016-11-03 14:45:31 -04001575 SkBlendMode bmode,
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001576 const uint16_t indices[], int indexCount,
1577 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001578 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -08001579 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001580 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVertices", fContext.get());
mtklein533eb782014-08-27 10:39:42 -07001581
halcanary96fcdcc2015-08-27 07:41:13 -07001582 // If both textures and vertex-colors are nullptr, strokes hairlines with the paint's color.
1583 if ((nullptr == texs || nullptr == paint.getShader()) && nullptr == colors) {
mtklein533eb782014-08-27 10:39:42 -07001584
halcanary96fcdcc2015-08-27 07:41:13 -07001585 texs = nullptr;
mtklein533eb782014-08-27 10:39:42 -07001586
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001587 SkPaint copy(paint);
1588 copy.setStyle(SkPaint::kStroke_Style);
1589 copy.setStrokeWidth(0);
mtklein533eb782014-08-27 10:39:42 -07001590
bsalomonf1b7a1d2015-09-28 06:26:28 -07001591 GrPaint grPaint;
dandov32a311b2014-07-15 19:46:26 -07001592 // we ignore the shader if texs is null.
Brian Osman11052242016-10-27 14:47:55 -04001593 if (!SkPaintToGrPaintNoShader(this->context(), fRenderTargetContext.get(), copy,
1594 &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -07001595 return;
1596 }
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001597
dandov32a311b2014-07-15 19:46:26 -07001598 int triangleCount = 0;
halcanary96fcdcc2015-08-27 07:41:13 -07001599 int n = (nullptr == indices) ? vertexCount : indexCount;
dandov32a311b2014-07-15 19:46:26 -07001600 switch (vmode) {
1601 case SkCanvas::kTriangles_VertexMode:
bsalomona098dd42014-08-06 11:01:44 -07001602 triangleCount = n / 3;
dandov32a311b2014-07-15 19:46:26 -07001603 break;
1604 case SkCanvas::kTriangleStrip_VertexMode:
1605 case SkCanvas::kTriangleFan_VertexMode:
bsalomona098dd42014-08-06 11:01:44 -07001606 triangleCount = n - 2;
dandov32a311b2014-07-15 19:46:26 -07001607 break;
1608 }
mtklein533eb782014-08-27 10:39:42 -07001609
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001610 VertState state(vertexCount, indices, indexCount);
1611 VertState::Proc vertProc = state.chooseProc(vmode);
mtklein533eb782014-08-27 10:39:42 -07001612
dandov32a311b2014-07-15 19:46:26 -07001613 //number of indices for lines per triangle with kLines
1614 indexCount = triangleCount * 6;
mtklein533eb782014-08-27 10:39:42 -07001615
Ben Wagner7ecc5962016-11-02 17:07:33 -04001616 std::unique_ptr<uint16_t[]> lineIndices(new uint16_t[indexCount]);
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001617 int i = 0;
1618 while (vertProc(&state)) {
bsalomonf1b7a1d2015-09-28 06:26:28 -07001619 lineIndices[i] = state.f0;
1620 lineIndices[i + 1] = state.f1;
1621 lineIndices[i + 2] = state.f1;
1622 lineIndices[i + 3] = state.f2;
1623 lineIndices[i + 4] = state.f2;
1624 lineIndices[i + 5] = state.f0;
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001625 i += 6;
1626 }
Brian Osman11052242016-10-27 14:47:55 -04001627 fRenderTargetContext->drawVertices(fClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001628 std::move(grPaint),
Brian Osman11052242016-10-27 14:47:55 -04001629 *draw.fMatrix,
1630 kLines_GrPrimitiveType,
1631 vertexCount,
1632 vertices,
1633 texs,
1634 colors,
1635 lineIndices.get(),
1636 indexCount);
bsalomonf1b7a1d2015-09-28 06:26:28 -07001637 return;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001638 }
1639
bsalomonf1b7a1d2015-09-28 06:26:28 -07001640 GrPrimitiveType primType = gVertexMode2PrimitiveType[vmode];
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001641
1642 SkAutoSTMalloc<128, GrColor> convertedColors(0);
bsalomon49f085d2014-09-05 13:34:00 -07001643 if (colors) {
bsalomonaa48d362015-10-01 08:34:17 -07001644 // need to convert byte order and from non-PM to PM. TODO: Keep unpremul until after
1645 // interpolation.
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001646 convertedColors.reset(vertexCount);
1647 for (int i = 0; i < vertexCount; ++i) {
bsalomonaa48d362015-10-01 08:34:17 -07001648 convertedColors[i] = SkColorToPremulGrColor(colors[i]);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001649 }
1650 colors = convertedColors.get();
1651 }
bsalomonf1b7a1d2015-09-28 06:26:28 -07001652 GrPaint grPaint;
bsalomonaa48d362015-10-01 08:34:17 -07001653 if (texs && paint.getShader()) {
1654 if (colors) {
Mike Reedfaba3712016-11-03 14:45:31 -04001655 // When there are texs and colors the shader and colors are combined using bmode.
Brian Osman11052242016-10-27 14:47:55 -04001656 if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), paint,
Mike Reedfaba3712016-11-03 14:45:31 -04001657 *draw.fMatrix, bmode, false, &grPaint)) {
bsalomonf1b7a1d2015-09-28 06:26:28 -07001658 return;
1659 }
1660 } else {
bsalomonaa48d362015-10-01 08:34:17 -07001661 // We have a shader, but no colors to blend it against.
Brian Osman11052242016-10-27 14:47:55 -04001662 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
brianosman8fe485b2016-07-25 12:31:51 -07001663 &grPaint)) {
bsalomonaa48d362015-10-01 08:34:17 -07001664 return;
1665 }
bsalomonf1b7a1d2015-09-28 06:26:28 -07001666 }
bsalomonaa48d362015-10-01 08:34:17 -07001667 } else {
1668 if (colors) {
1669 // We have colors, but either have no shader or no texture coords (which implies that
1670 // we should ignore the shader).
Brian Osman11052242016-10-27 14:47:55 -04001671 if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), fRenderTargetContext.get(),
1672 paint, &grPaint)) {
bsalomonaa48d362015-10-01 08:34:17 -07001673 return;
1674 }
1675 } else {
1676 // No colors and no shaders. Just draw with the paint color.
Brian Osman11052242016-10-27 14:47:55 -04001677 if (!SkPaintToGrPaintNoShader(this->context(), fRenderTargetContext.get(), paint,
1678 &grPaint)) {
bsalomonaa48d362015-10-01 08:34:17 -07001679 return;
1680 }
bsalomonf1b7a1d2015-09-28 06:26:28 -07001681 }
bsalomonf1b7a1d2015-09-28 06:26:28 -07001682 }
1683
Brian Osman11052242016-10-27 14:47:55 -04001684 fRenderTargetContext->drawVertices(fClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001685 std::move(grPaint),
Brian Osman11052242016-10-27 14:47:55 -04001686 *draw.fMatrix,
1687 primType,
1688 vertexCount,
1689 vertices,
1690 texs,
1691 colors,
1692 indices,
1693 indexCount);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001694}
1695
1696///////////////////////////////////////////////////////////////////////////////
1697
jvanverth31ff7622015-08-07 10:09:28 -07001698void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
reedca109532015-06-25 16:25:25 -07001699 const SkRect texRect[], const SkColor colors[], int count,
Mike Reedfaba3712016-11-03 14:45:31 -04001700 SkBlendMode mode, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001701 ASSERT_SINGLE_OWNER
reedca109532015-06-25 16:25:25 -07001702 if (paint.isAntiAlias()) {
jvanverth31ff7622015-08-07 10:09:28 -07001703 this->INHERITED::drawAtlas(draw, atlas, xform, texRect, colors, count, mode, paint);
reedca109532015-06-25 16:25:25 -07001704 return;
1705 }
1706
jvanverth31ff7622015-08-07 10:09:28 -07001707 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001708 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext.get());
herb11a7f7f2015-11-24 12:41:00 -08001709
reedca109532015-06-25 16:25:25 -07001710 SkPaint p(paint);
reed5671c5b2016-03-09 14:47:34 -08001711 p.setShader(atlas->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
reedca109532015-06-25 16:25:25 -07001712
jvanverth31ff7622015-08-07 10:09:28 -07001713 GrPaint grPaint;
robertphillips29ccdf82015-07-24 10:20:45 -07001714 if (colors) {
Brian Osman11052242016-10-27 14:47:55 -04001715 if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), p,
Mike Reed7d954ad2016-10-28 15:42:34 -04001716 *draw.fMatrix, (SkBlendMode)mode, true, &grPaint)) {
bsalomonf1b7a1d2015-09-28 06:26:28 -07001717 return;
1718 }
1719 } else {
Brian Osman11052242016-10-27 14:47:55 -04001720 if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), p, *draw.fMatrix,
1721 &grPaint)) {
jvanverth31ff7622015-08-07 10:09:28 -07001722 return;
robertphillips29ccdf82015-07-24 10:20:45 -07001723 }
1724 }
bsalomonf1b7a1d2015-09-28 06:26:28 -07001725
1726 SkDEBUGCODE(this->validate();)
Brian Salomon82f44312017-01-11 13:42:54 -05001727 fRenderTargetContext->drawAtlas(fClip, std::move(grPaint), *draw.fMatrix, count, xform, texRect,
1728 colors);
reedca109532015-06-25 16:25:25 -07001729}
1730
1731///////////////////////////////////////////////////////////////////////////////
1732
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001733void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
joshualitt5531d512014-12-17 15:50:11 -08001734 size_t byteLength, SkScalar x, SkScalar y,
1735 const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001736 ASSERT_SINGLE_OWNER
joshualitt5531d512014-12-17 15:50:11 -08001737 CHECK_SHOULD_DRAW(draw);
Hal Canary144caf52016-11-07 17:57:18 -05001738 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext.get());
jvanverth8c27a182014-10-14 08:45:50 -07001739 SkDEBUGCODE(this->validate();)
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +00001740
Brian Salomon6f1d36c2017-01-13 12:02:17 -05001741 fRenderTargetContext->drawText(fClip, paint, *draw.fMatrix,
Brian Salomon82f44312017-01-11 13:42:54 -05001742 (const char*)text, byteLength, x, y, draw.fRC->getBounds());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001743}
1744
fmalita05c4a432014-09-29 06:29:53 -07001745void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteLength,
1746 const SkScalar pos[], int scalarsPerPos,
1747 const SkPoint& offset, const SkPaint& paint) {
joshualittce894002016-01-11 13:29:31 -08001748 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -05001749 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPosText", fContext.get());
joshualitt5531d512014-12-17 15:50:11 -08001750 CHECK_SHOULD_DRAW(draw);
jvanverth8c27a182014-10-14 08:45:50 -07001751 SkDEBUGCODE(this->validate();)
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +00001752
Brian Salomon6f1d36c2017-01-13 12:02:17 -05001753 fRenderTargetContext->drawPosText(fClip, paint, *draw.fMatrix,
Brian Salomon82f44312017-01-11 13:42:54 -05001754 (const char*)text, byteLength, pos, scalarsPerPos, offset,
Brian Osman11052242016-10-27 14:47:55 -04001755 draw.fRC->getBounds());
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001756}
1757
joshualitt9c328182015-03-23 08:13:04 -07001758void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y,
1759 const SkPaint& paint, SkDrawFilter* drawFilter) {
joshualittce894002016-01-11 13:29:31 -08001760 ASSERT_SINGLE_OWNER
Hal Canary144caf52016-11-07 17:57:18 -05001761 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawTextBlob", fContext.get());
joshualitt9c328182015-03-23 08:13:04 -07001762 CHECK_SHOULD_DRAW(draw);
1763
1764 SkDEBUGCODE(this->validate();)
1765
Brian Osman11052242016-10-27 14:47:55 -04001766 fRenderTargetContext->drawTextBlob(fClip, paint, *draw.fMatrix,
1767 blob, x, y, drawFilter, draw.fRC->getBounds());
joshualitt9c328182015-03-23 08:13:04 -07001768}
1769
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001770///////////////////////////////////////////////////////////////////////////////
1771
reedb2db8982014-11-13 12:41:02 -08001772bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const {
joshualitt8e84a1e2016-02-16 11:09:25 -08001773 return GrTextUtils::ShouldDisableLCD(paint);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001774}
1775
1776void SkGpuDevice::flush() {
joshualittce894002016-01-11 13:29:31 -08001777 ASSERT_SINGLE_OWNER
joshualittbc907352016-01-13 06:45:40 -08001778
Brian Osman11052242016-10-27 14:47:55 -04001779 fRenderTargetContext->prepareForExternalIO();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001780}
1781
1782///////////////////////////////////////////////////////////////////////////////
1783
reed76033be2015-03-14 10:54:31 -07001784SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
joshualittce894002016-01-11 13:29:31 -08001785 ASSERT_SINGLE_OWNER
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001786
robertphillipsca6eafc2016-05-17 09:57:46 -07001787 SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001788
robertphillipsca6eafc2016-05-17 09:57:46 -07001789 // layers are never drawn in repeat modes, so we can request an approx
hcm4396fa52014-10-27 21:43:30 -07001790 // match and ignore any padding.
robertphillipsca6eafc2016-05-17 09:57:46 -07001791 SkBackingFit fit = kNever_TileUsage == cinfo.fTileUsage ? SkBackingFit::kApprox
1792 : SkBackingFit::kExact;
bsalomonafe30052015-01-16 07:32:33 -08001793
Brian Osman11052242016-10-27 14:47:55 -04001794 sk_sp<GrRenderTargetContext> rtc(fContext->makeRenderTargetContext(
1795 fit,
1796 cinfo.fInfo.width(), cinfo.fInfo.height(),
1797 fRenderTargetContext->config(),
Robert Phillips75a475c2017-01-13 09:18:59 -05001798 fRenderTargetContext->refColorSpace(),
Brian Osman11052242016-10-27 14:47:55 -04001799 fRenderTargetContext->desc().fSampleCnt,
1800 kDefault_GrSurfaceOrigin,
1801 &props));
1802 if (!rtc) {
Mike Kleine54c75f2016-10-13 14:18:09 -04001803 return nullptr;
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001804 }
robertphillipsca6eafc2016-05-17 09:57:46 -07001805
1806 // Skia's convention is to only clear a device if it is non-opaque.
1807 InitContents init = cinfo.fInfo.isOpaque() ? kUninit_InitContents : kClear_InitContents;
1808
Robert Phillips9fab7e92016-11-17 12:45:04 -05001809 return SkGpuDevice::Make(fContext.get(), std::move(rtc),
1810 cinfo.fInfo.width(), cinfo.fInfo.height(), init).release();
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +00001811}
1812
reede8f30622016-03-23 18:59:25 -07001813sk_sp<SkSurface> SkGpuDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
joshualittce894002016-01-11 13:29:31 -08001814 ASSERT_SINGLE_OWNER
bsalomonafe30052015-01-16 07:32:33 -08001815 // TODO: Change the signature of newSurface to take a budgeted parameter.
bsalomon5ec26ae2016-02-25 08:33:02 -08001816 static const SkBudgeted kBudgeted = SkBudgeted::kNo;
Hal Canary144caf52016-11-07 17:57:18 -05001817 return SkSurface::MakeRenderTarget(fContext.get(), kBudgeted, info,
Brian Osman11052242016-10-27 14:47:55 -04001818 fRenderTargetContext->desc().fSampleCnt,
1819 fRenderTargetContext->origin(), &props);
reed@google.com76f10a32014-02-05 15:32:21 +00001820}
1821
senorblanco900c3672016-04-27 11:31:23 -07001822SkImageFilterCache* SkGpuDevice::getImageFilterCache() {
joshualittce894002016-01-11 13:29:31 -08001823 ASSERT_SINGLE_OWNER
senorblanco55b6d8b2014-07-30 11:26:46 -07001824 // We always return a transient cache, so it is freed after each
1825 // filter traversal.
brianosman04a44d02016-09-21 09:46:57 -07001826 return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
senorblanco55b6d8b2014-07-30 11:26:46 -07001827}
reedf037e0b2014-10-30 11:34:15 -07001828
1829#endif