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

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

Merge "Moved all the rendering code to the new shader generator."

parents 15d6184b 889f8d14
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -327,6 +327,7 @@ void FontRenderer::initTextTexture() {
    mTextTexture = new unsigned char[mCacheWidth * mCacheHeight];
    mUploadTexture = false;

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &mTextureId);
    glBindTexture(GL_TEXTURE_2D, mTextureId);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+5 −0
Original line number Diff line number Diff line
@@ -152,6 +152,11 @@ void Matrix4::loadRotate(float angle, float x, float y, float z) {
    float s = sinf(angle);

    const float length = sqrtf(x * x + y * y + z * z);
    float recipLen = 1.0f / length;
    x *= recipLen;
    y *= recipLen;
    z *= recipLen;

    const float nc = 1.0f - c;
    const float xy = x * y;
    const float yz = y * z;
+117 −77
Original line number Diff line number Diff line
@@ -62,6 +62,15 @@ static const TextureVertex gMeshVertices[] = {
static const GLsizei gMeshStride = sizeof(TextureVertex);
static const GLsizei gMeshCount = 4;

/**
 * Structure mapping Skia xfermodes to OpenGL blending factors.
 */
struct Blender {
    SkXfermode::Mode mode;
    GLenum src;
    GLenum dst;
}; // struct Blender

// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
static const Blender gBlends[] = {
@@ -80,9 +89,15 @@ static const Blender gBlends[] = {
};

static const GLint gTileModes[] = {
        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
        GL_REPEAT,          // == SkShader::kRepeat_Mode
        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
        GL_CLAMP_TO_EDGE,   // SkShader::kClamp_TileMode
        GL_REPEAT,          // SkShader::kRepeat_Mode
        GL_MIRRORED_REPEAT  // SkShader::kMirror_TileMode
};

static const GLenum gTextureUnits[] = {
        GL_TEXTURE0,        // Bitmap or text
        GL_TEXTURE1,        // Gradient
        GL_TEXTURE2         // Bitmap shader
};

///////////////////////////////////////////////////////////////////////////////
@@ -119,11 +134,7 @@ OpenGLRenderer::OpenGLRenderer():
        LOGD("  Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE);
    }

    mDrawColorProgram = new DrawColorProgram;
    mDrawTextureProgram = new DrawTextureProgram;
    mDrawTextProgram = new DrawTextProgram;
    mDrawLinearGradientProgram = new DrawLinearGradientProgram;
    mCurrentProgram = mDrawTextureProgram;
    mCurrentProgram = NULL;

    mShader = kShaderNone;
    mShaderTileX = GL_CLAMP_TO_EDGE;
@@ -131,20 +142,13 @@ OpenGLRenderer::OpenGLRenderer():
    mShaderMatrix = NULL;
    mShaderBitmap = NULL;

    mLastTexture = 0;

    memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));

    ProgramDescription d;
    mProgramCache.get(d);
    d.hasTexture = true;
    mProgramCache.get(d);
    d.hasAlpha8Texture = true;
    d.hasGradient = true;
    d.hasBitmap = true;
    d.shadersMode = SkXfermode::kDstOut_Mode;
    d.colorOp = ProgramDescription::kColorMatrix;
    mProgramCache.get(d);
    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxTextureUnits);
    if (mMaxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
        LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
    }
    mLastTexture[0] = mLastTexture[1] = mLastTexture[2] = 0;
}

OpenGLRenderer::~OpenGLRenderer() {
@@ -468,6 +472,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
    const float u2 = srcRight / width;
    const float v2 = srcBottom / height;

    // TODO: Do this in the shader
    resetDrawTextureTexCoords(u1, v1, u2, v2);

    drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
@@ -532,6 +537,8 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
        return;
    }

    glActiveTexture(GL_TEXTURE0);

    float length;
    switch (paint->getTextAlign()) {
        case SkPaint::kCenter_Align:
@@ -558,22 +565,29 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,

    mModelView.loadIdentity();

    useProgram(mDrawTextProgram);
    mDrawTextProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
    ProgramDescription description;
    description.hasTexture = true;
    description.hasAlpha8Texture = true;

    useProgram(mProgramCache.get(description));
    mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);

    chooseBlending(true, mode);
    bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
    bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0);

    int texCoordsSlot = mCurrentProgram->getAttrib("texCoords");
    glEnableVertexAttribArray(texCoordsSlot);

    // Always premultiplied
    glUniform4f(mDrawTextProgram->color, r, g, b, a);
    glUniform4f(mCurrentProgram->color, r, g, b, a);

    // TODO: Implement scale properly
    const Rect& clip = mSnapshot->getLocalClip();

    mFontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize());
    mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDisableVertexAttribArray(texCoordsSlot);
}

