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

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

Merge "Implement support for PorterDuff's blending modes."

parents b151fe3b 026c5e16
Loading
Loading
Loading
Loading
+77 −30
Original line number Diff line number Diff line
@@ -40,34 +40,42 @@ namespace uirenderer {
// Globals
///////////////////////////////////////////////////////////////////////////////

const SimpleVertex gDrawColorVertices[] = {
static const SimpleVertex gDrawColorVertices[] = {
        SV(0.0f, 0.0f),
        SV(1.0f, 0.0f),
        SV(0.0f, 1.0f),
        SV(1.0f, 1.0f)
};
const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
const GLsizei gDrawColorVertexCount = 4;
static const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
static const GLsizei gDrawColorVertexCount = 4;

TextureVertex gDrawTextureVertices[] = {
// This array is never used directly but used as a memcpy source in the
// OpenGLRenderer constructor
static const 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),
        FV(1.0f, 1.0f, 1.0f, 0.0f)
};
const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
const GLsizei gDrawTextureVertexCount = 4;

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;
}
static const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
static const GLsizei gDrawTextureVertexCount = 4;

// 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[] = {
        { SkXfermode::kClear_Mode,   GL_ZERO,                 GL_ZERO },
        { SkXfermode::kSrc_Mode,     GL_ONE,                  GL_ZERO },
        { SkXfermode::kDst_Mode,     GL_ZERO,                 GL_ONE },
        { SkXfermode::kSrcOver_Mode, GL_ONE,                  GL_ONE_MINUS_SRC_ALPHA },
        { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_ONE },
        { SkXfermode::kSrcIn_Mode,   GL_DST_ALPHA,            GL_ZERO },
        { SkXfermode::kDstIn_Mode,   GL_ZERO,                 GL_SRC_ALPHA },
        { SkXfermode::kSrcOut_Mode,  GL_ONE_MINUS_DST_ALPHA,  GL_ZERO },
        { SkXfermode::kDstOut_Mode,  GL_ZERO,                 GL_ONE_MINUS_SRC_ALPHA },
        { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA,            GL_ONE_MINUS_SRC_ALPHA },
        { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_SRC_ALPHA },
        { SkXfermode::kXor_Mode,     GL_ONE_MINUS_DST_ALPHA,  GL_ONE_MINUS_SRC_ALPHA }
};

///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
@@ -78,6 +86,8 @@ OpenGLRenderer::OpenGLRenderer() {

    mDrawColorShader = new DrawColorProgram;
    mDrawTextureShader = new DrawTextureProgram;

    memcpy(mDrawTextureVertices, gDrawTextureVertices, sizeof(gDrawTextureVertices));
}

OpenGLRenderer::~OpenGLRenderer() {
@@ -336,22 +346,43 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
    // TODO: Set the transfer mode
    const Rect& clip = mSnapshot->clipRect;
    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color);
    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode);
}

void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) {
    // TODO Support more than  just color
    // TODO: Set the transfer mode
    drawColorRect(left, top, right, bottom, p->getColor());
    SkXfermode::Mode mode;

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

    // Skia draws using the color's alpha channel if < 255
    // Otherwise, it uses the paint's alpha
    int color = p->getColor();
    if (((color >> 24) & 0xFF) == 255) {
        color |= p->getAlpha() << 24;
    }

    drawColorRect(left, top, right, bottom, color, mode);
}

void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) {
    GLfloat a = ((color >> 24) & 0xFF) / 255.0f;
    GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
    GLfloat g = ((color >>  8) & 0xFF) / 255.0f;
    GLfloat b = ((color      ) & 0xFF) / 255.0f;
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
        int color, SkXfermode::Mode mode) {
    const int alpha = (color >> 24) & 0xFF;
    const bool blend = alpha < 255 || mode != SkXfermode::kSrcOver_Mode;

    const GLfloat a = alpha                  / 255.0f;
    const GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
    const GLfloat g = ((color >>  8) & 0xFF) / 255.0f;
    const GLfloat b = ((color      ) & 0xFF) / 255.0f;

    if (blend) {
        glEnable(GL_BLEND);
        glBlendFunc(gBlends[mode].src, gBlends[mode].dst);
    }

    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);
@@ -368,6 +399,10 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
    glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);

    glDisableVertexAttribArray(mDrawColorShader->position);

    if (blend) {
        glDisable(GL_BLEND);
    }
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -379,6 +414,7 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b

    // TODO Correctly set the blend function, based on texture format and xfermode
    glEnable(GL_BLEND);
    // For not pre-multiplied sources
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glBindTexture(GL_TEXTURE_2D, texture);
@@ -386,8 +422,8 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
    glActiveTexture(GL_TEXTURE0);
    glUniform1i(mDrawTextureShader->sampler, 0);

    const GLvoid* p = &gDrawTextureVertices[0].position[0];
    const GLvoid* t = &gDrawTextureVertices[0].texture[0];
    const GLvoid* p = &mDrawTextureVertices[0].position[0];
    const GLvoid* t = &mDrawTextureVertices[0].texture[0];

    glEnableVertexAttribArray(mDrawTextureShader->position);
    glVertexAttribPointer(mDrawTextureShader->position, 2, GL_FLOAT, GL_FALSE,
@@ -408,5 +444,16 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
    glDisable(GL_BLEND);
}

