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

Commit a1fb7779 authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Implement drawLayers() with buffer source."

parents 4a7b239c 0d5e1ebb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ cc_defaults {
        "libgui",
        "liblog",
        "libnativewindow",
        "libsync",
        "libui",
        "libutils",
    ],
+85 −13
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <math.h>
#include <fstream>
#include <sstream>
#include <unordered_set>

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -32,6 +33,7 @@
#include <renderengine/Mesh.h>
#include <renderengine/Texture.h>
#include <renderengine/private/Description.h>
#include <sync/sync.h>
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/Rect.h>
@@ -584,6 +586,46 @@ void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& i
    }
}

status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
                                                     sp<Fence> bufferFence) {
    std::unique_ptr<Image> newImage = createImage();

    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
    if (!created) {
        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
              buffer->getPixelFormat());
        bindExternalTextureImage(texName, *createImage());
        return NO_INIT;
    }

    bindExternalTextureImage(texName, *newImage);

    // Wait for the new buffer to be ready.
    if (bufferFence != nullptr && bufferFence->isValid()) {
        if (GLExtensions::getInstance().hasWaitSync()) {
            base::unique_fd fenceFd(bufferFence->dup());
            if (fenceFd == -1) {
                ALOGE("error dup'ing fence fd: %d", errno);
                return -errno;
            }
            if (!waitFence(std::move(fenceFd))) {
                ALOGE("failed to wait on fence fd");
                return UNKNOWN_ERROR;
            }
        } else {
            status_t err = bufferFence->waitForever("RenderEngine::bindExternalTextureBuffer");
            if (err != NO_ERROR) {
                ALOGE("error waiting for fence: %d", err);
                return err;
            }
        }
    }

    return NO_ERROR;
}

status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
    EGLImageKHR eglImage = glFramebuffer->getEGLImage();
@@ -673,32 +715,62 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,

    mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;

    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
    for (auto layer : layers) {
        // for now, assume that all pixel sources are solid colors.
        // TODO(alecmouri): support buffer sources
        if (layer.source.buffer.buffer != nullptr) {
            continue;
        }

        setColorTransform(display.colorTransform * layer.colorTransform);

        mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;

        FloatRect bounds = layer.geometry.boundaries;
        const FloatRect bounds = layer.geometry.boundaries;
        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
        position[0] = vec2(bounds.left, bounds.top);
        position[1] = vec2(bounds.left, bounds.bottom);
        position[2] = vec2(bounds.right, bounds.bottom);
        position[3] = vec2(bounds.right, bounds.top);

        half3 solidColor = layer.source.solidColor;
        half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
        setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true,
        setColorTransform(display.colorTransform * layer.colorTransform);

        bool usePremultipliedAlpha = true;
        bool disableTexture = true;

        if (layer.source.buffer.buffer != nullptr) {
            disableTexture = false;

            sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;

            bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
                                      layer.source.buffer.fence);

            usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
            Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
            texture.setMatrix(layer.source.buffer.textureTransform.asArray());
            texture.setFiltering(layer.source.buffer.useTextureFiltering);

            texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
            setSourceY410BT2020(layer.source.buffer.isY410BT2020);

            renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
            texCoords[0] = vec2(0.0, 1.0);
            texCoords[1] = vec2(0.0, 0.0);
            texCoords[2] = vec2(1.0, 0.0);
            texCoords[3] = vec2(1.0, 1.0);
            setupLayerTexturing(texture);
        }

        const half3 solidColor = layer.source.solidColor;
        const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
        // Buffer sources will have a black solid color ignored in the shader,
        // so in that scenario the solid color passed here is arbitrary.
        setupLayerBlending(usePremultipliedAlpha, layer.source.buffer.isOpaque, disableTexture,
                           color, /*cornerRadius=*/0.0);
        setSourceDataSpace(layer.sourceDataspace);

        drawMesh(mesh);

        // Cleanup if there's a buffer source
        if (layer.source.buffer.buffer != nullptr) {
            disableBlending();
            setSourceY410BT2020(false);
            disableTexturing();
        }
    }

    *drawFence = flush();
+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ private:
    // Defines the viewport, and sets the projection matrix to the projection
    // defined by the clip.
    void setViewportAndProjection(Rect viewport, Rect clip);
    status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence);

    EGLDisplay mEGLDisplay;
    EGLConfig mEGLConfig;
