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

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

Merge "Reduced the complexity of layers composition."

parents 1df11fc8 5cbbce53
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3,7 +3,8 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	Matrix.cpp \
	OpenGLRenderer.cpp
	OpenGLRenderer.cpp \
	Program.cpp

LOCAL_C_INCLUDES += \
	$(JNI_H_INCLUDE) \
+1 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

#define LOG_TAG "Matrix"
#define LOG_TAG "OpenGLRenderer"

#include <math.h>
#include <stdlib.h>
+36 −144
Original line number Diff line number Diff line
@@ -20,19 +20,11 @@
#include <stdint.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/Log.h>

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <SkCanvas.h>
#include <SkPaint.h>
#include <SkXfermode.h>

#include <utils/Log.h>

#include "OpenGLRenderer.h"
#include "Matrix.h"

namespace android {
namespace uirenderer {
@@ -57,7 +49,7 @@ const SimpleVertex gDrawColorVertices[] = {
const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
const GLsizei gDrawColorVertexCount = 4;

const TextureVertex gDrawTextureVertices[] = {
TextureVertex gDrawTextureVertices[] = {
        FV(0.0f, 0.0f, 0.0f, 1.0f),
        FV(1.0f, 0.0f, 1.0f, 1.0f),
        FV(0.0f, 1.0f, 0.0f, 0.0f),
@@ -66,134 +58,15 @@ const TextureVertex gDrawTextureVertices[] = {
const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
const GLsizei gDrawTextureVertexCount = 4;

///////////////////////////////////////////////////////////////////////////////
// Shaders
///////////////////////////////////////////////////////////////////////////////

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

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

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

Program::Program(const char* vertex, const char* fragment) {
    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);

    id = glCreateProgram();
    glAttachShader(id, vertexShader);
    glAttachShader(id, fragmentShader);
    glLinkProgram(id);

    GLint status;
    glGetProgramiv(id, GL_LINK_STATUS, &status);
    if (status != GL_TRUE) {
        GLint infoLen = 0;
        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
            char* log = (char*) malloc(sizeof(char) * infoLen);
            glGetProgramInfoLog(id, infoLen, 0, log);
            LOGE("Error while linking shaders: %s", log);
            delete log;
        }
        glDeleteProgram(id);
    }
}

Program::~Program() {
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteProgram(id);
}

void Program::use() {
    glUseProgram(id);
}

int Program::addAttrib(const char* name) {
    int slot = glGetAttribLocation(id, name);
    attributes.add(name, slot);
    return slot;
}

int Program::getAttrib(const char* name) {
    return attributes.valueFor(name);
}

int Program::addUniform(const char* name) {
    int slot = glGetUniformLocation(id, name);
    uniforms.add(name, slot);
    return slot;
}

int Program::getUniform(const char* name) {
    return uniforms.valueFor(name);
}

GLuint Program::buildShader(const char* source, GLenum type) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, 0);
    glCompileShader(shader);

    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE) {
        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
        // use a fixed size instead
        GLchar log[512];
        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
        LOGE("Error while compiling shader: %s", log);
        glDeleteShader(shader);
    }

    return shader;
}

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

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

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

void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
        const GLfloat* transformMatrix) {
    Program::use();
    glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
    glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix);
    glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix);
}

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

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

const Rect& Snapshot::getMappedClip() {
    if (flags & kFlagDirtyTransform) {
        flags &= ~kFlagDirtyTransform;
        mappedClip.set(clipRect);
        transform.mapRect(mappedClip);
    }
    return mappedClip;
static inline void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
    gDrawTextureVertices[0].texture[0] = u1;
    gDrawTextureVertices[0].texture[1] = v2;
    gDrawTextureVertices[1].texture[0] = u2;
    gDrawTextureVertices[1].texture[1] = v2;
    gDrawTextureVertices[2].texture[0] = u1;
    gDrawTextureVertices[2].texture[1] = v1;
    gDrawTextureVertices[3].texture[0] = u2;
    gDrawTextureVertices[3].texture[1] = v1;
}

