Implement textured gradients
Also clones SkGradientBitmapCache into GrGradientBitmapCache in the gpu/gradients folder. But after cleaning up the old gradient code, SkGradientBitmapCache will go away and SkGradientShader will have no reference to the bitmap cache or support for building bitmaps. The "new" GrGradientBitmapCache has been updated to hide the thread safety responsibilities and gradient bitmap generation code that had originally been a part of SkGradientShader. Bug: skia: Change-Id: Ida134c6437c866439fac44fa453d09a6a11549e7 Reviewed-on: https://skia-review.googlesource.com/150917 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
b68bcc4398
commit
a7914d3a8e
@ -405,6 +405,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/gradients/GrDualIntervalGradientColorizer.h",
|
||||
"$_src/gpu/gradients/GrSingleIntervalGradientColorizer.cpp",
|
||||
"$_src/gpu/gradients/GrSingleIntervalGradientColorizer.h",
|
||||
"$_src/gpu/gradients/GrTextureGradientColorizer.cpp",
|
||||
"$_src/gpu/gradients/GrTextureGradientColorizer.h",
|
||||
"$_src/gpu/gradients/GrLinearGradientLayout.cpp",
|
||||
"$_src/gpu/gradients/GrLinearGradientLayout.h",
|
||||
"$_src/gpu/gradients/GrRadialGradientLayout.cpp",
|
||||
@ -417,6 +419,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/gradients/GrClampedGradientEffect.h",
|
||||
"$_src/gpu/gradients/GrTiledGradientEffect.cpp",
|
||||
"$_src/gpu/gradients/GrTiledGradientEffect.h",
|
||||
"$_src/gpu/gradients/GrGradientBitmapCache.cpp",
|
||||
"$_src/gpu/gradients/GrGradientBitmapCache.h",
|
||||
"$_src/gpu/gradients/GrGradientShader.cpp",
|
||||
"$_src/gpu/gradients/GrGradientShader.h",
|
||||
|
||||
|
@ -48,6 +48,7 @@ skia_gpu_processor_sources = [
|
||||
"$_src/gpu/effects/GrYUVtoRGBEffect.fp",
|
||||
"$_src/gpu/gradients/GrDualIntervalGradientColorizer.fp",
|
||||
"$_src/gpu/gradients/GrSingleIntervalGradientColorizer.fp",
|
||||
"$_src/gpu/gradients/GrTextureGradientColorizer.fp",
|
||||
"$_src/gpu/gradients/GrLinearGradientLayout.fp",
|
||||
"$_src/gpu/gradients/GrRadialGradientLayout.fp",
|
||||
"$_src/gpu/gradients/GrSweepGradientLayout.fp",
|
||||
|
@ -140,6 +140,7 @@ public:
|
||||
kGrSweepGradient_ClassID,
|
||||
kGrSweepGradientLayout_ClassID,
|
||||
kGrTextureDomainEffect_ClassID,
|
||||
kGrTextureGradientColorizer_ClassID,
|
||||
kGrTiledGradientEffect_ClassID,
|
||||
kGrTwoPointConicalGradientLayout_ClassID,
|
||||
kGrUnpremulInputFragmentProcessor_ClassID,
|
||||
|
249
src/gpu/gradients/GrGradientBitmapCache.cpp
Normal file
249
src/gpu/gradients/GrGradientBitmapCache.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "GrGradientBitmapCache.h"
|
||||
|
||||
#include "SkMalloc.h"
|
||||
#include "SkFloatBits.h"
|
||||
#include "SkHalf.h"
|
||||
#include "SkPM4fPriv.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct GrGradientBitmapCache::Entry {
|
||||
Entry* fPrev;
|
||||
Entry* fNext;
|
||||
|
||||
void* fBuffer;
|
||||
size_t fSize;
|
||||
SkBitmap fBitmap;
|
||||
|
||||
Entry(const void* buffer, size_t size, const SkBitmap& bm)
|
||||
: fPrev(nullptr),
|
||||
fNext(nullptr),
|
||||
fBitmap(bm) {
|
||||
fBuffer = sk_malloc_throw(size);
|
||||
fSize = size;
|
||||
memcpy(fBuffer, buffer, size);
|
||||
}
|
||||
|
||||
~Entry() { sk_free(fBuffer); }
|
||||
|
||||
bool equals(const void* buffer, size_t size) const {
|
||||
return (fSize == size) && !memcmp(fBuffer, buffer, size);
|
||||
}
|
||||
};
|
||||
|
||||
GrGradientBitmapCache::GrGradientBitmapCache(int max, int res)
|
||||
: fMaxEntries(max)
|
||||
, fResolution(res) {
|
||||
fEntryCount = 0;
|
||||
fHead = fTail = nullptr;
|
||||
|
||||
this->validate();
|
||||
}
|
||||
|
||||
GrGradientBitmapCache::~GrGradientBitmapCache() {
|
||||
this->validate();
|
||||
|
||||
Entry* entry = fHead;
|
||||
while (entry) {
|
||||
Entry* next = entry->fNext;
|
||||
delete entry;
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
GrGradientBitmapCache::Entry* GrGradientBitmapCache::release(Entry* entry) const {
|
||||
if (entry->fPrev) {
|
||||
SkASSERT(fHead != entry);
|
||||
entry->fPrev->fNext = entry->fNext;
|
||||
} else {
|
||||
SkASSERT(fHead == entry);
|
||||
fHead = entry->fNext;
|
||||
}
|
||||
if (entry->fNext) {
|
||||
SkASSERT(fTail != entry);
|
||||
entry->fNext->fPrev = entry->fPrev;
|
||||
} else {
|
||||
SkASSERT(fTail == entry);
|
||||
fTail = entry->fPrev;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void GrGradientBitmapCache::attachToHead(Entry* entry) const {
|
||||
entry->fPrev = nullptr;
|
||||
entry->fNext = fHead;
|
||||
if (fHead) {
|
||||
fHead->fPrev = entry;
|
||||
} else {
|
||||
fTail = entry;
|
||||
}
|
||||
fHead = entry;
|
||||
}
|
||||
|
||||
bool GrGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
|
||||
AutoValidate av(this);
|
||||
|
||||
Entry* entry = fHead;
|
||||
while (entry) {
|
||||
if (entry->equals(buffer, size)) {
|
||||
if (bm) {
|
||||
*bm = entry->fBitmap;
|
||||
}
|
||||
// move to the head of our list, so we purge it last
|
||||
this->release(entry);
|
||||
this->attachToHead(entry);
|
||||
return true;
|
||||
}
|
||||
entry = entry->fNext;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GrGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
|
||||
AutoValidate av(this);
|
||||
|
||||
if (fEntryCount == fMaxEntries) {
|
||||
SkASSERT(fTail);
|
||||
delete this->release(fTail);
|
||||
fEntryCount -= 1;
|
||||
}
|
||||
|
||||
Entry* entry = new Entry(buffer, len, bm);
|
||||
this->attachToHead(entry);
|
||||
fEntryCount += 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void GrGradientBitmapCache::fillGradient(const GrColor4f* colors, const SkScalar* positions,
|
||||
int count, SkColorType colorType, SkBitmap* bitmap) {
|
||||
SkHalf* pixelsF16 = reinterpret_cast<SkHalf*>(bitmap->getPixels());
|
||||
uint32_t* pixels32 = reinterpret_cast<uint32_t*>(bitmap->getPixels());
|
||||
|
||||
typedef std::function<void(const Sk4f&, int)> pixelWriteFn_t;
|
||||
|
||||
pixelWriteFn_t writeF16Pixel = [&](const Sk4f& x, int index) {
|
||||
Sk4h c = SkFloatToHalf_finite_ftz(x);
|
||||
pixelsF16[4*index+0] = c[0];
|
||||
pixelsF16[4*index+1] = c[1];
|
||||
pixelsF16[4*index+2] = c[2];
|
||||
pixelsF16[4*index+3] = c[3];
|
||||
};
|
||||
pixelWriteFn_t write8888Pixel = [&](const Sk4f& c, int index) {
|
||||
pixels32[index] = Sk4f_toL32(c);
|
||||
};
|
||||
|
||||
pixelWriteFn_t writePixel =
|
||||
(colorType == kRGBA_F16_SkColorType) ? writeF16Pixel : write8888Pixel;
|
||||
|
||||
int prevIndex = 0;
|
||||
for (int i = 1; i < count; i++) {
|
||||
// Historically, stops have been mapped to [0, 256], with 256 then nudged to the next
|
||||
// smaller value, then truncate for the texture index. This seems to produce the best
|
||||
// results for some common distributions, so we preserve the behavior.
|
||||
int nextIndex = SkTMin(positions[i] * fResolution,
|
||||
SkIntToScalar(fResolution - 1));
|
||||
|
||||
if (nextIndex > prevIndex) {
|
||||
Sk4f c0 = Sk4f::Load(colors[i - 1].fRGBA),
|
||||
c1 = Sk4f::Load(colors[i ].fRGBA);
|
||||
|
||||
Sk4f step = Sk4f(1.0f / static_cast<float>(nextIndex - prevIndex));
|
||||
Sk4f delta = (c1 - c0) * step;
|
||||
|
||||
for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) {
|
||||
writePixel(c0, curIndex);
|
||||
c0 += delta;
|
||||
}
|
||||
}
|
||||
prevIndex = nextIndex;
|
||||
}
|
||||
SkASSERT(prevIndex == fResolution - 1);
|
||||
}
|
||||
|
||||
void GrGradientBitmapCache::getGradient(const GrColor4f* colors, const SkScalar* positions,
|
||||
int count, SkColorType colorType, SkAlphaType alphaType, SkBitmap* bitmap) {
|
||||
// build our key: [numColors + colors[] + positions[] + alphaType + colorType ]
|
||||
static_assert(sizeof(GrColor4f) % sizeof(int32_t) == 0, "");
|
||||
const int colorsAsIntCount = count * sizeof(GrColor4f) / sizeof(int32_t);
|
||||
int keyCount = 1 + colorsAsIntCount + 1 + 1;
|
||||
if (count > 2) {
|
||||
keyCount += count - 1;
|
||||
}
|
||||
|
||||
SkAutoSTMalloc<64, int32_t> storage(keyCount);
|
||||
int32_t* buffer = storage.get();
|
||||
|
||||
*buffer++ = count;
|
||||
memcpy(buffer, colors, count * sizeof(GrColor4f));
|
||||
buffer += colorsAsIntCount;
|
||||
if (count > 2) {
|
||||
for (int i = 1; i < count; i++) {
|
||||
*buffer++ = SkFloat2Bits(positions[i]);
|
||||
}
|
||||
}
|
||||
*buffer++ = static_cast<int32_t>(alphaType);
|
||||
*buffer++ = static_cast<int32_t>(colorType);
|
||||
SkASSERT(buffer - storage.get() == keyCount);
|
||||
|
||||
///////////////////////////////////
|
||||
|
||||
// acquire lock for checking/adding to cache
|
||||
SkAutoExclusive ama(fMutex);
|
||||
size_t size = keyCount * sizeof(int32_t);
|
||||
if (!this->find(storage.get(), size, bitmap)) {
|
||||
SkImageInfo info = SkImageInfo::Make(fResolution, 1, colorType, alphaType);
|
||||
bitmap->allocPixels(info);
|
||||
GrGradientBitmapCache::fillGradient(colors, positions, count, colorType, bitmap);
|
||||
bitmap->setImmutable();
|
||||
this->add(storage.get(), size, *bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
|
||||
void GrGradientBitmapCache::validate() const {
|
||||
SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
|
||||
|
||||
if (fEntryCount > 0) {
|
||||
SkASSERT(nullptr == fHead->fPrev);
|
||||
SkASSERT(nullptr == fTail->fNext);
|
||||
|
||||
if (fEntryCount == 1) {
|
||||
SkASSERT(fHead == fTail);
|
||||
} else {
|
||||
SkASSERT(fHead != fTail);
|
||||
}
|
||||
|
||||
Entry* entry = fHead;
|
||||
int count = 0;
|
||||
while (entry) {
|
||||
count += 1;
|
||||
entry = entry->fNext;
|
||||
}
|
||||
SkASSERT(count == fEntryCount);
|
||||
|
||||
entry = fTail;
|
||||
while (entry) {
|
||||
count -= 1;
|
||||
entry = entry->fPrev;
|
||||
}
|
||||
SkASSERT(0 == count);
|
||||
} else {
|
||||
SkASSERT(nullptr == fHead);
|
||||
SkASSERT(nullptr == fTail);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
62
src/gpu/gradients/GrGradientBitmapCache.h
Normal file
62
src/gpu/gradients/GrGradientBitmapCache.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GrGradientBitmapCache_DEFINED
|
||||
#define GrGradientBitmapCache_DEFINED
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkMutex.h"
|
||||
#include "SkNoncopyable.h"
|
||||
#include "GrColor.h"
|
||||
|
||||
class GrGradientBitmapCache : SkNoncopyable {
|
||||
public:
|
||||
GrGradientBitmapCache(int maxEntries, int resolution);
|
||||
~GrGradientBitmapCache();
|
||||
|
||||
// Assumes colors are compatible with the specified alphaType (e.g. if it's premul then colors
|
||||
// are already premultiplied). Thread safe.
|
||||
void getGradient(const GrColor4f* colors, const SkScalar* positions, int count,
|
||||
SkColorType colorType, SkAlphaType alphaType, SkBitmap* bitmap);
|
||||
|
||||
private:
|
||||
SkMutex fMutex;
|
||||
|
||||
int fEntryCount;
|
||||
const int fMaxEntries;
|
||||
const int fResolution;
|
||||
|
||||
struct Entry;
|
||||
mutable Entry* fHead;
|
||||
mutable Entry* fTail;
|
||||
|
||||
inline Entry* release(Entry*) const;
|
||||
inline void attachToHead(Entry*) const;
|
||||
|
||||
bool find(const void* buffer, size_t len, SkBitmap*) const;
|
||||
void add(const void* buffer, size_t len, const SkBitmap&);
|
||||
|
||||
void fillGradient(const GrColor4f* colors, const SkScalar* positions, int count,
|
||||
SkColorType colorType, SkBitmap* bitmap);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void validate() const;
|
||||
#else
|
||||
void validate() const {}
|
||||
#endif
|
||||
|
||||
class AutoValidate : SkNoncopyable {
|
||||
public:
|
||||
AutoValidate(const GrGradientBitmapCache* bc) : fBC(bc) { bc->validate(); }
|
||||
~AutoValidate() { fBC->validate(); }
|
||||
private:
|
||||
const GrGradientBitmapCache* fBC;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -17,15 +17,52 @@
|
||||
|
||||
#include "GrDualIntervalGradientColorizer.h"
|
||||
#include "GrSingleIntervalGradientColorizer.h"
|
||||
#include "GrTextureGradientColorizer.h"
|
||||
#include "GrGradientBitmapCache.h"
|
||||
|
||||
#include "SkGradientShaderPriv.h"
|
||||
#include "SkGr.h"
|
||||
#include "GrColor.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
|
||||
// Each cache entry costs 1K or 2K of RAM. Each bitmap will be 1x256 at either 32bpp or 64bpp.
|
||||
static const int kMaxNumCachedGradientBitmaps = 32;
|
||||
static const int kGradientTextureSize = 256;
|
||||
|
||||
// NOTE: signature takes raw pointers to the color/pos arrays and a count to make it easy for
|
||||
// MakeColorizer to transparently take care of hard stops at the end points of the gradient.
|
||||
static std::unique_ptr<GrFragmentProcessor> make_textured_colorizer(const GrColor4f* colors,
|
||||
const SkScalar* positions, int count, bool premul, const GrFPArgs& args) {
|
||||
static GrGradientBitmapCache gCache(kMaxNumCachedGradientBitmaps, kGradientTextureSize);
|
||||
|
||||
// Use 8888 or F16, depending on the destination config.
|
||||
// TODO: Use 1010102 for opaque gradients, at least if destination is 1010102?
|
||||
SkColorType colorType = kRGBA_8888_SkColorType;
|
||||
if (kLow_GrSLPrecision != GrSLSamplerPrecision(args.fDstColorSpaceInfo->config()) &&
|
||||
args.fContext->contextPriv().caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
|
||||
colorType = kRGBA_F16_SkColorType;
|
||||
}
|
||||
SkAlphaType alphaType = premul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
|
||||
|
||||
SkBitmap bitmap;
|
||||
gCache.getGradient(colors, positions, count, colorType, alphaType, &bitmap);
|
||||
SkASSERT(1 == bitmap.height() && SkIsPow2(bitmap.width()));
|
||||
SkASSERT(bitmap.isImmutable());
|
||||
|
||||
sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(
|
||||
args.fContext->contextPriv().proxyProvider(), bitmap);
|
||||
if (proxy == nullptr) {
|
||||
SkDebugf("Gradient won't draw. Could not create texture.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GrTextureGradientColorizer::Make(std::move(proxy));
|
||||
}
|
||||
|
||||
// Analyze the shader's color stops and positions and chooses an appropriate colorizer to represent
|
||||
// the gradient.
|
||||
static std::unique_ptr<GrFragmentProcessor> make_colorizer(const GrColor4f* colors,
|
||||
const SkScalar* positions,
|
||||
int count) {
|
||||
const SkScalar* positions, int count, bool premul, const GrFPArgs& args) {
|
||||
// If there are hard stops at the beginning or end, the first and/or last color should be
|
||||
// ignored by the colorizer since it should only be used in a clamped border color. By detecting
|
||||
// and removing these stops at the beginning, it makes optimizing the remaining color stops
|
||||
@ -34,8 +71,7 @@ static std::unique_ptr<GrFragmentProcessor> make_colorizer(const GrColor4f* colo
|
||||
// SkGradientShaderBase guarantees that pos[0] == 0 by adding a dummy
|
||||
bool bottomHardStop = SkScalarNearlyEqual(positions[0], positions[1]);
|
||||
// The same is true for pos[end] == 1
|
||||
bool topHardStop = SkScalarNearlyEqual(positions[count - 2],
|
||||
positions[count - 1]);
|
||||
bool topHardStop = SkScalarNearlyEqual(positions[count - 2], positions[count - 1]);
|
||||
|
||||
int offset = 0;
|
||||
if (bottomHardStop) {
|
||||
@ -63,7 +99,7 @@ static std::unique_ptr<GrFragmentProcessor> make_colorizer(const GrColor4f* colo
|
||||
positions[offset + 1]);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return make_textured_colorizer(colors + offset, positions + offset, count, premul, args);
|
||||
}
|
||||
|
||||
// Combines the colorizer and layout with an appropriately configured master effect based on the
|
||||
@ -106,8 +142,8 @@ static std::unique_ptr<GrFragmentProcessor> make_gradient(const SkGradientShader
|
||||
}
|
||||
|
||||
// All gradients are colorized the same way, regardless of layout
|
||||
std::unique_ptr<GrFragmentProcessor> colorizer = make_colorizer(colors.get(), positions,
|
||||
shader.fColorCount);
|
||||
std::unique_ptr<GrFragmentProcessor> colorizer = make_colorizer(
|
||||
colors.get(), positions, shader.fColorCount, inputPremul, args);
|
||||
if (colorizer == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
58
src/gpu/gradients/GrTextureGradientColorizer.cpp
Normal file
58
src/gpu/gradients/GrTextureGradientColorizer.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**************************************************************************************************
|
||||
*** This file was autogenerated from GrTextureGradientColorizer.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#include "GrTextureGradientColorizer.h"
|
||||
#include "glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLProgramBuilder.h"
|
||||
#include "GrTexture.h"
|
||||
#include "SkSLCPP.h"
|
||||
#include "SkSLUtil.h"
|
||||
class GrGLSLTextureGradientColorizer : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLTextureGradientColorizer() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrTextureGradientColorizer& _outer = args.fFp.cast<GrTextureGradientColorizer>();
|
||||
(void)_outer;
|
||||
fragBuilder->codeAppendf(
|
||||
"half2 coord = half2(%s.x, 0.5);\n%s = texture(%s, float2(coord)).%s;\n",
|
||||
args.fInputColor, args.fOutputColor,
|
||||
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
|
||||
fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {}
|
||||
};
|
||||
GrGLSLFragmentProcessor* GrTextureGradientColorizer::onCreateGLSLInstance() const {
|
||||
return new GrGLSLTextureGradientColorizer();
|
||||
}
|
||||
void GrTextureGradientColorizer::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {}
|
||||
bool GrTextureGradientColorizer::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrTextureGradientColorizer& that = other.cast<GrTextureGradientColorizer>();
|
||||
(void)that;
|
||||
if (fGradient != that.fGradient) return false;
|
||||
return true;
|
||||
}
|
||||
GrTextureGradientColorizer::GrTextureGradientColorizer(const GrTextureGradientColorizer& src)
|
||||
: INHERITED(kGrTextureGradientColorizer_ClassID, src.optimizationFlags())
|
||||
, fGradient(src.fGradient) {
|
||||
this->setTextureSamplerCnt(1);
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureGradientColorizer::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrTextureGradientColorizer(*this));
|
||||
}
|
||||
const GrFragmentProcessor::TextureSampler& GrTextureGradientColorizer::onTextureSampler(
|
||||
int index) const {
|
||||
return IthTextureSampler(index, fGradient);
|
||||
}
|
18
src/gpu/gradients/GrTextureGradientColorizer.fp
Normal file
18
src/gpu/gradients/GrTextureGradientColorizer.fp
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// Should have height = 1px, horizontal axis represents t = 0 to 1
|
||||
in uniform sampler2D gradient;
|
||||
|
||||
@samplerParams(gradient) {
|
||||
GrSamplerState::ClampBilerp()
|
||||
}
|
||||
|
||||
void main() {
|
||||
half2 coord = half2(sk_InColor.x, 0.5);
|
||||
sk_OutColor = texture(gradient, coord);
|
||||
}
|
39
src/gpu/gradients/GrTextureGradientColorizer.h
Normal file
39
src/gpu/gradients/GrTextureGradientColorizer.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**************************************************************************************************
|
||||
*** This file was autogenerated from GrTextureGradientColorizer.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#ifndef GrTextureGradientColorizer_DEFINED
|
||||
#define GrTextureGradientColorizer_DEFINED
|
||||
#include "SkTypes.h"
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "GrCoordTransform.h"
|
||||
class GrTextureGradientColorizer : public GrFragmentProcessor {
|
||||
public:
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> gradient) {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrTextureGradientColorizer(gradient));
|
||||
}
|
||||
GrTextureGradientColorizer(const GrTextureGradientColorizer& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "TextureGradientColorizer"; }
|
||||
|
||||
private:
|
||||
GrTextureGradientColorizer(sk_sp<GrTextureProxy> gradient)
|
||||
: INHERITED(kGrTextureGradientColorizer_ClassID, kNone_OptimizationFlags)
|
||||
, fGradient(std::move(gradient), GrSamplerState::ClampBilerp()) {
|
||||
this->setTextureSamplerCnt(1);
|
||||
}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
const TextureSampler& onTextureSampler(int) const override;
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
TextureSampler fGradient;
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user