1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2017 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkArenaAlloc.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAutoBlitterChoose.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkComposeShader.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDraw.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkNx.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPM4fPriv.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRasterClip.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkScan.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkShaderBase.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkVertState.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkArenaAlloc.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCoreBlitters.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpaceXform.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Matrix43 { 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot float fMat[12]; // column major 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sk4f map(float x, float y) const { 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return Sk4f::Load(&fMat[0]) * x + Sk4f::Load(&fMat[4]) * y + Sk4f::Load(&fMat[8]); 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setConcat(const Matrix43& a, const SkMatrix& b) { 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 0] = a.dot(0, b.getScaleX(), b.getSkewY()); 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 1] = a.dot(1, b.getScaleX(), b.getSkewY()); 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 2] = a.dot(2, b.getScaleX(), b.getSkewY()); 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 3] = a.dot(3, b.getScaleX(), b.getSkewY()); 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 4] = a.dot(0, b.getSkewX(), b.getScaleY()); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 5] = a.dot(1, b.getSkewX(), b.getScaleY()); 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 6] = a.dot(2, b.getSkewX(), b.getScaleY()); 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 7] = a.dot(3, b.getSkewX(), b.getScaleY()); 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 8] = a.dot(0, b.getTranslateX(), b.getTranslateY()) + a.fMat[ 8]; 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[ 9] = a.dot(1, b.getTranslateX(), b.getTranslateY()) + a.fMat[ 9]; 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[10] = a.dot(2, b.getTranslateX(), b.getTranslateY()) + a.fMat[10]; 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMat[11] = a.dot(3, b.getTranslateX(), b.getTranslateY()) + a.fMat[11]; 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot float dot(int index, float x, float y) const { 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fMat[index + 0] * x + fMat[index + 4] * y; 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint texs[], SkMatrix* matrix) { 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint src[3], dst[3]; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot src[0] = texs[state.f0]; 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot src[1] = texs[state.f1]; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot src[2] = texs[state.f2]; 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst[0] = verts[state.f0]; 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst[1] = verts[state.f1]; 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst[2] = verts[state.f2]; 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return matrix->setPolyToPoly(src, dst, 3); 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkTriColorShader : public SkShaderBase { 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTriColorShader(bool isOpaque) : fIsOpaque(isOpaque) {} 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Matrix43* getMatrix43() { return &fM43; } 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isOpaque() const override { return fIsOpaque; } 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TO_STRING_OVERRIDE() 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // For serialization. This will never be called. 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Factory getFactory() const override { SK_ABORT("not reached"); return nullptr; } 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override { 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onAppendStages(const StageRec& rec) const override { 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec.fPipeline->append_seed_shader(); 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec.fPipeline->append(SkRasterPipeline::matrix_4x3, &fM43); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Matrix43 fM43; 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const bool fIsOpaque; 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef SkShaderBase INHERITED; 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTriColorShader::toString(SkString* str) const { 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append("SkTriColorShader: ("); 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->INHERITED::toString(str); 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(")"); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool update_tricolor_matrix(const SkMatrix& ctmInv, 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint pts[], const SkPM4f colors[], 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int index0, int index1, int index2, Matrix43* result) { 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix m, im; 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.reset(); 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.set(0, pts[index1].fX - pts[index0].fX); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.set(1, pts[index2].fX - pts[index0].fX); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.set(2, pts[index0].fX); 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.set(3, pts[index1].fY - pts[index0].fY); 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.set(4, pts[index2].fY - pts[index0].fY); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.set(5, pts[index0].fY); 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!m.invert(&im)) { 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix dstToUnit; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dstToUnit.setConcat(im, ctmInv); 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sk4f c0 = colors[index0].to4f(), 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c1 = colors[index1].to4f(), 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c2 = colors[index2].to4f(); 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Matrix43 colorm; 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c1 - c0).store(&colorm.fMat[0]); 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c2 - c0).store(&colorm.fMat[4]); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c0.store(&colorm.fMat[8]); 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result->setConcat(colorm, dstToUnit); 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Convert the SkColors into float colors. The conversion depends on some conditions: 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - If the pixmap has a dst colorspace, we have to be "color-correct". 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Do we map into dst-colorspace before or after we interpolate? 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - We have to decide when to apply per-color alpha (before or after we interpolate) 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// For now, we will take a simple approach, but recognize this is just a start: 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - convert colors into dst colorspace before interpolation (matches gradients) 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - apply per-color alpha before interpolation (matches old version of vertices) 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkPM4f* convert_colors(const SkColor src[], int count, SkColorSpace* deviceCS, 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkArenaAlloc* alloc) { 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f* dst = alloc->makeArray<SkPM4f>(count); 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!deviceCS) { 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; ++i) { 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dst[i] = SkPM4f_from_SkColor(src[i], nullptr); 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto srcCS = SkColorSpace::MakeSRGB(); 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto dstCS = deviceCS->makeLinearGamma(); 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSpaceXform::Apply(dstCS.get(), SkColorSpaceXform::kRGBA_F32_ColorFormat, dst, 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot srcCS.get(), SkColorSpaceXform::kBGRA_8888_ColorFormat, src, 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count, SkColorSpaceXform::kPremul_AlphaOp); 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return dst; 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool compute_is_opaque(const SkColor colors[], int count) { 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t c = ~0; 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; ++i) { 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c &= colors[i]; 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkColorGetA(c) == 0xFF; 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawVertices(SkVertices::VertexMode vmode, int count, 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint vertices[], const SkPoint textures[], 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor colors[], SkBlendMode bmode, 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint16_t indices[], int indexCount, 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& paint) const { 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0 == count || vertices); 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // abort early if there is nothing to draw 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix ctmInv; 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fMatrix->invert(&ctmInv)) { 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // make textures and shader mutually consistent 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader* shader = paint.getShader(); 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!(shader && textures)) { 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shader = nullptr; 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot textures = nullptr; 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We can simplify things for certain blendmodes. This is for speed, and SkComposeShader 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // itself insists we don't pass kSrc or kDst to it. 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (colors && textures) { 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (bmode) { 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkBlendMode::kSrc: 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot colors = nullptr; 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkBlendMode::kDst: 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot textures = nullptr; 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: break; 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we don't use the shader if there are no textures 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!textures) { 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shader = nullptr; 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr size_t defCount = 16; 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr size_t outerSize = sizeof(SkTriColorShader) + 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sizeof(SkComposeShader) + 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (sizeof(SkPoint) + sizeof(SkPM4f)) * defCount; 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArenaAlloc<outerSize> outerAlloc; 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint* devVerts = outerAlloc.makeArray<SkPoint>(count); 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix->mapPoints(devVerts, vertices, count); 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VertState state(count, indices, indexCount); 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VertState::Proc vertProc = state.chooseProc(vmode); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (colors || textures) { 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f* dstColors = nullptr; 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Matrix43* matrix43 = nullptr; 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (colors) { 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dstColors = convert_colors(colors, count, fDst.colorSpace(), &outerAlloc); 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTriColorShader* triShader = outerAlloc.make<SkTriColorShader>( 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compute_is_opaque(colors, count)); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix43 = triShader->getMatrix43(); 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (shader) { 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shader = outerAlloc.make<SkComposeShader>(sk_ref_sp(triShader), sk_ref_sp(shader), 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bmode, 1); 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shader = triShader; 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint p(paint); 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p.setShader(sk_ref_sp(shader)); 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!textures) { // only tricolor shader 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(matrix43); 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *fMatrix, &outerAlloc); 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (vertProc(&state)) { 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!update_tricolor_matrix(ctmInv, vertices, dstColors, 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot state.f0, state.f1, state.f2, 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix43)) { 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint tmp[] = { 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillTriangle(tmp, *fRC, blitter); 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (vertProc(&state)) { 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArenaAlloc<2048> innerAlloc; 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* ctm = fMatrix; 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix tmpCtm; 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (textures) { 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix localM; 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot texture_to_matrix(state, vertices, textures, &localM); 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmpCtm = SkMatrix::Concat(*fMatrix, localM); 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctm = &tmpCtm; 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (matrix43 && !update_tricolor_matrix(ctmInv, vertices, dstColors, 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot state.f0, state.f1, state.f2, 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix43)) { 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint tmp[] = { 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *ctm, &innerAlloc); 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillTriangle(tmp, *fRC, blitter); 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // no colors[] and no texture, stroke hairlines with paint's color. 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint p; 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p.setStyle(SkPaint::kStroke_Style); 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitter(fDst, *fMatrix, p); 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Abort early if we failed to create a shader context. 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (blitter->isNullBlitter()) { 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias()); 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRasterClip& clip = *fRC; 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (vertProc(&state)) { 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint array[] = { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0] 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot hairProc(array, 4, clip, blitter.get()); 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 311