diff options
| author | 2010-09-20 17:53:08 -0700 | |
|---|---|---|
| committer | 2010-09-20 17:54:17 -0700 | |
| commit | ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6f (patch) | |
| tree | 4fd53bcd273d42fa1aebb064b18563aa293467b1 /libs/hwui | |
| parent | b5ab4173e0927e4668a45298c9900cd8007584e1 (diff) | |
Add support for SweepGradient in the GL renderer.
Change-Id: I7aa397ed4e34655ead9ba1f5b4ce087665e0f022
Diffstat (limited to 'libs/hwui')
| -rw-r--r-- | libs/hwui/GradientCache.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/GradientCache.h | 4 | ||||
| -rw-r--r-- | libs/hwui/ProgramCache.cpp | 67 | ||||
| -rw-r--r-- | libs/hwui/ProgramCache.h | 30 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.cpp | 62 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.h | 20 |
6 files changed, 155 insertions, 30 deletions
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 9957370a5ae6..97f4cb468c53 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -116,7 +116,7 @@ void GradientCache::clear() { mCache.clear(); } -Texture* GradientCache::addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, +Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1); diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index 51a8c0185adb..c829fd468007 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -46,8 +46,8 @@ public: * Adds a new linear gradient to the cache. The generated texture is * returned. */ - Texture* addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, - float* positions, int count, SkShader::TileMode tileMode); + Texture* addLinearGradient(SkShader* shader, uint32_t* colors, float* positions, + int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode); /** * Returns the texture associated with the specified shader. */ diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index becbc2277866..bcc1edfbb13c 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -33,11 +33,18 @@ const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n"; const char* gVS_Header_Uniforms = "uniform mat4 transform;\n"; -const char* gVS_Header_Uniforms_HasGradient = +const char* gVS_Header_Uniforms_HasGradient[3] = { + // Linear "uniform float gradientLength;\n" "uniform vec2 gradient;\n" "uniform vec2 gradientStart;\n" - "uniform mat4 screenSpace;\n"; + "uniform mat4 screenSpace;\n", + // Circular + "", + // Sweep + "uniform vec2 gradientStart;\n" + "uniform mat4 screenSpace;\n" +}; const char* gVS_Header_Uniforms_HasBitmap = "uniform mat4 textureTransform;\n" "uniform vec2 textureDimension;\n"; @@ -45,15 +52,28 @@ const char* gVS_Header_Varyings_HasTexture = "varying vec2 outTexCoords;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying vec2 outBitmapTexCoords;\n"; -const char* gVS_Header_Varyings_HasGradient = - "varying float index;\n"; +const char* gVS_Header_Varyings_HasGradient[3] = { + // Linear + "varying float index;\n", + // Circular + "", + // Sweep + "varying vec2 sweep;\n" +}; const char* gVS_Main = "\nvoid main(void) {\n"; const char* gVS_Main_OutTexCoords = " outTexCoords = texCoords;\n"; -const char* gVS_Main_OutGradientIndex = +const char* gVS_Main_OutGradient[3] = { + // Linear " vec4 location = screenSpace * position;\n" - " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n"; + " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n", + // Circular + "", + // Sweep + " vec4 location = screenSpace * position;\n" + " sweep = location.xy - gradientStart;\n" +}; const char* gVS_Main_OutBitmapTexCoords = " vec4 bitmapCoords = textureTransform * position;\n" " outBitmapTexCoords = bitmapCoords.xy * textureDimension;\n"; @@ -74,8 +94,14 @@ const char* gFS_Uniforms_Color = "uniform vec4 color;\n"; const char* gFS_Uniforms_TextureSampler = "uniform sampler2D sampler;\n"; -const char* gFS_Uniforms_GradientSampler = - "uniform sampler2D gradientSampler;\n"; +const char* gFS_Uniforms_GradientSampler[3] = { + // Linear + "uniform sampler2D gradientSampler;\n", + // Circular + "uniform sampler2D gradientSampler;\n", + // Sweep + "uniform sampler2D gradientSampler;\n" +}; const char* gFS_Uniforms_BitmapSampler = "uniform sampler2D bitmapSampler;\n"; const char* gFS_Uniforms_ColorOp[4] = { @@ -99,8 +125,15 @@ const char* gFS_Main_FetchTexture = " fragColor = color * texture2D(sampler, outTexCoords);\n"; const char* gFS_Main_FetchA8Texture = " fragColor = color * texture2D(sampler, outTexCoords).a;\n"; -const char* gFS_Main_FetchGradient = - " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n"; +const char* gFS_Main_FetchGradient[3] = { + // Linear + " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", + // Circular + "", + // Sweep + " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" + " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n" +}; const char* gFS_Main_FetchBitmap = " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; const char* gFS_Main_FetchBitmapNpot = @@ -217,7 +250,7 @@ Program* ProgramCache::get(const ProgramDescription& description) { ssize_t index = mCache.indexOfKey(key); Program* program = NULL; if (index < 0) { - PROGRAM_LOGD("Could not find program with key 0x%x", key); + description.log("Could not find program"); program = generateProgram(description, key); mCache.add(key, program); } else { @@ -247,7 +280,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description // Uniforms shader.append(gVS_Header_Uniforms); if (description.hasGradient) { - shader.append(gVS_Header_Uniforms_HasGradient); + shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Header_Uniforms_HasBitmap); @@ -257,7 +290,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasGradient) { - shader.append(gVS_Header_Varyings_HasGradient); + shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Header_Varyings_HasBitmap); @@ -269,7 +302,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Main_OutTexCoords); } if (description.hasGradient) { - shader.append(gVS_Main_OutGradientIndex); + shader.append(gVS_Main_OutGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Main_OutBitmapTexCoords); @@ -301,7 +334,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasGradient) { - shader.append(gVS_Header_Varyings_HasGradient); + shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { shader.append(gVS_Header_Varyings_HasBitmap); @@ -314,7 +347,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Uniforms_TextureSampler); } if (description.hasGradient) { - shader.append(gFS_Uniforms_GradientSampler); + shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); } if (description.hasBitmap) { shader.append(gFS_Uniforms_BitmapSampler); @@ -348,7 +381,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_FetchColor); } if (description.hasGradient) { - shader.append(gFS_Main_FetchGradient); + shader.append(gFS_Main_FetchGradient[description.gradientType]); } if (description.hasBitmap) { if (!description.isBitmapNpot) { diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index 0a1705279e7f..4fa80111d358 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -44,9 +44,6 @@ namespace uirenderer { #define PROGRAM_LOGD(...) #endif -/* - * IMPORTANT: All 32 bits are used, switch to a long. - */ #define PROGRAM_KEY_TEXTURE 0x1 #define PROGRAM_KEY_A8_TEXTURE 0x2 #define PROGRAM_KEY_BITMAP 0x4 @@ -70,14 +67,13 @@ namespace uirenderer { #define PROGRAM_BITMAP_WRAPS_SHIFT 9 #define PROGRAM_BITMAP_WRAPT_SHIFT 11 +#define PROGRAM_GRADIENT_TYPE_SHIFT 33 + /////////////////////////////////////////////////////////////////////////////// // Types /////////////////////////////////////////////////////////////////////////////// -/* - * IMPORTANT: All 32 bits are used, switch to a long. - */ -typedef uint32_t programid; +typedef uint64_t programid; /////////////////////////////////////////////////////////////////////////////// // Cache @@ -96,9 +92,16 @@ struct ProgramDescription { kColorBlend }; + enum Gradient { + kGradientLinear, + kGradientCircular, + kGradientSweep + }; + ProgramDescription(): hasTexture(false), hasAlpha8Texture(false), hasBitmap(false), isBitmapNpot(false), hasGradient(false), + gradientType(kGradientLinear), shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false), bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE), colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode), @@ -112,8 +115,12 @@ struct ProgramDescription { // Shaders bool hasBitmap; bool isBitmapNpot; + bool hasGradient; + Gradient gradientType; + SkXfermode::Mode shadersMode; + bool isBitmapFirst; GLenum bitmapWrapS; GLenum bitmapWrapT; @@ -152,7 +159,8 @@ struct ProgramDescription { } } if (hasGradient) key |= PROGRAM_KEY_GRADIENT; - if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST; + key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT; + if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST; if (hasBitmap && hasGradient) { key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT; } @@ -174,6 +182,12 @@ struct ProgramDescription { if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST; return key; } + + void log(const char* message) const { + programid k = key(); + PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), + uint32_t(k & 0xffffffff)); + } }; // struct ProgramDescription /** diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 946cc4b95c94..c5d97674ad7a 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -164,6 +164,7 @@ SkiaLinearGradientShader::~SkiaLinearGradientShader() { void SkiaLinearGradientShader::describe(ProgramDescription& description, const Extensions& extensions) { description.hasGradient = true; + description.gradientType = ProgramDescription::kGradientLinear; } void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView, @@ -173,8 +174,7 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV Texture* texture = mGradientCache->get(mKey); if (!texture) { - texture = mGradientCache->addLinearGradient(mKey, mBounds, mColors, mPositions, - mCount, mTileX); + texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX); } Rect start(mBounds[0], mBounds[1], mBounds[2], mBounds[3]); @@ -209,6 +209,64 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo } /////////////////////////////////////////////////////////////////////////////// +// Sweep gradient shader +/////////////////////////////////////////////////////////////////////////////// + +SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors, + float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend): + SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode, matrix, blend), + mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { +} + +SkiaSweepGradientShader::~SkiaSweepGradientShader() { + delete[] mColors; + delete[] mPositions; +} + +void SkiaSweepGradientShader::describe(ProgramDescription& description, + const Extensions& extensions) { + description.hasGradient = true; + description.gradientType = ProgramDescription::kGradientSweep; +} + +void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView, + const Snapshot& snapshot, GLuint* textureUnit) { + GLuint textureSlot = (*textureUnit)++; + glActiveTexture(gTextureUnitsMap[textureSlot]); + + Texture* texture = mGradientCache->get(mKey); + if (!texture) { + texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount); + } + + float left = mX; + float top = mY; + + if (mMatrix) { + mat4 shaderMatrix(*mMatrix); + shaderMatrix.mapPoint(left, top); + } + snapshot.transform->mapPoint(left, top); + + mat4 screenSpace(*snapshot.transform); + screenSpace.multiply(modelView); + + // Uniforms + bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot); + glUniform1i(program->getUniform("gradientSampler"), textureSlot); + glUniform2f(program->getUniform("gradientStart"), left, top); + glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); +} + +void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView, + const Snapshot& snapshot) { + mat4 screenSpace(*snapshot.transform); + screenSpace.multiply(modelView); + glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); +} + +/////////////////////////////////////////////////////////////////////////////// // Compose shader /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index cc94ae6c815f..b67bfee66919 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -145,6 +145,26 @@ private: }; // struct SkiaLinearGradientShader /** + * A shader that draws a sweep gradient. + */ +struct SkiaSweepGradientShader: public SkiaShader { + SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count, + SkShader* key, SkMatrix* matrix, bool blend); + ~SkiaSweepGradientShader(); + + void describe(ProgramDescription& description, const Extensions& extensions); + void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, + GLuint* textureUnit); + void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); + +private: + float mX, mY; + uint32_t* mColors; + float* mPositions; + int mCount; +}; // struct SkiaSweepGradientShader + +/** * A shader that draws two shaders, composited with an xfermode. */ struct SkiaComposeShader: public SkiaShader { |