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

Commit d55a8612 authored by Romain Guy's avatar Romain Guy
Browse files

Add support for saveLayer().

saveLayer() is affected by the paint's alpha and xfermode.

Change-Id: I28693a9337052643adccdb4889a8f228d4e17903
parent 8f704d89
Loading
Loading
Loading
Loading
+77 −44
Original line number Diff line number Diff line
@@ -171,6 +171,16 @@ bool OpenGLRenderer::restoreSnapshot() {
    sp<Snapshot> previous = mSnapshot->previous;

    if (restoreLayer) {
        composeLayer(current, previous);
    }

    mSnapshot = previous;
    mSaveCount--;

    return restoreClip;
}

void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
    // 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);
@@ -194,7 +204,7 @@ bool OpenGLRenderer::restoreSnapshot() {
    resetDrawTextureTexCoords(u1, v1, u2, v1);

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

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

@@ -202,37 +212,49 @@ bool OpenGLRenderer::restoreSnapshot() {
    glDeleteTextures(1, &current->texture);
}

    mSnapshot = previous;
    mSaveCount--;

    return restoreClip;
}

///////////////////////////////////////////////////////////////////////////////
// Layers
///////////////////////////////////////////////////////////////////////////////

int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
        const SkPaint* p, int flags) {
    // TODO Implement
    return saveSnapshot();
    int count = saveSnapshot();

    int alpha = 255;
    SkXfermode::Mode mode;

    if (p) {
        alpha = p->getAlpha();
        const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
        if (!isMode) {
            // Assume SRC_OVER
            mode = SkXfermode::kSrcOver_Mode;
        }
    } else {
        mode = SkXfermode::kSrcOver_Mode;
    }

    createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags);

    return count;
}

int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
        int alpha, int flags) {
    int count = saveSnapshot();
    createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
    return count;
}

    mSnapshot->flags |= Snapshot::kFlagIsLayer;
    mSnapshot->alpha = alpha / 255.0f;
    mSnapshot->layer.set(left, top, right, bottom);

bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
        float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) {
    // Generate the FBO and attach the texture
    glGenFramebuffers(1, &mSnapshot->fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, mSnapshot->fbo);
    glGenFramebuffers(1, &snapshot->fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);

    // Generate the texture in which the FBO will draw
    glGenTextures(1, &mSnapshot->texture);
    glBindTexture(GL_TEXTURE_2D, mSnapshot->texture);
    glGenTextures(1, &snapshot->texture);
    glBindTexture(GL_TEXTURE_2D, snapshot->texture);

    // The FBO will not be scaled, so we can use lower quality filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -255,17 +277,24 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot

    // Bind texture to FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            mSnapshot->texture, 0);
            snapshot->texture, 0);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        LOGD("Framebuffer incomplete %d", status);

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

        return false;
    }

    return count;
    snapshot->flags |= Snapshot::kFlagIsLayer;
    snapshot->mode = mode;
    snapshot->alpha = alpha / 255.0f;
    snapshot->layer.set(left, top, right, bottom);

    return true;
}

///////////////////////////////////////////////////////////////////////////////
@@ -406,16 +435,20 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
        GLuint texture, float alpha) {
        GLuint texture, float alpha, SkXfermode::Mode mode, bool isPremultiplied) {
    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);

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

    // TODO Correctly set the blend function, based on texture format and xfermode
    GLenum sourceMode = gBlends[mode].src;
    if (!isPremultiplied && sourceMode == GL_ONE) {
        sourceMode = GL_SRC_ALPHA;
    }

    // TODO: Try to disable blending when the texture is opaque and alpha == 1.0f
    glEnable(GL_BLEND);
    // For not pre-multiplied sources
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBlendFunc(sourceMode, gBlends[mode].dst);

    glBindTexture(GL_TEXTURE_2D, texture);

+31 −1
Original line number Diff line number Diff line
@@ -125,6 +125,34 @@ private:
     */
    void setScissorFromClip();

    /**
     * Compose the layer defined in the current snapshot with the layer
     * defined by the previous snapshot.
     *
     * The current snapshot *must* be a layer (flag kFlagIsLayer set.)
     *
     * @param curent The current snapshot containing the layer to compose
     * @param previous The previous snapshot to compose the current layer with
     */
    void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);

    /**
     * Creates a new layer stored in the specified snapshot.
     *
     * @param snapshot The snapshot associated with the new layer
     * @param left The left coordinate of the layer
     * @param top The top coordinate of the layer
     * @param right The right coordinate of the layer
     * @param bottom The bottom coordinate of the layer
     * @param alpha The translucency of the layer
     * @param mode The blending mode of the layer
     * @param flags The layer save flags
     *
     * @return True if the layer was successfully created, false otherwise
     */
    bool createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom,
            int alpha, SkXfermode::Mode mode, int flags);

    /**
     * Draws a colored rectangle with the specified color. The specified coordinates
     * are transformed by the current snapshot's transform matrix.
@@ -149,9 +177,11 @@ private:
     * @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
     * @param mode The blending mode
     * @param isPremultiplied Indicates whether the texture has premultiplied alpha
     */
    void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
            float alpha);
            float alpha, SkXfermode::Mode mode, bool isPremultiplied = false);

    /**
     * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
+7 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <SkXfermode.h>

#include <utils/RefBase.h>

#include "Matrix.h"
@@ -133,6 +135,11 @@ public:
     * Only set when the flag kFlagIsLayer is set.
     */
    float alpha;
    /**
     * Blending mode of the layer.
     * Only set when the flag kFlagIsLayer is set.
     */
    SkXfermode::Mode mode;

private:
    // Clipping rectangle mapped with the transform
+12 −2
Original line number Diff line number Diff line
@@ -22,8 +22,18 @@
        android:hardwareAccelerated="true">

        <activity
                android:name="HwUiActivity"
                android:label="_Layers">
                android:name="AlphaLayersActivity"
                android:label="_αLayers">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity
                android:name="LayersActivity"
                android:label="_Layers"
                android:theme="@android:style/Theme.Translucent">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import android.view.animation.Animation;
import android.widget.FrameLayout;

@SuppressWarnings({"UnusedDeclaration"})
public class HwUiActivity extends Activity {
public class AlphaLayersActivity extends Activity {
    private static final String LOG_TAG = "HwUi";

    @Override
Loading