///////////////////////////////////////////////////////////////////////////////
@@ -599,8 +613,7 @@ void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tile
}

void OpenGLRenderer::setupLinearGradientShader(SkShader* shader, float* bounds, uint32_t* colors,
        float* positions, int count, SkShader::TileMode tileMode, SkMatrix* matrix,
        bool hasAlpha) {
        float* positions, int count, SkShader::TileMode tileMode, SkMatrix* matrix, bool hasAlpha) {
    // TODO: We should use a struct to describe each shader
    mShader = OpenGLRenderer::kShaderLinearGradient;
    mShaderKey = shader;
@@ -650,30 +663,31 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);

    if (!useProgram(mDrawColorProgram)) {
    ProgramDescription description;
    Program* program = mProgramCache.get(description);
    if (!useProgram(program)) {
        const GLvoid* vertices = &mMeshVertices[0].position[0];
        const GLvoid* texCoords = &mMeshVertices[0].texture[0];

        glVertexAttribPointer(mDrawColorProgram->position, 2, GL_FLOAT, GL_FALSE,
        glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE,
                gMeshStride, vertices);
        glVertexAttribPointer(mDrawColorProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
                gMeshStride, texCoords);
    }

    if (!ignoreTransform) {
        mDrawColorProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
        mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
    } else {
        mat4 identity;
        mDrawColorProgram->set(mOrthoMatrix, mModelView, identity);
        mCurrentProgram->set(mOrthoMatrix, mModelView, identity);
    }

    glUniform4f(mDrawColorProgram->color, r, g, b, a);
    glUniform4f(mCurrentProgram->color, r, g, b, a);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}