+10 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <math/mat4.h>
#include <math/vec3.h>
#include <renderengine/Texture.h>
#include <ui/Fence.h>
#include <ui/FloatRect.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
@@ -36,6 +37,9 @@ struct Buffer {
    // ignored.
    sp<GraphicBuffer> buffer = nullptr;

    // Fence that will fire when the buffer is ready to be bound.
    sp<Fence> fence = nullptr;

    // Texture identifier to bind the external texture to.
    // TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
    uint32_t textureName = 0;
@@ -49,6 +53,11 @@ struct Buffer {
    // Wheteher to use pre-multiplied alpha
    bool usePremultipliedAlpha = true;

    // Override flag that alpha for each pixel in the buffer *must* be 1.0.
    // LayerSettings::alpha is still used if isOpaque==true - this flag only
    // overrides the alpha channel of the buffer.
    bool isOpaque = false;

    // HDR color-space setting for Y410.
    bool isY410BT2020 = false;
};
@@ -81,7 +90,7 @@ struct LayerSettings {
    // Source pixels for this layer.
    PixelSource source = PixelSource();

    // Alpha option to apply to the source pixels
    // Alpha option to blend with the source pixels
    half alpha = half(0.0);

    // Color space describing how the source pixels should be interpreted.
+339 −11
Original line number Diff line number Diff line
@@ -27,15 +27,30 @@ constexpr int DEFAULT_DISPLAY_OFFSET = 64;
namespace android {

struct RenderEngineTest : public ::testing::Test {
    sp<GraphicBuffer> allocateDefaultBuffer() {
    static sp<GraphicBuffer> allocateDefaultBuffer() {
        return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
                                 HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
                                         GRALLOC_USAGE_HW_RENDER,
                                 "output");
    }

    // Allocates a 1x1 buffer to fill with a solid color
    static sp<GraphicBuffer> allocateSourceBuffer(uint32_t width, uint32_t height) {
        return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
                                         GRALLOC_USAGE_HW_TEXTURE,
                                 "input");
    }

    RenderEngineTest() { mBuffer = allocateDefaultBuffer(); }

    ~RenderEngineTest() {
        for (uint32_t texName : mTexNames) {
            sRE->deleteTextures(1, &texName);
        }
    }

    void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
                           uint8_t tolerance = 0) {
        uint8_t* pixels;
@@ -145,28 +160,101 @@ struct RenderEngineTest : public ::testing::Test {
    template <typename SourceVariant>
    void fillBufferCheckersRotate270();

    template <typename SourceVariant>
    void fillBufferWithLayerTransform();

    template <typename SourceVariant>
    void fillBufferLayerTransform();

    template <typename SourceVariant>
    void fillBufferWithColorTransform();

    template <typename SourceVariant>
    void fillBufferColorTransform();

    void fillRedBufferTextureTransform();

    void fillBufferTextureTransform();

    void fillRedBufferWithPremultiplyAlpha();

    void fillBufferWithPremultiplyAlpha();

    void fillRedBufferWithoutPremultiplyAlpha();

    void fillBufferWithoutPremultiplyAlpha();

    // Dumb hack to get aroud the fact that tear-down for renderengine isn't
    // well defined right now, so we can't create multiple instances
    static std::unique_ptr<renderengine::RenderEngine> sRE;

    sp<GraphicBuffer> mBuffer;

    std::vector<uint32_t> mTexNames;
};

std::unique_ptr<renderengine::RenderEngine> RenderEngineTest::sRE =
        renderengine::RenderEngine::create(static_cast<int32_t>(ui::PixelFormat::RGBA_8888), 0);

struct ColorSourceVariant {
    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b) {
    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
                          RenderEngineTest* /*fixture*/) {
        layer.source.solidColor = half3(r, g, b);
    }
};

struct RelaxOpaqueBufferVariant {
    static void setOpaqueBit(renderengine::LayerSettings& layer) {
        layer.source.buffer.isOpaque = false;
    }

    static uint8_t getAlphaChannel() { return 255; }
};

struct ForceOpaqueBufferVariant {
    static void setOpaqueBit(renderengine::LayerSettings& layer) {
        layer.source.buffer.isOpaque = true;
    }

    static uint8_t getAlphaChannel() {
        // The isOpaque bit will override the alpha channel, so this should be
        // arbitrary.
        return 10;
    }
};

template <typename OpaquenessVariant>
struct BufferSourceVariant {
    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
                          RenderEngineTest* fixture) {
        sp<GraphicBuffer> buf = RenderEngineTest::allocateSourceBuffer(1, 1);
        uint32_t texName;
        RenderEngineTest::sRE->genTextures(1, &texName);
        fixture->mTexNames.push_back(texName);

        uint8_t* pixels;
        buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                  reinterpret_cast<void**>(&pixels));

        for (int32_t j = 0; j < buf->getHeight(); j++) {
            uint8_t* iter = pixels + (buf->getStride() * j) * 4;
            for (int32_t i = 0; i < buf->getWidth(); i++) {
                iter[0] = uint8_t(r * 255);
                iter[1] = uint8_t(g * 255);
                iter[2] = uint8_t(b * 255);
                iter[3] = OpaquenessVariant::getAlphaChannel();
                iter += 4;
            }
        }

        buf->unlock();

        layer.source.buffer.buffer = buf;
        layer.source.buffer.textureName = texName;
        OpaquenessVariant::setOpaqueBit(layer);
    }
};

