blob: c5829444d6545d5fc3f0c65d84df7d28fe1a52b8 [file] [log] [blame] [edit]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/testing/testing.h"
#include "impeller/base/allocation.h"
#include "impeller/renderer/backend/gles/context_gles.h"
#include "impeller/toolkit/interop/context.h"
#include "impeller/toolkit/interop/dl.h"
#include "impeller/toolkit/interop/dl_builder.h"
#include "impeller/toolkit/interop/formats.h"
#include "impeller/toolkit/interop/impeller.h"
#include "impeller/toolkit/interop/paint.h"
#include "impeller/toolkit/interop/paragraph.h"
#include "impeller/toolkit/interop/paragraph_builder.h"
#include "impeller/toolkit/interop/paragraph_style.h"
#include "impeller/toolkit/interop/playground_test.h"
#include "impeller/toolkit/interop/surface.h"
#include "impeller/toolkit/interop/texture.h"
#include "impeller/toolkit/interop/typography_context.h"
namespace impeller::interop::testing {
using InteropPlaygroundTest = PlaygroundTest;
INSTANTIATE_OPENGLES_PLAYGROUND_SUITE(InteropPlaygroundTest);
TEST_P(InteropPlaygroundTest, CanCreateContext) {
auto context = CreateContext();
ASSERT_TRUE(context);
}
TEST_P(InteropPlaygroundTest, CanCreateDisplayListBuilder) {
auto builder = ImpellerDisplayListBuilderNew(nullptr);
ASSERT_NE(builder, nullptr);
ImpellerMatrix matrix;
ImpellerDisplayListBuilderGetTransform(builder, &matrix);
ASSERT_TRUE(ToImpellerType(matrix).IsIdentity());
ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 1u);
ImpellerDisplayListBuilderSave(builder);
ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 2u);
// ImpellerDisplayListBuilderSave(nullptr); <-- Compiler error.
ImpellerDisplayListBuilderRestore(builder);
ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 1u);
ImpellerDisplayListBuilderRelease(builder);
}
TEST_P(InteropPlaygroundTest, CanCreateSurface) {
auto context = CreateContext();
ASSERT_TRUE(context);
const auto window_size = GetWindowSize();
ImpellerISize size = {window_size.width, window_size.height};
auto surface = Adopt<Surface>(ImpellerSurfaceCreateWrappedFBONew(
context.GetC(), //
0u, //
ImpellerPixelFormat::kImpellerPixelFormatRGBA8888, //
&size) //
);
ASSERT_TRUE(surface);
}
TEST_P(InteropPlaygroundTest, CanDrawRect) {
auto builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
auto paint = Adopt<Paint>(ImpellerPaintNew());
ImpellerColor color = {0.0, 0.0, 1.0, 1.0};
ImpellerPaintSetColor(paint.GetC(), &color);
ImpellerRect rect = {10, 20, 100, 200};
ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC());
color = {1.0, 0.0, 0.0, 1.0};
ImpellerPaintSetColor(paint.GetC(), &color);
ImpellerDisplayListBuilderTranslate(builder.GetC(), 110, 210);
ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC());
auto dl = Adopt<DisplayList>(
ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
ASSERT_TRUE(dl);
ASSERT_TRUE(
OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
return true;
}));
}
TEST_P(InteropPlaygroundTest, CanDrawImage) {
auto compressed = LoadFixtureImageCompressed(
flutter::testing::OpenFixtureAsMapping("boston.jpg"));
ASSERT_NE(compressed, nullptr);
auto decompressed = compressed->Decode().ConvertToRGBA();
ASSERT_TRUE(decompressed.IsValid());
ImpellerMapping mapping = {};
mapping.data = decompressed.GetAllocation()->GetMapping();
mapping.length = decompressed.GetAllocation()->GetSize();
auto context = GetInteropContext();
ImpellerTextureDescriptor desc = {};
desc.pixel_format = ImpellerPixelFormat::kImpellerPixelFormatRGBA8888;
desc.size = {decompressed.GetSize().width, decompressed.GetSize().height};
desc.mip_count = 1u;
auto texture = Adopt<Texture>(ImpellerTextureCreateWithContentsNew(
context.GetC(), &desc, &mapping, nullptr));
ASSERT_TRUE(texture);
auto builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
ImpellerPoint point = {100, 100};
ImpellerDisplayListBuilderDrawTexture(builder.GetC(), texture.GetC(), &point,
kImpellerTextureSamplingLinear,
nullptr);
auto dl = Adopt<DisplayList>(
ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
ASSERT_TRUE(
OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
return true;
}));
}
TEST_P(InteropPlaygroundTest, CanCreateOpenGLImage) {
auto context = GetInteropContext();
auto impeller_context = context->GetContext();
if (impeller_context->GetBackendType() !=
impeller::Context::BackendType::kOpenGLES) {
GTEST_SKIP() << "This test works with OpenGL handles is only suitable for "
"that backend.";
return;
}
const auto& gl_context = ContextGLES::Cast(*impeller_context);
const auto& gl = gl_context.GetReactor()->GetProcTable();
constexpr ISize external_texture_size = {200, 300};
Allocation texture_data;
ASSERT_TRUE(
texture_data.Truncate(Bytes{external_texture_size.Area() * 4u}, false));
const auto kClearColor = Color::Fuchsia().ToR8G8B8A8();
for (size_t i = 0; i < external_texture_size.Area() * 4u; i += 4u) {
memcpy(texture_data.GetBuffer() + i, kClearColor.data(), 4);
}
GLuint external_texture = GL_NONE;
gl.GenTextures(1u, &external_texture);
ASSERT_NE(external_texture, 0u);
gl.BindTexture(GL_TEXTURE_2D, external_texture);
gl.TexImage2D(GL_TEXTURE_2D, //
0, //
GL_RGBA, //
external_texture_size.width, //
external_texture_size.height, //
0, //
GL_RGBA, //
GL_UNSIGNED_BYTE, //
texture_data.GetBuffer() //
);
ImpellerTextureDescriptor desc = {};
desc.pixel_format = ImpellerPixelFormat::kImpellerPixelFormatRGBA8888;
desc.size = {external_texture_size.width, external_texture_size.height};
desc.mip_count = 1u;
auto texture = Adopt<Texture>(ImpellerTextureCreateWithOpenGLTextureHandleNew(
context.GetC(), //
&desc, //
external_texture //
));
ASSERT_TRUE(texture);
ASSERT_EQ(ImpellerTextureGetOpenGLHandle(texture.GetC()), external_texture);
auto builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
ImpellerPoint point = {100, 100};
ImpellerDisplayListBuilderDrawTexture(builder.GetC(), texture.GetC(), &point,
kImpellerTextureSamplingLinear,
nullptr);
auto dl = Adopt<DisplayList>(
ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
ASSERT_TRUE(
OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
return true;
}));
}
TEST_P(InteropPlaygroundTest, CanCreateParagraphs) {
// Create a typography context.
auto type_context = Adopt<TypographyContext>(ImpellerTypographyContextNew());
ASSERT_TRUE(type_context);
// Create a builder.
auto builder =
Adopt<ParagraphBuilder>(ImpellerParagraphBuilderNew(type_context.GetC()));
ASSERT_TRUE(builder);
// Create a paragraph style with the font size and foreground and background
// colors.
auto style = Adopt<ParagraphStyle>(ImpellerParagraphStyleNew());
ASSERT_TRUE(style);
ImpellerParagraphStyleSetFontSize(style.GetC(), 150.0f);
{
auto paint = Adopt<Paint>(ImpellerPaintNew());
ASSERT_TRUE(paint);
ImpellerColor color = {1.0, 0.0, 0.0, 1.0};
ImpellerPaintSetColor(paint.GetC(), &color);
ImpellerParagraphStyleSetForeground(style.GetC(), paint.GetC());
}
{
auto paint = Adopt<Paint>(ImpellerPaintNew());
ASSERT_TRUE(paint);
ImpellerColor color = {1.0, 1.0, 1.0, 1.0};
ImpellerPaintSetColor(paint.GetC(), &color);
ImpellerParagraphStyleSetBackground(style.GetC(), paint.GetC());
}
// Push the style onto the style stack.
ImpellerParagraphBuilderPushStyle(builder.GetC(), style.GetC());
std::string text = "the ⚡️ quick ⚡️ brown 🦊 fox jumps over the lazy dog 🐶.";
// Add the paragraph text data.
ImpellerParagraphBuilderAddText(builder.GetC(),
reinterpret_cast<const uint8_t*>(text.data()),
text.size());
// Layout and build the paragraph.
auto paragraph = Adopt<Paragraph>(
ImpellerParagraphBuilderBuildParagraphNew(builder.GetC(), 1200.0f));
ASSERT_TRUE(paragraph);
// Create a display list with just the paragraph drawn into it.
auto dl_builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
ImpellerPoint point = {20, 20};
ImpellerDisplayListBuilderDrawParagraph(dl_builder.GetC(), paragraph.GetC(),
&point);
auto dl = Adopt<DisplayList>(
ImpellerDisplayListBuilderCreateDisplayListNew(dl_builder.GetC()));
ASSERT_TRUE(
OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
return true;
}));
}
} // namespace impeller::interop::testing