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

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

Merge changes I16ce79ab,Ib86a7309

* changes:
  Correctly set the viewport in layers.
  Cleanup, better code reuse.
parents de8db545 1d83e198
Loading
Loading
Loading
Loading
+188 −200
Original line number Diff line number Diff line
@@ -183,12 +183,12 @@ OpenGLRenderer::~OpenGLRenderer() {

void OpenGLRenderer::setViewport(int width, int height) {
    glViewport(0, 0, width, height);

    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);

    mWidth = width;
    mHeight = height;
    mFirstSnapshot->height = height;
    mFirstSnapshot->viewport.set(0, 0, width, height);
}

void OpenGLRenderer::prepare() {
@@ -254,6 +254,8 @@ bool OpenGLRenderer::restoreSnapshot() {
    sp<Snapshot> previous = mSnapshot->previous;

    if (restoreOrtho) {
        Rect& r = previous->viewport;
        glViewport(r.left, r.top, r.right, r.bottom);
        mOrthoMatrix.load(current->orthoMatrix);
    }

@@ -267,39 +269,6 @@ bool OpenGLRenderer::restoreSnapshot() {
    return restoreClip;
}

void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
    if (!current->layer) {
        LOGE("Attempting to compose a layer that does not exist");
        return;
    }

    // Unbind current FBO and restore previous one
    // 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->clipRect;
    glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());

    Layer* layer = current->layer;
    const Rect& rect = layer->layer;

    drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
            layer->texture, layer->alpha, layer->mode, layer->blend);

    LayerSize size(rect.getWidth(), rect.getHeight());
    // Failing to add the layer to the cache should happen only if the
    // layer is too large
    if (!mLayerCache.put(size, layer)) {
        LAYER_LOGD("Deleting layer");

        glDeleteFramebuffers(1, &layer->fbo);
        glDeleteTextures(1, &layer->texture);

        delete layer;
    }
}

///////////////////////////////////////////////////////////////////////////////
// Layers
///////////////////////////////////////////////////////////////////////////////
@@ -366,21 +335,58 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,

    // Creates a new snapshot to draw into the FBO
    saveSnapshot();
    // TODO: This doesn't preserve other transformations (check Skia first)

    mSnapshot->transform.loadTranslate(-left, -top, 0.0f);
    mSnapshot->setClip(0.0f, 0.0f, right - left, bottom - top);
    mSnapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top);
    mSnapshot->height = bottom - top;

    setScissorFromClip();

    mSnapshot->flags = Snapshot::kFlagDirtyOrtho | Snapshot::kFlagClipSet;
    mSnapshot->orthoMatrix.load(mOrthoMatrix);

    // Change the ortho projection
    mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f);
    glViewport(0, 0, right - left, bottom - top);
    // Don't flip the FBO, it will get flipped when drawing back to the framebuffer
    mOrthoMatrix.loadOrtho(0.0f, right - left, 0.0f, bottom - top, -1.0f, 1.0f);

    return true;
}

void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
    if (!current->layer) {
        LOGE("Attempting to compose a layer that does not exist");
        return;
    }

    // Unbind current FBO and restore previous one
    // 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->clipRect;
    glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());

    Layer* layer = current->layer;
    const Rect& rect = layer->layer;

    drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
            layer->texture, layer->alpha, layer->mode, layer->blend);

    LayerSize size(rect.getWidth(), rect.getHeight());
    // Failing to add the layer to the cache should happen only if the
    // layer is too large
    if (!mLayerCache.put(size, layer)) {
        LAYER_LOGD("Deleting layer");

        glDeleteFramebuffers(1, &layer->fbo);
        glDeleteTextures(1, &layer->texture);

        delete layer;
    }
}

///////////////////////////////////////////////////////////////////////////////
// Transforms
///////////////////////////////////////////////////////////////////////////////
@@ -424,14 +430,9 @@ const Rect& OpenGLRenderer::getClipBounds() {
}

bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
    SkRect sr;
    sr.set(left, top, right, bottom);

    SkMatrix m;
    mSnapshot->transform.copyTo(m);
    m.mapRect(&sr);
    Rect r(left, top, right, bottom);
    mSnapshot->transform.mapRect(r);

    Rect r(sr.fLeft, sr.fTop, sr.fRight, sr.fBottom);
    return !mSnapshot->clipRect.intersects(r);
}