template <typename SourceVariant>
void RenderEngineTest::fillBuffer(half r, half g, half b, half a) {
    renderengine::DisplaySettings settings;
@@ -177,7 +265,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) {

    renderengine::LayerSettings layer;
    layer.geometry.boundaries = fullscreenRect().toFloatRect();
    SourceVariant::fillColor(layer, r, g, b);
    SourceVariant::fillColor(layer, r, g, b, this);
    layer.alpha = a;

    layers.push_back(layer);
@@ -219,7 +307,7 @@ void RenderEngineTest::fillRedOffsetBuffer() {

    renderengine::LayerSettings layer;
    layer.geometry.boundaries = offsetRectAtZero().toFloatRect();
    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f);
    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
    layer.alpha = 1.0f;

    layers.push_back(layer);
@@ -253,19 +341,19 @@ void RenderEngineTest::fillBufferCheckers(mat4 transform) {
    renderengine::LayerSettings layerOne;
    Rect rectOne(0, 0, 1, 1);
    layerOne.geometry.boundaries = rectOne.toFloatRect();
    SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f);
    SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this);
    layerOne.alpha = 1.0f;

    renderengine::LayerSettings layerTwo;
    Rect rectTwo(0, 1, 1, 2);
    layerTwo.geometry.boundaries = rectTwo.toFloatRect();
    SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f);
    SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this);
    layerTwo.alpha = 1.0f;

    renderengine::LayerSettings layerThree;
    Rect rectThree(1, 0, 2, 1);
    layerThree.geometry.boundaries = rectThree.toFloatRect();
    SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f);
    SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this);
    layerThree.alpha = 1.0f;

    layers.push_back(layerOne);
