Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecd31740 authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Add 3D transforms support to all gradients."

parents 170bf59c 14830948
Loading
Loading
Loading
Loading
+3 −10
Original line number Diff line number Diff line
@@ -37,12 +37,8 @@ const char* gVS_Header_Uniforms_HasGradient[3] = {
        // Linear
        "uniform mat4 screenSpace;\n",
        // Circular
        "uniform vec2 gradientStart;\n"
        "uniform mat4 gradientMatrix;\n"
        "uniform mat4 screenSpace;\n",
        // Sweep
        "uniform vec2 gradientStart;\n"
        "uniform mat4 gradientMatrix;\n"
        "uniform mat4 screenSpace;\n"
};
const char* gVS_Header_Uniforms_HasBitmap =
@@ -68,11 +64,9 @@ const char* gVS_Main_OutGradient[3] = {
        // Linear
        "    index = (screenSpace * position).x;\n",
        // Circular
        "    vec4 location = screenSpace * position;\n"
        "    circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n",
        "    circular = (screenSpace * position).xy;\n",
        // Sweep
        "    vec4 location = screenSpace * position;\n"
        "    sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n"
        "    sweep = (screenSpace * position).xy;\n"
};
const char* gVS_Main_OutBitmapTexCoords =
        "    vec4 bitmapCoords = textureTransform * position;\n"
@@ -98,7 +92,6 @@ const char* gFS_Uniforms_GradientSampler[3] = {
        // Linear
        "uniform sampler2D gradientSampler;\n",
        // Circular
        "uniform float gradientRadius;\n"
        "uniform sampler2D gradientSampler;\n",
        // Sweep
        "uniform sampler2D gradientSampler;\n"
@@ -130,7 +123,7 @@ const char* gFS_Main_FetchGradient[3] = {
        // Linear
        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
        // Circular
        "    float index = length(circular) * gradientRadius;\n"
        "    float index = length(circular);\n"
        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
        // Sweep
        "    float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
+38 −65
Original line number Diff line number Diff line
@@ -49,7 +49,8 @@ static const GLint gTileModes[] = {

SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
        mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mMatrix(matrix), mBlend(blend) {
        mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) {
    setMatrix(matrix);
}

SkiaShader::~SkiaShader() {
@@ -69,6 +70,11 @@ void SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
}

void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
    screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
    screenSpace.multiply(modelView);
}

///////////////////////////////////////////////////////////////////////////////
// Bitmap shader
///////////////////////////////////////////////////////////////////////////////
@@ -76,6 +82,7 @@ void SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint
SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
        SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
    updateLocalMatrix(matrix);
}

void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
@@ -116,14 +123,7 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
    const float height = texture->height;

    mat4 textureTransform;
    if (mMatrix) {
        SkMatrix inverse;
        mMatrix->invert(&inverse);
        textureTransform.load(inverse);
        textureTransform.multiply(modelView);
    } else {
        textureTransform.load(modelView);
    }
    computeScreenSpaceMatrix(textureTransform, modelView);

    // Uniforms
    bindTexture(texture->id, mWrapS, mWrapT, textureSlot);
@@ -136,15 +136,7 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
void SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView,
        const Snapshot& snapshot) {
    mat4 textureTransform;
    if (mMatrix) {
        SkMatrix inverse;
        mMatrix->invert(&inverse);
        textureTransform.load(inverse);
        textureTransform.multiply(modelView);
    } else {
        textureTransform.load(modelView);
    }

    computeScreenSpaceMatrix(textureTransform, modelView);
    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
            GL_FALSE, &textureTransform.data[0]);
}
@@ -192,23 +184,6 @@ void SkiaLinearGradientShader::describe(ProgramDescription& description,
    description.gradientType = ProgramDescription::kGradientLinear;
}

void SkiaLinearGradientShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
    screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
    screenSpace.multiply(modelView);
}

void SkiaLinearGradientShader::updateLocalMatrix(const SkMatrix* matrix) {
    if (matrix) {
        mat4 localMatrix(*matrix);
        mShaderMatrix.loadInverse(localMatrix);
    }
}

