Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit aa9f821

Browse files
committed
[Impeller] Add support for external GL textures to TiledTextureContents.
1 parent dd620fc commit aa9f821

File tree

10 files changed

+150
-24
lines changed

10 files changed

+150
-24
lines changed

impeller/compiler/shader_lib/impeller/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ copy("impeller") {
1010
"constants.glsl",
1111
"conversions.glsl",
1212
"dithering.glsl",
13+
"external_texture_oes.glsl",
1314
"gaussian.glsl",
1415
"gradient.glsl",
1516
"path.glsl",
1617
"texture.glsl",
18+
"tile_mode.glsl",
1719
"transform.glsl",
1820
"types.glsl",
1921
]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include <impeller/tile_mode.glsl>
6+
7+
/// A triangle wave. 0->0, 1->1, 2->0, and so on... works with negative numbers.
8+
float TriangleWave(float x) {
9+
return abs(mod(x + 1, 2) - 1);
10+
}
11+
12+
/// OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, so we
13+
/// emulate all other tile modes here by remapping the texture coordinates.
14+
vec4 IPSampleWithTileModeOES(sampler2D tex,
15+
vec2 coords,
16+
float x_tile_mode,
17+
float y_tile_mode) {
18+
if (x_tile_mode == kTileModeDecal && (coords.x < 0 || coords.x >= 1) ||
19+
y_tile_mode == kTileModeDecal && (coords.y < 0 || coords.y >= 1)) {
20+
return vec4(0);
21+
}
22+
23+
if (x_tile_mode == kTileModeRepeat) {
24+
coords.x = mod(coords.x, 1);
25+
} else if (x_tile_mode == kTileModeMirror) {
26+
coords.x = TriangleWave(coords.x);
27+
}
28+
29+
if (y_tile_mode == kTileModeRepeat) {
30+
coords.y = mod(coords.y, 1);
31+
} else if (y_tile_mode == kTileModeMirror) {
32+
coords.y = TriangleWave(coords.y);
33+
}
34+
35+
return texture(tex, coords);
36+
}

impeller/compiler/shader_lib/impeller/texture.glsl

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <impeller/branching.glsl>
99
#include <impeller/conversions.glsl>
10+
#include <impeller/tile_mode.glsl>
1011
#include <impeller/types.glsl>
1112

1213
/// Sample from a texture.
@@ -35,13 +36,6 @@ vec4 IPSampleLinear(sampler2D texture_sampler,
3536
return IPSample(texture_sampler, coords, y_coord_scale);
3637
}
3738

38-
// These values must correspond to the order of the items in the
39-
// 'Entity::TileMode' enum class.
40-
const float kTileModeClamp = 0;
41-
const float kTileModeRepeat = 1;
42-
const float kTileModeMirror = 2;
43-
const float kTileModeDecal = 3;
44-
4539
/// Remap a float using a tiling mode.
4640
///
4741
/// When `tile_mode` is `kTileModeDecal`, no tiling is applied and `t` is
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// These values must correspond to the order of the items in the
6+
// 'Entity::TileMode' enum class.
7+
const float kTileModeClamp = 0;
8+
const float kTileModeRepeat = 1;
9+
const float kTileModeMirror = 2;
10+
const float kTileModeDecal = 3;