void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right, float bottom,
        float alpha, SkXfermode::Mode mode) {
    glActiveTexture(GL_TEXTURE1);
    Texture* texture = mGradientCache.get(mShaderKey);
    if (!texture) {
        SkShader::TileMode tileMode = SkShader::kClamp_TileMode;
@@ -690,14 +704,18 @@ void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right
                mShaderPositions, mShaderCount, tileMode);
    }

    ProgramDescription description;
    description.hasGradient = true;

    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);

    useProgram(mDrawLinearGradientProgram);
    mDrawLinearGradientProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
    useProgram(mProgramCache.get(description));
    mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);

    chooseBlending(mShaderBlend || alpha < 1.0f, mode);
    bindTexture(texture->id, mShaderTileX, mShaderTileY);
    bindTexture(texture->id, mShaderTileX, mShaderTileY, 1);
    glUniform1i(mCurrentProgram->getUniform("gradientSampler"), 1);

    Rect start(mShaderBounds[0], mShaderBounds[1], mShaderBounds[2], mShaderBounds[3]);
    if (mShaderMatrix) {
@@ -713,15 +731,15 @@ void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right
    screenSpace.multiply(mModelView);

    // Always premultiplied
    glUniform4f(mDrawLinearGradientProgram->color, alpha, alpha, alpha, alpha);
    glUniform2f(mDrawLinearGradientProgram->start, start.left, start.top);
    glUniform2f(mDrawLinearGradientProgram->gradient, gradientX, gradientY);
    glUniform1f(mDrawLinearGradientProgram->gradientLength,
    glUniform4f(mCurrentProgram->color, alpha, alpha, alpha, alpha);
    glUniform2f(mCurrentProgram->getUniform("gradientStart"), start.left, start.top);
    glUniform2f(mCurrentProgram->getUniform("gradient"), gradientX, gradientY);
    glUniform1f(mCurrentProgram->getUniform("gradientLength"),
            1.0f / (gradientX * gradientX + gradientY * gradientY));
    glUniformMatrix4fv(mDrawLinearGradientProgram->screenSpace, 1, GL_FALSE,
    glUniformMatrix4fv(mCurrentProgram->getUniform("screenSpace"), 1, GL_FALSE,
            &screenSpace.data[0]);

    glVertexAttribPointer(mDrawLinearGradientProgram->position, 2, GL_FLOAT, GL_FALSE,
    glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE,
            gMeshStride, &mMeshVertices[0].position[0]);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -729,42 +747,55 @@ void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right

void OpenGLRenderer::drawBitmapShader(float left, float top, float right, float bottom,
        float alpha, SkXfermode::Mode mode) {
    glActiveTexture(GL_TEXTURE2);
    const Texture* texture = mTextureCache.get(mShaderBitmap);

    const float width = texture->width;
    const float height = texture->height;

    // This could be done in the vertex shader but we have only 4 vertices
    float u1 = 0.0f;
    float v1 = 0.0f;
    float u2 = right - left;
    float v2 = bottom - top;
    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);

    // TODO: If the texture is not pow, use a shader to support repeat/mirror
    mat4 textureTransform;
    if (mShaderMatrix) {
        SkMatrix inverse;
        mShaderMatrix->invert(&inverse);
        mat4 m(inverse);
        Rect r(u1, v1, u2, v2);
        m.mapRect(r);
        textureTransform.load(inverse);
        textureTransform.multiply(mModelView);
    } else {
        textureTransform.load(mModelView);
    }

        u1 = r.left;
        u2 = r.right;
        v1 = r.top;
        v2 = r.bottom;
    ProgramDescription description;
    description.hasBitmap = true;
    // The driver does not support non-power of two mirrored/repeated
    // textures, so do it ourselves
    if (!mExtensions.hasNPot()) {
        description.isBitmapNpot = true;
        description.bitmapWrapS = mShaderTileX;
        description.bitmapWrapT = mShaderTileY;
    }

    u1 /= width;
    u2 /= width;
    v1 /= height;
    v2 /= height;
    useProgram(mProgramCache.get(description));
    mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);

    resetDrawTextureTexCoords(u1, v1, u2, v2);
    chooseBlending(texture->blend || alpha < 1.0f, mode);

    drawTextureMesh(left, top, right, bottom, texture->id, alpha, mode, texture->blend,
            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
    // Texture
    bindTexture(texture->id, mShaderTileX, mShaderTileY, 2);
    glUniform1i(mCurrentProgram->getUniform("bitmapSampler"), 2);
    glUniformMatrix4fv(mCurrentProgram->getUniform("textureTransform"), 1,
            GL_FALSE, &textureTransform.data[0]);
    glUniform2f(mCurrentProgram->getUniform("textureDimension"), 1.0f / width, 1.0f / height);

    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
    // Always premultiplied
    glUniform4f(mCurrentProgram->color, alpha, alpha, alpha, alpha);

    // Mesh
    glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE,
            gMeshStride, &mMeshVertices[0].position[0]);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -786,28 +817,37 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
        GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) {
    ProgramDescription description;
    description.hasTexture = true;

    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);

    useProgram(mDrawTextureProgram);
    mDrawTextureProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
    useProgram(mProgramCache.get(description));
    mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);

    chooseBlending(blend || alpha < 1.0f, mode);
    bindTexture(texture, mShaderTileX, mShaderTileY);

    // Texture
    bindTexture(texture, mShaderTileX, mShaderTileY, 0);
    glUniform1i(mCurrentProgram->getUniform("sampler"), 0);

    // Always premultiplied
    glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha);
    glUniform4f(mCurrentProgram->color, alpha, alpha, alpha, alpha);

    glVertexAttribPointer(mDrawTextureProgram->position, 2, GL_FLOAT, GL_FALSE,
    // Mesh
    int texCoordsSlot = mCurrentProgram->getAttrib("texCoords");
    glEnableVertexAttribArray(texCoordsSlot);
    glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE,
            gMeshStride, vertices);
    glVertexAttribPointer(mDrawTextureProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
            gMeshStride, texCoords);
    glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);

    if (!indices) {
        glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
    } else {
        glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices);
    }
    glDisableVertexAttribArray(texCoordsSlot);
}