@@ -562,82 +563,6 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
    drawColorRect(left, top, right, bottom, color, mode);
}

void OpenGLRenderer::renderShadow(const ShadowTexture* texture, float x, float y,
        SkXfermode::Mode mode) {
    const float sx = x - texture->left + mShadowDx;
    const float sy = y - texture->top + mShadowDy;

    const GLfloat a = ((mShadowColor >> 24) & 0xFF) / 255.0f;
    const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f;
    const GLfloat g = a * ((mShadowColor >>  8) & 0xFF) / 255.0f;
    const GLfloat b = a * ((mShadowColor      ) & 0xFF) / 255.0f;

    GLuint textureUnit = 0;
    renderTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, false);
}

void OpenGLRenderer::renderTextureAlpha8(const Texture* texture, GLuint& textureUnit,
        float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode,
        bool applyFilters) {
     // Describe the required shaders
     ProgramDescription description;
     description.hasTexture = true;
     description.hasAlpha8Texture = true;

     if (applyFilters) {
         if (mShader) {
             mShader->describe(description, mExtensions);
         }
         if (mColorFilter) {
             mColorFilter->describe(description, mExtensions);
         }
     }

     // Build and use the appropriate shader
     useProgram(mProgramCache.get(description));

     // Setup the blending mode
     chooseBlending(true, mode);
     bindTexture(texture->id, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit);
     glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit);

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

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

     // Setup uniforms
     mModelView.loadTranslate(x, y, 0.0f);
     mModelView.scale(texture->width, texture->height, 1.0f);
     mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);

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

     textureUnit++;
     if (applyFilters) {
         // Setup attributes and uniforms required by the shaders
         if (mShader) {
             mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
         }
         if (mColorFilter) {
             mColorFilter->setupProgram(mCurrentProgram);
         }
     }

     // Draw the mesh
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);

     glDisableVertexAttribArray(texCoordsSlot);
}

#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
#define kStdUnderline_Offset    (1.0f / 9.0f)
#define kStdUnderline_Thickness (1.0f / 18.0f)

void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
        float x, float y, SkPaint* paint) {
    if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
@@ -668,7 +593,12 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
        const ShadowTexture* shadow = mDropShadowCache.get(paint, text, bytesCount,
                count, mShadowRadius);
        const AutoTexture autoCleanup(shadow);
        renderShadow(shadow, x, y, mode);

        setupShadow(shadow, x, y, mode);

        // Draw the mesh
        glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
        glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords"));
    }

    uint32_t color = paint->getColor();
@@ -677,94 +607,19 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
    const GLfloat g = a * ((color >>  8) & 0xFF) / 255.0f;
    const GLfloat b = a * ((color      ) & 0xFF) / 255.0f;

    mModelView.loadIdentity();

    GLuint textureUnit = 0;
    // Needs to be set prior to calling FontRenderer::getTexture()
    glActiveTexture(gTextureUnits[textureUnit]);

    ProgramDescription description;
    description.hasTexture = true;
    description.hasAlpha8Texture = true;
    if (mShader) {
        mShader->describe(description, mExtensions);
    }
    if (mColorFilter) {
        mColorFilter->describe(description, mExtensions);
    }

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

    // Text is always blended, no need to check the shader
    chooseBlending(true, mode);
    bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit);
    glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit);

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

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

    textureUnit++;
    // Setup attributes and uniforms required by the shaders
    if (mShader) {
        mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
    }
    if (mColorFilter) {
        mColorFilter->setupProgram(mCurrentProgram);
    }
    setupTextureAlpha8(mFontRenderer.getTexture(), 0, 0, textureUnit, x, y, r, g, b, a,
            mode, false, true);

    const Rect& clip = mSnapshot->getLocalClip();
    mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDisableVertexAttribArray(texCoordsSlot);
    glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords"));

    // Handle underline and strike-through
    uint32_t flags = paint->getFlags();
    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
        float underlineWidth = length;
        // If length is > 0.0f, we already measured the text for the text alignment
        if (length <= 0.0f) {
            underlineWidth = paint->measureText(text, bytesCount);
        }

        float offsetX = 0;
        switch (paint->getTextAlign()) {
            case SkPaint::kCenter_Align:
                offsetX = underlineWidth * 0.5f;
                break;
            case SkPaint::kRight_Align:
                offsetX = underlineWidth;
                break;
            default:
                break;
        }

        if (underlineWidth > 0.0f) {
            float textSize = paint->getTextSize();
            float height = textSize * kStdUnderline_Thickness;

            float left = x - offsetX;
            float top = 0.0f;
            float right = left + underlineWidth;
            float bottom = 0.0f;

            if (flags & SkPaint::kUnderlineText_Flag) {
                top = y + textSize * kStdUnderline_Offset;
                bottom = top + height;
                drawRect(left, top, right, bottom, paint);
            }

            if (flags & SkPaint::kStrikeThruText_Flag) {
                top = y + textSize * kStdStrikeThru_Offset;
                bottom = top + height;
                drawRect(left, top, right, bottom, paint);
            }
        }
    }
    drawTextDecorations(text, bytesCount, length, x, y, paint);
}

