blob: 8f3b39e58bf1c7f35baeacb3b07cb870dfecee13 [file] [log] [blame]
robertphillips@google.com58b20212012-06-27 20:44:52 +00001/*
2 * Copyright 2012 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrSWMaskHelper.h"
Brian Osmanf9810662017-08-30 10:02:10 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/private/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrCaps.h"
12#include "src/gpu/GrProxyProvider.h"
13#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrSurfaceContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040015#include "src/gpu/GrTextureProxy.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040016#include "src/gpu/geometry/GrShape.h"
robertphillips@google.com58b20212012-06-27 20:44:52 +000017
robertphillips@google.com58b20212012-06-27 20:44:52 +000018/*
19 * Convert a boolean operation into a transfer mode code
20 */
reed374772b2016-10-05 17:33:02 -070021static SkBlendMode op_to_mode(SkRegion::Op op) {
robertphillips@google.com58b20212012-06-27 20:44:52 +000022
reed374772b2016-10-05 17:33:02 -070023 static const SkBlendMode modeMap[] = {
24 SkBlendMode::kDstOut, // kDifference_Op
25 SkBlendMode::kModulate, // kIntersect_Op
26 SkBlendMode::kSrcOver, // kUnion_Op
27 SkBlendMode::kXor, // kXOR_Op
28 SkBlendMode::kClear, // kReverseDifference_Op
29 SkBlendMode::kSrc, // kReplace_Op
robertphillips@google.com58b20212012-06-27 20:44:52 +000030 };
31
32 return modeMap[op];
33}
34
robertphillips@google.com58b20212012-06-27 20:44:52 +000035/**
36 * Draw a single rect element of the clip stack into the accumulation bitmap
37 */
Brian Salomon74077562017-08-30 13:55:35 -040038void GrSWMaskHelper::drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA aa,
39 uint8_t alpha) {
robertphillips@google.com58b20212012-06-27 20:44:52 +000040 SkPaint paint;
reed374772b2016-10-05 17:33:02 -070041 paint.setBlendMode(op_to_mode(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -050042 paint.setAntiAlias(GrAA::kYes == aa);
robertphillips@google.com366f1c62012-06-29 21:38:47 +000043 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
robertphillips@google.com58b20212012-06-27 20:44:52 +000044
Brian Salomon74077562017-08-30 13:55:35 -040045 SkMatrix translatedMatrix = matrix;
46 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);
47 fDraw.fMatrix = &translatedMatrix;
48
robertphillips@google.com366f1c62012-06-29 21:38:47 +000049 fDraw.drawRect(rect, paint);
robertphillips@google.com58b20212012-06-27 20:44:52 +000050}
51
52/**
53 * Draw a single path element of the clip stack into the accumulation bitmap
54 */
Brian Salomon74077562017-08-30 13:55:35 -040055void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkRegion::Op op,
56 GrAA aa, uint8_t alpha) {
robertphillips@google.com58b20212012-06-27 20:44:52 +000057 SkPaint paint;
Robert Phillipsf809c1e2017-01-13 11:02:42 -050058 paint.setPathEffect(shape.style().refPathEffect());
bsalomon8acedde2016-06-24 10:42:16 -070059 shape.style().strokeRec().applyToPaint(&paint);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -050060 paint.setAntiAlias(GrAA::kYes == aa);
reed@google.com84e922b2013-11-04 20:57:36 +000061
Brian Salomon74077562017-08-30 13:55:35 -040062 SkMatrix translatedMatrix = matrix;
63 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);
64 fDraw.fMatrix = &translatedMatrix;
65
bsalomon8acedde2016-06-24 10:42:16 -070066 SkPath path;
67 shape.asPath(&path);
reed@google.com126f7f52013-11-07 16:06:53 +000068 if (SkRegion::kReplace_Op == op && 0xFF == alpha) {
69 SkASSERT(0xFF == paint.getAlpha());
robertphillips98377402016-05-13 05:47:23 -070070 fDraw.drawPathCoverage(path, paint);
reed@google.com126f7f52013-11-07 16:06:53 +000071 } else {
reed374772b2016-10-05 17:33:02 -070072 paint.setBlendMode(op_to_mode(op));
reed@google.com126f7f52013-11-07 16:06:53 +000073 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
robertphillips98377402016-05-13 05:47:23 -070074 fDraw.drawPath(path, paint);
reed@google.com126f7f52013-11-07 16:06:53 +000075 }
Brian Salomon74077562017-08-30 13:55:35 -040076};
robertphillips@google.com58b20212012-06-27 20:44:52 +000077
Brian Salomon74077562017-08-30 13:55:35 -040078bool GrSWMaskHelper::init(const SkIRect& resultBounds) {
79 // We will need to translate draws so the bound's UL corner is at the origin
80 fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)};
robertphillips98377402016-05-13 05:47:23 -070081 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height());
krajcevski25a67bc2014-07-29 11:44:26 -070082
robertphillips98377402016-05-13 05:47:23 -070083 const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height());
Brian Osmanf9810662017-08-30 10:02:10 -040084 if (!fPixels->tryAlloc(bmImageInfo)) {
robertphillips98377402016-05-13 05:47:23 -070085 return false;
krajcevskib8ccc2f2014-08-07 08:15:14 -070086 }
Brian Osmanf9810662017-08-30 10:02:10 -040087 fPixels->erase(0);
krajcevskib8ccc2f2014-08-07 08:15:14 -070088
Brian Osmanf9810662017-08-30 10:02:10 -040089 fDraw.fDst = *fPixels;
robertphillips@google.com58b20212012-06-27 20:44:52 +000090 fRasterClip.setRect(bounds);
reed41e010c2015-06-09 12:16:53 -070091 fDraw.fRC = &fRasterClip;
robertphillips@google.com58b20212012-06-27 20:44:52 +000092 return true;
93}
94
Robert Phillips6f0e02f2019-02-13 11:02:28 -050095sk_sp<GrTextureProxy> GrSWMaskHelper::toTextureProxy(GrRecordingContext* context,
96 SkBackingFit fit) {
Robert Phillipscb7b8312018-04-20 11:49:51 -040097 SkImageInfo ii = SkImageInfo::MakeA8(fPixels->width(), fPixels->height());
98 size_t rowBytes = fPixels->rowBytes();
krajcevskifb4f5cb2014-06-12 09:20:38 -070099
Robert Phillipscb7b8312018-04-20 11:49:51 -0400100 sk_sp<SkData> data = fPixels->detachPixelsAsData();
101 if (!data) {
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500102 return nullptr;
bsalomon39ef7fb2016-09-21 11:16:05 -0700103 }
robertphillips@google.com58b20212012-06-27 20:44:52 +0000104
Robert Phillipscb7b8312018-04-20 11:49:51 -0400105 sk_sp<SkImage> img = SkImage::MakeRasterData(ii, std::move(data), rowBytes);
106 if (!img) {
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500107 return nullptr;
108 }
cblumeed828002016-02-16 13:00:01 -0800109
Kevin Lubicka96ec092018-12-17 11:08:36 -0500110 auto clearFlag = kNone_GrSurfaceFlags;
Kevin Lubickf58e49f2019-04-08 12:14:21 -0400111 if (context->priv().caps()->shouldInitializeTextures() && fit == SkBackingFit::kApprox) {
112 clearFlag = kPerformInitialClear_GrSurfaceFlag;
113 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500114 return context->priv().proxyProvider()->createTextureProxy(
Robert Phillips10d17212019-04-24 14:09:10 -0400115 std::move(img), clearFlag, 1, SkBudgeted::kYes, fit);
robertphillips@google.com58b20212012-06-27 20:44:52 +0000116}