void SkiaLinearGradientShader::setMatrix(SkMatrix* matrix) {
    SkiaShader::setMatrix(matrix);
    updateLocalMatrix(matrix);
}

void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
        const Snapshot& snapshot, GLuint* textureUnit) {
    GLuint textureSlot = (*textureUnit)++;
@@ -239,12 +214,23 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo
// Circular gradient shader
///////////////////////////////////////////////////////////////////////////////

static void toCircularUnitMatrix(const float x, const float y, const float radius,
        SkMatrix* matrix) {
    const float inv = 1.0f / radius;
    matrix->setTranslate(-x, -y);
    matrix->postScale(inv, inv);
}

SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
        SkMatrix* matrix, bool blend):
        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
                tileMode, matrix, blend),
        mRadius(radius) {
                tileMode, matrix, blend) {
    SkMatrix unitMatrix;
    toCircularUnitMatrix(x, y, radius, &unitMatrix);
    mUnitMatrix.load(unitMatrix);

    updateLocalMatrix(matrix);
}

void SkiaCircularGradientShader::describe(ProgramDescription& description,
@@ -253,28 +239,31 @@ void SkiaCircularGradientShader::describe(ProgramDescription& description,
    description.gradientType = ProgramDescription::kGradientCircular;
}

void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView,
        const Snapshot& snapshot, GLuint* textureUnit) {
    SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit);
    glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius);
}

///////////////////////////////////////////////////////////////////////////////
// Sweep gradient shader
///////////////////////////////////////////////////////////////////////////////

static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
    matrix->setTranslate(-x, -y);
}

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) {
        mColors(colors), mPositions(positions), mCount(count) {
    SkMatrix unitMatrix;
    toSweepUnitMatrix(x, y, &unitMatrix);
    mUnitMatrix.load(unitMatrix);

    updateLocalMatrix(matrix);
}

SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
        SkMatrix* matrix, bool blend):
        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
        mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
        mColors(colors), mPositions(positions), mCount(count) {
}

SkiaSweepGradientShader::~SkiaSweepGradientShader() {
@@ -298,35 +287,19 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi
        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount);
    }

    float left = mX;
    float top = mY;

    mat4 shaderMatrix;
    if (mMatrix) {
        shaderMatrix.load(*mMatrix);
        shaderMatrix.mapPoint(left, top);
    }

    mat4 copy(shaderMatrix);
    shaderMatrix.loadInverse(copy);

    snapshot.transform->mapPoint(left, top);

    mat4 screenSpace(*snapshot.transform);
    screenSpace.multiply(modelView);
    mat4 screenSpace;
    computeScreenSpaceMatrix(screenSpace, modelView);

    // Uniforms
    bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
    glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]);
    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);
    mat4 screenSpace;
    computeScreenSpaceMatrix(screenSpace, modelView);
    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}

+17 −18
Original line number Diff line number Diff line
@@ -77,10 +77,21 @@ struct SkiaShader {
            const Snapshot& snapshot) {
    }

    virtual void setMatrix(SkMatrix* matrix) {
        mMatrix = matrix;
    void setMatrix(SkMatrix* matrix) {
        updateLocalMatrix(matrix);
    }

    void updateLocalMatrix(const SkMatrix* matrix) {
        if (matrix) {
            mat4 localMatrix(*matrix);
            mShaderMatrix.loadInverse(localMatrix);
        } else {
            mShaderMatrix.loadIdentity();
        }
    }

    void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);

protected:
    inline void bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit);

@@ -88,11 +99,13 @@ protected:
    SkShader* mKey;
    SkShader::TileMode mTileX;
    SkShader::TileMode mTileY;
    SkMatrix* mMatrix;
    bool mBlend;

    TextureCache* mTextureCache;
    GradientCache* mGradientCache;

    mat4 mUnitMatrix;
    mat4 mShaderMatrix;
}; // struct SkiaShader


@@ -139,15 +152,7 @@ struct SkiaLinearGradientShader: public SkiaShader {
            GLuint* textureUnit);
    void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);

    void setMatrix(SkMatrix* matrix);