void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) {
@@ -836,9 +876,9 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPr
    mBlend = blend;
}

bool OpenGLRenderer::useProgram(const sp<Program>& program) {
bool OpenGLRenderer::useProgram(Program* program) {
    if (!program->isInUse()) {
        mCurrentProgram->remove();
        if (mCurrentProgram != NULL) mCurrentProgram->remove();
        program->use();
        mCurrentProgram = program;
        return false;
@@ -875,12 +915,12 @@ void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermod
    }
}

void OpenGLRenderer::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT) {
    if (texture != mLastTexture) {
void OpenGLRenderer::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) {
    glActiveTexture(gTextureUnits[textureUnit]);
    if (texture != mLastTexture[textureUnit]) {
        glBindTexture(GL_TEXTURE_2D, texture);
        mLastTexture = texture;
        mLastTexture[textureUnit] = texture;
    }
    // TODO: Don't set the texture parameters every time
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
}
+7 −21
Original line number Diff line number Diff line
@@ -46,23 +46,12 @@
namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Support
///////////////////////////////////////////////////////////////////////////////

/**
 * Structure mapping Skia xfermodes to OpenGL blending factors.
 */
struct Blender {
    SkXfermode::Mode mode;
    GLenum src;
    GLenum dst;
}; // struct Blender

///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////

#define REQUIRED_TEXTURE_UNITS_COUNT 3

/**
 * OpenGL renderer used to draw accelerated 2D graphics. The API is a
 * simplified version of Skia's Canvas API.
@@ -294,7 +283,7 @@ private:
    /**
     * Binds the specified texture with the specified wrap modes.
     */
    inline void bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT);
    inline void bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit = 0);

    /**
     * Enable or disable blending as necessary. This function sets the appropriate
@@ -312,7 +301,7 @@ private:
     *
     * @return true If the specified program was already in use, false otherwise.
     */
    inline bool useProgram(const sp<Program>& program);
    inline bool useProgram(Program* program);

    // Dimensions of the drawing surface
    int mWidth, mHeight;
@@ -331,17 +320,14 @@ private:
    sp<Snapshot> mSnapshot;

    // Shaders
    sp<Program> mCurrentProgram;
    sp<DrawColorProgram> mDrawColorProgram;
    sp<DrawTextureProgram> mDrawTextureProgram;
    sp<DrawTextProgram> mDrawTextProgram;
    sp<DrawLinearGradientProgram> mDrawLinearGradientProgram;
    Program* mCurrentProgram;

    // Used to draw textured quads
    TextureVertex mMeshVertices[4];

    // Current texture state
    GLuint mLastTexture;
    GLuint mLastTexture[REQUIRED_TEXTURE_UNITS_COUNT];
    GLint mMaxTextureUnits;

    // Last known blend state
    bool mBlend;
+22 −103
Original line number Diff line number Diff line
@@ -27,16 +27,6 @@ namespace uirenderer {

#define SHADER_SOURCE(name, source) const char* name = #source

#include "shaders/drawColor.frag"

#include "shaders/drawTexture.vert"
#include "shaders/drawTexture.frag"

#include "shaders/drawText.frag"

#include "shaders/drawLinearGradient.vert"
#include "shaders/drawLinearGradient.frag"

///////////////////////////////////////////////////////////////////////////////
// Base program
///////////////////////////////////////////////////////////////////////////////
@@ -65,6 +55,10 @@ Program::Program(const char* vertex, const char* fragment) {
    }

    mUse = false;

    position = addAttrib("position");
    color = addUniform("color");
    transform = addUniform("transform");
}