void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
@@ -787,7 +642,12 @@ void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {

    const float x = texture->left - texture->offset;
    const float y = texture->top - texture->offset;
    renderTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true);

    setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true);

    // Draw the mesh
    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
    glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords"));
}

///////////////////////////////////////////////////////////////////////////////
@@ -837,6 +697,134 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
// Drawing implementation
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y,
        SkXfermode::Mode mode) {
    const float sx = x - texture->left + mShadowDx;
    const float sy = y - texture->top + mShadowDy;

    const GLfloat a = ((mShadowColor >> 24) & 0xFF) / 255.0f;
    const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f;
    const GLfloat g = a * ((mShadowColor >>  8) & 0xFF) / 255.0f;
    const GLfloat b = a * ((mShadowColor      ) & 0xFF) / 255.0f;

    GLuint textureUnit = 0;
    setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false);
}

void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit,
        float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode,
        bool transforms, bool applyFilters) {
    setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit,
            x, y, r, g, b, a, mode, transforms, applyFilters);
}

void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
        GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
        SkXfermode::Mode mode, bool transforms, bool applyFilters) {
     // Describe the required shaders
     ProgramDescription description;
     description.hasTexture = true;
     description.hasAlpha8Texture = true;

     if (applyFilters) {
         if (mShader) {
             mShader->describe(description, mExtensions);
         }
         if (mColorFilter) {
             mColorFilter->describe(description, mExtensions);
         }
     }

     // Build and use the appropriate shader
     useProgram(mProgramCache.get(description));

     // Setup the blending mode
     chooseBlending(true, mode);
     bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit);
     glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit);

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

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

     // Setup uniforms
     if (transforms) {
         mModelView.loadTranslate(x, y, 0.0f);
         mModelView.scale(width, height, 1.0f);
     } else {
         mModelView.loadIdentity();
     }
     mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
     glUniform4f(mCurrentProgram->color, r, g, b, a);

     textureUnit++;
     if (applyFilters) {
         // Setup attributes and uniforms required by the shaders
         if (mShader) {
             mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
         }
         if (mColorFilter) {
             mColorFilter->setupProgram(mCurrentProgram);
         }
     }
}

#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
#define kStdUnderline_Offset    (1.0f / 9.0f)
#define kStdUnderline_Thickness (1.0f / 18.0f)

void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length,
        float x, float y, SkPaint* paint) {
    // Handle underline and strike-through
    uint32_t flags = paint->getFlags();
    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
        float underlineWidth = length;
        // If length is > 0.0f, we already measured the text for the text alignment
        if (length <= 0.0f) {
            underlineWidth = paint->measureText(text, bytesCount);
        }

        float offsetX = 0;
        switch (paint->getTextAlign()) {
            case SkPaint::kCenter_Align:
                offsetX = underlineWidth * 0.5f;
                break;
            case SkPaint::kRight_Align:
                offsetX = underlineWidth;
                break;
            default:
                break;
        }

        if (underlineWidth > 0.0f) {
            float textSize = paint->getTextSize();
            float height = textSize * kStdUnderline_Thickness;

            float left = x - offsetX;
            float top = 0.0f;
            float right = left + underlineWidth;
            float bottom = 0.0f;

            if (flags & SkPaint::kUnderlineText_Flag) {
                top = y + textSize * kStdUnderline_Offset;
                bottom = top + height;
                drawRect(left, top, right, bottom, paint);
            }

            if (flags & SkPaint::kStrikeThruText_Flag) {
                top = y + textSize * kStdStrikeThru_Offset;
                bottom = top + height;
                drawRect(left, top, right, bottom, paint);
            }
        }
    }
}

