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

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

Merge "New, better line drawing implementation. Bug #3207544 Bug #3225875"

parents 324c3162 a957eea7
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@
#include "PathCache.h"
#include "TextDropShadowCache.h"
#include "FboCache.h"
#include "Line.h"
#include "ResourceCache.h"

namespace android {
@@ -158,8 +157,6 @@ public:
    GammaFontRenderer fontRenderer;
    ResourceCache resourceCache;

    Line line;

private:
    DebugLevel mDebugLevel;
}; // class Caches

libs/hwui/Line.h

deleted100644 → 0
+0 −127
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.
 */

#ifndef ANDROID_HWUI_LINE_H
#define ANDROID_HWUI_LINE_H

#include <GLES2/gl2.h>

#include <cmath>

#include <sys/types.h>

#include "Patch.h"

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////////////

// Alpha8 texture used to perform texture anti-aliasing
static const uint8_t gLineTexture[] = {
        0,   0,   0,   0, 0,
        0, 255, 255, 255, 0,
        0, 255, 255, 255, 0,
        0, 255, 255, 255, 0,
        0,   0,   0,   0, 0
};
static const GLsizei gLineTextureWidth = 5;
static const GLsizei gLineTextureHeight = 5;
static const float gLineAABias = 1.0f;

///////////////////////////////////////////////////////////////////////////////
// Line
///////////////////////////////////////////////////////////////////////////////

