You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2035 lines
79 KiB
2035 lines
79 KiB
/*
|
|
* Copyright 2018 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.
|
|
*/
|
|
|
|
#undef LOG_TAG
|
|
#define LOG_TAG "RenderEngineTest"
|
|
|
|
// TODO(b/129481165): remove the #pragma below and fix conversion issues
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wconversion"
|
|
#pragma clang diagnostic ignored "-Wextra"
|
|
|
|
#include <cutils/properties.h>
|
|
#include <gtest/gtest.h>
|
|
#include <renderengine/ExternalTexture.h>
|
|
#include <renderengine/RenderEngine.h>
|
|
#include <sync/sync.h>
|
|
#include <ui/PixelFormat.h>
|
|
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
#include <fstream>
|
|
|
|
#include "../gl/GLESRenderEngine.h"
|
|
#include "../skia/SkiaGLRenderEngine.h"
|
|
#include "../threaded/RenderEngineThreaded.h"
|
|
|
|
constexpr int DEFAULT_DISPLAY_WIDTH = 128;
|
|
constexpr int DEFAULT_DISPLAY_HEIGHT = 256;
|
|
constexpr int DEFAULT_DISPLAY_OFFSET = 64;
|
|
constexpr bool WRITE_BUFFER_TO_FILE_ON_FAILURE = false;
|
|
|
|
namespace android {
|
|
namespace renderengine {
|
|
|
|
class RenderEngineFactory {
|
|
public:
|
|
virtual ~RenderEngineFactory() = default;
|
|
|
|
virtual std::string name() = 0;
|
|
virtual renderengine::RenderEngine::RenderEngineType type() = 0;
|
|
virtual std::unique_ptr<renderengine::RenderEngine> createRenderEngine() = 0;
|
|
virtual std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() {
|
|
return nullptr;
|
|
}
|
|
virtual bool useColorManagement() const = 0;
|
|
};
|
|
|
|
class GLESRenderEngineFactory : public RenderEngineFactory {
|
|
public:
|
|
std::string name() override { return "GLESRenderEngineFactory"; }
|
|
|
|
renderengine::RenderEngine::RenderEngineType type() {
|
|
return renderengine::RenderEngine::RenderEngineType::GLES;
|
|
}
|
|
|
|
std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
|
|
return createGLESRenderEngine();
|
|
}
|
|
|
|
std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() {
|
|
renderengine::RenderEngineCreationArgs reCreationArgs =
|
|
renderengine::RenderEngineCreationArgs::Builder()
|
|
.setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
|
|
.setImageCacheSize(1)
|
|
.setUseColorManagerment(false)
|
|
.setEnableProtectedContext(false)
|
|
.setPrecacheToneMapperShaderOnly(false)
|
|
.setSupportsBackgroundBlur(true)
|
|
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
|
|
.setRenderEngineType(type())
|
|
.setUseColorManagerment(useColorManagement())
|
|
.build();
|
|
return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
|
|
}
|
|
|
|
bool useColorManagement() const override { return false; }
|
|
};
|
|
|
|
class GLESCMRenderEngineFactory : public RenderEngineFactory {
|
|
public:
|
|
std::string name() override { return "GLESCMRenderEngineFactory"; }
|
|
|
|
renderengine::RenderEngine::RenderEngineType type() {
|
|
return renderengine::RenderEngine::RenderEngineType::GLES;
|
|
}
|
|
|
|
std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
|
|
return createGLESRenderEngine();
|
|
}
|
|
|
|
std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() override {
|
|
renderengine::RenderEngineCreationArgs reCreationArgs =
|
|
renderengine::RenderEngineCreationArgs::Builder()
|
|
.setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
|
|
.setImageCacheSize(1)
|
|
.setEnableProtectedContext(false)
|
|
.setPrecacheToneMapperShaderOnly(false)
|
|
.setSupportsBackgroundBlur(true)
|
|
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
|
|
.setRenderEngineType(type())
|
|
.setUseColorManagerment(useColorManagement())
|
|
.build();
|
|
return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
|
|
}
|
|
|
|
bool useColorManagement() const override { return true; }
|
|
};
|
|
|
|
class SkiaGLESRenderEngineFactory : public RenderEngineFactory {
|
|
public:
|
|
std::string name() override { return "SkiaGLRenderEngineFactory"; }
|
|
|
|
renderengine::RenderEngine::RenderEngineType type() {
|
|
return renderengine::RenderEngine::RenderEngineType::SKIA_GL;
|
|
}
|
|
|
|
std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
|
|
renderengine::RenderEngineCreationArgs reCreationArgs =
|
|
renderengine::RenderEngineCreationArgs::Builder()
|
|
.setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
|
|
.setImageCacheSize(1)
|
|
.setEnableProtectedContext(false)
|
|
.setPrecacheToneMapperShaderOnly(false)
|
|
.setSupportsBackgroundBlur(true)
|
|
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
|
|
.setRenderEngineType(type())
|
|
.setUseColorManagerment(useColorManagement())
|
|
.build();
|
|
return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
|
|
}
|
|
|
|
bool useColorManagement() const override { return false; }
|
|
};
|
|
|
|
class SkiaGLESCMRenderEngineFactory : public RenderEngineFactory {
|
|
public:
|
|
std::string name() override { return "SkiaGLCMRenderEngineFactory"; }
|
|
|
|
renderengine::RenderEngine::RenderEngineType type() {
|
|
return renderengine::RenderEngine::RenderEngineType::SKIA_GL;
|
|
}
|
|
|
|
std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
|
|
renderengine::RenderEngineCreationArgs reCreationArgs =
|
|
renderengine::RenderEngineCreationArgs::Builder()
|
|
.setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
|
|
.setImageCacheSize(1)
|
|
.setEnableProtectedContext(false)
|
|
.setPrecacheToneMapperShaderOnly(false)
|
|
.setSupportsBackgroundBlur(true)
|
|
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
|
|
.setRenderEngineType(type())
|
|
.setUseColorManagerment(useColorManagement())
|
|
.build();
|
|
return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
|
|
}
|
|
|
|
bool useColorManagement() const override { return true; }
|
|
};
|
|
|
|
class RenderEngineTest : public ::testing::TestWithParam<std::shared_ptr<RenderEngineFactory>> {
|
|
public:
|
|
std::shared_ptr<renderengine::ExternalTexture> allocateDefaultBuffer() {
|
|
return std::make_shared<
|
|
renderengine::
|
|
ExternalTexture>(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_HW_RENDER |
|
|
GRALLOC_USAGE_HW_TEXTURE,
|
|
"output"),
|
|
*mRE,
|
|
renderengine::ExternalTexture::Usage::READABLE |
|
|
renderengine::ExternalTexture::Usage::WRITEABLE);
|
|
}
|
|
|
|
// Allocates a 1x1 buffer to fill with a solid color
|
|
std::shared_ptr<renderengine::ExternalTexture> allocateSourceBuffer(uint32_t width,
|
|
uint32_t height) {
|
|
return std::make_shared<
|
|
renderengine::
|
|
ExternalTexture>(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"),
|
|
*mRE,
|
|
renderengine::ExternalTexture::Usage::READABLE |
|
|
renderengine::ExternalTexture::Usage::WRITEABLE);
|
|
}
|
|
|
|
RenderEngineTest() {
|
|
const ::testing::TestInfo* const test_info =
|
|
::testing::UnitTest::GetInstance()->current_test_info();
|
|
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
|
|
}
|
|
|
|
~RenderEngineTest() {
|
|
if (WRITE_BUFFER_TO_FILE_ON_FAILURE && ::testing::Test::HasFailure()) {
|
|
writeBufferToFile("/data/texture_out_");
|
|
}
|
|
for (uint32_t texName : mTexNames) {
|
|
mRE->deleteTextures(1, &texName);
|
|
if (mGLESRE != nullptr) {
|
|
EXPECT_FALSE(mGLESRE->isTextureNameKnownForTesting(texName));
|
|
}
|
|
}
|
|
const ::testing::TestInfo* const test_info =
|
|
::testing::UnitTest::GetInstance()->current_test_info();
|
|
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
|
|
}
|
|
|
|
void writeBufferToFile(const char* basename) {
|
|
std::string filename(basename);
|
|
filename.append(::testing::UnitTest::GetInstance()->current_test_info()->name());
|
|
filename.append(".ppm");
|
|
std::ofstream file(filename.c_str(), std::ios::binary);
|
|
if (!file.is_open()) {
|
|
ALOGE("Unable to open file: %s", filename.c_str());
|
|
ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
|
|
"surfaceflinger to write debug images");
|
|
return;
|
|
}
|
|
|
|
uint8_t* pixels;
|
|
mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
|
reinterpret_cast<void**>(&pixels));
|
|
|
|
file << "P6\n";
|
|
file << mBuffer->getBuffer()->getWidth() << "\n";
|
|
file << mBuffer->getBuffer()->getHeight() << "\n";
|
|
file << 255 << "\n";
|
|
|
|
std::vector<uint8_t> outBuffer(mBuffer->getBuffer()->getWidth() *
|
|
mBuffer->getBuffer()->getHeight() * 3);
|
|
auto outPtr = reinterpret_cast<uint8_t*>(outBuffer.data());
|
|
|
|
for (int32_t j = 0; j < mBuffer->getBuffer()->getHeight(); j++) {
|
|
const uint8_t* src = pixels + (mBuffer->getBuffer()->getStride() * j) * 4;
|
|
for (int32_t i = 0; i < mBuffer->getBuffer()->getWidth(); i++) {
|
|
// Only copy R, G and B components
|
|
outPtr[0] = src[0];
|
|
outPtr[1] = src[1];
|
|
outPtr[2] = src[2];
|
|
outPtr += 3;
|
|
|
|
src += 4;
|
|
}
|
|
}
|
|
file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
|
|
mBuffer->getBuffer()->unlock();
|
|
}
|
|
|
|
void expectBufferColor(const Region& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
|
size_t c;
|
|
Rect const* rect = region.getArray(&c);
|
|
for (size_t i = 0; i < c; i++, rect++) {
|
|
expectBufferColor(*rect, r, g, b, a);
|
|
}
|
|
}
|
|
|
|
void expectBufferColor(const Point& point, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
|
|
uint8_t tolerance = 0) {
|
|
expectBufferColor(Rect(point.x, point.y, point.x + 1, point.y + 1), r, g, b, a, tolerance);
|
|
}
|
|
|
|
void expectBufferColor(const Rect& rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
|
|
uint8_t tolerance = 0) {
|
|
auto colorCompare = [tolerance](const uint8_t* colorA, const uint8_t* colorB) {
|
|
auto colorBitCompare = [tolerance](uint8_t a, uint8_t b) {
|
|
uint8_t tmp = a >= b ? a - b : b - a;
|
|
return tmp <= tolerance;
|
|
};
|
|
return std::equal(colorA, colorA + 4, colorB, colorBitCompare);
|
|
};
|
|
|
|
expectBufferColor(rect, r, g, b, a, colorCompare);
|
|
}
|
|
|
|
void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
|
|
std::function<bool(const uint8_t* a, const uint8_t* b)> colorCompare) {
|
|
uint8_t* pixels;
|
|
mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
|
reinterpret_cast<void**>(&pixels));
|
|
int32_t maxFails = 10;
|
|
int32_t fails = 0;
|
|
for (int32_t j = 0; j < region.getHeight(); j++) {
|
|
const uint8_t* src = pixels +
|
|
(mBuffer->getBuffer()->getStride() * (region.top + j) + region.left) * 4;
|
|
for (int32_t i = 0; i < region.getWidth(); i++) {
|
|
const uint8_t expected[4] = {r, g, b, a};
|
|
bool equal = colorCompare(src, expected);
|
|
EXPECT_TRUE(equal)
|
|
<< GetParam()->name().c_str() << ": "
|
|
<< "pixel @ (" << region.left + i << ", " << region.top + j << "): "
|
|
<< "expected (" << static_cast<uint32_t>(r) << ", "
|
|
<< static_cast<uint32_t>(g) << ", " << static_cast<uint32_t>(b) << ", "
|
|
<< static_cast<uint32_t>(a) << "), "
|
|
<< "got (" << static_cast<uint32_t>(src[0]) << ", "
|
|
<< static_cast<uint32_t>(src[1]) << ", " << static_cast<uint32_t>(src[2])
|
|
<< ", " << static_cast<uint32_t>(src[3]) << ")";
|
|
src += 4;
|
|
if (!equal && ++fails >= maxFails) {
|
|
break;
|
|
}
|
|
}
|
|
if (fails >= maxFails) {
|
|
break;
|
|
}
|
|
}
|
|
mBuffer->getBuffer()->unlock();
|
|
}
|
|
|
|
void expectAlpha(const Rect& rect, uint8_t a) {
|
|
auto colorCompare = [](const uint8_t* colorA, const uint8_t* colorB) {
|
|
return colorA[3] == colorB[3];
|
|
};
|
|
expectBufferColor(rect, 0.0f /* r */, 0.0f /*g */, 0.0f /* b */, a, colorCompare);
|
|
}
|
|
|
|
void expectShadowColor(const renderengine::LayerSettings& castingLayer,
|
|
const renderengine::ShadowSettings& shadow, const ubyte4& casterColor,
|
|
const ubyte4& backgroundColor) {
|
|
const Rect casterRect(castingLayer.geometry.boundaries);
|
|
Region casterRegion = Region(casterRect);
|
|
const float casterCornerRadius = castingLayer.geometry.roundedCornersRadius;
|
|
if (casterCornerRadius > 0.0f) {
|
|
// ignore the corners if a corner radius is set
|
|
Rect cornerRect(casterCornerRadius, casterCornerRadius);
|
|
casterRegion.subtractSelf(cornerRect.offsetTo(casterRect.left, casterRect.top));
|
|
casterRegion.subtractSelf(
|
|
cornerRect.offsetTo(casterRect.right - casterCornerRadius, casterRect.top));
|
|
casterRegion.subtractSelf(
|
|
cornerRect.offsetTo(casterRect.left, casterRect.bottom - casterCornerRadius));
|
|
casterRegion.subtractSelf(cornerRect.offsetTo(casterRect.right - casterCornerRadius,
|
|
casterRect.bottom - casterCornerRadius));
|
|
}
|
|
|
|
const float shadowInset = shadow.length * -1.0f;
|
|
const Rect casterWithShadow =
|
|
Rect(casterRect).inset(shadowInset, shadowInset, shadowInset, shadowInset);
|
|
const Region shadowRegion = Region(casterWithShadow).subtractSelf(casterRect);
|
|
const Region backgroundRegion = Region(fullscreenRect()).subtractSelf(casterWithShadow);
|
|
|
|
// verify casting layer
|
|
expectBufferColor(casterRegion, casterColor.r, casterColor.g, casterColor.b, casterColor.a);
|
|
|
|
// verify shadows by testing just the alpha since its difficult to validate the shadow color
|
|
size_t c;
|
|
Rect const* r = shadowRegion.getArray(&c);
|
|
for (size_t i = 0; i < c; i++, r++) {
|
|
expectAlpha(*r, 255);
|
|
}
|
|
|
|
// verify background
|
|
expectBufferColor(backgroundRegion, backgroundColor.r, backgroundColor.g, backgroundColor.b,
|
|
backgroundColor.a);
|
|
}
|
|
|
|
void expectShadowColorWithoutCaster(const FloatRect& casterBounds,
|
|
const renderengine::ShadowSettings& shadow,
|
|
const ubyte4& backgroundColor) {
|
|
const float shadowInset = shadow.length * -1.0f;
|
|
const Rect casterRect(casterBounds);
|
|
const Rect shadowRect =
|
|
Rect(casterRect).inset(shadowInset, shadowInset, shadowInset, shadowInset);
|
|
|
|
const Region backgroundRegion =
|
|
Region(fullscreenRect()).subtractSelf(casterRect).subtractSelf(shadowRect);
|
|
|
|
expectAlpha(shadowRect, 255);
|
|
// (0, 0, 0) fill on the bounds of the layer should be ignored.
|
|
expectBufferColor(casterRect, 255, 255, 255, 255, 254);
|
|
|
|
// verify background
|
|
expectBufferColor(backgroundRegion, backgroundColor.r, backgroundColor.g, backgroundColor.b,
|
|
backgroundColor.a);
|
|
}
|
|
|
|
static renderengine::ShadowSettings getShadowSettings(const vec2& casterPos, float shadowLength,
|
|
bool casterIsTranslucent) {
|
|
renderengine::ShadowSettings shadow;
|
|
shadow.ambientColor = {0.0f, 0.0f, 0.0f, 0.039f};
|
|
shadow.spotColor = {0.0f, 0.0f, 0.0f, 0.19f};
|
|
shadow.lightPos = vec3(casterPos.x, casterPos.y, 0);
|
|
shadow.lightRadius = 0.0f;
|
|
shadow.length = shadowLength;
|
|
shadow.casterIsTranslucent = casterIsTranslucent;
|
|
return shadow;
|
|
}
|
|
|
|
static Rect fullscreenRect() { return Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); }
|
|
|
|
static Rect offsetRect() {
|
|
return Rect(DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT);
|
|
}
|
|
|
|
static Rect offsetRectAtZero() {
|
|
return Rect(DEFAULT_DISPLAY_WIDTH - DEFAULT_DISPLAY_OFFSET,
|
|
DEFAULT_DISPLAY_HEIGHT - DEFAULT_DISPLAY_OFFSET);
|
|
}
|
|
|
|
void invokeDraw(renderengine::DisplaySettings settings,
|
|
std::vector<const renderengine::LayerSettings*> layers) {
|
|
base::unique_fd fence;
|
|
status_t status =
|
|
mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence);
|
|
|
|
int fd = fence.release();
|
|
if (fd >= 0) {
|
|
sync_wait(fd, -1);
|
|
close(fd);
|
|
}
|
|
|
|
ASSERT_EQ(NO_ERROR, status);
|
|
if (layers.size() > 0 && mGLESRE != nullptr) {
|
|
ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId()));
|
|
}
|
|
}
|
|
|
|
void drawEmptyLayers() {
|
|
renderengine::DisplaySettings settings;
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void fillBuffer(half r, half g, half b, half a);
|
|
|
|
template <typename SourceVariant>
|
|
void fillRedBuffer();
|
|
|
|
template <typename SourceVariant>
|
|
void fillGreenBuffer();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBlueBuffer();
|
|
|
|
template <typename SourceVariant>
|
|
void fillRedTransparentBuffer();
|
|
|
|
template <typename SourceVariant>
|
|
void fillRedOffsetBuffer();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferPhysicalOffset();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferCheckers(uint32_t rotation);
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferCheckersRotate0();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferCheckersRotate90();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferCheckersRotate180();
|
|
|
|
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();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferWithColorTransformZeroLayerAlpha();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferColorTransformZeroLayerAlpha();
|
|
|
|
template <typename SourceVariant>
|
|
void fillRedBufferWithRoundedCorners();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferWithRoundedCorners();
|
|
|
|
template <typename SourceVariant>
|
|
void fillBufferAndBlurBackground();
|
|
|
|
template <typename SourceVariant>
|
|
void fillSmallLayerAndBlurBackground();
|
|
|
|
template <typename SourceVariant>
|
|
void overlayCorners();
|
|
|
|
void fillRedBufferTextureTransform();
|
|
|
|
void fillBufferTextureTransform();
|
|
|
|
void fillRedBufferWithPremultiplyAlpha();
|
|
|
|
void fillBufferWithPremultiplyAlpha();
|
|
|
|
void fillRedBufferWithoutPremultiplyAlpha();
|
|
|
|
void fillBufferWithoutPremultiplyAlpha();
|
|
|
|
void fillGreenColorBufferThenClearRegion();
|
|
|
|
void clearLeftRegion();
|
|
|
|
void clearRegion();
|
|
|
|
template <typename SourceVariant>
|
|
void drawShadow(const renderengine::LayerSettings& castingLayer,
|
|
const renderengine::ShadowSettings& shadow, const ubyte4& casterColor,
|
|
const ubyte4& backgroundColor);
|
|
|
|
void drawShadowWithoutCaster(const FloatRect& castingBounds,
|
|
const renderengine::ShadowSettings& shadow,
|
|
const ubyte4& backgroundColor);
|
|
|
|
void initializeRenderEngine();
|
|
|
|
std::unique_ptr<renderengine::RenderEngine> mRE;
|
|
std::shared_ptr<renderengine::ExternalTexture> mBuffer;
|
|
// GLESRenderEngine for testing GLES-specific behavior.
|
|
// Owened by mRE, but this is downcasted.
|
|
renderengine::gl::GLESRenderEngine* mGLESRE = nullptr;
|
|
|
|
std::vector<uint32_t> mTexNames;
|
|
};
|
|
|
|
void RenderEngineTest::initializeRenderEngine() {
|
|
const auto& renderEngineFactory = GetParam();
|
|
if (renderEngineFactory->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
|
|
// Only GLESRenderEngine exposes test-only methods. Provide a pointer to the
|
|
// GLESRenderEngine if we're using it so that we don't need to dynamic_cast
|
|
// every time.
|
|
std::unique_ptr<renderengine::gl::GLESRenderEngine> renderEngine =
|
|
renderEngineFactory->createGLESRenderEngine();
|
|
mGLESRE = renderEngine.get();
|
|
mRE = std::move(renderEngine);
|
|
} else {
|
|
mRE = renderEngineFactory->createRenderEngine();
|
|
}
|
|
mBuffer = allocateDefaultBuffer();
|
|
}
|
|
|
|
struct ColorSourceVariant {
|
|
static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
|
|
RenderEngineTest* /*fixture*/) {
|
|
layer.source.solidColor = half3(r, g, b);
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
}
|
|
};
|
|
|
|
struct RelaxOpaqueBufferVariant {
|
|
static void setOpaqueBit(renderengine::LayerSettings& layer) {
|
|
layer.source.buffer.isOpaque = false;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
}
|
|
|
|
static uint8_t getAlphaChannel() { return 255; }
|
|
};
|
|
|
|
struct ForceOpaqueBufferVariant {
|
|
static void setOpaqueBit(renderengine::LayerSettings& layer) {
|
|
layer.source.buffer.isOpaque = true;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
}
|
|
|
|
static uint8_t getAlphaChannel() {
|
|
// The isOpaque bit will override the alpha channel, so this should be
|
|
// arbitrary.
|
|
return 50;
|
|
}
|
|
};
|
|
|
|
template <typename OpaquenessVariant>
|
|
struct BufferSourceVariant {
|
|
static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
|
|
RenderEngineTest* fixture) {
|
|
const auto buf = fixture->allocateSourceBuffer(1, 1);
|
|
uint32_t texName;
|
|
fixture->mRE->genTextures(1, &texName);
|
|
fixture->mTexNames.push_back(texName);
|
|
|
|
uint8_t* pixels;
|
|
buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
|
reinterpret_cast<void**>(&pixels));
|
|
|
|
for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) {
|
|
uint8_t* iter = pixels + (buf->getBuffer()->getStride() * j) * 4;
|
|
for (int32_t i = 0; i < buf->getBuffer()->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->getBuffer()->unlock();
|
|
|
|
layer.source.buffer.buffer = buf;
|
|
layer.source.buffer.textureName = texName;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
OpaquenessVariant::setOpaqueBit(layer);
|
|
}
|
|
};
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBuffer(half r, half g, half b, half a) {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
layer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
SourceVariant::fillColor(layer, r, g, b, this);
|
|
layer.alpha = a;
|
|
|
|
layers.push_back(&layer);
|
|
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillRedBuffer() {
|
|
fillBuffer<SourceVariant>(1.0f, 0.0f, 0.0f, 1.0f);
|
|
expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillGreenBuffer() {
|
|
fillBuffer<SourceVariant>(0.0f, 1.0f, 0.0f, 1.0f);
|
|
expectBufferColor(fullscreenRect(), 0, 255, 0, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBlueBuffer() {
|
|
fillBuffer<SourceVariant>(0.0f, 0.0f, 1.0f, 1.0f);
|
|
expectBufferColor(fullscreenRect(), 0, 0, 255, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillRedTransparentBuffer() {
|
|
fillBuffer<SourceVariant>(1.0f, 0.0f, 0.0f, .2f);
|
|
expectBufferColor(fullscreenRect(), 51, 0, 0, 51);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillRedOffsetBuffer() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = offsetRect();
|
|
settings.clip = offsetRectAtZero();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
layer.geometry.boundaries = offsetRectAtZero().toFloatRect();
|
|
SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
|
|
layer.alpha = 1.0f;
|
|
|
|
layers.push_back(&layer);
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferPhysicalOffset() {
|
|
fillRedOffsetBuffer<SourceVariant>();
|
|
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT),
|
|
255, 0, 0, 255);
|
|
Rect offsetRegionLeft(DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_HEIGHT);
|
|
Rect offsetRegionTop(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_OFFSET);
|
|
|
|
expectBufferColor(offsetRegionLeft, 0, 0, 0, 0);
|
|
expectBufferColor(offsetRegionTop, 0, 0, 0, 0);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) {
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
// Here logical space is 2x2
|
|
settings.clip = Rect(2, 2);
|
|
settings.orientation = orientationFlag;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layerOne;
|
|
layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
Rect rectOne(0, 0, 1, 1);
|
|
layerOne.geometry.boundaries = rectOne.toFloatRect();
|
|
SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this);
|
|
layerOne.alpha = 1.0f;
|
|
|
|
renderengine::LayerSettings layerTwo;
|
|
layerTwo.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
Rect rectTwo(0, 1, 1, 2);
|
|
layerTwo.geometry.boundaries = rectTwo.toFloatRect();
|
|
SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this);
|
|
layerTwo.alpha = 1.0f;
|
|
|
|
renderengine::LayerSettings layerThree;
|
|
layerThree.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
Rect rectThree(1, 0, 2, 1);
|
|
layerThree.geometry.boundaries = rectThree.toFloatRect();
|
|
SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this);
|
|
layerThree.alpha = 1.0f;
|
|
|
|
layers.push_back(&layerOne);
|
|
layers.push_back(&layerTwo);
|
|
layers.push_back(&layerThree);
|
|
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferCheckersRotate0() {
|
|
fillBufferCheckers<SourceVariant>(ui::Transform::ROT_0);
|
|
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 255, 0, 0,
|
|
255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT / 2),
|
|
0, 0, 255, 255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 0, 0);
|
|
expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
|
|
DEFAULT_DISPLAY_HEIGHT),
|
|
0, 255, 0, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferCheckersRotate90() {
|
|
fillBufferCheckers<SourceVariant>(ui::Transform::ROT_90);
|
|
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 255, 0,
|
|
255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT / 2),
|
|
255, 0, 0, 255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 255, 255);
|
|
expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
|
|
DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 0, 0);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferCheckersRotate180() {
|
|
fillBufferCheckers<SourceVariant>(ui::Transform::ROT_180);
|
|
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0,
|
|
0);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT / 2),
|
|
0, 255, 0, 255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
255, 0, 0, 255);
|
|
expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
|
|
DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 255, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferCheckersRotate270() {
|
|
fillBufferCheckers<SourceVariant>(ui::Transform::ROT_270);
|
|
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 255,
|
|
255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT / 2),
|
|
0, 0, 0, 0);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 255, 0, 255);
|
|
expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
|
|
DEFAULT_DISPLAY_HEIGHT),
|
|
255, 0, 0, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferWithLayerTransform() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
// Here logical space is 2x2
|
|
settings.clip = Rect(2, 2);
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
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);
|
|
}
|
|
|
|
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,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
255, 0, 0, 255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferWithColorTransform() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = Rect(1, 1);
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
|
|
SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
|
|
layer.alpha = 1.0f;
|
|
|
|
// construct a fake color matrix
|
|
// annihilate green and blue channels
|
|
settings.colorTransform = mat4::scale(vec4(0.9f, 0, 0, 1));
|
|
// 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);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferColorTransform() {
|
|
fillBufferWithColorTransform<SourceVariant>();
|
|
expectBufferColor(fullscreenRect(), 172, 0, 0, 255, 1);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = Rect(1, 1);
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
|
|
SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
|
|
layer.alpha = 0;
|
|
|
|
// construct a fake color matrix
|
|
// simple inverse color
|
|
settings.colorTransform = mat4(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 1, 1, 1, 1);
|
|
|
|
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
|
|
|
|
layers.push_back(&layer);
|
|
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferColorTransformZeroLayerAlpha() {
|
|
fillBufferWithColorTransformZeroLayerAlpha<SourceVariant>();
|
|
expectBufferColor(fullscreenRect(), 0, 0, 0, 0);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillRedBufferWithRoundedCorners() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
layer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
layer.geometry.roundedCornersRadius = 5.0f;
|
|
layer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
|
|
SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
|
|
layer.alpha = 1.0f;
|
|
|
|
layers.push_back(&layer);
|
|
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferWithRoundedCorners() {
|
|
fillRedBufferWithRoundedCorners<SourceVariant>();
|
|
// Corners should be ignored...
|
|
expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 0);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, 0, DEFAULT_DISPLAY_WIDTH, 1), 0, 0, 0, 0);
|
|
expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT - 1, 1, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 0, 0);
|
|
// ...And the non-rounded portion should be red.
|
|
// Other pixels may be anti-aliased, so let's not check those.
|
|
expectBufferColor(Rect(5, 5, DEFAULT_DISPLAY_WIDTH - 5, DEFAULT_DISPLAY_HEIGHT - 5), 255, 0, 0,
|
|
255);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillBufferAndBlurBackground() {
|
|
auto blurRadius = 50;
|
|
auto center = DEFAULT_DISPLAY_WIDTH / 2;
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings backgroundLayer;
|
|
backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
SourceVariant::fillColor(backgroundLayer, 0.0f, 1.0f, 0.0f, this);
|
|
backgroundLayer.alpha = 1.0f;
|
|
layers.push_back(&backgroundLayer);
|
|
|
|
renderengine::LayerSettings leftLayer;
|
|
leftLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
leftLayer.geometry.boundaries =
|
|
Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT).toFloatRect();
|
|
SourceVariant::fillColor(leftLayer, 1.0f, 0.0f, 0.0f, this);
|
|
leftLayer.alpha = 1.0f;
|
|
layers.push_back(&leftLayer);
|
|
|
|
renderengine::LayerSettings blurLayer;
|
|
blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
blurLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
blurLayer.backgroundBlurRadius = blurRadius;
|
|
SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this);
|
|
blurLayer.alpha = 0;
|
|
layers.push_back(&blurLayer);
|
|
|
|
invokeDraw(settings, layers);
|
|
|
|
// solid color
|
|
expectBufferColor(Rect(0, 0, 1, 1), 255, 0, 0, 255, 0 /* tolerance */);
|
|
|
|
if (mRE->supportsBackgroundBlur()) {
|
|
// blurred color (downsampling should result in the center color being close to 128)
|
|
expectBufferColor(Rect(center - 1, center - 5, center + 1, center + 5), 128, 128, 0, 255,
|
|
50 /* tolerance */);
|
|
}
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::fillSmallLayerAndBlurBackground() {
|
|
auto blurRadius = 50;
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings backgroundLayer;
|
|
backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
SourceVariant::fillColor(backgroundLayer, 1.0f, 0.0f, 0.0f, this);
|
|
backgroundLayer.alpha = 1.0f;
|
|
layers.push_back(&backgroundLayer);
|
|
|
|
renderengine::LayerSettings blurLayer;
|
|
blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
blurLayer.geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f);
|
|
blurLayer.backgroundBlurRadius = blurRadius;
|
|
SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this);
|
|
blurLayer.alpha = 0;
|
|
layers.push_back(&blurLayer);
|
|
|
|
invokeDraw(settings, layers);
|
|
|
|
// Give a generous tolerance - the blur rectangle is very small and this test is
|
|
// mainly concerned with ensuring that there's no device failure.
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), 255, 0, 0, 255,
|
|
40 /* tolerance */);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::overlayCorners() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layersFirst;
|
|
|
|
renderengine::LayerSettings layerOne;
|
|
layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
layerOne.geometry.boundaries =
|
|
FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH / 3.0, DEFAULT_DISPLAY_HEIGHT / 3.0);
|
|
SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this);
|
|
layerOne.alpha = 0.2;
|
|
|
|
layersFirst.push_back(&layerOne);
|
|
invokeDraw(settings, layersFirst);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 0, 0);
|
|
|
|
std::vector<const renderengine::LayerSettings*> layersSecond;
|
|
renderengine::LayerSettings layerTwo;
|
|
layerTwo.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
layerTwo.geometry.boundaries =
|
|
FloatRect(DEFAULT_DISPLAY_WIDTH / 3.0, DEFAULT_DISPLAY_HEIGHT / 3.0,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
|
|
SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this);
|
|
layerTwo.alpha = 1.0f;
|
|
|
|
layersSecond.push_back(&layerTwo);
|
|
invokeDraw(settings, layersSecond);
|
|
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 255, 0, 255);
|
|
}
|
|
|
|
void RenderEngineTest::fillRedBufferTextureTransform() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = Rect(1, 1);
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
// Here will allocate a checker board texture, but transform texture
|
|
// coordinates so that only the upper left is applied.
|
|
const auto buf = allocateSourceBuffer(2, 2);
|
|
uint32_t texName;
|
|
RenderEngineTest::mRE->genTextures(1, &texName);
|
|
this->mTexNames.push_back(texName);
|
|
|
|
uint8_t* pixels;
|
|
buf->getBuffer()->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->getBuffer()->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);
|
|
}
|
|
|
|
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<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
const auto buf = allocateSourceBuffer(1, 1);
|
|
uint32_t texName;
|
|
RenderEngineTest::mRE->genTextures(1, &texName);
|
|
this->mTexNames.push_back(texName);
|
|
|
|
uint8_t* pixels;
|
|
buf->getBuffer()->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->getBuffer()->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);
|
|
}
|
|
|
|
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<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings layer;
|
|
const auto buf = allocateSourceBuffer(1, 1);
|
|
uint32_t texName;
|
|
RenderEngineTest::mRE->genTextures(1, &texName);
|
|
this->mTexNames.push_back(texName);
|
|
|
|
uint8_t* pixels;
|
|
buf->getBuffer()->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->getBuffer()->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);
|
|
}
|
|
|
|
void RenderEngineTest::fillBufferWithoutPremultiplyAlpha() {
|
|
fillRedBufferWithoutPremultiplyAlpha();
|
|
expectBufferColor(fullscreenRect(), 128, 0, 0, 128, 1);
|
|
}
|
|
|
|
void RenderEngineTest::clearLeftRegion() {
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
// Here logical space is 4x4
|
|
settings.clip = Rect(4, 4);
|
|
settings.clearRegion = Region(Rect(2, 4));
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
// fake layer, without bounds should not render anything
|
|
renderengine::LayerSettings layer;
|
|
layers.push_back(&layer);
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
void RenderEngineTest::clearRegion() {
|
|
// Reuse mBuffer
|
|
clearLeftRegion();
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 255);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
|
|
DEFAULT_DISPLAY_HEIGHT),
|
|
0, 0, 0, 0);
|
|
}
|
|
|
|
template <typename SourceVariant>
|
|
void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLayer,
|
|
const renderengine::ShadowSettings& shadow,
|
|
const ubyte4& casterColor, const ubyte4& backgroundColor) {
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
// add background layer
|
|
renderengine::LayerSettings bgLayer;
|
|
bgLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
bgLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f,
|
|
backgroundColor.b / 255.0f, this);
|
|
bgLayer.alpha = backgroundColor.a / 255.0f;
|
|
layers.push_back(&bgLayer);
|
|
|
|
// add shadow layer
|
|
renderengine::LayerSettings shadowLayer;
|
|
shadowLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
shadowLayer.geometry.boundaries = castingLayer.geometry.boundaries;
|
|
shadowLayer.alpha = castingLayer.alpha;
|
|
shadowLayer.shadow = shadow;
|
|
layers.push_back(&shadowLayer);
|
|
|
|
// add layer casting the shadow
|
|
renderengine::LayerSettings layer = castingLayer;
|
|
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
SourceVariant::fillColor(layer, casterColor.r / 255.0f, casterColor.g / 255.0f,
|
|
casterColor.b / 255.0f, this);
|
|
layers.push_back(&layer);
|
|
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds,
|
|
const renderengine::ShadowSettings& shadow,
|
|
const ubyte4& backgroundColor) {
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
// add background layer
|
|
renderengine::LayerSettings bgLayer;
|
|
bgLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
bgLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f,
|
|
backgroundColor.b / 255.0f, this);
|
|
bgLayer.alpha = backgroundColor.a / 255.0f;
|
|
layers.push_back(&bgLayer);
|
|
|
|
// add shadow layer
|
|
renderengine::LayerSettings shadowLayer;
|
|
shadowLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
shadowLayer.geometry.boundaries = castingBounds;
|
|
shadowLayer.skipContentDraw = true;
|
|
shadowLayer.alpha = 1.0f;
|
|
ColorSourceVariant::fillColor(shadowLayer, 0, 0, 0, this);
|
|
shadowLayer.shadow = shadow;
|
|
layers.push_back(&shadowLayer);
|
|
|
|
invokeDraw(settings, layers);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(PerRenderEngineType, RenderEngineTest,
|
|
testing::Values(std::make_shared<GLESRenderEngineFactory>(),
|
|
std::make_shared<GLESCMRenderEngineFactory>(),
|
|
std::make_shared<SkiaGLESRenderEngineFactory>(),
|
|
std::make_shared<SkiaGLESCMRenderEngineFactory>()));
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) {
|
|
initializeRenderEngine();
|
|
drawEmptyLayers();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) {
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
// 255, 255, 255, 255 is full opaque white.
|
|
const ubyte4 backgroundColor(255.f, 255.f, 255.f, 255.f);
|
|
// Create layer with given color.
|
|
renderengine::LayerSettings bgLayer;
|
|
bgLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
bgLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
bgLayer.source.solidColor = half3(backgroundColor.r / 255.0f, backgroundColor.g / 255.0f,
|
|
backgroundColor.b / 255.0f);
|
|
bgLayer.alpha = backgroundColor.a / 255.0f;
|
|
// Transform the red color.
|
|
bgLayer.colorTransform = mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
layers.push_back(&bgLayer);
|
|
|
|
invokeDraw(settings, layers);
|
|
|
|
// Expect to see full opaque pixel (with inverted red from the transform).
|
|
expectBufferColor(Rect(0, 0, 10, 10), 0.f, backgroundColor.g, backgroundColor.b,
|
|
backgroundColor.a);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) {
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
renderengine::LayerSettings layer;
|
|
layer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
|
|
layers.push_back(&layer);
|
|
base::unique_fd fence;
|
|
status_t status = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd(), &fence);
|
|
|
|
ASSERT_EQ(BAD_VALUE, status);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_nullOutputFence) {
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
renderengine::LayerSettings layer;
|
|
layer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
|
|
layer.alpha = 1.0;
|
|
layers.push_back(&layer);
|
|
|
|
status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr);
|
|
ASSERT_EQ(NO_ERROR, status);
|
|
expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) {
|
|
const auto& renderEngineFactory = GetParam();
|
|
|
|
if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
|
|
// GLES-specific test
|
|
return;
|
|
}
|
|
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
renderengine::LayerSettings layer;
|
|
layer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
|
|
layer.alpha = 1.0;
|
|
layers.push_back(&layer);
|
|
|
|
status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr);
|
|
ASSERT_EQ(NO_ERROR, status);
|
|
ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId()));
|
|
expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_colorSource) {
|
|
initializeRenderEngine();
|
|
fillRedBuffer<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_colorSource) {
|
|
initializeRenderEngine();
|
|
fillGreenBuffer<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBlueBuffer<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_colorSource) {
|
|
initializeRenderEngine();
|
|
fillRedTransparentBuffer<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferPhysicalOffset<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate0<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate90<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate180<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate270<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferLayerTransform<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferColorTransform<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferWithRoundedCorners<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferColorTransformZeroLayerAlpha<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_colorSource) {
|
|
initializeRenderEngine();
|
|
fillBufferAndBlurBackground<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillSmallLayerAndBlurBackground_colorSource) {
|
|
initializeRenderEngine();
|
|
fillSmallLayerAndBlurBackground<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_overlayCorners_colorSource) {
|
|
initializeRenderEngine();
|
|
overlayCorners<ColorSourceVariant>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillGreenBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBlueBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillRedTransparentBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferPhysicalOffset<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate0<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate90<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate180<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate270<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferColorTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferColorTransformZeroLayerAlpha<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferAndBlurBackground<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillSmallLayerAndBlurBackground_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
fillSmallLayerAndBlurBackground<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_overlayCorners_opaqueBufferSource) {
|
|
initializeRenderEngine();
|
|
overlayCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillGreenBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBlueBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillRedTransparentBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferPhysicalOffset<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate0<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate90<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate180<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferCheckersRotate270<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferColorTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferColorTransformZeroLayerAlpha<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillBufferAndBlurBackground<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillSmallLayerAndBlurBackground_bufferSource) {
|
|
initializeRenderEngine();
|
|
fillSmallLayerAndBlurBackground<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_overlayCorners_bufferSource) {
|
|
initializeRenderEngine();
|
|
overlayCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
|
|
initializeRenderEngine();
|
|
fillBufferTextureTransform();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
|
|
initializeRenderEngine();
|
|
fillBufferWithPremultiplyAlpha();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
|
|
initializeRenderEngine();
|
|
fillBufferWithoutPremultiplyAlpha();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_clearRegion) {
|
|
initializeRenderEngine();
|
|
clearRegion();
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) {
|
|
initializeRenderEngine();
|
|
|
|
const ubyte4 backgroundColor(255, 255, 255, 255);
|
|
const float shadowLength = 5.0f;
|
|
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
|
|
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
|
|
renderengine::ShadowSettings settings =
|
|
getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength,
|
|
false /* casterIsTranslucent */);
|
|
|
|
drawShadowWithoutCaster(casterBounds.toFloatRect(), settings, backgroundColor);
|
|
expectShadowColorWithoutCaster(casterBounds.toFloatRect(), settings, backgroundColor);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterLayerMinSize) {
|
|
initializeRenderEngine();
|
|
|
|
const ubyte4 casterColor(255, 0, 0, 255);
|
|
const ubyte4 backgroundColor(255, 255, 255, 255);
|
|
const float shadowLength = 5.0f;
|
|
Rect casterBounds(1, 1);
|
|
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
|
|
renderengine::LayerSettings castingLayer;
|
|
castingLayer.geometry.boundaries = casterBounds.toFloatRect();
|
|
castingLayer.alpha = 1.0f;
|
|
renderengine::ShadowSettings settings =
|
|
getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength,
|
|
false /* casterIsTranslucent */);
|
|
|
|
drawShadow<ColorSourceVariant>(castingLayer, settings, casterColor, backgroundColor);
|
|
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterColorLayer) {
|
|
initializeRenderEngine();
|
|
|
|
const ubyte4 casterColor(255, 0, 0, 255);
|
|
const ubyte4 backgroundColor(255, 255, 255, 255);
|
|
const float shadowLength = 5.0f;
|
|
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
|
|
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
|
|
renderengine::LayerSettings castingLayer;
|
|
castingLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
castingLayer.geometry.boundaries = casterBounds.toFloatRect();
|
|
castingLayer.alpha = 1.0f;
|
|
renderengine::ShadowSettings settings =
|
|
getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength,
|
|
false /* casterIsTranslucent */);
|
|
|
|
drawShadow<ColorSourceVariant>(castingLayer, settings, casterColor, backgroundColor);
|
|
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterOpaqueBufferLayer) {
|
|
initializeRenderEngine();
|
|
|
|
const ubyte4 casterColor(255, 0, 0, 255);
|
|
const ubyte4 backgroundColor(255, 255, 255, 255);
|
|
const float shadowLength = 5.0f;
|
|
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
|
|
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
|
|
renderengine::LayerSettings castingLayer;
|
|
castingLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
castingLayer.geometry.boundaries = casterBounds.toFloatRect();
|
|
castingLayer.alpha = 1.0f;
|
|
renderengine::ShadowSettings settings =
|
|
getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength,
|
|
false /* casterIsTranslucent */);
|
|
|
|
drawShadow<BufferSourceVariant<ForceOpaqueBufferVariant>>(castingLayer, settings, casterColor,
|
|
backgroundColor);
|
|
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillShadow_casterWithRoundedCorner) {
|
|
initializeRenderEngine();
|
|
|
|
const ubyte4 casterColor(255, 0, 0, 255);
|
|
const ubyte4 backgroundColor(255, 255, 255, 255);
|
|
const float shadowLength = 5.0f;
|
|
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
|
|
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
|
|
renderengine::LayerSettings castingLayer;
|
|
castingLayer.geometry.boundaries = casterBounds.toFloatRect();
|
|
castingLayer.geometry.roundedCornersRadius = 3.0f;
|
|
castingLayer.geometry.roundedCornersCrop = casterBounds.toFloatRect();
|
|
castingLayer.alpha = 1.0f;
|
|
renderengine::ShadowSettings settings =
|
|
getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength,
|
|
false /* casterIsTranslucent */);
|
|
|
|
drawShadow<BufferSourceVariant<ForceOpaqueBufferVariant>>(castingLayer, settings, casterColor,
|
|
backgroundColor);
|
|
expectShadowColor(castingLayer, settings, casterColor, backgroundColor);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) {
|
|
initializeRenderEngine();
|
|
|
|
const ubyte4 casterColor(255, 0, 0, 255);
|
|
const ubyte4 backgroundColor(255, 255, 255, 255);
|
|
const float shadowLength = 5.0f;
|
|
Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f);
|
|
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
|
|
renderengine::LayerSettings castingLayer;
|
|
castingLayer.geometry.boundaries = casterBounds.toFloatRect();
|
|
castingLayer.alpha = 0.5f;
|
|
renderengine::ShadowSettings settings =
|
|
getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength,
|
|
true /* casterIsTranslucent */);
|
|
|
|
drawShadow<BufferSourceVariant<RelaxOpaqueBufferVariant>>(castingLayer, settings, casterColor,
|
|
backgroundColor);
|
|
|
|
// verify only the background since the shadow will draw behind the caster
|
|
const float shadowInset = settings.length * -1.0f;
|
|
const Rect casterWithShadow =
|
|
Rect(casterBounds).inset(shadowInset, shadowInset, shadowInset, shadowInset);
|
|
const Region backgroundRegion = Region(fullscreenRect()).subtractSelf(casterWithShadow);
|
|
expectBufferColor(backgroundRegion, backgroundColor.r, backgroundColor.g, backgroundColor.b,
|
|
backgroundColor.a);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
renderengine::LayerSettings layer;
|
|
layer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
|
|
layer.alpha = 1.0;
|
|
layers.push_back(&layer);
|
|
|
|
base::unique_fd fenceOne;
|
|
mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fenceOne);
|
|
base::unique_fd fenceTwo;
|
|
mRE->drawLayers(settings, layers, mBuffer, true, std::move(fenceOne), &fenceTwo);
|
|
|
|
const int fd = fenceTwo.get();
|
|
if (fd >= 0) {
|
|
sync_wait(fd, -1);
|
|
}
|
|
// Only cleanup the first time.
|
|
EXPECT_FALSE(mRE->canSkipPostRenderCleanup());
|
|
mRE->cleanupPostRender();
|
|
EXPECT_TRUE(mRE->canSkipPostRenderCleanup());
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, testRoundedCornersCrop) {
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings redLayer;
|
|
redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
redLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
redLayer.geometry.roundedCornersRadius = 5.0f;
|
|
redLayer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
|
|
// Red background.
|
|
redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
|
|
redLayer.alpha = 1.0f;
|
|
|
|
layers.push_back(&redLayer);
|
|
|
|
// Green layer with 1/3 size.
|
|
renderengine::LayerSettings greenLayer;
|
|
greenLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
greenLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
greenLayer.geometry.roundedCornersRadius = 5.0f;
|
|
// Bottom right corner is not going to be rounded.
|
|
greenLayer.geometry.roundedCornersCrop =
|
|
Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3, DEFAULT_DISPLAY_HEIGHT,
|
|
DEFAULT_DISPLAY_HEIGHT)
|
|
.toFloatRect();
|
|
greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f);
|
|
greenLayer.alpha = 1.0f;
|
|
|
|
layers.push_back(&greenLayer);
|
|
|
|
invokeDraw(settings, layers);
|
|
|
|
// Corners should be ignored...
|
|
// Screen size: width is 128, height is 256.
|
|
expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 0);
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, 0, DEFAULT_DISPLAY_WIDTH, 1), 0, 0, 0, 0);
|
|
expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT - 1, 1, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
|
|
// Bottom right corner is kept out of the clipping, and it's green.
|
|
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1,
|
|
DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
|
|
0, 255, 0, 255);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, testRoundedCornersParentCrop) {
|
|
initializeRenderEngine();
|
|
|
|
renderengine::DisplaySettings settings;
|
|
settings.physicalDisplay = fullscreenRect();
|
|
settings.clip = fullscreenRect();
|
|
settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers;
|
|
|
|
renderengine::LayerSettings redLayer;
|
|
redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
|
|
redLayer.geometry.boundaries = fullscreenRect().toFloatRect();
|
|
redLayer.geometry.roundedCornersRadius = 5.0f;
|
|
redLayer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
|
|
// Red background.
|
|
redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
|
|
redLayer.alpha = 1.0f;
|
|
|
|
layers.push_back(&redLayer);
|
|
|
|
// Green layer with 1/2 size with parent crop rect.
|
|
renderengine::LayerSettings greenLayer = redLayer;
|
|
greenLayer.geometry.boundaries =
|
|
FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2);
|
|
greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f);
|
|
|
|
layers.push_back(&greenLayer);
|
|
|
|
invokeDraw(settings, layers);
|
|
|
|
// Due to roundedCornersRadius, the corners are untouched.
|
|
expectBufferColor(Point(0, 0), 0, 0, 0, 0);
|
|
expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH - 1, 0), 0, 0, 0, 0);
|
|
expectBufferColor(Point(0, DEFAULT_DISPLAY_HEIGHT - 1), 0, 0, 0, 0);
|
|
expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1), 0, 0, 0, 0);
|
|
|
|
// top middle should be green and the bottom middle red
|
|
expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH / 2, 0), 0, 255, 0, 255);
|
|
expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 255, 0, 0, 255);
|
|
|
|
// the bottom edge of the green layer should not be rounded
|
|
expectBufferColor(Point(0, (DEFAULT_DISPLAY_HEIGHT / 2) - 1), 0, 255, 0, 255);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, testClear) {
|
|
initializeRenderEngine();
|
|
|
|
const auto rect = fullscreenRect();
|
|
const renderengine::DisplaySettings display{
|
|
.physicalDisplay = rect,
|
|
.clip = rect,
|
|
};
|
|
|
|
const renderengine::LayerSettings redLayer{
|
|
.geometry.boundaries = rect.toFloatRect(),
|
|
.source.solidColor = half3(1.0f, 0.0f, 0.0f),
|
|
.alpha = 1.0f,
|
|
};
|
|
|
|
// This mimics prepareClearClientComposition. This layer should overwrite
|
|
// the redLayer, so that the buffer is transparent, rather than red.
|
|
const renderengine::LayerSettings clearLayer{
|
|
.geometry.boundaries = rect.toFloatRect(),
|
|
.source.solidColor = half3(0.0f, 0.0f, 0.0f),
|
|
.alpha = 0.0f,
|
|
.disableBlending = true,
|
|
};
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers{&redLayer, &clearLayer};
|
|
invokeDraw(display, layers);
|
|
expectBufferColor(rect, 0, 0, 0, 0);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, testDisableBlendingBuffer) {
|
|
initializeRenderEngine();
|
|
|
|
const auto rect = Rect(0, 0, 1, 1);
|
|
const renderengine::DisplaySettings display{
|
|
.physicalDisplay = rect,
|
|
.clip = rect,
|
|
};
|
|
|
|
const renderengine::LayerSettings redLayer{
|
|
.geometry.boundaries = rect.toFloatRect(),
|
|
.source.solidColor = half3(1.0f, 0.0f, 0.0f),
|
|
.alpha = 1.0f,
|
|
};
|
|
|
|
// The next layer will overwrite redLayer with a GraphicBuffer that is green
|
|
// applied with a translucent alpha.
|
|
const auto buf = allocateSourceBuffer(1, 1);
|
|
{
|
|
uint8_t* pixels;
|
|
buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
|
reinterpret_cast<void**>(&pixels));
|
|
pixels[0] = 0;
|
|
pixels[1] = 255;
|
|
pixels[2] = 0;
|
|
pixels[3] = 255;
|
|
buf->getBuffer()->unlock();
|
|
}
|
|
|
|
const renderengine::LayerSettings greenLayer{
|
|
.geometry.boundaries = rect.toFloatRect(),
|
|
.source =
|
|
renderengine::PixelSource{
|
|
.buffer =
|
|
renderengine::Buffer{
|
|
.buffer = buf,
|
|
.usePremultipliedAlpha = true,
|
|
},
|
|
},
|
|
.alpha = 0.5f,
|
|
.disableBlending = true,
|
|
};
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers{&redLayer, &greenLayer};
|
|
invokeDraw(display, layers);
|
|
expectBufferColor(rect, 0, 128, 0, 128);
|
|
}
|
|
|
|
TEST_P(RenderEngineTest, test_isOpaque) {
|
|
initializeRenderEngine();
|
|
|
|
const auto rect = Rect(0, 0, 1, 1);
|
|
const renderengine::DisplaySettings display{
|
|
.physicalDisplay = rect,
|
|
.clip = rect,
|
|
.outputDataspace = ui::Dataspace::DISPLAY_P3,
|
|
};
|
|
|
|
// Create an unpremul buffer that is green with no alpha. Using isOpaque
|
|
// should make the green show.
|
|
const auto buf = allocateSourceBuffer(1, 1);
|
|
{
|
|
uint8_t* pixels;
|
|
buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
|
reinterpret_cast<void**>(&pixels));
|
|
pixels[0] = 0;
|
|
pixels[1] = 255;
|
|
pixels[2] = 0;
|
|
pixels[3] = 0;
|
|
buf->getBuffer()->unlock();
|
|
}
|
|
|
|
const renderengine::LayerSettings greenLayer{
|
|
.geometry.boundaries = rect.toFloatRect(),
|
|
.source =
|
|
renderengine::PixelSource{
|
|
.buffer =
|
|
renderengine::Buffer{
|
|
.buffer = buf,
|
|
// Although the pixels are not
|
|
// premultiplied in practice, this
|
|
// matches the input we see.
|
|
.usePremultipliedAlpha = true,
|
|
.isOpaque = true,
|
|
},
|
|
},
|
|
.alpha = 1.0f,
|
|
};
|
|
|
|
std::vector<const renderengine::LayerSettings*> layers{&greenLayer};
|
|
invokeDraw(display, layers);
|
|
|
|
if (GetParam()->useColorManagement()) {
|
|
expectBufferColor(rect, 117, 251, 76, 255);
|
|
} else {
|
|
expectBufferColor(rect, 0, 255, 0, 255);
|
|
}
|
|
}
|
|
} // namespace renderengine
|
|
} // namespace android
|
|
|
|
// TODO(b/129481165): remove the #pragma below and fix conversion issues
|
|
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
|