Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -744,24 +744,6 @@ void Canvas::DrawImageRect(const std::shared_ptr<Texture>& image,
return;
}

if (image->GetTextureDescriptor().type == TextureType::kTextureExternalOES) {
auto texture_contents = std::make_shared<TiledTextureContents>();
texture_contents->SetTexture(image);
texture_contents->SetGeometry(Geometry::MakeRect(dest));
texture_contents->SetSamplerDescriptor(std::move(sampler));
texture_contents->SetInheritedOpacity(paint.color.alpha);

std::shared_ptr<Contents> contents = texture_contents;

Entity entity;
entity.SetBlendMode(paint.blend_mode);
entity.SetContents(paint.WithFilters(contents));
entity.SetTransform(GetCurrentTransform());

AddRenderEntityToCurrentPass(std::move(entity));
return;
}

auto texture_contents = TextureContents::MakeRect(dest);
texture_contents->SetTexture(image);
texture_contents->SetSourceRect(source);
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ using VerticesUberShader = RenderPipelineHandle<PorterDuffBlendVertexShader,

#ifdef IMPELLER_ENABLE_OPENGLES
using TiledTextureExternalPipeline =
RenderPipelineHandle<TextureUvFillVertexShader,
RenderPipelineHandle<TextureFillVertexShader,
TiledTextureFillExternalFragmentShader>;
#endif // IMPELLER_ENABLE_OPENGLES

Expand Down
39 changes: 37 additions & 2 deletions impeller/entity/contents/texture_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "impeller/entity/texture_fill.frag.h"
#include "impeller/entity/texture_fill.vert.h"
#include "impeller/entity/texture_fill_strict_src.frag.h"
#include "impeller/entity/tiled_texture_fill_external.frag.h"
#include "impeller/geometry/constants.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/vertex_buffer_builder.h"
Expand Down Expand Up @@ -118,9 +119,11 @@ bool TextureContents::Render(const ContentContext& renderer,
return true; // Nothing to render.
}

[[maybe_unused]] bool is_external_texture =
#ifdef IMPELLER_ENABLE_OPENGLES
using FSExternal = TiledTextureFillExternalFragmentShader;
bool is_external_texture =
texture_->GetTextureDescriptor().type == TextureType::kTextureExternalOES;
FML_DCHECK(!is_external_texture);
#endif // IMPELLER_ENABLE_OPENGLES

auto texture_coords =
Rect::MakeSize(texture_->GetSize()).Project(source_rect_);
Expand Down Expand Up @@ -159,9 +162,21 @@ bool TextureContents::Render(const ContentContext& renderer,
pipeline_options.depth_write_enabled =
stencil_enabled_ && pipeline_options.blend_mode == BlendMode::kSource;

#ifdef IMPELLER_ENABLE_OPENGLES
if (is_external_texture) {
pass.SetPipeline(
renderer.GetTiledTextureExternalPipeline(pipeline_options));
} else {
pass.SetPipeline(
strict_source_rect_enabled_
? renderer.GetTextureStrictSrcPipeline(pipeline_options)
: renderer.GetTexturePipeline(pipeline_options));
}
#else
pass.SetPipeline(strict_source_rect_enabled_
? renderer.GetTextureStrictSrcPipeline(pipeline_options)
: renderer.GetTexturePipeline(pipeline_options));
#endif // IMPELLER_ENABLE_OPENGLES

pass.SetVertexBuffer(vertex_buffer);
VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
Expand All @@ -181,6 +196,26 @@ bool TextureContents::Render(const ContentContext& renderer,
pass, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
sampler_descriptor_));
#ifdef IMPELLER_ENABLE_OPENGLES
} else if (is_external_texture) {
FSExternal::FragInfo frag_info;
frag_info.x_tile_mode =
static_cast<Scalar>(sampler_descriptor_.width_address_mode);
frag_info.y_tile_mode =
static_cast<Scalar>(sampler_descriptor_.height_address_mode);
frag_info.alpha = GetOpacity();
FSExternal::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));