class Line {
public:
    Line(): mXDivsCount(2), mYDivsCount(2) {
        mPatch = new Patch(mXDivsCount, mYDivsCount);
        mXDivs = new int32_t[mXDivsCount];
        mYDivs = new int32_t[mYDivsCount];

        mXDivs[0] = mYDivs[0] = 2;
        mXDivs[1] = mYDivs[1] = 3;

        mPatch->copy(mXDivs, mYDivs);

        glGenTextures(1, &mTexture);
        glBindTexture(GL_TEXTURE_2D, mTexture);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gLineTextureWidth, gLineTextureHeight, 0,
                GL_ALPHA, GL_UNSIGNED_BYTE, gLineTexture);
    }

    ~Line() {
        delete mPatch;
        delete[] mXDivs;
        delete[] mYDivs;

        glDeleteTextures(1, &mTexture);
    }

    inline float getLength(float x1, float y1, float x2, float y2) {
        return sqrtf((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    }

    void update(float x1, float y1, float x2, float y2, float lineWidth, float& tx, float& ty) {
        const float length = getLength(x1, y1, x2, y2);
        const float half = lineWidth * 0.5f;

        mPatch->updateVertices(gLineTextureWidth, gLineTextureHeight,
                -gLineAABias, -half - gLineAABias, length + gLineAABias, half + gLineAABias);

        tx = -gLineAABias;
        ty = lineWidth <= 1.0f ? -gLineAABias : -half - gLineAABias;
    }

    inline GLuint getMeshBuffer() const {
        return mPatch->meshBuffer;
    }

    inline GLsizei getElementsCount() const {
        return mPatch->verticesCount;
    }

    inline GLuint getTexture() const {
        return mTexture;
    }

private:
    uint32_t mXDivsCount;
    uint32_t mYDivsCount;

    int32_t* mXDivs;
    int32_t* mYDivs;

    Patch* mPatch;

    GLuint mTexture;
}; // class Line

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

#endif // ANDROID_HWUI_LINE_H
+96 −43
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#include "OpenGLRenderer.h"
#include "DisplayListRenderer.h"
#include "Vector.h"

namespace android {
namespace uirenderer {
@@ -989,6 +990,12 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
    // TODO: Should do quickReject for each line
    if (mSnapshot->invisible) return;

    const bool isAA = paint->isAntiAlias();
    const float strokeWidth = paint->getStrokeWidth() * 0.5f;
    // A stroke width of 0 has a special meaningin Skia:
    // it draws an unscaled 1px wide line
    const bool isHairLine = paint->getStrokeWidth() == 0.0f;

    setupDraw();

    int alpha;
@@ -1001,59 +1008,105 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
    const GLfloat g = a * ((color >>  8) & 0xFF) / 255.0f;
    const GLfloat b = a * ((color      ) & 0xFF) / 255.0f;

    const bool isAA = paint->isAntiAlias();
    if (isAA) {
    // Used only with AA lines
    GLuint textureUnit = 0;
        glActiveTexture(gTextureUnits[textureUnit]);
        setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
                mode, false, true, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
                mCaches.line.getMeshBuffer());
    } else {
        setupColorRect(0.0f, 0.0f, 1.0f, 1.0f, r, g, b, a, mode, false, true);

    // Describe the required shaders
    ProgramDescription description;
    const bool setColor = description.setColor(r, g, b, a);

    if (mShader) {
        mShader->describe(description, mCaches.extensions);
    }
    if (mColorFilter) {
        mColorFilter->describe(description, mCaches.extensions);
    }

    const float strokeWidth = paint->getStrokeWidth();
    const GLsizei elementsCount = isAA ? mCaches.line.getElementsCount() : gMeshCount;
    const GLenum drawMode = isAA ? GL_TRIANGLES : GL_TRIANGLE_STRIP;
    // Setup the blending mode
    chooseBlending(a < 1.0f || (mShader && mShader->blend()), mode, description);

    for (int i = 0; i < count; i += 4) {
        float tx = 0.0f;
        float ty = 0.0f;
    // We're not drawing with VBOs here
    mCaches.unbindMeshBuffer();

        if (isAA) {
            mCaches.line.update(points[i], points[i + 1], points[i + 2], points[i + 3],
                    strokeWidth, tx, ty);
    int verticesCount = count >> 2;
    if (!isHairLine) {
        // TODO: AA needs more vertices
        verticesCount *= 6;
    } else {
            ty = strokeWidth <= 1.0f ? 0.0f : -strokeWidth * 0.5f;
        // TODO: AA will be different
        verticesCount *= 2;
    }

        const float dx = points[i + 2] - points[i];
        const float dy = points[i + 3] - points[i + 1];
        const float mag = sqrtf(dx * dx + dy * dy);
        const float angle = acos(dx / mag);
    TextureVertex lines[verticesCount];
    TextureVertex* vertex = &lines[0];

        mModelView.loadTranslate(points[i], points[i + 1], 0.0f);
        if (angle > MIN_ANGLE || angle < -MIN_ANGLE) {
            mModelView.rotate(angle * RAD_TO_DEG, 0.0f, 0.0f, 1.0f);
        }
        mModelView.translate(tx, ty, 0.0f);
        if (!isAA) {
            float length = mCaches.line.getLength(points[i], points[i + 1],
                    points[i + 2], points[i + 3]);
            mModelView.scale(length, strokeWidth, 1.0f);
        }
    glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
            gMeshStride, vertex);

    mModelView.loadIdentity();

    // Build and use the appropriate shader
    useProgram(mCaches.programCache.get(description));
    mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
        // TODO: Add bounds to the layer's region

        if (mShader) {
            mShader->updateTransforms(mCaches.currentProgram, mModelView, *mSnapshot);
    if (!mShader || (mShader && setColor)) {
        mCaches.currentProgram->setColor(r, g, b, a);
    }

        glDrawArrays(drawMode, 0, elementsCount);
    if (mShader) {
        mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit);
    }
    if (mColorFilter) {
        mColorFilter->setupProgram(mCaches.currentProgram);
    }

    if (isAA) {
        glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
    if (!isHairLine) {
        // TODO: Handle the AA case
        for (int i = 0; i < count; i += 4) {
            // a = start point, b = end point
            vec2 a(points[i], points[i + 1]);
            vec2 b(points[i + 2], points[i + 3]);

            // Bias to snap to the same pixels as Skia
            a += 0.375;
            b += 0.375;

            // Find the normal to the line
            vec2 n = (b - a).copyNormalized() * strokeWidth;
            float x = n.x;
            n.x = -n.y;
            n.y = x;

            // Four corners of the rectangle defining a thick line
            vec2 p1 = a - n;
            vec2 p2 = a + n;
            vec2 p3 = b + n;
            vec2 p4 = b - n;

            // Draw the line as 2 triangles, could be optimized
            // by using only 4 vertices and the correct indices
            // Also we should probably used non textured vertices
            // when line AA is disabled to save on bandwidth
            TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
            TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
            TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
            TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
            TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
            TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);

            // TODO: Mark the dirty regions when RENDER_LAYERS_AS_REGIONS is set
        }

        // GL_LINE does not give the result we want to match Skia
        glDrawArrays(GL_TRIANGLES, 0, verticesCount);
    } else {
        // TODO: Handle the AA case
        for (int i = 0; i < count; i += 4) {
            TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
            TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
        }
        glLineWidth(1.0f);
        glDrawArrays(GL_LINES, 0, verticesCount);
    }
}

libs/hwui/Vector.h

0 → 100644
+119 −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.
 */

#ifndef ANDROID_HWUI_VECTOR_H
#define ANDROID_HWUI_VECTOR_H

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Classes
///////////////////////////////////////////////////////////////////////////////

struct Vector2 {
    float x;
    float y;

    Vector2() :
        x(0.0f), y(0.0f) {
    }

    Vector2(float px, float py) :
        x(px), y(py) {
    }

    float length() const {
        return sqrt(x * x + y * y);
    }

    void operator+=(const Vector2& v) {
        x += v.x;
        y += v.y;
    }

    void operator-=(const Vector2& v) {
        x -= v.x;
        y -= v.y;
    }

    void operator+=(const float v) {
        x += v;
        y += v;
    }

    void operator-=(const float v) {
        x -= v;
        y -= v;
    }

    void operator/=(float s) {
        x /= s;
        y /= s;
    }

    void operator*=(float s) {
        x *= s;
        y *= s;
    }

    Vector2 operator+(const Vector2& v) const {
        return Vector2(x + v.x, y + v.y);
    }

    Vector2 operator-(const Vector2& v) const {
        return Vector2(x - v.x, y - v.y);
    }

    Vector2 operator/(float s) const {
        return Vector2(x / s, y / s);
    }

    Vector2 operator*(float s) const {
        return Vector2(x * s, y * s);
    }

    void normalize() {
        float s = 1.0f / length();
        x *= s;
        y *= s;
    }

    Vector2 copyNormalized() const {
        Vector2 v(x, y);
        v.normalize();
        return v;
    }

    float dot(const Vector2& v) const {
        return x * v.x + y * v.y;
    }

    void dump() {
        LOGD("Vector2[%.2f, %.2f]", x, y);
    }
}; // class Vector2

///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////

typedef Vector2 vec2;

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

#endif // ANDROID_HWUI_VECTOR_H
+1 −2
Original line number Diff line number Diff line
@@ -261,8 +261,7 @@

        <activity
                android:name="LinesActivity"
                android:label="_Lines"
                android:hardwareAccelerated="true">
                android:label="_Lines">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
Loading