Program::~Program() {
@@ -73,15 +67,6 @@ Program::~Program() {
    glDeleteProgram(id);
}

void Program::use() {
    glUseProgram(id);
    mUse = true;
}

void Program::remove() {
    mUse = false;
}

int Program::addAttrib(const char* name) {
    int slot = glGetAttribLocation(id, name);
    attributes.add(name, slot);
@@ -89,7 +74,11 @@ int Program::addAttrib(const char* name) {
}

int Program::getAttrib(const char* name) {
    return attributes.valueFor(name);
    ssize_t index = attributes.indexOfKey(name);
    if (index >= 0) {
        return attributes.valueAt(index);
    }
    return addAttrib(name);
}

int Program::addUniform(const char* name) {
@@ -99,7 +88,11 @@ int Program::addUniform(const char* name) {
}

int Program::getUniform(const char* name) {
    return uniforms.valueFor(name);
    ssize_t index = uniforms.indexOfKey(name);
    if (index >= 0) {
        return uniforms.valueAt(index);
    }
    return addUniform(name);
}

GLuint Program::buildShader(const char* source, GLenum type) {
@@ -121,28 +114,7 @@ GLuint Program::buildShader(const char* source, GLenum type) {
    return shader;
}

///////////////////////////////////////////////////////////////////////////////
// Draw color
///////////////////////////////////////////////////////////////////////////////

DrawColorProgram::DrawColorProgram():
        Program(gDrawTextureVertexShader, gDrawColorFragmentShader) {
    getAttribsAndUniforms();
}

DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment):
        Program(vertex, fragment) {
    getAttribsAndUniforms();
}

void DrawColorProgram::getAttribsAndUniforms() {
    position = addAttrib("position");
    texCoords = addAttrib("texCoords");
    color = addUniform("color");
    transform = addUniform("transform");
}

void DrawColorProgram::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
        const mat4& transformMatrix) {
    mat4 t(projectionMatrix);
    t.multiply(transformMatrix);
@@ -151,70 +123,17 @@ void DrawColorProgram::set(const mat4& projectionMatrix, const mat4& modelViewMa
    glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]);
}

void DrawColorProgram::use() {
    Program::use();
    glEnableVertexAttribArray(position);
    glEnableVertexAttribArray(texCoords);
}

void DrawColorProgram::remove() {
    Program::remove();
    glDisableVertexAttribArray(position);
    glDisableVertexAttribArray(texCoords);
}

///////////////////////////////////////////////////////////////////////////////
// Draw texture
///////////////////////////////////////////////////////////////////////////////

DrawTextureProgram::DrawTextureProgram():
        DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) {
    sampler = addUniform("sampler");
}

DrawTextureProgram::DrawTextureProgram(const char* vertex, const char* fragment):
        DrawColorProgram(vertex, fragment) {
    sampler = addUniform("sampler");
}

void DrawTextureProgram::use() {
    DrawColorProgram::use();
    glUniform1i(sampler, 0);
}

void DrawTextureProgram::remove() {
    DrawColorProgram::remove();
}

///////////////////////////////////////////////////////////////////////////////
// Draw text
///////////////////////////////////////////////////////////////////////////////

DrawTextProgram::DrawTextProgram():
        DrawTextureProgram(gDrawTextureVertexShader, gDrawTextFragmentShader) {
}

///////////////////////////////////////////////////////////////////////////////
// Draw linear gradient
///////////////////////////////////////////////////////////////////////////////
void Program::use() {
    glUseProgram(id);
    mUse = true;

DrawLinearGradientProgram::DrawLinearGradientProgram():
        DrawColorProgram(gDrawLinearGradientVertexShader, gDrawLinearGradientFragmentShader) {
    gradient = addUniform("gradient");
    gradientLength = addUniform("gradientLength");
    sampler = addUniform("sampler");
    start = addUniform("start");
    screenSpace = addUniform("screenSpace");
    glEnableVertexAttribArray(position);
}

void DrawLinearGradientProgram::use() {
    DrawColorProgram::use();
    glActiveTexture(GL_TEXTURE0);
    glUniform1i(sampler, 0);
}
void Program::remove() {
    mUse = false;

void DrawLinearGradientProgram::remove() {
    DrawColorProgram::remove();
    glDisableVertexAttribArray(position);
}

}; // namespace uirenderer
Loading