@@ -343,7 +431,7 @@ void RenderEngineTest::fillBufferCheckersRotate270() {
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferLayerTransform() {
void RenderEngineTest::fillBufferWithLayerTransform() {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    // Here logical space is 2x2
@@ -355,13 +443,18 @@ void RenderEngineTest::fillBufferLayerTransform() {
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
    // Translate one pixel diagonally
    layer.geometry.positionTransform = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1);
    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
    layer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
    layer.alpha = 1.0f;

    layers.push_back(layer);

    invokeDraw(settings, layers, mBuffer);
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferLayerTransform() {
    fillBufferWithLayerTransform<SourceVariant>();
    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0, 0);
    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
@@ -370,7 +463,7 @@ void RenderEngineTest::fillBufferLayerTransform() {
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferColorTransform() {
void RenderEngineTest::fillBufferWithColorTransform() {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    settings.clip = Rect(1, 1);
@@ -379,7 +472,7 @@ void RenderEngineTest::fillBufferColorTransform() {

    renderengine::LayerSettings layer;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
    layer.source.solidColor = half3(0.5f, 0.25f, 0.125f);
    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
    layer.alpha = 1.0f;

    // construct a fake color matrix
@@ -388,13 +481,148 @@ void RenderEngineTest::fillBufferColorTransform() {
    // set red channel to red + green
    layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);

    layer.alpha = 1.0f;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();

    layers.push_back(layer);

    invokeDraw(settings, layers, mBuffer);
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferColorTransform() {
    fillBufferWithColorTransform<SourceVariant>();
    expectBufferColor(fullscreenRect(), 191, 0, 0, 255);
}

void RenderEngineTest::fillRedBufferTextureTransform() {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    settings.clip = Rect(1, 1);

    std::vector<renderengine::LayerSettings> layers;

    renderengine::LayerSettings layer;
    // Here will allocate a checker board texture, but transform texture
    // coordinates so that only the upper left is applied.
    sp<GraphicBuffer> buf = allocateSourceBuffer(2, 2);
    uint32_t texName;
    RenderEngineTest::sRE->genTextures(1, &texName);
    this->mTexNames.push_back(texName);

    uint8_t* pixels;
    buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
              reinterpret_cast<void**>(&pixels));
    // Red top left, Green top right, Blue bottom left, Black bottom right
    pixels[0] = 255;
    pixels[1] = 0;
    pixels[2] = 0;
    pixels[3] = 255;
    pixels[4] = 0;
    pixels[5] = 255;
    pixels[6] = 0;
    pixels[7] = 255;
    pixels[8] = 0;
    pixels[9] = 0;
    pixels[10] = 255;
    pixels[11] = 255;
    buf->unlock();

    layer.source.buffer.buffer = buf;
    layer.source.buffer.textureName = texName;
    // Transform coordinates to only be inside the red quadrant.
    layer.source.buffer.textureTransform = mat4::scale(vec4(0.2, 0.2, 1, 1));
    layer.alpha = 1.0f;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();

    layers.push_back(layer);

    invokeDraw(settings, layers, mBuffer);
}

void RenderEngineTest::fillBufferTextureTransform() {
    fillRedBufferTextureTransform();
    expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
}

void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    // Here logical space is 1x1
    settings.clip = Rect(1, 1);

    std::vector<renderengine::LayerSettings> layers;

    renderengine::LayerSettings layer;
    sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
    uint32_t texName;
    RenderEngineTest::sRE->genTextures(1, &texName);
    this->mTexNames.push_back(texName);

    uint8_t* pixels;
    buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
              reinterpret_cast<void**>(&pixels));
    pixels[0] = 255;
    pixels[1] = 0;
    pixels[2] = 0;
    pixels[3] = 255;
    buf->unlock();

    layer.source.buffer.buffer = buf;
    layer.source.buffer.textureName = texName;
    layer.source.buffer.usePremultipliedAlpha = true;
    layer.alpha = 0.5f;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();

    layers.push_back(layer);

    invokeDraw(settings, layers, mBuffer);
}

void RenderEngineTest::fillBufferWithPremultiplyAlpha() {
    fillRedBufferWithPremultiplyAlpha();
    expectBufferColor(fullscreenRect(), 128, 0, 0, 128);
}

void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    // Here logical space is 1x1
    settings.clip = Rect(1, 1);

    std::vector<renderengine::LayerSettings> layers;

    renderengine::LayerSettings layer;
    sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
    uint32_t texName;
    RenderEngineTest::sRE->genTextures(1, &texName);
    this->mTexNames.push_back(texName);

    uint8_t* pixels;
    buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
              reinterpret_cast<void**>(&pixels));
    pixels[0] = 255;
    pixels[1] = 0;
    pixels[2] = 0;
    pixels[3] = 255;
    buf->unlock();

    layer.source.buffer.buffer = buf;
    layer.source.buffer.textureName = texName;
    layer.source.buffer.usePremultipliedAlpha = false;
    layer.alpha = 0.5f;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();

    layers.push_back(layer);

    invokeDraw(settings, layers, mBuffer);
}

void RenderEngineTest::fillBufferWithoutPremultiplyAlpha() {
    fillRedBufferWithoutPremultiplyAlpha();
    expectBufferColor(fullscreenRect(), 128, 0, 0, 64, 1);
}

TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
    drawEmptyLayers();
}
@@ -443,4 +671,104 @@ TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
    fillBufferLayerTransform<ColorSourceVariant>();
}

TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
    fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
    fillGreenBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
    fillBlueBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
    fillRedTransparentBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
    fillBufferPhysicalOffset<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
    fillBufferCheckersRotate0<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
    fillBufferCheckersRotate90<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
    fillBufferCheckersRotate180<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
    fillBufferCheckersRotate270<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
    fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
    fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
    fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
    fillGreenBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
    fillBlueBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
    fillRedTransparentBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
    fillBufferPhysicalOffset<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
    fillBufferCheckersRotate0<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
    fillBufferCheckersRotate90<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
    fillBufferCheckersRotate180<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
    fillBufferCheckersRotate270<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
    fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
    fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_F(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
    fillBufferTextureTransform();
}

TEST_F(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
    fillBufferWithPremultiplyAlpha();
}

TEST_F(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
    fillBufferWithoutPremultiplyAlpha();
}

} // namespace android