void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
        int color, SkXfermode::Mode mode, bool ignoreTransform) {
    // If a shader is set, preserve only the alpha
+44 −5
Original line number Diff line number Diff line
@@ -226,17 +226,17 @@ private:
            GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0);

    /**
     * Renders the specified shadow.
     * Prepares the renderer to draw the specified shadow.
     *
     * @param texture The shadow texture
     * @param x The x coordinate of the shadow
     * @param y The y coordinate of the shadow
     * @param mode The blending mode
     */
    void renderShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode);
    void setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode);

    /**
     * Renders the specified Alpha8 texture as a rectangle.
     * Prepares the renderer to draw the specified Alpha8 texture as a rectangle.
     *
     * @param texture The texture to render with
     * @param textureUnit The texture unit to use, may be modified
@@ -247,11 +247,50 @@ private:
     * @param b The blue component of the color
     * @param a The alpha component of the color
     * @param mode The blending mode
     * @param transforms True if the matrix passed to the shader should be multiplied
     *        by the model-view matrix
     * @param applyFilters Whether or not to take color filters and
     *        shaders into account
     */
    void renderTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y,
            float r, float g, float b, float a, SkXfermode::Mode mode, bool applyFilters);
    void setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y,
            float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms,
            bool applyFilters);

    /**
     * Prepares the renderer to draw the specified Alpha8 texture as a rectangle.
     *
     * @param texture The texture to render with
     * @param width The width of the texture
     * @param height The height of the texture
     * @param textureUnit The texture unit to use, may be modified
     * @param x The x coordinate of the rectangle to draw
     * @param y The y coordinate of the rectangle to draw
     * @param r The red component of the color
     * @param g The green component of the color
     * @param b The blue component of the color
     * @param a The alpha component of the color
     * @param mode The blending mode
     * @param transforms True if the matrix passed to the shader should be multiplied
     *        by the model-view matrix
     * @param applyFilters Whether or not to take color filters and
     *        shaders into account
     */
    void setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
            GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
            SkXfermode::Mode mode, bool transforms, bool applyFilters);

    /**
     * Draws text underline and strike-through if needed.
     *
     * @param text The text to decor
     * @param bytesCount The number of bytes in the text
     * @param length The length in pixels of the text, can be <= 0.0f to force a measurement
     * @param x The x coordinate where the text will be drawn
     * @param y The y coordinate where the text will be drawn
     * @param paint The paint to draw the text with
     */
    void drawTextDecorations(const char* text, int bytesCount, float length,
            float x, float y, SkPaint* paint);

    /**
     * Resets the texture coordinates stored in mMeshVertices. Setting the values
+7 −1
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@ public:
            flags(0),
            previous(s),
            layer(NULL),
            fbo(s->fbo) {
            fbo(s->fbo),
            viewport(s->viewport) {
        if ((s->flags & Snapshot::kFlagClipSet) &&
                !(s->flags & Snapshot::kFlagDirtyLocalClip)) {
            localClip.set(s->localClip);
@@ -179,6 +180,11 @@ public:
    Layer* layer;
    GLuint fbo;

    /**
     * Current viewport.
     */
    Rect viewport;

    /**
     * Contains the previous ortho matrix.
     */
+1 −1
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ struct ShadowText {

    ShadowText(const ShadowText& shadow):
            paint(shadow.paint), radius(shadow.radius), len(shadow.len), hash(shadow.hash) {
        text = new char[len];
        text = new char[shadow.len];
        memcpy(text, shadow.text, shadow.len);
    }

+9 −0
Original line number Diff line number Diff line
@@ -189,5 +189,14 @@
            </intent-filter>
        </activity>

        <activity
                android:name="StackActivity"
                android:label="_Stacks">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>
Loading