Add support for SweepGradient in the GL renderer.
Change-Id: I7aa397ed4e34655ead9ba1f5b4ce087665e0f022
This commit is contained in:
@@ -318,6 +318,59 @@ static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
|
||||
return s;
|
||||
}
|
||||
|
||||
static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
|
||||
float x, float y, jintArray colorArray, jfloatArray posArray) {
|
||||
#ifdef USE_OPENGL_RENDERER
|
||||
size_t count = env->GetArrayLength(colorArray);
|
||||
const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
|
||||
|
||||
jfloat* storedPositions = new jfloat[count];
|
||||
uint32_t* storedColors = new uint32_t[count];
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
storedColors[i] = static_cast<uint32_t>(colorValues[i]);
|
||||
}
|
||||
|
||||
if (posArray) {
|
||||
AutoJavaFloatArray autoPos(env, posArray, count);
|
||||
const float* posValues = autoPos.ptr();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
storedPositions[i] = posValues[i];
|
||||
}
|
||||
} else {
|
||||
storedPositions[0] = 0.0f;
|
||||
storedPositions[1] = 1.0f;
|
||||
}
|
||||
|
||||
SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
|
||||
shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
|
||||
|
||||
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
|
||||
return skiaShader;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
|
||||
float x, float y, int color0, int color1) {
|
||||
#ifdef USE_OPENGL_RENDERER
|
||||
float* storedPositions = new float[2];
|
||||
storedPositions[0] = 0.0f;
|
||||
storedPositions[1] = 1.0f;
|
||||
|
||||
uint32_t* storedColors = new uint32_t[2];
|
||||
storedColors[0] = static_cast<uint32_t>(color0);
|
||||
storedColors[1] = static_cast<uint32_t>(color1);
|
||||
|
||||
SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
|
||||
shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
|
||||
|
||||
return skiaShader;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static SkShader* ComposeShader_create1(JNIEnv* env, jobject o,
|
||||
@@ -389,8 +442,10 @@ static JNINativeMethod gRadialGradientMethods[] = {
|
||||
};
|
||||
|
||||
static JNINativeMethod gSweepGradientMethods[] = {
|
||||
{"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
|
||||
{"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }
|
||||
{"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
|
||||
{"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 },
|
||||
{ "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 },
|
||||
{ "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 }
|
||||
};
|
||||
|
||||
static JNINativeMethod gComposeShaderMethods[] = {
|
||||
|
||||
@@ -71,7 +71,8 @@ public class Shader {
|
||||
* @param localM The shader's new local matrix, or null to specify identity
|
||||
*/
|
||||
public void setLocalMatrix(Matrix localM) {
|
||||
nativeSetLocalMatrix(native_instance, native_shader, localM.native_instance);
|
||||
nativeSetLocalMatrix(native_instance, native_shader,
|
||||
localM == null ? 0 : localM.native_instance);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
|
||||
@@ -42,6 +42,7 @@ public class SweepGradient extends Shader {
|
||||
"color and position arrays must be of equal length");
|
||||
}
|
||||
native_instance = nativeCreate1(cx, cy, colors, positions);
|
||||
native_shader = nativePostCreate1(native_instance, cx, cy, colors, positions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,11 +55,15 @@ public class SweepGradient extends Shader {
|
||||
*/
|
||||
public SweepGradient(float cx, float cy, int color0, int color1) {
|
||||
native_instance = nativeCreate2(cx, cy, color0, color1);
|
||||
native_shader = nativePostCreate2(native_instance, cx, cy, color0, color1);
|
||||
}
|
||||
|
||||
private static native int nativeCreate1(float x, float y,
|
||||
int colors[], float positions[]);
|
||||
private static native int nativeCreate2(float x, float y,
|
||||
int color0, int color1);
|
||||
private static native int nativeCreate1(float x, float y, int colors[], float positions[]);
|
||||
private static native int nativeCreate2(float x, float y, int color0, int color1);
|
||||
|
||||
private static native int nativePostCreate1(int native_shader, float cx, float cy,
|
||||
int[] colors, float[] positions);
|
||||
private static native int nativePostCreate2(int native_shader, float cx, float cy,
|
||||
int color0, int color1);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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]);
|
||||
@@ -208,6 +208,64 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo
|
||||
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -144,6 +144,26 @@ private:
|
||||
int mCount;
|
||||
}; // 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.
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="AdvancedGradientsActivity"
|
||||
android:label="_Advanced Gradients">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="ResizeActivity"
|
||||
android:label="_Resize"
|
||||
@@ -250,7 +259,7 @@
|
||||
|
||||
<activity
|
||||
android:name="AdvancedBlendActivity"
|
||||
android:label="_AdvancedBlend">
|
||||
android:label="_Advanced Blend">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.test.hwui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.SweepGradient;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public class AdvancedGradientsActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(new GradientsView(this));
|
||||
}
|
||||
|
||||
static class GradientsView extends View {
|
||||
private final Paint mPaint;
|
||||
private final SweepGradient mSweepGradient;
|
||||
private final RadialGradient mRadialGradient;
|
||||
private final Matrix mMatrix;
|
||||
private final Matrix mMatrix2;
|
||||
|
||||
GradientsView(Context c) {
|
||||
super(c);
|
||||
|
||||
mSweepGradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff);
|
||||
mRadialGradient = new RadialGradient(100.0f, 100.0f, 100.0f, 0xff000000, 0xffffffff,
|
||||
Shader.TileMode.MIRROR);
|
||||
|
||||
mMatrix = new Matrix();
|
||||
mMatrix.setTranslate(50.0f, 50.0f);
|
||||
|
||||
mMatrix2 = new Matrix();
|
||||
mMatrix2.setScale(2.0f, 2.0f);
|
||||
|
||||
mPaint = new Paint();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.drawRGB(255, 255, 255);
|
||||
|
||||
// Bitmap shaders
|
||||
canvas.save();
|
||||
canvas.translate(130.0f, 100.0f);
|
||||
|
||||
mSweepGradient.setLocalMatrix(null);
|
||||
mPaint.setShader(mSweepGradient);
|
||||
canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
|
||||
|
||||
canvas.translate(400.0f, 000.0f);
|
||||
|
||||
mPaint.setShader(mRadialGradient);
|
||||
canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
|
||||
|
||||
canvas.translate(400.0f, 000.0f);
|
||||
|
||||
mSweepGradient.setLocalMatrix(mMatrix);
|
||||
mPaint.setShader(mSweepGradient);
|
||||
canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
|
||||
|
||||
canvas.translate(-800.0f, 300.0f);
|
||||
|
||||
mSweepGradient.setLocalMatrix(mMatrix2);
|
||||
mPaint.setShader(mSweepGradient);
|
||||
canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
|
||||
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user