SamplerDescriptor sampler_desc;
// OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, so
// we emulate all other tile modes here by remapping the texture
// coordinates.
sampler_desc.width_address_mode = SamplerAddressMode::kClampToEdge;
sampler_desc.height_address_mode = SamplerAddressMode::kClampToEdge;
FSExternal::BindSAMPLEREXTERNALOESTextureSampler(
pass, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc));
#endif // IMPELLER_ENABLE_OPENGLES
} else {
FS::FragInfo frag_info;
frag_info.alpha = GetOpacity();
Expand Down
94 changes: 25 additions & 69 deletions impeller/entity/contents/tiled_texture_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,96 +116,52 @@ bool TiledTextureContents::Render(const ContentContext& renderer,

using VS = TextureUvFillVertexShader;
using FS = TiledTextureFillFragmentShader;
using FSExternal = TiledTextureFillExternalFragmentShader;

const auto texture_size = texture_->GetSize();
if (texture_size.IsEmpty()) {
return true;
}

bool is_external_texture =
texture_->GetTextureDescriptor().type == TextureType::kTextureExternalOES;

VS::FrameInfo frame_info;
frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
frame_info.uv_transform =
Rect::MakeSize(texture_size).GetNormalizingTransform() *
GetInverseEffectTransform();

PipelineBuilderMethod pipeline_method;

#ifdef IMPELLER_ENABLE_OPENGLES
if (is_external_texture) {
pipeline_method = &ContentContext::GetTiledTextureExternalPipeline;
} else {
pipeline_method = &ContentContext::GetTiledTexturePipeline;
}
#else
pipeline_method = &ContentContext::GetTiledTexturePipeline;
#endif // IMPELLER_ENABLE_OPENGLES

PipelineBuilderCallback pipeline_callback =
[&renderer, &pipeline_method](ContentContextOptions options) {
return (renderer.*pipeline_method)(options);
[&renderer](ContentContextOptions options) {
return renderer.GetTiledTexturePipeline(options);
};
return ColorSourceContents::DrawGeometry<VS>(
renderer, entity, pass, pipeline_callback, frame_info,
[this, &renderer, &is_external_texture, &entity](RenderPass& pass) {
[this, &renderer, &entity](RenderPass& pass) {
auto& host_buffer = renderer.GetTransientsBuffer();

#ifdef IMPELLER_DEBUG
pass.SetCommandLabel("TextureFill");

if (is_external_texture) {
FSExternal::FragInfo frag_info;
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
frag_info.alpha =
GetOpacityFactor() *
GetGeometry()->ComputeAlphaCoverage(entity.GetTransform());
FSExternal::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
#endif // IMPELLER_DEBUG

FS::FragInfo frag_info;
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
frag_info.alpha =
GetOpacityFactor() *
GetGeometry()->ComputeAlphaCoverage(entity.GetTransform());
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));

if (color_filter_) {
auto filtered_texture = CreateFilterTexture(renderer);
if (!filtered_texture) {
return false;
}
FS::BindTextureSampler(
pass, filtered_texture,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
CreateSamplerDescriptor(renderer.GetDeviceCapabilities())));
} else {
FS::FragInfo frag_info;
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
frag_info.alpha =
GetOpacityFactor() *
GetGeometry()->ComputeAlphaCoverage(entity.GetTransform());
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
}

if (is_external_texture) {
SamplerDescriptor sampler_desc;
// OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, so
// we emulate all other tile modes here by remapping the texture
// coordinates.
sampler_desc.width_address_mode = SamplerAddressMode::kClampToEdge;
sampler_desc.height_address_mode = SamplerAddressMode::kClampToEdge;

// Also, external textures cannot be bound to color filters, so ignore
// this case for now.
FML_DCHECK(!color_filter_) << "Color filters are not currently "
"supported for external textures.";

FSExternal::BindSAMPLEREXTERNALOESTextureSampler(
FS::BindTextureSampler(
pass, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
sampler_desc));
} else {
if (color_filter_) {
auto filtered_texture = CreateFilterTexture(renderer);
if (!filtered_texture) {
return false;
}
FS::BindTextureSampler(
pass, filtered_texture,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
CreateSamplerDescriptor(renderer.GetDeviceCapabilities())));
} else {
FS::BindTextureSampler(
pass, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
CreateSamplerDescriptor(renderer.GetDeviceCapabilities())));
}
CreateSamplerDescriptor(renderer.GetDeviceCapabilities())));
}

return true;
Expand Down
24 changes: 17 additions & 7 deletions impeller/entity/contents/tiled_texture_contents_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "impeller/core/formats.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/entity/contents/test/recording_render_pass.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/contents/tiled_texture_contents.h"
#include "impeller/entity/entity_playground.h"
#include "impeller/playground/playground_test.h"
Expand Down Expand Up @@ -44,8 +45,14 @@ TEST_P(EntityTest, TiledTextureContentsRendersWithCorrectPipeline) {
const std::vector<Command>& commands = recording_pass->GetCommands();

ASSERT_EQ(commands.size(), 1u);
#ifdef IMPELLER_DEBUG
EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
"TextureFill Pipeline") != std::string::npos);
#endif // IMPELLER_DEBUG
auto options = OptionsFromPassAndEntity(*recording_pass, {});
options.primitive_type = PrimitiveType::kTriangleStrip;
EXPECT_EQ(commands[0].pipeline,
GetContentContext()->GetTiledTexturePipeline(options));

if (GetParam() == PlaygroundBackend::kMetal) {
recording_pass->EncodeCommands();
Expand All @@ -67,10 +74,10 @@ TEST_P(EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES) {
texture_desc.storage_mode = StorageMode::kDevicePrivate;
auto texture =
GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);

TiledTextureContents contents;
contents.SetTexture(texture);
contents.SetGeometry(Geometry::MakeCover());
auto contents = TextureContents::MakeRect(Rect::MakeSize(texture->GetSize()));
contents->SetTexture(texture);
contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
contents->SetStrictSourceRect(false);

auto content_context = GetContentContext();
auto buffer = content_context->GetContext()->CreateCommandBuffer();
Expand All @@ -80,12 +87,15 @@ TEST_P(EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES) {
/*mip_count=*/1);
auto render_pass = buffer->CreateRenderPass(render_target);

ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));
ASSERT_TRUE(contents->Render(*GetContentContext(), {}, *render_pass));
const std::vector<Command>& commands = render_pass->GetCommands();

ASSERT_EQ(commands.size(), 1u);
EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
"TiledTextureFillExternal Pipeline") != std::string::npos);

auto options = OptionsFromPassAndEntity(*render_pass, {});
options.primitive_type = PrimitiveType::kTriangleStrip;
EXPECT_EQ(commands[0].pipeline,
GetContentContext()->GetTiledTextureExternalPipeline(options));
}
#endif

Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/tiled_texture_fill_external.frag
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ uniform FragInfo {
}
frag_info;

in vec2 v_texture_coords;
in highp vec2 v_texture_coords;

out vec4 frag_color;

Expand Down
Loading