impeller/entity/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impeller_shaders("entity_shaders") {
5151
"shaders/texture_fill.vert",
5252
"shaders/texture_fill_external.frag",
5353
"shaders/tiled_texture_fill.frag",
54+
"shaders/tiled_texture_fill_external.frag",
5455
"shaders/vertices.frag",
5556
"shaders/yuv_to_rgb_filter.frag",
5657
"shaders/yuv_to_rgb_filter.vert",

impeller/entity/contents/content_context.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ ContentContext::ContentContext(
340340
if (GetContext()->GetBackendType() == Context::BackendType::kOpenGLES) {
341341
texture_external_pipelines_.CreateDefault(*context_, options);
342342
}
343+
if (GetContext()->GetBackendType() == Context::BackendType::kOpenGLES) {
344+
tiled_texture_external_pipelines_.CreateDefault(*context_, options);
345+
}
343346
#endif // IMPELLER_ENABLE_OPENGLES
344347
if (context_->GetCapabilities()->SupportsCompute()) {
345348
auto pipeline_desc =

impeller/entity/contents/content_context.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484

8585
#ifdef IMPELLER_ENABLE_OPENGLES
8686
#include "impeller/entity/texture_fill_external.frag.h"
87+
#include "impeller/entity/tiled_texture_fill_external.frag.h"
8788
#endif // IMPELLER_ENABLE_OPENGLES
8889

8990
#if IMPELLER_ENABLE_3D
@@ -249,6 +250,10 @@ using UvComputeShaderPipeline = ComputePipelineBuilder<UvComputeShader>;
249250
#ifdef IMPELLER_ENABLE_OPENGLES
250251
using TextureExternalPipeline =
251252
RenderPipelineT<TextureFillVertexShader, TextureFillExternalFragmentShader>;
253+
254+
using TiledTextureExternalPipeline =
255+
RenderPipelineT<TextureFillVertexShader,
256+
TiledTextureFillExternalFragmentShader>;
252257
#endif // IMPELLER_ENABLE_OPENGLES
253258

254259
/// Pipeline state configuration.
@@ -398,6 +403,13 @@ class ContentContext {
398403
Context::BackendType::kOpenGLES);
399404
return GetPipeline(texture_external_pipelines_, opts);
400405
}
406+
407+
std::shared_ptr<Pipeline<PipelineDescriptor>> GetTiledTextureExternalPipeline(
408+
ContentContextOptions opts) const {
409+
FML_DCHECK(GetContext()->GetBackendType() ==
410+
Context::BackendType::kOpenGLES);
411+
return GetPipeline(tiled_texture_external_pipelines_, opts);
412+
}
401413
#endif // IMPELLER_ENABLE_OPENGLES
402414

403415
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPositionUVPipeline(
@@ -768,6 +780,8 @@ class ContentContext {
768780
mutable Variants<TexturePipeline> texture_pipelines_;
769781
#ifdef IMPELLER_ENABLE_OPENGLES
770782
mutable Variants<TextureExternalPipeline> texture_external_pipelines_;
783+
mutable Variants<TiledTextureExternalPipeline>
784+
tiled_texture_external_pipelines_;
771785
#endif // IMPELLER_ENABLE_OPENGLES
772786
mutable Variants<PositionUVPipeline> position_uv_pipelines_;
773787
mutable Variants<TiledTexturePipeline> tiled_texture_pipelines_;

impeller/entity/contents/tiled_texture_contents.cc

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "impeller/entity/texture_fill.frag.h"
1111
#include "impeller/entity/texture_fill.vert.h"
1212
#include "impeller/entity/tiled_texture_fill.frag.h"
13+
#include "impeller/entity/tiled_texture_fill_external.frag.h"
1314
#include "impeller/geometry/path_builder.h"
1415
#include "impeller/renderer/render_pass.h"
1516
#include "impeller/renderer/sampler_library.h"
@@ -78,7 +79,7 @@ std::shared_ptr<Texture> TiledTextureContents::CreateFilterTexture(
7879
return nullptr;
7980
}
8081

81-
SamplerDescriptor TiledTextureContents::CreateDescriptor(
82+
SamplerDescriptor TiledTextureContents::CreateSamplerDescriptor(
8283
const Capabilities& capabilities) const {
8384
SamplerDescriptor descriptor = sampler_descriptor_;
8485
auto width_mode = TileModeToAddressMode(x_tile_mode_, capabilities);
@@ -119,12 +120,16 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
119120

120121
using VS = TextureFillVertexShader;
121122
using FS = TiledTextureFillFragmentShader;
123+
using FSExternal = TiledTextureFillExternalFragmentShader;
122124

123125
const auto texture_size = texture_->GetSize();
124126
if (texture_size.IsEmpty()) {
125127
return true;
126128
}
127129

130+
bool is_external_texture =
131+
texture_->GetTextureDescriptor().type == TextureType::kTextureExternalOES;
132+
128133
auto& host_buffer = pass.GetTransientsBuffer();
129134

130135
auto geometry_result = GetGeometry()->GetPositionUVBuffer(
@@ -153,34 +158,64 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
153158
options.stencil_operation = StencilOperation::kIncrementClamp;
154159
}
155160
options.primitive_type = geometry_result.type;
161+
162+
#ifdef IMPELLER_ENABLE_OPENGLES
163+
if (is_external_texture) {
164+
cmd.pipeline = renderer.GetTiledTextureExternalPipeline(options);
165+
} else {
166+
cmd.pipeline = uses_emulated_tile_mode
167+
? renderer.GetTiledTexturePipeline(options)
168+
: renderer.GetTexturePipeline(options);
169+
}
170+
#else
156171
cmd.pipeline = uses_emulated_tile_mode
157172
? renderer.GetTiledTexturePipeline(options)
158173
: renderer.GetTexturePipeline(options);
174+
#endif // IMPELLER_ENABLE_OPENGLES
159175

160176
cmd.BindVertices(geometry_result.vertex_buffer);
161177
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
162178

163-
if (uses_emulated_tile_mode) {
179+
if (is_external_texture) {
180+
FSExternal::FragInfo frag_info;
181+
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
182+
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
183+
FSExternal::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
184+
} else if (uses_emulated_tile_mode) {
164185
FS::FragInfo frag_info;
165186
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
166187
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
167188
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
168189
}
169190

170-
if (color_filter_) {
171-
auto filtered_texture = CreateFilterTexture(renderer);
172-
if (!filtered_texture) {
173-
return false;
174-
}
175-
FS::BindTextureSampler(
176-
cmd, filtered_texture,
177-
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
178-
CreateDescriptor(renderer.GetDeviceCapabilities())));
179-
} else {
180-
FS::BindTextureSampler(
191+
if (is_external_texture) {
192+
SamplerDescriptor sampler_desc;
193+
// OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, so we
194+
// emulate all other tile modes here by remapping the texture coordinates.
195+
sampler_desc.width_address_mode = SamplerAddressMode::kClampToEdge;
196+
sampler_desc.height_address_mode = SamplerAddressMode::kClampToEdge;
197+
198+
// Also, external textures cannot be bound to color filters, so ignore this
199+
// case for now.
200+
FSExternal::BindSAMPLEREXTERNALOESTextureSampler(
181201
cmd, texture_,
182-
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
183-
CreateDescriptor(renderer.GetDeviceCapabilities())));
202+
renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc));
203+
} else {
204+
if (color_filter_) {
205+
auto filtered_texture = CreateFilterTexture(renderer);
206+
if (!filtered_texture) {
207+
return false;
208+
}
209+
FS::BindTextureSampler(
210+
cmd, filtered_texture,
211+
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
212+
CreateSamplerDescriptor(renderer.GetDeviceCapabilities())));
213+
} else {
214+
FS::BindTextureSampler(
215+
cmd, texture_,
216+
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
217+
CreateSamplerDescriptor(renderer.GetDeviceCapabilities())));
218+
}
184219
}
185220

186221
if (!pass.AddCommand(std::move(cmd))) {

impeller/entity/contents/tiled_texture_contents.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class TiledTextureContents final : public ColorSourceContents {
4545
/// @param color_filter
4646
///
4747
/// When applying a color filter to a tiled texture, we can reduce the
48-
/// size and number of the subpasses required and the shader workloadby
48+
/// size and number of the subpasses required and the shader workload by
4949
/// applying the filter to the untiled image and absorbing the opacity before
5050
/// tiling it into the final location.
5151
///
@@ -66,7 +66,8 @@ class TiledTextureContents final : public ColorSourceContents {
6666
std::shared_ptr<Texture> CreateFilterTexture(
6767
const ContentContext& renderer) const;
6868

69-
SamplerDescriptor CreateDescriptor(const Capabilities& capabilities) const;
69+
SamplerDescriptor CreateSamplerDescriptor(
70+
const Capabilities& capabilities) const;
7071

7172
bool UsesEmulatedTileMode(const Capabilities& capabilities) const;
7273

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
precision mediump float;
6+
7+
#include <impeller/external_texture_oes.glsl>
8+
9+
uniform sampler2D SAMPLER_EXTERNAL_OES_texture_sampler;
10+
11+
uniform FragInfo {
12+
float x_tile_mode;
13+
float y_tile_mode;
14+
}
15+
frag_info;
16+
17+
in vec2 v_texture_coords;
18+
in float v_alpha;
19+
20+
out vec4 frag_color;
21+
22+
void main() {
23+
frag_color =
24+
IPSampleWithTileModeOES(SAMPLER_EXTERNAL_OES_texture_sampler, // sampler
25+
v_texture_coords, // texture coordinates
26+
frag_info.x_tile_mode, // x tile mode
27+
frag_info.y_tile_mode // y tile mode
28+
) *
29+
v_alpha;
30+
}

0 commit comments

Comments
 (0)