blob: 77285a41b326fed58258b2b38df47951b9a667d3 [file] [log] [blame]
Mike Reed560e9172019-08-05 13:04:18 -04001/*
2 * Copyright 2019 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 "include/core/SkColorFilter.h"
9#include "include/core/SkRSXform.h"
Mike Reed9318a6c2019-08-16 16:16:25 -040010#include "src/core/SkBlendModePriv.h"
11#include "src/core/SkColorSpacePriv.h"
12#include "src/core/SkColorSpaceXformSteps.h"
13#include "src/core/SkCoreBlitters.h"
Mike Reed560e9172019-08-05 13:04:18 -040014#include "src/core/SkDraw.h"
Brian Osman9aaec362020-05-08 14:54:37 -040015#include "src/core/SkMatrixProvider.h"
Mike Reed121c2af2020-03-10 14:02:56 -040016#include "src/core/SkRasterClip.h"
Mike Reed9318a6c2019-08-16 16:16:25 -040017#include "src/core/SkRasterPipeline.h"
Mike Reed560e9172019-08-05 13:04:18 -040018#include "src/core/SkScan.h"
19#include "src/shaders/SkShaderBase.h"
20
Mike Reed9318a6c2019-08-16 16:16:25 -040021#include "include/core/SkMatrix.h"
22#include "src/core/SkScan.h"
23
24static void fill_rect(const SkMatrix& ctm, const SkRasterClip& rc,
Mike Reed375721d2020-08-07 16:00:06 -040025 const SkRect& r, SkBlitter* blitter) {
Mike Reed9318a6c2019-08-16 16:16:25 -040026 if (ctm.rectStaysRect()) {
27 SkRect dr;
28 ctm.mapRect(&dr, r);
29 SkScan::FillRect(dr, rc, blitter);
30 } else {
Mike Reedf6cb6ed2019-09-06 15:17:14 -040031 SkPoint pts[4];
32 r.toQuad(pts);
33 ctm.mapPoints(pts, pts, 4);
34
Mike Reed375721d2020-08-07 16:00:06 -040035 SkRect bounds;
36 bounds.setBounds(pts, 4);
37
38 SkScan::FillPath(SkPathView_quad(pts, bounds), rc, blitter);
Mike Reed9318a6c2019-08-16 16:16:25 -040039 }
40}
41
42static void load_color(SkRasterPipeline_UniformColorCtx* ctx, const float rgba[]) {
43 // only need one of these. can I query the pipeline to know if its lowp or highp?
44 ctx->rgba[0] = SkScalarRoundToInt(rgba[0]*255); ctx->r = rgba[0];
45 ctx->rgba[1] = SkScalarRoundToInt(rgba[1]*255); ctx->g = rgba[1];
46 ctx->rgba[2] = SkScalarRoundToInt(rgba[2]*255); ctx->b = rgba[2];
47 ctx->rgba[3] = SkScalarRoundToInt(rgba[3]*255); ctx->a = rgba[3];
48}
49
Mike Reed560e9172019-08-05 13:04:18 -040050void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect textures[],
51 const SkColor colors[], int count, SkBlendMode bmode, const SkPaint& paint) {
Mike Reed9318a6c2019-08-16 16:16:25 -040052 sk_sp<SkShader> atlasShader = atlas->makeShader();
53 if (!atlasShader) {
54 return;
55 }
Mike Reed560e9172019-08-05 13:04:18 -040056
Mike Reed9318a6c2019-08-16 16:16:25 -040057 SkPaint p(paint);
Mike Reed560e9172019-08-05 13:04:18 -040058 p.setAntiAlias(false); // we never respect this for drawAtlas(or drawVertices)
59 p.setStyle(SkPaint::kFill_Style);
60 p.setShader(nullptr);
61 p.setMaskFilter(nullptr);
62
Mike Reed9318a6c2019-08-16 16:16:25 -040063 SkSTArenaAlloc<256> alloc;
64 SkRasterPipeline pipeline(&alloc);
65 SkStageRec rec = {
Brian Osman9aaec362020-05-08 14:54:37 -040066 &pipeline, &alloc, fDst.colorType(), fDst.colorSpace(), p, nullptr, *fMatrixProvider
Mike Reed9318a6c2019-08-16 16:16:25 -040067 };
68
69 SkStageUpdater* updator = as_SB(atlasShader.get())->appendUpdatableStages(rec);
70 if (!updator) {
71 SkDraw draw(*this);
72
73 p.setShader(atlasShader);
74 for (int i = 0; i < count; ++i) {
75 if (colors) {
76 p.setShader(SkShaders::Blend(bmode, SkShaders::Color(colors[i]), atlasShader));
77 }
78 SkMatrix mx;
79 mx.setRSXform(xform[i]);
80 mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
Brian Osman9aaec362020-05-08 14:54:37 -040081 SkPreConcatMatrixProvider matrixProvider(*fMatrixProvider, mx);
82 draw.fMatrixProvider = &matrixProvider;
Mike Reed9318a6c2019-08-16 16:16:25 -040083 draw.drawRect(textures[i], p);
84 }
Mike Reed41974002019-08-07 11:00:19 -040085 return;
Mike Reed560e9172019-08-05 13:04:18 -040086 }
87
Mike Reed9318a6c2019-08-16 16:16:25 -040088 SkRasterPipeline_UniformColorCtx* uniformCtx = nullptr;
89 SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
90 rec.fDstCS, kUnpremul_SkAlphaType);
91
92 if (colors) {
93 // we will late-bind the values in ctx, once for each color in the loop
94 uniformCtx = alloc.make<SkRasterPipeline_UniformColorCtx>();
95 rec.fPipeline->append(SkRasterPipeline::uniform_color_dst, uniformCtx);
96 SkBlendMode_AppendStages(bmode, rec.fPipeline);
97 }
98
99 bool isOpaque = !colors && atlasShader->isOpaque();
100 if (p.getAlphaf() != 1) {
101 rec.fPipeline->append(SkRasterPipeline::scale_1_float, alloc.make<float>(p.getAlphaf()));
102 isOpaque = false;
103 }
104
Mike Kleine66636c2020-06-19 14:03:39 -0500105 if (auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc,
106 fRC->clipShader())) {
Mike Kleine66636c2020-06-19 14:03:39 -0500107 for (int i = 0; i < count; ++i) {
108 if (colors) {
109 SkColor4f c4 = SkColor4f::FromColor(colors[i]);
110 steps.apply(c4.vec());
111 load_color(uniformCtx, c4.premul().vec());
112 }
Mike Reed9318a6c2019-08-16 16:16:25 -0400113
Mike Kleine66636c2020-06-19 14:03:39 -0500114 SkMatrix mx;
115 mx.setRSXform(xform[i]);
116 mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
117 mx.postConcat(fMatrixProvider->localToDevice());
Mike Reed9318a6c2019-08-16 16:16:25 -0400118
Mike Kleine66636c2020-06-19 14:03:39 -0500119 if (updator->update(mx, nullptr)) {
Mike Reed375721d2020-08-07 16:00:06 -0400120 fill_rect(mx, *fRC, textures[i], blitter);
Mike Kleine66636c2020-06-19 14:03:39 -0500121 }
Mike Kleine1508882020-04-28 08:45:01 -0500122 }
Mike Reed560e9172019-08-05 13:04:18 -0400123 }
124}