///////////////////////////////////////////////////////////////////////////////
@@ -292,11 +165,28 @@ bool OpenGLRenderer::restoreSnapshot() {
        // Most of the time, previous->fbo will be 0 to bind the default buffer
        glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);

        // Restore the clip from the previous snapshot
        const Rect& clip = previous->getMappedClip();
        glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());

        // Compute the correct texture coordinates for the FBO texture
        // The texture is currently as big as the window but drawn with
        // a quad of the appropriate size
        const Rect& layer = current->layer;
        clipRect(layer.left, layer.top, layer.right, layer.bottom);
        mSnapshot->transform.loadIdentity();
        Rect texCoords(current->layer);
        mSnapshot->transform.mapRect(texCoords);

        const float u1 = texCoords.left / float(mWidth);
        const float v1 = (mHeight - texCoords.top) / float(mHeight);
        const float u2 = texCoords.right / float(mWidth);
        const float v2 = (mHeight - texCoords.bottom) / float(mHeight);

        drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha);
        resetDrawTextureTexCoords(u1, v1, u2, v1);

        drawTextureRect(layer.left, layer.top, layer.right, layer.bottom,
                current->texture, current->alpha);

        resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);

        glDeleteFramebuffers(1, &current->fbo);
        glDeleteTextures(1, &current->texture);
@@ -337,11 +227,14 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot
    // The FBO will not be scaled, so we can use lower quality filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // TODO ***** IMPORTANT *****
    // Creating a texture-backed FBO works only if the texture is the same size
    // as the original rendering buffer (in this case, mWidth and mHeight.)
    // This is expensive and wasteful and must be fixed.
    // TODO Additionally we should use an FBO cache

    const GLsizei width = mWidth; //right - left;
    const GLsizei height = mHeight; //bottom - right;
@@ -425,7 +318,6 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto
     *     const Rect& clip = mSnapshot->getMappedClip();
     *     return !clip.intersects(r);
     */

    Rect r(left, top, right, bottom);
    return !mSnapshot->clipRect.intersects(r);
}
@@ -485,7 +377,7 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b

    mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);

    // TODO Correctly set the blend function
    // TODO Correctly set the blend function, based on texture format and xfermode
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

+53 −104
Original line number Diff line number Diff line
@@ -23,11 +23,12 @@
#include <SkMatrix.h>
#include <SkXfermode.h>

#include <utils/KeyedVector.h>
#include <utils/RefBase.h>

#include "Matrix.h"
#include "Program.h"
#include "Rect.h"
#include "Snapshot.h"

namespace android {
namespace uirenderer {
@@ -36,122 +37,30 @@ namespace uirenderer {
// Support
///////////////////////////////////////////////////////////////////////////////

class Snapshot: public LightRefBase<Snapshot> {
public:
    Snapshot() {
    }

    Snapshot(const sp<Snapshot> s):
            transform(s->transform),
            clipRect(s->clipRect),
            flags(kFlagDirtyTransform),
            previous(s),
            layer(0.0f, 0.0f, 0.0f, 0.0f),
            texture(0),
            fbo(0),
            alpha(255) {
    }

    enum Flags {
        kFlagClipSet = 0x1,
        kFlagDirtyTransform = 0x2,
        kFlagIsLayer = 0x4,
    };

    const Rect& getMappedClip();

    // Local transformations
    mat4 transform;

    // Clipping rectangle at the time of this snapshot
    Rect clipRect;

    // Dirty flags
    int flags;

    // Previous snapshot in the frames stack
    sp<Snapshot> previous;

    // Layer, only set if kFlagIsLayer is set
    Rect layer;
    GLuint texture;
    GLuint fbo;
    float alpha;

private:
    // Clipping rectangle mapped with the transform
    Rect mappedClip;
}; // class Snapshot

/**
 * Simple structure to describe a vertex with a position.
 * This is used to draw filled rectangles without a texture.
 */
struct SimpleVertex {
    float position[2];
}; // struct SimpleVertex

/**
 * Simple structure to describe a vertex with a position and a texture.
 */
struct TextureVertex {
    float position[2];
    float texture[2];
}; // struct TextureVertex

class Program: public LightRefBase<Program> {
public:
    Program(const char* vertex, const char* fragment);
    ~Program();

    void use();

protected:
    int addAttrib(const char* name);
    int getAttrib(const char* name);

    int addUniform(const char* name);
    int getUniform(const char* name);

private:
    GLuint buildShader(const char* source, GLenum type);

    // Handle of the OpenGL program
    GLuint id;

    // Handles of the shaders
    GLuint vertexShader;
    GLuint fragmentShader;

    // Keeps track of attributes and uniforms slots
    KeyedVector<const char*, int> attributes;
    KeyedVector<const char*, int> uniforms;
}; // class Program

class DrawColorProgram: public Program {
public:
    DrawColorProgram();
    DrawColorProgram(const char* vertex, const char* fragment);

    void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
             const GLfloat* transformMatrix);

    int position;
    int color;

    int projection;
    int modelView;
    int transform;

protected:
    void getAttribsAndUniforms();
};

class DrawTextureProgram: public DrawColorProgram {
public:
    DrawTextureProgram();

