1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2006 The Android Open Source Project 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 <algorithm> 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Sk4fLinearGradient.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpace_XYZ.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpaceXformer.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFloatBits.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGradientBitmapCache.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGradientShaderPriv.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkHalf.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkLinearGradient.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMallocPixelRef.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRadialGradient.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReadBuffer.h" 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSweepGradient.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTwoPointConicalGradient.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWriteBuffer.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../../jumper/SkJumper.h" 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum GradientSerializationFlags { 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Bits 29:31 used for various boolean flags 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHasPosition_GSF = 0x80000000, 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHasLocalMatrix_GSF = 0x40000000, 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHasColorSpace_GSF = 0x20000000, 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Bits 12:28 unused 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Bits 8:11 for fTileMode 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kTileModeShift_GSF = 8, 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kTileModeMask_GSF = 0xF, 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Bits 0:7 for fGradFlags (note that kForce4fContext_PrivateFlag is 0x80) 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kGradFlagsShift_GSF = 0, 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kGradFlagsMask_GSF = 0xFF, 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const { 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags = 0; 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fPos) { 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags |= kHasPosition_GSF; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLocalMatrix) { 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags |= kHasLocalMatrix_GSF; 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr; 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (colorSpaceData) { 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags |= kHasColorSpace_GSF; 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(static_cast<uint32_t>(fTileMode) <= kTileModeMask_GSF); 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags |= (fTileMode << kTileModeShift_GSF); 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fGradFlags <= kGradFlagsMask_GSF); 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags |= (fGradFlags << kGradFlagsShift_GSF); 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeUInt(flags); 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeColor4fArray(fColors, fCount); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (colorSpaceData) { 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeDataAsByteArray(colorSpaceData.get()); 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fPos) { 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeScalarArray(fPos, fCount); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLocalMatrix) { 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeMatrix(*fLocalMatrix); 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) { 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // New gradient format. Includes floating point color, color space, densely packed flags 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags = buffer.readUInt(); 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTileMode = (SkShader::TileMode)((flags >> kTileModeShift_GSF) & kTileModeMask_GSF); 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fGradFlags = (flags >> kGradFlagsShift_GSF) & kGradFlagsMask_GSF; 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCount = buffer.getArrayCount(); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fCount > kStorageCount) { 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t allocSize = (sizeof(SkColor4f) + sizeof(SkScalar)) * fCount; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDynamicStorage.reset(allocSize); 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors = (SkColor4f*)fDynamicStorage.get(); 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPos = (SkScalar*)(fColors + fCount); 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors = fColorStorage; 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPos = fPosStorage; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!buffer.readColor4fArray(mutableColors(), fCount)) { 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkToBool(flags & kHasColorSpace_GSF)) { 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data = buffer.readByteArrayAsData(); 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorSpace = SkColorSpace::Deserialize(data->data(), data->size()); 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorSpace = nullptr; 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkToBool(flags & kHasPosition_GSF)) { 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!buffer.readScalarArray(mutablePos(), fCount)) { 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPos = nullptr; 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkToBool(flags & kHasLocalMatrix_GSF)) { 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLocalMatrix = &fLocalMatrixStorage; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.readMatrix(&fLocalMatrixStorage); 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLocalMatrix = nullptr; 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return buffer.isValid(); 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////// 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit) 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : INHERITED(desc.fLocalMatrix) 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fPtsToUnit(ptsToUnit) 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fColorsAreOpaque(true) 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPtsToUnit.getType(); // Precache so reads are threadsafe. 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(desc.fCount > 1); 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fGradFlags = static_cast<uint8_t>(desc.fGradFlags); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTileMode = desc.fTileMode; 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* Note: we let the caller skip the first and/or last position. 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot i.e. pos[0] = 0.3, pos[1] = 0.7 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot In these cases, we insert dummy entries to ensure that the final data 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot will be bracketed by [0, 1]. 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Thus colorCount (the caller's value, and fColorCount (our value) may 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot differ by up to 2. In the above example: 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot colorCount = 2 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorCount = 4 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorCount = desc.fCount; 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check if we need to add in dummy start and/or end position/colors 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool dummyFirst = false; 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool dummyLast = false; 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (desc.fPos) { 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dummyFirst = desc.fPos[0] != 0; 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1; 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorCount += dummyFirst + dummyLast; 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t storageSize = fColorCount * (sizeof(SkColor4f) + (desc.fPos ? sizeof(SkScalar) : 0)); 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOrigColors4f = reinterpret_cast<SkColor4f*>(fStorage.reset(storageSize)); 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOrigPos = desc.fPos ? reinterpret_cast<SkScalar*>(fOrigColors4f + fColorCount) 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : nullptr; 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now copy over the colors, adding the dummies as needed 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor4f* origColors = fOrigColors4f; 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (dummyFirst) { 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *origColors++ = desc.fColors[0]; 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < desc.fCount; ++i) { 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot origColors[i] = desc.fColors[i]; 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorsAreOpaque = fColorsAreOpaque && (desc.fColors[i].fA == 1); 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (dummyLast) { 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot origColors += desc.fCount; 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *origColors = desc.fColors[desc.fCount - 1]; 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!desc.fColorSpace) { 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This happens if we were constructed from SkColors, so our colors are really sRGB 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorSpace = SkColorSpace::MakeSRGBLinear(); 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The color space refers to the float colors, so it must be linear gamma 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: GPU code no longer requires this (see GrGradientEffect). Remove this restriction? 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(desc.fColorSpace->gammaIsLinear()); 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorSpace = desc.fColorSpace; 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (desc.fPos) { 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar prev = 0; 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar* origPosPtr = fOrigPos; 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *origPosPtr++ = prev; // force the first pos to 0 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int startIndex = dummyFirst ? 0 : 1; 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = desc.fCount + dummyLast; 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool uniformStops = true; 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar uniformStep = desc.fPos[startIndex] - prev; 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = startIndex; i < count; i++) { 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Pin the last value to 1.0, and make sure pos is monotonic. 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto curr = (i == desc.fCount) ? 1 : SkScalarPin(desc.fPos[i], prev, 1); 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uniformStops &= SkScalarNearlyEqual(uniformStep, curr - prev); 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *origPosPtr++ = prev = curr; 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If the stops are uniform, treat them as implicit. 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (uniformStops) { 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOrigPos = nullptr; 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkGradientShaderBase::~SkGradientShaderBase() {} 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Descriptor desc; 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fColors = fOrigColors4f; 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fColorSpace = fColorSpace; 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fPos = fOrigPos; 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fCount = fColorCount; 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fTileMode = fTileMode; 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fGradFlags = fGradFlags; 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix& m = this->getLocalMatrix(); 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fLocalMatrix = m.isIdentity() ? nullptr : &m; 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.flatten(buffer); 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void add_stop_color(SkJumper_GradientCtx* ctx, size_t stop, SkPM4f Fs, SkPM4f Bs) { 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->fs[0])[stop] = Fs.r(); 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->fs[1])[stop] = Fs.g(); 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->fs[2])[stop] = Fs.b(); 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->fs[3])[stop] = Fs.a(); 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->bs[0])[stop] = Bs.r(); 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->bs[1])[stop] = Bs.g(); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->bs[2])[stop] = Bs.b(); 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (ctx->bs[3])[stop] = Bs.a(); 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void add_const_color(SkJumper_GradientCtx* ctx, size_t stop, SkPM4f color) { 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot add_stop_color(ctx, stop, SkPM4f::FromPremulRGBA(0,0,0,0), color); 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Calculate a factor F and a bias B so that color = F*t + B when t is in range of 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the stop. Assume that the distance between stops is 1/gapCount. 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void init_stop_evenly( 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkJumper_GradientCtx* ctx, float gapCount, size_t stop, SkPM4f c_l, SkPM4f c_r) { 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Clankium's GCC 4.9 targeting ARMv7 is barfing when we use Sk4f math here, so go scalar... 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f Fs = {{ 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.r() - c_l.r()) * gapCount, 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.g() - c_l.g()) * gapCount, 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.b() - c_l.b()) * gapCount, 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.a() - c_l.a()) * gapCount, 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }}; 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f Bs = {{ 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.r() - Fs.r()*(stop/gapCount), 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.g() - Fs.g()*(stop/gapCount), 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.b() - Fs.b()*(stop/gapCount), 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.a() - Fs.a()*(stop/gapCount), 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }}; 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot add_stop_color(ctx, stop, Fs, Bs); 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// For each stop we calculate a bias B and a scale factor F, such that 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// for any t between stops n and n+1, the color we want is B[n] + F[n]*t. 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void init_stop_pos( 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkJumper_GradientCtx* ctx, size_t stop, float t_l, float t_r, SkPM4f c_l, SkPM4f c_r) { 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // See note about Clankium's old compiler in init_stop_evenly(). 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f Fs = {{ 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.r() - c_l.r()) / (t_r - t_l), 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.g() - c_l.g()) / (t_r - t_l), 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.b() - c_l.b()) / (t_r - t_l), 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (c_r.a() - c_l.a()) / (t_r - t_l), 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }}; 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f Bs = {{ 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.r() - Fs.r()*t_l, 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.g() - Fs.g()*t_l, 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.b() - Fs.b()*t_l, 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l.a() - Fs.a()*t_l, 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }}; 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->ts[stop] = t_l; 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot add_stop_color(ctx, stop, Fs, Bs); 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkGradientShaderBase::onAppendStages(const StageRec& rec) const { 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRasterPipeline* p = rec.fPipeline; 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkArenaAlloc* alloc = rec.fAlloc; 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSpace* dstCS = rec.fDstCS; 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix matrix; 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &matrix)) { 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postConcat(fPtsToUnit); 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRasterPipeline_<256> postPipeline; 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append_seed_shader(); 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append_matrix(alloc, matrix); 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->appendGradientStages(alloc, p, &postPipeline); 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch(fTileMode) { 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x_1); break; 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x_1); break; 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kClamp_TileMode: 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fOrigPos) { 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We clamp only when the stops are evenly spaced. 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If not, there may be hard stops, and clamping ruins hard stops at 0 and/or 1. 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // In that case, we must make sure we're using the general "gradient" stage, 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // which is the only stage that will correctly handle unclamped t. 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::clamp_x_1); 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag; 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto prepareColor = [premulGrad, dstCS, this](int i) { 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor4f c = this->getXformedColor(i, dstCS); 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return premulGrad ? c.premul() 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : SkPM4f::From4f(Sk4f::Load(&c)); 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The two-stop case with stops at 0 and 1. 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorCount == 2 && fOrigPos == nullptr) { 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPM4f c_l = prepareColor(0), 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_r = prepareColor(1); 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // See F and B below. 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2); 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f()); 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot f_and_b[1] = c_l; 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::evenly_spaced_2_stop_gradient, f_and_b); 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto* ctx = alloc->make<SkJumper_GradientCtx>(); 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Note: In order to handle clamps in search, the search assumes a stop conceptully placed 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // at -inf. Therefore, the max number of stops is fColorCount+1. 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < 4; i++) { 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Allocate at least at for the AVX2 gather from a YMM register. 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->fs[i] = alloc->makeArray<float>(std::max(fColorCount+1, 8)); 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->bs[i] = alloc->makeArray<float>(std::max(fColorCount+1, 8)); 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fOrigPos == nullptr) { 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Handle evenly distributed stops. 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t stopCount = fColorCount; 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot float gapCount = stopCount - 1; 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f c_l = prepareColor(0); 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < stopCount - 1; i++) { 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f c_r = prepareColor(i + 1); 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot init_stop_evenly(ctx, gapCount, i, c_l, c_r); 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l = c_r; 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot add_const_color(ctx, stopCount - 1, c_l); 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->stopCount = stopCount; 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::evenly_spaced_gradient, ctx); 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Handle arbitrary stops. 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->ts = alloc->makeArray<float>(fColorCount+1); 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Remove the dummy stops inserted by SkGradientShaderBase::SkGradientShaderBase 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // because they are naturally handled by the search method. 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int firstStop; 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int lastStop; 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorCount > 2) { 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot firstStop = fOrigColors4f[0] != fOrigColors4f[1] ? 0 : 1; 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastStop = fOrigColors4f[fColorCount - 2] != fOrigColors4f[fColorCount - 1] 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? fColorCount - 1 : fColorCount - 2; 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot firstStop = 0; 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastStop = 1; 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t stopCount = 0; 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot float t_l = fOrigPos[firstStop]; 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f c_l = prepareColor(firstStop); 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot add_const_color(ctx, stopCount++, c_l); 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // N.B. lastStop is the index of the last stop, not one after. 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = firstStop; i < lastStop; i++) { 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot float t_r = fOrigPos[i + 1]; 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPM4f c_r = prepareColor(i + 1); 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(t_l <= t_r); 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (t_l < t_r) { 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot init_stop_pos(ctx, stopCount, t_l, t_r, c_l, c_r); 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stopCount += 1; 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot t_l = t_r; 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c_l = c_r; 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->ts[stopCount] = t_l; 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot add_const_color(ctx, stopCount++, c_l); 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->stopCount = stopCount; 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::gradient, ctx); 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!premulGrad && !this->colorsAreOpaque()) { 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::premul); 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->extend(postPipeline); 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkGradientShaderBase::isOpaque() const { 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fColorsAreOpaque; 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic unsigned rounded_divide(unsigned numer, unsigned denom) { 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (numer + (denom >> 1)) / denom; 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkGradientShaderBase::onAsLuminanceColor(SkColor* lum) const { 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we just compute an average color. 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // possibly we could weight this based on the proportional width for each color 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // assuming they are not evenly distributed in the fPos array. 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int r = 0; 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int g = 0; 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int b = 0; 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int n = fColorCount; 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: use linear colors? 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < n; ++i) { 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor c = this->getLegacyColor(i); 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r += SkColorGetR(c); 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot g += SkColorGetG(c); 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot b += SkColorGetB(c); 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *lum = SkColorSetRGB(rounded_divide(r, n), rounded_divide(g, n), rounded_divide(b, n)); 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkGradientShaderBase::AutoXformColors::AutoXformColors(const SkGradientShaderBase& grad, 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSpaceXformer* xformer) 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fColors(grad.fColorCount) { 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: stay in 4f to preserve precision? 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoSTMalloc<8, SkColor> origColors(grad.fColorCount); 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < grad.fColorCount; ++i) { 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot origColors[i] = grad.getLegacyColor(i); 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot xformer->apply(fColors.get(), origColors.get(), grad.fColorCount); 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic constexpr int kGradientTextureSize = 256; 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkGradientShaderBase::initLinearBitmap(SkBitmap* bitmap, GradientBitmapType bitmapType) const { 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const bool interpInPremul = SkToBool(fGradFlags & 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShader::kInterpolateColorsInPremul_Flag); 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkHalf* pixelsF16 = reinterpret_cast<SkHalf*>(bitmap->getPixels()); 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* pixels32 = reinterpret_cast<uint32_t*>(bitmap->getPixels()); 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef std::function<void(const Sk4f&, int)> pixelWriteFn_t; 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelWriteFn_t writeF16Pixel = [&](const Sk4f& x, int index) { 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sk4h c = SkFloatToHalf_finite_ftz(x); 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelsF16[4*index+0] = c[0]; 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelsF16[4*index+1] = c[1]; 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelsF16[4*index+2] = c[2]; 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelsF16[4*index+3] = c[3]; 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelWriteFn_t writeS32Pixel = [&](const Sk4f& c, int index) { 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixels32[index] = Sk4f_toS32(c); 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelWriteFn_t writeL32Pixel = [&](const Sk4f& c, int index) { 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixels32[index] = Sk4f_toL32(c); 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelWriteFn_t writeSizedPixel = 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (bitmapType == GradientBitmapType::kHalfFloat) ? writeF16Pixel : 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (bitmapType == GradientBitmapType::kSRGB ) ? writeS32Pixel : writeL32Pixel; 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelWriteFn_t writeUnpremulPixel = [&](const Sk4f& c, int index) { 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writeSizedPixel(c * Sk4f(c[3], c[3], c[3], 1.0f), index); 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixelWriteFn_t writePixel = interpInPremul ? writeSizedPixel : writeUnpremulPixel; 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // When not in legacy mode, we just want the original 4f colors - so we pass in 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // our own CS for identity/no transform. 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto* cs = bitmapType != GradientBitmapType::kLegacy ? fColorSpace.get() : nullptr; 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int prevIndex = 0; 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 1; i < fColorCount; i++) { 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Historically, stops have been mapped to [0, 256], with 256 then nudged to the 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // next smaller value, then truncate for the texture index. This seems to produce 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the best results for some common distributions, so we preserve the behavior. 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int nextIndex = SkTMin(this->getPos(i) * kGradientTextureSize, 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(kGradientTextureSize - 1)); 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nextIndex > prevIndex) { 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor4f color0 = this->getXformedColor(i - 1, cs), 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot color1 = this->getXformedColor(i , cs); 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sk4f c0 = Sk4f::Load(color0.vec()), 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c1 = Sk4f::Load(color1.vec()); 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (interpInPremul) { 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c0 = c0 * Sk4f(c0[3], c0[3], c0[3], 1.0f); 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c1 = c1 * Sk4f(c1[3], c1[3], c1[3], 1.0f); 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sk4f step = Sk4f(1.0f / static_cast<float>(nextIndex - prevIndex)); 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sk4f delta = (c1 - c0) * step; 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) { 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writePixel(c0, curIndex); 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c0 += delta; 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prevIndex = nextIndex; 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(prevIndex == kGradientTextureSize - 1); 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkColor4f SkGradientShaderBase::getXformedColor(size_t i, SkColorSpace* dstCS) const { 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (dstCS) { 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS); 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Legacy/srgb color. 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We quantize upfront to ensure stable SkColor round-trips. 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto rgb255 = sk_linear_to_srgb(Sk4f::Load(fOrigColors4f[i].vec())); 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto rgb = SkNx_cast<float>(rgb255) * (1/255.0f); 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return { rgb[0], rgb[1], rgb[2], fOrigColors4f[i].fA }; 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(gGradientCacheMutex); 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Because our caller might rebuild the same (logically the same) gradient 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * over and over, we'd like to return exactly the same "bitmap" if possible, 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * To do that, we maintain a private cache of built-bitmaps, based on our 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * colors and positions. 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap, 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GradientBitmapType bitmapType) const { 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // build our key: [numColors + colors[] + {positions[]} + flags + colorType ] 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static_assert(sizeof(SkColor4f) % sizeof(int32_t) == 0, ""); 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int colorsAsIntCount = fColorCount * sizeof(SkColor4f) / sizeof(int32_t); 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = 1 + colorsAsIntCount + 1 + 1; 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorCount > 2) { 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count += fColorCount - 1; 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoSTMalloc<64, int32_t> storage(count); 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int32_t* buffer = storage.get(); 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *buffer++ = fColorCount; 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(buffer, fOrigColors4f, fColorCount * sizeof(SkColor4f)); 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer += colorsAsIntCount; 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorCount > 2) { 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 1; i < fColorCount; i++) { 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *buffer++ = SkFloat2Bits(this->getPos(i)); 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *buffer++ = fGradFlags; 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *buffer++ = static_cast<int32_t>(bitmapType); 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(buffer - storage.get() == count); 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /////////////////////////////////// 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static SkGradientBitmapCache* gCache; 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // each cache cost 1K or 2K of RAM, since each bitmap will be 1x256 at either 32bpp or 64bpp 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ama(gGradientCacheMutex); 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == gCache) { 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gCache = new SkGradientBitmapCache(MAX_NUM_CACHED_GRADIENT_BITMAPS); 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t size = count * sizeof(int32_t); 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!gCache->find(storage.get(), size, bitmap)) { 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // For these cases we use the bitmap cache, but not the GradientShaderCache. So just 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // allocate and populate the bitmap's data directly. 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo info; 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (bitmapType) { 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GradientBitmapType::kLegacy: 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info = SkImageInfo::Make(kGradientTextureSize, 1, kRGBA_8888_SkColorType, 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kPremul_SkAlphaType); 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GradientBitmapType::kSRGB: 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info = SkImageInfo::Make(kGradientTextureSize, 1, kRGBA_8888_SkColorType, 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kPremul_SkAlphaType, SkColorSpace::MakeSRGB()); 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GradientBitmapType::kHalfFloat: 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info = SkImageInfo::Make(kGradientTextureSize, 1, kRGBA_F16_SkColorType, 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kPremul_SkAlphaType, SkColorSpace::MakeSRGBLinear()); 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap->allocPixels(info); 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->initLinearBitmap(bitmap, bitmapType); 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gCache->add(storage.get(), size, *bitmap); 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info) { 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info->fColorCount >= fColorCount) { 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info->fColors) { 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fColorCount; ++i) { 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fColors[i] = this->getLegacyColor(i); 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info->fColorOffsets) { 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fColorCount; ++i) { 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fColorOffsets[i] = this->getPos(i); 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fColorCount = fColorCount; 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fTileMode = fTileMode; 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fGradientFlags = fGradFlags; 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkGradientShaderBase::toString(SkString* str) const { 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf("%d colors: ", fColorCount); 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fColorCount; ++i) { 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendHex(this->getLegacyColor(i), 8); 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (i < fColorCount-1) { 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(", "); 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorCount > 2) { 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(" points: ("); 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fColorCount; ++i) { 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(this->getPos(i)); 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (i < fColorCount-1) { 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(", "); 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(")"); 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const char* gTileModeName[SkShader::kTileModeCount] = { 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "clamp", "repeat", "mirror" 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(" "); 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(gTileModeName[fTileMode]); 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->INHERITED::toString(str); 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Return true if these parameters are valid/legal/safe to construct a gradient 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool valid_grad(const SkColor4f colors[], const SkScalar pos[], int count, 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned tileMode) { 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr != colors && count >= 1 && tileMode < (unsigned)SkShader::kTileModeCount; 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void desc_init(SkGradientShaderBase::Descriptor* desc, 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace, 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], int colorCount, 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, uint32_t flags, const SkMatrix* localMatrix) { 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(colorCount > 1); 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fColors = colors; 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fColorSpace = std::move(colorSpace); 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fPos = pos; 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fCount = colorCount; 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fTileMode = mode; 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fGradFlags = flags; 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc->fLocalMatrix = localMatrix; 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// assumes colors is SkColor4f* and pos is SkScalar* 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define EXPAND_1_COLOR(count) \ 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor4f tmp[2]; \ 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { \ 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (1 == count) { \ 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmp[0] = tmp[1] = colors[0]; \ 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot colors = tmp; \ 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pos = nullptr; \ 685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count = 2; \ 686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } \ 687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (0) 688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct ColorStopOptimizer { 690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorStopOptimizer(const SkColor4f* colors, const SkScalar* pos, 691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkShader::TileMode mode) 692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fColors(colors) 693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fPos(pos) 694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fCount(count) { 695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!pos || count != 3) { 697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyEqual(pos[0], 0.0f) && 701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarNearlyEqual(pos[1], 0.0f) && 702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarNearlyEqual(pos[2], 1.0f)) { 703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkShader::kRepeat_TileMode == mode || 705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::kMirror_TileMode == mode || 706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot colors[0] == colors[1]) { 707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Ignore the leftmost color/pos. 709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors += 1; 710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPos += 1; 711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCount = 2; 712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (SkScalarNearlyEqual(pos[0], 0.0f) && 714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarNearlyEqual(pos[1], 1.0f) && 715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarNearlyEqual(pos[2], 1.0f)) { 716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkShader::kRepeat_TileMode == mode || 718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::kMirror_TileMode == mode || 719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot colors[1] == colors[2]) { 720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Ignore the rightmost color/pos. 722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCount = 2; 723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor4f* fColors; 728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar* fPos; 729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fCount; 730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct ColorConverter { 733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorConverter(const SkColor* colors, int count) { 734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; ++i) { 735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors4f.push_back(SkColor4f::FromColor(colors[i])); 736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArray<2, SkColor4f, true> fColors4f; 740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeLinear(const SkPoint pts[2], 743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor colors[], 744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], int colorCount, 745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorConverter converter(colors, colorCount); 749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return MakeLinear(pts, converter.fColors4f.begin(), nullptr, pos, colorCount, mode, flags, 750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot localMatrix); 751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeLinear(const SkPoint pts[2], 754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor4f colors[], 755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkColorSpace> colorSpace, 756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], int colorCount, 757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!pts || !SkScalarIsFinite((pts[1] - pts[0]).length())) { 761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!valid_grad(colors, pos, colorCount, mode)) { 764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (1 == colorCount) { 767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkShader::MakeColorShader(colors[0], std::move(colorSpace)); 768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (localMatrix && !localMatrix->invert(nullptr)) { 770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorStopOptimizer opt(colors, pos, colorCount, mode); 774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShaderBase::Descriptor desc; 776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags, 777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot localMatrix); 778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_make_sp<SkLinearGradient>(pts, desc); 779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeRadial(const SkPoint& center, SkScalar radius, 782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor colors[], 783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], int colorCount, 784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorConverter converter(colors, colorCount); 788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return MakeRadial(center, radius, converter.fColors4f.begin(), nullptr, pos, colorCount, mode, 789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags, localMatrix); 790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeRadial(const SkPoint& center, SkScalar radius, 793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor4f colors[], 794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkColorSpace> colorSpace, 795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], int colorCount, 796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (radius <= 0) { 800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!valid_grad(colors, pos, colorCount, mode)) { 803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (1 == colorCount) { 806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkShader::MakeColorShader(colors[0], std::move(colorSpace)); 807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (localMatrix && !localMatrix->invert(nullptr)) { 809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorStopOptimizer opt(colors, pos, colorCount, mode); 813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShaderBase::Descriptor desc; 815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags, 816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot localMatrix); 817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_make_sp<SkRadialGradient>(center, radius, desc); 818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start, 821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar startRadius, 822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& end, 823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar endRadius, 824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor colors[], 825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], 826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int colorCount, 827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorConverter converter(colors, colorCount); 831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return MakeTwoPointConical(start, startRadius, end, endRadius, converter.fColors4f.begin(), 832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nullptr, pos, colorCount, mode, flags, localMatrix); 833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start, 836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar startRadius, 837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& end, 838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar endRadius, 839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor4f colors[], 840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkColorSpace> colorSpace, 841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], 842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int colorCount, 843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (startRadius < 0 || endRadius < 0) { 847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyZero((start - end).length()) && SkScalarNearlyZero(startRadius)) { 850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We can treat this gradient as radial, which is faster. 851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return MakeRadial(start, endRadius, colors, std::move(colorSpace), pos, colorCount, 852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mode, flags, localMatrix); 853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!valid_grad(colors, pos, colorCount, mode)) { 855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (startRadius == endRadius) { 858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (start == end || startRadius == 0) { 859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkShader::MakeEmptyShader(); 860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (localMatrix && !localMatrix->invert(nullptr)) { 863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot EXPAND_1_COLOR(colorCount); 866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorStopOptimizer opt(colors, pos, colorCount, mode); 868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShaderBase::Descriptor desc; 870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags, 871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot localMatrix); 872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkTwoPointConicalGradient::Create(start, startRadius, end, endRadius, desc); 873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy, 876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor colors[], 877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], 878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int colorCount, 879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar startAngle, 881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar endAngle, 882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorConverter converter(colors, colorCount); 885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return MakeSweep(cx, cy, converter.fColors4f.begin(), nullptr, pos, colorCount, 886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mode, startAngle, endAngle, flags, localMatrix); 887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy, 890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkColor4f colors[], 891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkColorSpace> colorSpace, 892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], 893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int colorCount, 894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::TileMode mode, 895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar startAngle, 896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar endAngle, 897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags, 898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* localMatrix) { 899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!valid_grad(colors, pos, colorCount, mode)) { 900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (1 == colorCount) { 903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkShader::MakeColorShader(colors[0], std::move(colorSpace)); 904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (startAngle >= endAngle) { 906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (localMatrix && !localMatrix->invert(nullptr)) { 909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (startAngle <= 0 && endAngle >= 360) { 913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If the t-range includes [0,1], then we can always use clamping (presumably faster). 914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mode = SkShader::kClamp_TileMode; 915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ColorStopOptimizer opt(colors, pos, colorCount, mode); 918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShaderBase::Descriptor desc; 920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags, 921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot localMatrix); 922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar t0 = startAngle / 360, 924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot t1 = endAngle / 360; 925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_make_sp<SkSweepGradient>(SkPoint::Make(cx, cy), t0, t1, desc); 927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) 930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) 931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) 932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) 933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) 934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU 939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrColorSpaceXform.h" 941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContext.h" 942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContextPriv.h" 943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrShaderCaps.h" 944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextureStripAtlas.h" 945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gl/GrGLContext.h" 946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentShaderBuilder.h" 947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLProgramDataManager.h" 948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLUniformHandler.h" 949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h" 950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniformHandler, 952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrGradientEffect& ge) { 953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (ge.fStrategy) { 954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThreshold: 955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp0: 956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp1: 957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fThresholdUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kFloat_GrSLType, 959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHigh_GrSLPrecision, 960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "Threshold"); 961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // fall through 962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kSingle: 963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIntervalsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, 964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHalf4_GrSLType, 965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "Intervals", 966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ge.fIntervals.count()); 967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kTexture: 969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, 970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "GradientYCoordFS"); 971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman, 976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrFragmentProcessor& processor) { 977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrGradientEffect& e = processor.cast<GrGradientEffect>(); 978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (e.fStrategy) { 980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThreshold: 981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp0: 982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp1: 983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pdman.set1f(fThresholdUni, e.fThreshold); 984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // fall through 985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kSingle: 986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pdman.set4fv(fIntervalsUni, e.fIntervals.count(), 987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot reinterpret_cast<const float*>(e.fIntervals.begin())); 988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kTexture: 990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (e.fYCoord != fCachedYCoord) { 991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pdman.set1f(fFSYUni, e.fYCoord); 992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCachedYCoord = e.fYCoord; 993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGradientEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { 999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot b->add32(GLSLProcessor::GenBaseGradientKey(*this)); 1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotuint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) { 1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrGradientEffect& e = processor.cast<GrGradientEffect>(); 1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Build a key using the following bit allocation: 1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr uint32_t kStrategyBits = 3; 1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr uint32_t kPremulBits = 1; 1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(static constexpr uint32_t kWrapModeBits = 2;) 1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t key = static_cast<uint32_t>(e.fStrategy); 1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(key < (1 << kStrategyBits)); 1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is already baked into the table for texture gradients, 1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // and only changes behavior for analytical gradients. 1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (e.fStrategy != InterpolationStrategy::kTexture && 1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot e.fPremulType == GrGradientEffect::kBeforeInterp_PremulType) { 1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot key |= 1 << kStrategyBits; 1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(key < (1 << (kStrategyBits + kPremulBits))); 1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot key |= static_cast<uint32_t>(e.fWrapMode) << (kStrategyBits + kPremulBits); 1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(key < (1 << (kStrategyBits + kPremulBits + kWrapModeBits))); 1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return key; 1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilder* fragBuilder, 1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrGLSLUniformHandler* uniformHandler, 1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrShaderCaps* shaderCaps, 1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrGradientEffect& ge, 1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* t, 1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* outputColor, 1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* inputColor) { 1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // First, apply tiling rules. 1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (ge.fWrapMode) { 1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrSamplerState::WrapMode::kClamp: 1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (ge.fStrategy) { 1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp0: 1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // allow t > 1, in order to hit the clamp interval (1, inf) 1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half tiled_t = max(%s, 0.0);", t); 1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp1: 1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // allow t < 0, in order to hit the clamp interval (-inf, 0) 1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half tiled_t = min(%s, 1.0);", t); 1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // regular [0, 1] clamping 1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half tiled_t = clamp(%s, 0.0, 1.0);", t); 1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrSamplerState::WrapMode::kRepeat: 1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half tiled_t = fract(%s);", t); 1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrSamplerState::WrapMode::kMirrorRepeat: 1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half t_1 = %s - 1.0;", t); 1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half tiled_t = t_1 - 2.0 * floor(t_1 * 0.5) - 1.0;"); 1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (shaderCaps->mustDoOpBetweenFloorAndAbs()) { 1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // At this point the expected value of tiled_t should between -1 and 1, so this 1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // clamp has no effect other than to break up the floor and abs calls and make sure 1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the compiler doesn't merge them back together. 1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("tiled_t = clamp(tiled_t, -1.0, 1.0);"); 1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("tiled_t = abs(tiled_t);"); 1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Calculate the color. 1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* intervals = uniformHandler->getUniformCStr(fIntervalsUni); 1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (ge.fStrategy) { 1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kSingle: 1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(ge.fIntervals.count() == 2); 1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf( 1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "half4 color_scale = %s[0]," 1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot " color_bias = %s[1];" 1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , intervals, intervals 1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ); 1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThreshold: 1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp0: 1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case GrGradientEffect::InterpolationStrategy::kThresholdClamp1: 1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(ge.fIntervals.count() == 4); 1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* threshold = uniformHandler->getUniformCStr(fThresholdUni); 1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf( 1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "half4 color_scale, color_bias;" 1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "if (tiled_t < %s) {" 1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot " color_scale = %s[0];" 1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot " color_bias = %s[1];" 1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "} else {" 1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot " color_scale = %s[2];" 1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot " color_bias = %s[3];" 1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "}" 1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , threshold, intervals, intervals, intervals, intervals 1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ); 1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } break; 1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(false); 1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppend("half4 colorTemp = tiled_t * color_scale + color_bias;"); 1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We could skip this step if all colors are known to be opaque. Two considerations: 1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The gradient SkShader reporting opaque is more restrictive than necessary in the two 1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // pt case. Make sure the key reflects this optimization (and note that it can use the 1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // same shader as the kBeforeInterp case). 1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ge.fPremulType == GrGradientEffect::kAfterInterp_PremulType) { 1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;"); 1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If the input colors were floats, or there was a color space xform, we may end up out of 1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // range. The simplest solution is to always clamp our (premul) value here. We only need to 1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // clamp RGB, but that causes hangs on the Tegra3 Nexus7. Clamping RGBA avoids the problem. 1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppend("colorTemp = clamp(colorTemp, 0, colorTemp.a);"); 1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("%s = %s * colorTemp;", outputColor, inputColor); 1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBuilder, 1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrGLSLUniformHandler* uniformHandler, 1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrShaderCaps* shaderCaps, 1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrGradientEffect& ge, 1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* gradientTValue, 1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* outputColor, 1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* inputColor, 1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const TextureSamplers& texSamplers) { 1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ge.fStrategy != InterpolationStrategy::kTexture) { 1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->emitAnalyticalColor(fragBuilder, uniformHandler, shaderCaps, ge, gradientTValue, 1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot outputColor, inputColor); 1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* fsyuni = uniformHandler->getUniformCStr(fFSYUni); 1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("half2 coord = half2(%s, %s);", gradientTValue, fsyuni); 1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppendf("%s = ", outputColor); 1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord", 1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kFloat2_GrSLType); 1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fragBuilder->codeAppend(";"); 1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////// 1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline GrFragmentProcessor::OptimizationFlags GrGradientEffect::OptFlags(bool isOpaque) { 1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return isOpaque 1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? kPreservesOpaqueInput_OptimizationFlag | 1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kCompatibleWithCoverageAsAlpha_OptimizationFlag 1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : kCompatibleWithCoverageAsAlpha_OptimizationFlag; 1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGradientEffect::addInterval(const SkGradientShaderBase& shader, size_t idx0, size_t idx1, 1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSpace* dstCS) { 1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(idx0 <= idx1); 1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto c4f0 = shader.getXformedColor(idx0, dstCS), 1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c4f1 = shader.getXformedColor(idx1, dstCS); 1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto c0 = (fPremulType == kBeforeInterp_PremulType) 1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? c4f0.premul().to4f() : Sk4f::Load(c4f0.vec()), 1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c1 = (fPremulType == kBeforeInterp_PremulType) 1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? c4f1.premul().to4f() : Sk4f::Load(c4f1.vec()); 1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto t0 = shader.getPos(idx0), 1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot t1 = shader.getPos(idx1), 1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dt = t1 - t0; 1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(dt >= 0); 1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // dt can be 0 for clamp intervals => in this case we want a scale == 0 1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto scale = SkScalarNearlyZero(dt) ? 0 : (c1 - c0) / dt, 1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bias = c0 - t0 * scale; 1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Intervals are stored as (scale, bias) tuples. 1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!(fIntervals.count() & 1)); 1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIntervals.emplace_back(scale[0], scale[1], scale[2], scale[3]); 1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIntervals.emplace_back( bias[0], bias[1], bias[2], bias[3]); 1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGradientEffect::GrGradientEffect(ClassID classID, const CreateArgs& args, bool isOpaque) 1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : INHERITED(classID, OptFlags(isOpaque)) 1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fWrapMode(args.fWrapMode) 1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fRow(-1) 1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fIsOpaque(args.fShader->isOpaque()) 1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fStrategy(InterpolationStrategy::kTexture) 1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fThreshold(0) { 1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkGradientShaderBase& shader(*args.fShader); 1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPremulType = (args.fShader->getGradFlags() & SkGradientShader::kInterpolateColorsInPremul_Flag) 1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? kBeforeInterp_PremulType : kAfterInterp_PremulType; 1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // First, determine the interpolation strategy and params. 1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (shader.fColorCount) { 1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case 2: 1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!shader.fOrigPos); 1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kSingle; 1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 0, 1, args.fDstColorSpace); 1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case 3: 1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fThreshold = shader.getPos(1); 1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (shader.fOrigPos) { 1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[0], 0)); 1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[2], 1)); 1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyEqual(shader.fOrigPos[1], 0)) { 1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // hard stop on the left edge. 1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fWrapMode == GrSamplerState::WrapMode::kClamp) { 1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kThresholdClamp1; 1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Clamp interval (scale == 0, bias == colors[0]). 1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 0, 0, args.fDstColorSpace); 1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We can ignore the hard stop when not clamping. 1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kSingle; 1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 1, 2, args.fDstColorSpace); 1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyEqual(shader.fOrigPos[1], 1)) { 1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // hard stop on the right edge. 1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 0, 1, args.fDstColorSpace); 1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fWrapMode == GrSamplerState::WrapMode::kClamp) { 1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kThresholdClamp0; 1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Clamp interval (scale == 0, bias == colors[2]). 1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 2, 2, args.fDstColorSpace); 1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We can ignore the hard stop when not clamping. 1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kSingle; 1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Two arbitrary interpolation intervals. 1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kThreshold; 1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 0, 1, args.fDstColorSpace); 1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 1, 2, args.fDstColorSpace); 1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case 4: 1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (shader.fOrigPos && SkScalarNearlyEqual(shader.fOrigPos[1], shader.fOrigPos[2])) { 1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[0], 0)); 1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[3], 1)); 1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Single hard stop => two arbitrary interpolation intervals. 1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrategy = InterpolationStrategy::kThreshold; 1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fThreshold = shader.getPos(1); 1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 0, 1, args.fDstColorSpace); 1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addInterval(shader, 2, 3, args.fDstColorSpace); 1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now that we've locked down a strategy, adjust any dependent params. 1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fStrategy != InterpolationStrategy::kTexture) { 1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Analytical cases. 1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoordTransform.reset(*args.fMatrix); 1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShaderBase::GradientBitmapType bitmapType = 1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGradientShaderBase::GradientBitmapType::kLegacy; 1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (args.fDstColorSpace) { 1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Try to use F16 if we can 1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (args.fContext->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) { 1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmapType = SkGradientShaderBase::GradientBitmapType::kHalfFloat; 1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (args.fContext->caps()->isConfigTexturable(kSRGBA_8888_GrPixelConfig)) { 1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmapType = SkGradientShaderBase::GradientBitmapType::kSRGB; 1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This can happen, but only if someone explicitly creates an unsupported 1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // (eg sRGB) surface. Just fall back to legacy behavior. 1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bitmap; 1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shader.getGradientTableBitmap(&bitmap, bitmapType); 1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(1 == bitmap.height() && SkIsPow2(bitmap.width())); 1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrTextureStripAtlas::Desc desc; 1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fWidth = bitmap.width(); 1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fHeight = 32; 1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fRowHeight = bitmap.height(); 1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fContext = args.fContext; 1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *args.fContext->caps()); 1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAtlas = GrTextureStripAtlas::GetAtlas(desc); 1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fAtlas); 1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We always filter the gradient table. Each table is one row of a texture, always 1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // y-clamp. 1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrSamplerState samplerState(args.fWrapMode, GrSamplerState::Filter::kBilerp); 1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRow = fAtlas->lockRow(bitmap); 1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (-1 != fRow) { 1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fYCoord = fAtlas->getYOffset(fRow)+SK_ScalarHalf*fAtlas->getNormalizedTexelHeight(); 1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is 1/2 places where auto-normalization is disabled 1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoordTransform.reset(*args.fMatrix, fAtlas->asTextureProxyRef().get(), false); 1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTextureSampler.reset(fAtlas->asTextureProxyRef(), samplerState); 1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // In this instance we know the samplerState state is: 1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // clampY, bilerp 1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // and the proxy is: 1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // exact fit, power of two in both dimensions 1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Only the x-tileMode is unknown. However, given all the other knowns we know 1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // that GrMakeCachedBitmapProxy is sufficient (i.e., it won't need to be 1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // extracted to a subset or mipmapped). 1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy( 1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.fContext->contextPriv().proxyProvider(), 1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap); 1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!proxy) { 1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("Gradient won't draw. Could not create texture."); 1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is 2/2 places where auto-normalization is disabled 1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoordTransform.reset(*args.fMatrix, proxy.get(), false); 1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTextureSampler.reset(std::move(proxy), samplerState); 1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fYCoord = SK_ScalarHalf; 1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addTextureSampler(&fTextureSampler); 1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addCoordTransform(&fCoordTransform); 1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGradientEffect::GrGradientEffect(const GrGradientEffect& that) 1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : INHERITED(that.classID(), OptFlags(that.fIsOpaque)) 1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fIntervals(that.fIntervals) 1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fWrapMode(that.fWrapMode) 1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fCoordTransform(that.fCoordTransform) 1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fTextureSampler(that.fTextureSampler) 1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fYCoord(that.fYCoord) 1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fAtlas(that.fAtlas) 1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fRow(that.fRow) 1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fIsOpaque(that.fIsOpaque) 1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fStrategy(that.fStrategy) 1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fThreshold(that.fThreshold) 1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fPremulType(that.fPremulType) { 1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addCoordTransform(&fCoordTransform); 1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fStrategy == InterpolationStrategy::kTexture) { 1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->addTextureSampler(&fTextureSampler); 1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->useAtlas()) { 1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAtlas->lockRow(fRow); 1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGradientEffect::~GrGradientEffect() { 1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->useAtlas()) { 1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAtlas->unlockRow(fRow); 1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const { 1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrGradientEffect& ge = processor.cast<GrGradientEffect>(); 1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fWrapMode != ge.fWrapMode || fStrategy != ge.fStrategy) { 1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->useAtlas() == ge.useAtlas()); 1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fStrategy == InterpolationStrategy::kTexture) { 1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fYCoord != ge.fYCoord) { 1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fThreshold != ge.fThreshold || 1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIntervals != ge.fIntervals || 1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPremulType != ge.fPremulType) { 1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if GR_TEST_UTILS 1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGradientEffect::RandomGradientParams::RandomGradientParams(SkRandom* random) { 1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Set color count to min of 2 so that we don't trigger the const color optimization and make 1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // a non-gradient processor. 1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorCount = random->nextRangeU(2, kMaxRandomGradientColors); 1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fUseColors4f = random->nextBool(); 1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if one color, omit stops, otherwise randomly decide whether or not to 1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorCount == 1 || (fColorCount >= 2 && random->nextBool())) { 1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStops = nullptr; 1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStops = fStopStorage; 1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if using SkColor4f, attach a random (possibly null) color space (with linear gamma) 1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fUseColors4f) { 1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorSpace = GrTest::TestColorSpace(random); 1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fColorSpace) { 1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColorSpace = fColorSpace->makeLinearGamma(); 1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar stop = 0.f; 1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fColorCount; ++i) { 1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fUseColors4f) { 1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors4f[i].fR = random->nextUScalar1(); 1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors4f[i].fG = random->nextUScalar1(); 1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors4f[i].fB = random->nextUScalar1(); 1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors4f[i].fA = random->nextUScalar1(); 1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fColors[i] = random->nextU(); 1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fStops) { 1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStops[i] = stop; 1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stop = i < fColorCount - 1 ? stop + random->nextUScalar1() * (1.f - stop) : 1.f; 1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTileMode = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileModeCount)); 1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1413