private:
    void updateLocalMatrix(const SkMatrix* matrix);
    void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);

    mat4 mUnitMatrix;
    mat4 mShaderMatrix;

    float* mBounds;
    uint32_t* mColors;
    float* mPositions;
@@ -163,7 +168,7 @@ struct SkiaSweepGradientShader: public SkiaShader {
    ~SkiaSweepGradientShader();

    virtual void describe(ProgramDescription& description, const Extensions& extensions);
    virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
            GLuint* textureUnit);
    void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);

@@ -171,7 +176,6 @@ protected:
    SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
            int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);

    float mX, mY;
    uint32_t* mColors;
    float* mPositions;
    int mCount;
@@ -185,11 +189,6 @@ struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
            int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);

    void describe(ProgramDescription& description, const Extensions& extensions);
    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
            GLuint* textureUnit);

private:
    float mRadius;
}; // struct SkiaCircularGradientShader

/**
+102 −1
Original line number Diff line number Diff line
@@ -18,11 +18,16 @@ package com.android.test.hwui;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.RadialGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
@@ -36,8 +41,13 @@ public class GradientsActivity extends Activity {
        super.onCreate(savedInstanceState);

        final FrameLayout layout = new FrameLayout(this);

        final ShadersView shadersView = new ShadersView(this);
        final GradientView gradientView = new GradientView(this);
        final RadialGradientView radialGradientView = new RadialGradientView(this);
        final SweepGradientView sweepGradientView = new SweepGradientView(this);
        final BitmapView bitmapView = new BitmapView(this);

        final SeekBar rotateView = new SeekBar(this);
        rotateView.setMax(360);
        rotateView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@@ -52,12 +62,28 @@ public class GradientsActivity extends Activity {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                gradientView.setRotationY((float) progress);
                radialGradientView.setRotationX((float) progress);
                sweepGradientView.setRotationY((float) progress);
                bitmapView.setRotationX((float) progress);
            }
        });
        
        layout.addView(shadersView);
        layout.addView(gradientView, new FrameLayout.LayoutParams(
                200, 200, Gravity.CENTER));

        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER);
        lp.setMargins(220, 0, 0, 0);
        layout.addView(radialGradientView, lp);

        lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER);
        lp.setMargins(440, 0, 0, 0);
        layout.addView(sweepGradientView, lp);

        lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER);
        lp.setMargins(220, -220, 0, 0);
        layout.addView(bitmapView, lp);

        layout.addView(rotateView, new FrameLayout.LayoutParams(
                300, FrameLayout.LayoutParams.WRAP_CONTENT,
                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
@@ -65,6 +91,32 @@ public class GradientsActivity extends Activity {
        setContentView(layout);
    }
    
    static class BitmapView extends View {
        private final Paint mPaint;

        BitmapView(Context c) {
            super(c);

            Bitmap texture = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
            BitmapShader shader = new BitmapShader(texture, Shader.TileMode.REPEAT,
                    Shader.TileMode.REPEAT);
            mPaint = new Paint();
            mPaint.setShader(shader);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            setMeasuredDimension(200, 200);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
        }
    }
    
    static class GradientView extends View {
        private final Paint mPaint;

@@ -90,6 +142,55 @@ public class GradientsActivity extends Activity {
        }
    }

    static class RadialGradientView extends View {
        private final Paint mPaint;

        RadialGradientView(Context c) {
            super(c);

            RadialGradient gradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff,
                    Shader.TileMode.MIRROR);
            mPaint = new Paint();
            mPaint.setShader(gradient);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            setMeasuredDimension(200, 200);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
        }
    }
    
    static class SweepGradientView extends View {
        private final Paint mPaint;

        SweepGradientView(Context c) {
            super(c);

            SweepGradient gradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff);                
            mPaint = new Paint();
            mPaint.setShader(gradient);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            setMeasuredDimension(200, 200);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
        }
    }
        
    static class ShadersView extends View {
        private final Paint mPaint;
        private final float mDrawWidth;