void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
    mDrawTextureVertices[0].texture[0] = u1;
    mDrawTextureVertices[0].texture[1] = v2;
    mDrawTextureVertices[1].texture[0] = u2;
    mDrawTextureVertices[1].texture[1] = v2;
    mDrawTextureVertices[2].texture[0] = u1;
    mDrawTextureVertices[2].texture[1] = v1;
    mDrawTextureVertices[3].texture[0] = u2;
    mDrawTextureVertices[3].texture[1] = v1;
}

}; // namespace uirenderer
}; // namespace android
+28 −1
Original line number Diff line number Diff line
@@ -53,6 +53,15 @@ struct TextureVertex {
    float texture[2];
}; // struct TextureVertex

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

///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////
@@ -125,8 +134,10 @@ private:
     * @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
     * @param mode The Skia xfermode to use
     */
    void drawColorRect(float left, float top, float right, float bottom, int color);
    void drawColorRect(float left, float top, float right, float bottom,
    		int color, SkXfermode::Mode mode);

    /**
     * Draws a textured rectangle with the specified texture. The specified coordinates
@@ -142,6 +153,19 @@ private:
    void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
            float alpha);

    /**
     * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
     * back to default is achieved by calling:
     *
     * resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
     *
     * @param u1 The left coordinate of the texture
     * @param v1 The bottom coordinate of the texture
     * @param u2 The right coordinate of the texture
     * @param v2 The top coordinate of the texture
     */
    void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2);

    // Dimensions of the drawing surface
    int mWidth, mHeight;

@@ -161,6 +185,9 @@ private:
    // Shaders
    sp<DrawColorProgram> mDrawColorShader;
    sp<DrawTextureProgram> mDrawTextureShader;

    // Used to draw textured quads
    TextureVertex mDrawTextureVertices[4];
}; // class OpenGLRenderer

}; // namespace uirenderer
+13 −1
Original line number Diff line number Diff line
@@ -21,7 +21,19 @@
        android:label="HwUi"
        android:hardwareAccelerated="true">

        <activity android:name="HwUiActivity">
        <activity
                android:name="HwUiActivity"
                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="XfermodeActivity"
                android:label="_Xfermodes"
                android:theme="@android:style/Theme.Translucent">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
+142 −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.
 */

package com.google.android.test.hwui;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.View;

import static android.graphics.PorterDuff.Mode;

@SuppressWarnings({"UnusedDeclaration"})
public class XfermodeActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(new XfermodesView(this));
    }
    
    @SuppressWarnings({"UnusedDeclaration"})
    static int dipToPx(Context c, int dip) {
        return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f);
    }

    static class XfermodesView extends View {
        private final Paint mBluePaint;
        private final Paint mRedPaint;

        XfermodesView(Context c) {
            super(c);

            mBluePaint = new Paint();
            mBluePaint.setColor(0xff0000ff);
            
            mRedPaint = new Paint();
            mRedPaint.setColor(0x7fff0000);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //canvas.drawRGB(255, 255, 255);

            canvas.translate(100.0f, 100.0f);
            
            // SRC modes
            canvas.save();

            drawRects(canvas, Mode.SRC_OVER);
            canvas.translate(0.0f, 100.0f);

            drawRects(canvas, Mode.SRC_IN);
            canvas.translate(0.0f, 100.0f);            

            drawRects(canvas, Mode.SRC_OUT);
            canvas.translate(0.0f, 100.0f);

            drawRects(canvas, Mode.SRC_ATOP);
            canvas.translate(0.0f, 100.0f);
            
            drawRects(canvas, Mode.SRC);

            canvas.restore();
            
            canvas.translate(100.0f, 0.0f);
            
            // DST modes
            canvas.save();

            drawRects(canvas, Mode.DST_OVER);
            canvas.translate(0.0f, 100.0f);

            drawRects(canvas, Mode.DST_IN);
            canvas.translate(0.0f, 100.0f);            

            drawRects(canvas, Mode.DST_OUT);
            canvas.translate(0.0f, 100.0f);

            drawRects(canvas, Mode.DST_ATOP);
            canvas.translate(0.0f, 100.0f);
            
            drawRects(canvas, Mode.DST);

            canvas.restore();
            
            canvas.translate(100.0f, 0.0f);
            
            // Other modes
            canvas.save();

            drawRects(canvas, Mode.CLEAR);
            canvas.translate(0.0f, 100.0f);

            drawRects(canvas, Mode.XOR);
            
            canvas.translate(0.0f, 100.0f);
            
            mBluePaint.setAlpha(127);
            canvas.drawRect(0.0f, 0.0f, 50.0f, 50.0f, mBluePaint);
            
            canvas.translate(0.0f, 100.0f);
            
            mBluePaint.setAlpha(10);
            mBluePaint.setColor(0x7f0000ff);
            canvas.drawRect(0.0f, 0.0f, 50.0f, 50.0f, mBluePaint);
            
            mBluePaint.setColor(0xff0000ff);
            mBluePaint.setAlpha(255);

            canvas.restore();
        }

        private void drawRects(Canvas canvas, PorterDuff.Mode mode) {
            canvas.drawRect(0.0f, 0.0f, 50.0f, 50.0f, mBluePaint);

            canvas.save();
            canvas.translate(25.0f, 25.0f);
            mRedPaint.setXfermode(new PorterDuffXfermode(mode));
            canvas.drawRect(0.0f, 0.0f, 50.0f, 50.0f, mRedPaint);
            canvas.restore();
        }
    }
}