    int sampler;
    int texCoords;
};

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

/**
 * OpenGL renderer used to draw accelerated 2D graphics. The API is a
 * simplified version of Skia's Canvas API.
 */
class OpenGLRenderer {
public:
    OpenGLRenderer();
@@ -184,12 +93,52 @@ public:
    void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);

private:
    /**
     * Saves the current state of the renderer as a new snapshot.
     * The new snapshot is saved in mSnapshot and the previous snapshot
     * is linked from mSnapshot->previous.
     *
     * @return The new save count. This value can be passed to #restoreToCount()
     */
    int saveSnapshot();

    /**
     * Restores the current snapshot; mSnapshot becomes mSnapshot->previous.
     *
     * @return True if the clip should be also reapplied by calling
     *         #setScissorFromClip().
     */
    bool restoreSnapshot();

    /**
     * Sets the clipping rectangle using glScissor. The clip is defined by
     * the current snapshot's clipRect member.
     */
    void setScissorFromClip();

    /**
     * Draws a colored rectangle with the specified color. The specified coordinates
     * are transformed by the current snapshot's transform matrix.
     *
     * @param left The left coordinate of the rectangle
     * @param top The top coordinate of the rectangle
     * @param right The right coordinate of the rectangle
     * @param bottom The bottom coordinate of the rectangle
     * @param color The rectangle's ARGB color, defined as a packed 32 bits word
     */
    void drawColorRect(float left, float top, float right, float bottom, int color);

    /**
     * Draws a textured rectangle with the specified texture. The specified coordinates
     * are transformed by the current snapshot's transform matrix.
     *
     * @param left The left coordinate of the rectangle
     * @param top The top coordinate of the rectangle
     * @param right The right coordinate of the rectangle
     * @param bottom The bottom coordinate of the rectangle
     * @param texture The texture name to map onto the rectangle
     * @param alpha An additional translucency parameter, between 0.0f and 1.0f
     */
    void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
            float alpha);

libs/hwui/Program.cpp

0 → 100644
+154 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#define LOG_TAG "OpenGLRenderer"

#include "Program.h"

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Shaders
///////////////////////////////////////////////////////////////////////////////

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

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

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

///////////////////////////////////////////////////////////////////////////////
// Base program
///////////////////////////////////////////////////////////////////////////////

Program::Program(const char* vertex, const char* fragment) {
    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);

    id = glCreateProgram();
    glAttachShader(id, vertexShader);
    glAttachShader(id, fragmentShader);
    glLinkProgram(id);

    GLint status;
    glGetProgramiv(id, GL_LINK_STATUS, &status);
    if (status != GL_TRUE) {
        GLint infoLen = 0;
        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
            char* log = (char*) malloc(sizeof(char) * infoLen);
            glGetProgramInfoLog(id, infoLen, 0, log);
            LOGE("Error while linking shaders: %s", log);
            delete log;
        }
        glDeleteProgram(id);
    }
}

Program::~Program() {
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteProgram(id);
}

void Program::use() {
    glUseProgram(id);
}

int Program::addAttrib(const char* name) {
    int slot = glGetAttribLocation(id, name);
    attributes.add(name, slot);
    return slot;
}

int Program::getAttrib(const char* name) {
    return attributes.valueFor(name);
}

int Program::addUniform(const char* name) {
    int slot = glGetUniformLocation(id, name);
    uniforms.add(name, slot);
    return slot;
}

int Program::getUniform(const char* name) {
    return uniforms.valueFor(name);
}

GLuint Program::buildShader(const char* source, GLenum type) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, 0);
    glCompileShader(shader);

    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE) {
        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
        // use a fixed size instead
        GLchar log[512];
        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
        LOGE("Error while compiling shader: %s", log);
        glDeleteShader(shader);
    }

    return shader;
}

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

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

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

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

void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
        const GLfloat* transformMatrix) {
    Program::use();
    glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
    glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix);
    glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix);
}

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

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

}; // namespace uirenderer
}; // namespace android
Loading