This CL implements the Ganesh path for the SkTable_ColorFilter color transformation.
A new texture stage dedicated to color transforms has been added, along with the new custom stage implementing the LUT. Review URL: https://codereview.appspot.com/6351081 git-svn-id: http://skia.googlecode.com/svn/trunk@4663 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
855cd7aa5e
commit
5807116946
@ -287,6 +287,8 @@
|
||||
'../src/gpu/gr_unittests.cpp',
|
||||
|
||||
'../src/gpu/effects/Gr1DKernelEffect.h',
|
||||
'../src/gpu/effects/GrColorTableEffect.cpp',
|
||||
'../src/gpu/effects/GrColorTableEffect.h',
|
||||
'../src/gpu/effects/GrConvolutionEffect.cpp',
|
||||
'../src/gpu/effects/GrConvolutionEffect.h',
|
||||
'../src/gpu/effects/GrGradientEffects.cpp',
|
||||
|
@ -24,7 +24,7 @@
|
||||
class GrPaint {
|
||||
public:
|
||||
enum {
|
||||
kMaxTextures = 1,
|
||||
kMaxTextures = 2,
|
||||
kMaxMasks = 1,
|
||||
};
|
||||
|
||||
|
@ -182,7 +182,19 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) {
|
||||
fBitmap = new SkBitmap;
|
||||
fBitmap->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
|
||||
fBitmap->allocPixels();
|
||||
memcpy(fBitmap->getAddr8(0, 0), fStorage, 256 * 4);
|
||||
uint8_t* bitmapPixels = fBitmap->getAddr8(0, 0);
|
||||
int offset = 0;
|
||||
static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
|
||||
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
if (!(fFlags & kFlags[x])) {
|
||||
memcpy(bitmapPixels, gIdentityTable, sizeof(gIdentityTable));
|
||||
} else {
|
||||
memcpy(bitmapPixels, fStorage + offset, 256);
|
||||
offset += 256;
|
||||
}
|
||||
bitmapPixels += 256;
|
||||
}
|
||||
}
|
||||
*table = *fBitmap;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
* GrPathRenderer-derived classes.
|
||||
*/
|
||||
enum {
|
||||
kNumStages = 4,
|
||||
kNumStages = 5,
|
||||
kMaxTexCoords = kNumStages
|
||||
};
|
||||
|
||||
|
@ -67,19 +67,22 @@ void gen_globals() {
|
||||
}
|
||||
|
||||
/* These values were generated by the above function */
|
||||
|
||||
const GrVertexLayout gStageTexCoordMasks[] = {
|
||||
0x1111,
|
||||
0x2222,
|
||||
0x4444,
|
||||
0x8888,
|
||||
0x108421,
|
||||
0x210842,
|
||||
0x421084,
|
||||
0x842108,
|
||||
0x1084210,
|
||||
};
|
||||
GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
|
||||
|
||||
const GrVertexLayout gTexCoordMasks[] = {
|
||||
0xf,
|
||||
0xf0,
|
||||
0xf00,
|
||||
0xf000,
|
||||
0x1f,
|
||||
0x3e0,
|
||||
0x7c00,
|
||||
0xf8000,
|
||||
0x1f00000,
|
||||
};
|
||||
GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "SkGpuDevice.h"
|
||||
|
||||
#include "effects/GrGradientEffects.h"
|
||||
#include "effects/GrColorTableEffect.h"
|
||||
#include "effects/GrTextureDomainEffect.h"
|
||||
|
||||
#include "GrContext.h"
|
||||
@ -41,7 +42,8 @@
|
||||
// (since drawBitmap, drawSprite, and drawDevice ignore skia's shader)
|
||||
enum {
|
||||
kBitmapTextureIdx = 0,
|
||||
kShaderTextureIdx = 0
|
||||
kShaderTextureIdx = 0,
|
||||
kColorFilterTextureIdx = 1
|
||||
};
|
||||
|
||||
|
||||
@ -448,10 +450,12 @@ namespace {
|
||||
// Callers may subsequently modify the GrPaint. Setting constantColor indicates
|
||||
// that the final paint will draw the same color at every pixel. This allows
|
||||
// an optimization where the the color filter can be applied to the skPaint's
|
||||
// color once while converting to GrPain and then ignored.
|
||||
inline bool skPaint2GrPaintNoShader(const SkPaint& skPaint,
|
||||
// color once while converting to GrPaint and then ignored.
|
||||
inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev,
|
||||
const SkPaint& skPaint,
|
||||
bool justAlpha,
|
||||
bool constantColor,
|
||||
SkGpuDevice::SkAutoCachedTexture* act,
|
||||
GrPaint* grPaint) {
|
||||
|
||||
grPaint->fDither = skPaint.isDither();
|
||||
@ -487,6 +491,7 @@ inline bool skPaint2GrPaintNoShader(const SkPaint& skPaint,
|
||||
SkColor color;
|
||||
SkXfermode::Mode filterMode;
|
||||
SkScalar matrix[20];
|
||||
SkBitmap colorTransformTable;
|
||||
if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
|
||||
grPaint->fColorMatrixEnabled = false;
|
||||
if (!constantColor) {
|
||||
@ -501,6 +506,17 @@ inline bool skPaint2GrPaintNoShader(const SkPaint& skPaint,
|
||||
grPaint->fColorMatrixEnabled = true;
|
||||
memcpy(grPaint->fColorMatrix, matrix, sizeof(matrix));
|
||||
grPaint->fColorFilterXfermode = SkXfermode::kDst_Mode;
|
||||
} else if (colorFilter != NULL && colorFilter->asComponentTable(
|
||||
&colorTransformTable)) {
|
||||
grPaint->resetColorFilter();
|
||||
|
||||
GrSamplerState* colorSampler = grPaint->textureSampler(kColorFilterTextureIdx);
|
||||
GrTexture* texture = act->set(dev, colorTransformTable, colorSampler);
|
||||
|
||||
colorSampler->setCustomStage(SkNEW_ARGS(GrColorTableEffect, (texture)))->unref();
|
||||
colorSampler->setFilter(GrSamplerState::kNearest_Filter);
|
||||
colorSampler->setWrapX(GrSamplerState::kClamp_WrapMode);
|
||||
colorSampler->setWrapY(GrSamplerState::kClamp_WrapMode);
|
||||
} else {
|
||||
grPaint->resetColorFilter();
|
||||
}
|
||||
@ -514,18 +530,18 @@ inline bool skPaint2GrPaintNoShader(const SkPaint& skPaint,
|
||||
inline bool skPaint2GrPaintShader(SkGpuDevice* dev,
|
||||
const SkPaint& skPaint,
|
||||
bool constantColor,
|
||||
SkGpuDevice::SkAutoCachedTexture* act,
|
||||
SkGpuDevice::SkAutoCachedTexture textures[GrPaint::kMaxTextures],
|
||||
GrPaint* grPaint) {
|
||||
|
||||
SkASSERT(NULL != act);
|
||||
|
||||
SkShader* shader = skPaint.getShader();
|
||||
if (NULL == shader) {
|
||||
return skPaint2GrPaintNoShader(skPaint,
|
||||
return skPaint2GrPaintNoShader(dev,
|
||||
skPaint,
|
||||
false,
|
||||
constantColor,
|
||||
&textures[kColorFilterTextureIdx],
|
||||
grPaint);
|
||||
} else if (!skPaint2GrPaintNoShader(skPaint, true, false, grPaint)) {
|
||||
} else if (!skPaint2GrPaintNoShader(dev, skPaint, true, false,
|
||||
&textures[kColorFilterTextureIdx], grPaint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -549,16 +565,18 @@ inline bool skPaint2GrPaintShader(SkGpuDevice* dev,
|
||||
// modulate the paint alpha by the shader's solid color alpha
|
||||
U8CPU newA = SkMulDiv255Round(SkColorGetA(color), copy.getAlpha());
|
||||
copy.setColor(SkColorSetA(color, newA));
|
||||
return skPaint2GrPaintNoShader(copy,
|
||||
return skPaint2GrPaintNoShader(dev,
|
||||
copy,
|
||||
false,
|
||||
constantColor,
|
||||
&textures[kColorFilterTextureIdx],
|
||||
grPaint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GrSamplerState* sampler = grPaint->textureSampler(kShaderTextureIdx);
|
||||
GrTexture* texture = act->set(dev, bitmap, sampler);
|
||||
GrTexture* texture = textures[kShaderTextureIdx].set(dev, bitmap, sampler);
|
||||
if (NULL == texture) {
|
||||
SkDebugf("Couldn't convert bitmap to texture.\n");
|
||||
return false;
|
||||
@ -634,11 +652,11 @@ void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
|
||||
CHECK_SHOULD_DRAW(draw);
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
true,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -670,11 +688,11 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
|
||||
}
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
true,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -732,11 +750,11 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
|
||||
}
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
true,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -1011,11 +1029,11 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||
bool doFill = true;
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
true,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -1249,7 +1267,8 @@ void SkGpuDevice::drawBitmap(const SkDraw& draw,
|
||||
}
|
||||
|
||||
GrPaint grPaint;
|
||||
if (!skPaint2GrPaintNoShader(paint, true, false, &grPaint)) {
|
||||
SkAutoCachedTexture colorLutTexture;
|
||||
if (!skPaint2GrPaintNoShader(this, paint, true, false, &colorLutTexture, &grPaint)) {
|
||||
return;
|
||||
}
|
||||
GrSamplerState* sampler = grPaint.textureSampler(kBitmapTextureIdx);
|
||||
@ -1531,7 +1550,8 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
int h = bitmap.height();
|
||||
|
||||
GrPaint grPaint;
|
||||
if(!skPaint2GrPaintNoShader(paint, true, false, &grPaint)) {
|
||||
SkAutoCachedTexture colorLutTexture;
|
||||
if(!skPaint2GrPaintNoShader(this, paint, true, false, &colorLutTexture, &grPaint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1576,8 +1596,9 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* device,
|
||||
CHECK_SHOULD_DRAW(draw);
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture colorLutTexture;
|
||||
if (!dev->bindDeviceAsTexture(&grPaint) ||
|
||||
!skPaint2GrPaintNoShader(paint, true, false, &grPaint)) {
|
||||
!skPaint2GrPaintNoShader(this, paint, true, false, &colorLutTexture, &grPaint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1682,12 +1703,14 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
|
||||
CHECK_SHOULD_DRAW(draw);
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
// we ignore the shader if texs is null.
|
||||
if (NULL == texs) {
|
||||
if (!skPaint2GrPaintNoShader(paint,
|
||||
if (!skPaint2GrPaintNoShader(this,
|
||||
paint,
|
||||
false,
|
||||
NULL == colors,
|
||||
&textures[kColorFilterTextureIdx],
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -1695,7 +1718,7 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
NULL == colors,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -1795,12 +1818,11 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
|
||||
SkDraw myDraw(draw);
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
true,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
@ -1824,11 +1846,11 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
|
||||
SkDraw myDraw(draw);
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
SkAutoCachedTexture textures[GrPaint::kMaxTextures];
|
||||
if (!skPaint2GrPaintShader(this,
|
||||
paint,
|
||||
true,
|
||||
&act,
|
||||
textures,
|
||||
&grPaint)) {
|
||||
return;
|
||||
}
|
||||
|
92
src/gpu/effects/GrColorTableEffect.cpp
Normal file
92
src/gpu/effects/GrColorTableEffect.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrColorTableEffect.h"
|
||||
#include "gl/GrGLProgramStage.h"
|
||||
#include "GrProgramStageFactory.h"
|
||||
#include "SkString.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrGLColorTableEffect : public GrGLProgramStage {
|
||||
public:
|
||||
GrGLColorTableEffect(const GrProgramStageFactory& factory,
|
||||
const GrCustomStage& stage);
|
||||
|
||||
virtual void setupVariables(GrGLShaderBuilder* state,
|
||||
int stage) SK_OVERRIDE {}
|
||||
virtual void emitVS(GrGLShaderBuilder* state,
|
||||
const char* vertexCoords) SK_OVERRIDE {}
|
||||
virtual void emitFS(GrGLShaderBuilder* state,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const char* samplerName) SK_OVERRIDE;
|
||||
|
||||
virtual void initUniforms(const GrGLShaderBuilder*,
|
||||
const GrGLInterface*,
|
||||
int programID) SK_OVERRIDE {}
|
||||
|
||||
virtual void setData(const GrGLInterface*,
|
||||
const GrCustomStage&,
|
||||
const GrRenderTarget*,
|
||||
int stageNum) SK_OVERRIDE {}
|
||||
|
||||
static inline StageKey GenKey(const GrCustomStage&);
|
||||
|
||||
private:
|
||||
typedef GrGLProgramStage INHERITED;
|
||||
};
|
||||
|
||||
GrGLColorTableEffect::GrGLColorTableEffect(
|
||||
const GrProgramStageFactory& factory, const GrCustomStage& stage)
|
||||
: INHERITED(factory) {
|
||||
}
|
||||
|
||||
void GrGLColorTableEffect::emitFS(GrGLShaderBuilder* state,
|
||||
const char* outputColor,
|
||||
const char* inputColor,
|
||||
const char* samplerName) {
|
||||
static const float kColorScaleFactor = 255.0f / 256.0f;
|
||||
static const float kColorOffsetFactor = 1.0f / 512.0f;
|
||||
SkString* code = &state->fFSCode;
|
||||
code->appendf("\t\tvec4 coord = vec4(%s.rgb / %s.a, %s.a);\n",
|
||||
inputColor, inputColor, inputColor);
|
||||
code->appendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
|
||||
kColorScaleFactor,
|
||||
kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor);
|
||||
code->appendf("\t\t%s.a = texture2D(%s, vec2(coord.a, 0.125)).a;\n",
|
||||
outputColor, samplerName);
|
||||
code->appendf("\t\t%s.r = texture2D(%s, vec2(coord.r, 0.375)).a;\n",
|
||||
outputColor, samplerName);
|
||||
code->appendf("\t\t%s.g = texture2D(%s, vec2(coord.g, 0.625)).a;\n",
|
||||
outputColor, samplerName);
|
||||
code->appendf("\t\t%s.b = texture2D(%s, vec2(coord.b, 0.875)).a;\n",
|
||||
outputColor, samplerName);
|
||||
code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
|
||||
}
|
||||
|
||||
GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(
|
||||
const GrCustomStage& s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrColorTableEffect::GrColorTableEffect(GrTexture* texture)
|
||||
: INHERITED(texture) {
|
||||
}
|
||||
|
||||
GrColorTableEffect::~GrColorTableEffect() {
|
||||
}
|
||||
|
||||
const GrProgramStageFactory& GrColorTableEffect::getFactory() const {
|
||||
return GrTProgramStageFactory<GrColorTableEffect>::getInstance();
|
||||
}
|
||||
|
||||
bool GrColorTableEffect::isEqual(const GrCustomStage& sBase) const {
|
||||
return INHERITED::isEqual(sBase);
|
||||
}
|
38
src/gpu/effects/GrColorTableEffect.h
Normal file
38
src/gpu/effects/GrColorTableEffect.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrColorTableEffect_DEFINED
|
||||
#define GrColorTableEffect_DEFINED
|
||||
|
||||
#include "GrSingleTextureEffect.h"
|
||||
#include "GrTexture.h"
|
||||
|
||||
class GrGLColorTableEffect;
|
||||
|
||||
/**
|
||||
* LUT-based color transformation effect. This class implements the Gr
|
||||
* counterpart to the SkTable_ColorFilter effect. A 256 * 4 (single-channel)
|
||||
* LUT is used to transform the input colors of the image.
|
||||
*/
|
||||
class GrColorTableEffect : public GrSingleTextureEffect {
|
||||
|
||||
public:
|
||||
|
||||
GrColorTableEffect(GrTexture* texture);
|
||||
virtual ~GrColorTableEffect();
|
||||
|
||||
static const char* Name() { return "ColorTable"; }
|
||||
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
|
||||
virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
|
||||
|
||||
typedef GrGLColorTableEffect GLProgramStage;
|
||||
|
||||
private:
|
||||
|
||||
typedef GrSingleTextureEffect INHERITED;
|
||||
};
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
#include "GrGpuGL.h"
|
||||
|
||||
#include "effects/GrColorTableEffect.h"
|
||||
#include "effects/GrConvolutionEffect.h"
|
||||
#include "effects/GrGradientEffects.h"
|
||||
#include "effects/GrMorphologyEffect.h"
|
||||
@ -47,6 +48,7 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc,
|
||||
kSpecularPoint_EffectType,
|
||||
kSpecularSpot_EffectType,
|
||||
kSweepGradient_EffectType,
|
||||
kColorTable_EffectType,
|
||||
|
||||
kEffectCount
|
||||
};
|
||||
@ -207,6 +209,9 @@ GrCustomStage* create_random_effect(StageDesc* stageDesc,
|
||||
SkASSERT(ok);
|
||||
return stage;
|
||||
}
|
||||
case kColorTable_EffectType: {
|
||||
return SkNEW_ARGS(GrColorTableEffect, (NULL));
|
||||
}
|
||||
default:
|
||||
GrCrash("Unexpected custom effect type");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user