зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1686244 - Accelerate nearest repeat filtering in SWGL. r=jrmuizel
Some sites use pixelated/crisp image-rendering and/or 1x1 images as color sources. When we hit these, we fall off the fast-path. Try to handle some of those cases we are finding in the wild, namely nearest filtering and repeat filtering. There is some slight movement in the wrench fuzz due to the composite shader being accelerated in situations it was previously not due to nearest filter. Differential Revision: https://phabricator.services.mozilla.com/D105864
This commit is contained in:
Родитель
7d3755c3f6
Коммит
38845a4afa
|
@ -3825,42 +3825,6 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio
|
|||
vec![Type::new(*s)],
|
||||
RunClass::Scalar,
|
||||
);
|
||||
declare_function_ext(
|
||||
state,
|
||||
"swgl_textureLayerOffset",
|
||||
None,
|
||||
Type::new(Int),
|
||||
vec![Type::new(*s), Type::new(Float)],
|
||||
RunClass::Scalar,
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_linearQuantize",
|
||||
None,
|
||||
Type::new(Vec2),
|
||||
vec![Type::new(*s), Type::new(Vec2)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_linearQuantizeStep",
|
||||
None,
|
||||
Type::new(Vec2),
|
||||
vec![Type::new(*s), Type::new(Vec2)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureLinearChunkRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Int)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureLinearChunkColorRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Int)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureLinearRGBA8",
|
||||
|
@ -3896,6 +3860,80 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio
|
|||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Float), Type::new(Float)],
|
||||
);
|
||||
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureLinearRepeatRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureLinearRepeatColorRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureNearestRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureNearestColorRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureNearestRepeatRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureNearestRepeatColorRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureColorRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureRepeatRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitTextureRepeatColorRGBA8",
|
||||
None,
|
||||
Type::new(Void),
|
||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Vec4), Type::new(Vec4), Type::new(Float)],
|
||||
);
|
||||
|
||||
declare_function(
|
||||
state,
|
||||
"swgl_commitGaussianBlurRGBA8",
|
||||
|
|
|
@ -59,29 +59,6 @@ the edge ends on that vertex. The easiest way to understand this ordering
|
|||
is that for a rectangle (x0,y0,x1,y1) then the edge Nth edge bit corresponds
|
||||
to the edge where Nth coordinate in the rectangle is constant.
|
||||
|
||||
```
|
||||
swgl_commitTextureLinearRGBA8(sampler, vec2 uv, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureLinearR8(sampler, vec2 uv, vec4 uv_bounds, float layer);
|
||||
|
||||
swgl_commitTextureLinearColorRGBA8(sampler, vec2 uv, vec4 uv_bounds, vec4|float color, float layer);
|
||||
swgl_commitTextureLinearColorR8(sampler, vec2 uv, vec4 uv_bounds, vec4|float color, float layer);
|
||||
|
||||
swgl_commitTextureLinearChunkRGBA8(sampler, vec2 uv, int layerOffset);
|
||||
swgl_commitTextureLinearChunkColorRGBA8(sampler, vec2 uv, vec4 color, int layerOffset);
|
||||
```
|
||||
|
||||
Samples and commits an entire span of texture starting at the given uv and
|
||||
within the supplied uv bounds from the given layer. The color variations
|
||||
also accept a supplied color that modulates the result.
|
||||
|
||||
The RGBA8 versions may only be used to commit within swgl_drawSpanRGBA8, and
|
||||
the R8 versions may only be used to commit within swgl_drawSpanR8.
|
||||
|
||||
The chunk variations only commit a single chunk rather than an entire span. The
|
||||
uv coordinates must be clamped beforehand and then scaled appropriately with
|
||||
swgl_linearQuantize. The layer offset must be resolved to a linear offset with
|
||||
with swgl_textureLayerOffset.
|
||||
|
||||
SWGL tries to use an anti-aliasing method that is reasonably close to WR's
|
||||
signed-distance field approximation. WR would normally try to discern the
|
||||
2D local-space coordinates of a given destination pixel relative to the
|
||||
|
@ -105,3 +82,47 @@ Essentially, SWGL just performs anti-aliasing on the actual geometry bounds,
|
|||
but when the pixels on a span's edge are determined to be partially covered
|
||||
during span rasterization, it uses the same distance field method as WR on
|
||||
those span boundary pixels to estimate the coverage based on edge slope.
|
||||
|
||||
```
|
||||
swgl_commitTextureLinearRGBA8(sampler, vec2 uv, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureLinearR8(sampler, vec2 uv, vec4 uv_bounds, float layer);
|
||||
|
||||
swgl_commitTextureLinearColorRGBA8(sampler, vec2 uv, vec4 uv_bounds, vec4|float color, float layer);
|
||||
swgl_commitTextureLinearColorR8(sampler, vec2 uv, vec4 uv_bounds, vec4|float color, float layer);
|
||||
|
||||
swgl_commitTextureLinearRepeatRGBA8(sampler, vec2 uv, vec4 uv_repeat, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureLinearRepeatColorRGBA8(sampler, vec2 uv, vec4 uv_repeat, vec4 uv_bounds, vec4|float color, float layer);
|
||||
|
||||
swgl_commitTextureNearestRGBA8(sampler, vec2 uv, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureNearestColorRGBA8(sampler, vec2 uv, vec4 uv_bounds, vec4|float color, float layer);
|
||||
|
||||
swgl_commitTextureNearestRepeatRGBA8(sampler, vec2 uv, vec4 uv_repeat, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureNearestRepeatColorRGBA8(sampler, vec2 uv, vec4 uv_repeat, vec4 uv_bounds, vec4|float color, float layer);
|
||||
|
||||
swgl_commitTextureRGBA8(sampler, vec2 uv, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureColorRGBA8(sampler, vec2 uv, vec4 uv_bounds, vec4|float color, float layer);
|
||||
|
||||
swgl_commitTextureRepeatRGBA8(sampler, vec2 uv, vec4 uv_repeat, vec4 uv_bounds, float layer);
|
||||
swgl_commitTextureRepeatColorRGBA8(sampler, vec2 uv, vec4 uv_repeat, vec4 uv_bounds, vec4|float color, float layer);
|
||||
```
|
||||
|
||||
Samples and commits an entire span of texture starting at the given uv and
|
||||
within the supplied uv bounds from the given layer. The color variations
|
||||
also accept a supplied color that modulates the result.
|
||||
|
||||
The RGBA8 versions may only be used to commit within swgl_drawSpanRGBA8, and
|
||||
the R8 versions may only be used to commit within swgl_drawSpanR8.
|
||||
|
||||
The Linear variations use a linear filter that bilinearly interpolates between
|
||||
the four samples near the pixel. The Nearest variations use a nearest filter
|
||||
that chooses the closest aliased sample to the center of the pixel. If neither
|
||||
Linear nor Nearest is specified in the swgl_commitTexture variation name, then
|
||||
it will automatically select either the Linear or Nearest variation depending
|
||||
on the sampler's specified filter.
|
||||
|
||||
The Repeat variations require an optional repeat rect that specifies how to
|
||||
scale and offset the UVs, assuming the UVs are normalized to repeat in the
|
||||
range 0 to 1. For NearestRepeat variations, it is assumed the repeat rect is
|
||||
always within the bounds.
|
||||
|
||||
|
||||
|
|
|
@ -3439,20 +3439,20 @@ static ALWAYS_INLINE WideRGBA8 blend_pixels(uint32_t* buf, PackedRGBA8 pdst,
|
|||
case BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||
WideRGBA8 secondary =
|
||||
muldiv256(dst,
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.0f));
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.49f));
|
||||
return src + dst - secondary;
|
||||
}
|
||||
case MASK_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||
WideRGBA8 secondary =
|
||||
muldiv256(dst,
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.0f));
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.49f));
|
||||
WideRGBA8 mask = load_clip_mask(buf, span);
|
||||
return muldiv255(src, mask) + dst - muldiv255(secondary, mask);
|
||||
}
|
||||
case AA_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||
WideRGBA8 secondary =
|
||||
muldiv256(dst,
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.0f));
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.49f));
|
||||
DO_AA(RGBA8, {
|
||||
src = muldiv256(src, aa);
|
||||
secondary = muldiv256(secondary, aa);
|
||||
|
@ -3462,7 +3462,7 @@ static ALWAYS_INLINE WideRGBA8 blend_pixels(uint32_t* buf, PackedRGBA8 pdst,
|
|||
case AA_MASK_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||
WideRGBA8 secondary =
|
||||
muldiv256(dst,
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.0f));
|
||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.49f));
|
||||
WideRGBA8 mask = load_clip_mask(buf, span);
|
||||
DO_AA(RGBA8, mask = muldiv256(mask, aa));
|
||||
return muldiv255(src, mask) + dst - muldiv255(secondary, mask);
|
||||
|
|
|
@ -1672,6 +1672,14 @@ struct vec4_scalar {
|
|||
return *this;
|
||||
}
|
||||
|
||||
vec4_scalar& operator*=(vec4_scalar a) {
|
||||
x *= a.x;
|
||||
y *= a.y;
|
||||
z *= a.z;
|
||||
w *= a.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const vec4_scalar& l, const vec4_scalar& r) {
|
||||
return l.x == r.x && l.y == r.y && l.z == r.z && l.w == r.w;
|
||||
}
|
||||
|
@ -1866,6 +1874,13 @@ struct vec4 {
|
|||
w /= a.w;
|
||||
return *this;
|
||||
}
|
||||
vec4& operator*=(vec4 a) {
|
||||
x *= a.x;
|
||||
y *= a.y;
|
||||
z *= a.z;
|
||||
w *= a.w;
|
||||
return *this;
|
||||
}
|
||||
vec4& operator*=(Float a) {
|
||||
x *= a;
|
||||
y *= a;
|
||||
|
|
|
@ -32,20 +32,22 @@ static ALWAYS_INLINE P applyColor(P src, P color) {
|
|||
return muldiv256(src, color);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE PackedRGBA8 applyColor(PackedRGBA8 src, WideRGBA8 color) {
|
||||
return pack(muldiv256(unpack(src), color));
|
||||
static ALWAYS_INLINE WideRGBA8 applyColor(PackedRGBA8 src, WideRGBA8 color) {
|
||||
return muldiv256(unpack(src), color);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE PackedR8 applyColor(PackedR8 src, WideR8 color) {
|
||||
return pack(muldiv256(unpack(src), color));
|
||||
static ALWAYS_INLINE WideR8 applyColor(PackedR8 src, WideR8 color) {
|
||||
return muldiv256(unpack(src), color);
|
||||
}
|
||||
|
||||
// Packs a color on a scale of 0..256 rather than 0..255 to allow faster scale
|
||||
// math with muldiv256. Note that this can cause a slight rounding difference in
|
||||
// the result versus the 255 scale.
|
||||
// the result versus the 255 scale. To alleviate this we scale by 256.49, so
|
||||
// that the color rounds slightly up and in turn causes the the value it scales
|
||||
// to round slightly up as well.
|
||||
template <typename P, typename C>
|
||||
static ALWAYS_INLINE auto packColor(P* buf, C color) {
|
||||
return pack_span(buf, color, 256.0f);
|
||||
return pack_span(buf, color, 256.49f);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
|
@ -57,6 +59,10 @@ static ALWAYS_INLINE void commit_span(uint32_t* buf, WideRGBA8 r) {
|
|||
unaligned_store(buf, pack(r));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void commit_span(uint32_t* buf, WideRGBA8 r, int len) {
|
||||
partial_store_span(buf, pack(r), len);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE WideRGBA8 blend_span(uint32_t* buf, WideRGBA8 r) {
|
||||
return blend_pixels(buf, unaligned_load<PackedRGBA8>(buf), r);
|
||||
}
|
||||
|
@ -69,14 +75,27 @@ static ALWAYS_INLINE void commit_span(uint32_t* buf, PackedRGBA8 r) {
|
|||
unaligned_store(buf, r);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void commit_span(uint32_t* buf, PackedRGBA8 r, int len) {
|
||||
partial_store_span(buf, r, len);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE PackedRGBA8 blend_span(uint32_t* buf, PackedRGBA8 r) {
|
||||
return pack(blend_span(buf, unpack(r)));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE PackedRGBA8 blend_span(uint32_t* buf, PackedRGBA8 r,
|
||||
int len) {
|
||||
return pack(blend_span(buf, unpack(r), len));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void commit_span(uint8_t* buf, WideR8 r) {
|
||||
unaligned_store(buf, pack(r));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void commit_span(uint8_t* buf, WideR8 r, int len) {
|
||||
partial_store_span(buf, pack(r), len);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE WideR8 blend_span(uint8_t* buf, WideR8 r) {
|
||||
return blend_pixels(buf, unpack(unaligned_load<PackedR8>(buf)), r);
|
||||
}
|
||||
|
@ -175,6 +194,15 @@ static ALWAYS_INLINE void commit_blend_span(P* buf, R r) {
|
|||
}
|
||||
}
|
||||
|
||||
template <bool BLEND, typename P, typename R>
|
||||
static ALWAYS_INLINE void commit_blend_span(P* buf, R r, int len) {
|
||||
if (BLEND) {
|
||||
commit_span(buf, blend_span(buf, r, len), len);
|
||||
} else {
|
||||
commit_span(buf, r, len);
|
||||
}
|
||||
}
|
||||
|
||||
// Forces a value with vector run-class to have scalar run-class.
|
||||
template <typename T>
|
||||
static ALWAYS_INLINE auto swgl_forceScalar(T v) -> decltype(force_scalar(v)) {
|
||||
|
@ -545,9 +573,9 @@ static int blendTextureLinear(S sampler, vec2 uv, int span,
|
|||
// bounds. This requires a pointer to the destination buffer. An optional color
|
||||
// modulus can be supplied.
|
||||
template <bool BLEND, typename S, typename C, typename P>
|
||||
static int blendTextureNearest(S sampler, vec2 uv, int span,
|
||||
const vec4_scalar& uv_rect, C color, P* buf,
|
||||
float layer = 0) {
|
||||
static int blendTextureNearestFast(S sampler, vec2 uv, int span,
|
||||
const vec4_scalar& uv_rect, C color, P* buf,
|
||||
float layer = 0) {
|
||||
if (!matchTextureFormat(sampler, buf)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -587,23 +615,15 @@ static int blendTextureNearest(S sampler, vec2 uv, int span,
|
|||
int n = max(min(maxX + 1, endX) - curX, 0);
|
||||
// Try to process as many chunks as possible with full loads and stores.
|
||||
for (int end = curX + (n & ~3); curX < end; curX += 4, buf += 4) {
|
||||
auto src =
|
||||
applyColor(unpack(unaligned_load<packed_type>(&row[curX])), color);
|
||||
auto src = applyColor(unaligned_load<packed_type>(&row[curX]), color);
|
||||
commit_blend_span<BLEND>(buf, src);
|
||||
}
|
||||
n &= 3;
|
||||
// If we have any leftover samples after processing chunks, use partial loads
|
||||
// and stores.
|
||||
if (n > 0) {
|
||||
if (BLEND) {
|
||||
auto src = applyColor(
|
||||
unpack(partial_load_span<packed_type>(&row[curX], n)), color);
|
||||
partial_store_span(buf, pack(blend_span(buf, src, n)), n);
|
||||
} else {
|
||||
auto src =
|
||||
applyColor(partial_load_span<packed_type>(&row[curX], n), color);
|
||||
partial_store_span(buf, src, n);
|
||||
}
|
||||
auto src = applyColor(partial_load_span<packed_type>(&row[curX], n), color);
|
||||
commit_blend_span<BLEND>(buf, src, n);
|
||||
buf += n;
|
||||
curX += n;
|
||||
}
|
||||
|
@ -616,6 +636,16 @@ static int blendTextureNearest(S sampler, vec2 uv, int span,
|
|||
return span;
|
||||
}
|
||||
|
||||
// We need to verify that the pixel step reasonably approximates stepping
|
||||
// by a single texel for every pixel we need to reproduce. Try to ensure
|
||||
// that the margin of error is no more than approximately 2^-7.
|
||||
template <typename T>
|
||||
static ALWAYS_INLINE bool spanNeedsScale(int span, T P) {
|
||||
span &= ~(128 - 1);
|
||||
span += 128;
|
||||
return round((P.x.y - P.x.x) * span) != span;
|
||||
}
|
||||
|
||||
// Helper function to decide whether we can safely apply 1:1 nearest filtering
|
||||
// without diverging too much from the linear filter.
|
||||
template <typename S, typename T>
|
||||
|
@ -625,16 +655,11 @@ static inline LinearFilter needsTextureLinear(S sampler, T P, int span) {
|
|||
return LINEAR_FILTER_FALLBACK;
|
||||
}
|
||||
P = samplerScale(sampler, P);
|
||||
// We need to verify that the pixel step reasonably approximates stepping
|
||||
// by a single texel for every pixel we need to reproduce. Try to ensure
|
||||
// that the margin of error is no more than approximately 2^-7.
|
||||
span &= ~(128 - 1);
|
||||
span += 128;
|
||||
float dx = P.x.y - P.x.x;
|
||||
if (round(dx * span) != span) {
|
||||
// If the source region is smaller than the destination, then we can use the
|
||||
// upscaling filter since row Y is constant.
|
||||
return dx >= 0 && dx <= 1 ? LINEAR_FILTER_UPSCALE : LINEAR_FILTER_FALLBACK;
|
||||
if (spanNeedsScale(span, P)) {
|
||||
// If the source region is not flipped and smaller than the destination,
|
||||
// then we can use the upscaling filter since row Y is constant.
|
||||
return P.x.x <= P.x.y && P.x.y - P.x.x <= 1 ? LINEAR_FILTER_UPSCALE
|
||||
: LINEAR_FILTER_FALLBACK;
|
||||
}
|
||||
// Also verify that we're reasonably close to the center of a texel
|
||||
// so that it doesn't look that much different than if a linear filter
|
||||
|
@ -652,59 +677,227 @@ static inline LinearFilter needsTextureLinear(S sampler, T P, int span) {
|
|||
return LINEAR_FILTER_NEAREST;
|
||||
}
|
||||
|
||||
// Commit a single chunk from a linear texture fetch
|
||||
#define swgl_commitTextureLinear(format, s, p, uv_rect, color, ...) \
|
||||
do { \
|
||||
auto packed_color = packColor(swgl_Out##format, color); \
|
||||
int drawn = 0; \
|
||||
if (LinearFilter filter = needsTextureLinear(s, p, swgl_SpanLength)) { \
|
||||
if (blend_key) { \
|
||||
drawn = blendTextureLinear<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
filter, __VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureLinear<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
filter, __VA_ARGS__); \
|
||||
} \
|
||||
} else if (blend_key) { \
|
||||
drawn = blendTextureNearest<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureNearest<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
swgl_Out##format += drawn; \
|
||||
swgl_SpanLength -= drawn; \
|
||||
// Commit an entire span with linear filtering
|
||||
#define swgl_commitTextureLinear(format, s, p, uv_rect, color, ...) \
|
||||
do { \
|
||||
auto packed_color = packColor(swgl_Out##format, color); \
|
||||
int drawn = 0; \
|
||||
if (LinearFilter filter = needsTextureLinear(s, p, swgl_SpanLength)) { \
|
||||
if (blend_key) { \
|
||||
drawn = blendTextureLinear<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
filter, __VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureLinear<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
filter, __VA_ARGS__); \
|
||||
} \
|
||||
} else if (blend_key) { \
|
||||
drawn = blendTextureNearestFast<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureNearestFast<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
swgl_Out##format += drawn; \
|
||||
swgl_SpanLength -= drawn; \
|
||||
} while (0)
|
||||
#define swgl_commitTextureLinearRGBA8(s, p, uv_rect, ...) \
|
||||
swgl_commitTextureLinear(RGBA8, s, p, uv_rect, NoColor(), __VA_ARGS__)
|
||||
#define swgl_commitTextureLinearR8(s, p, uv_rect, ...) \
|
||||
swgl_commitTextureLinear(R8, s, p, uv_rect, NoColor(), __VA_ARGS__)
|
||||
|
||||
// Commit a single chunk from a linear texture fetch that is scaled by a color
|
||||
// Commit an entire span with linear filtering that is scaled by a color
|
||||
#define swgl_commitTextureLinearColorRGBA8(s, p, uv_rect, color, ...) \
|
||||
swgl_commitTextureLinear(RGBA8, s, p, uv_rect, color, __VA_ARGS__)
|
||||
#define swgl_commitTextureLinearColorR8(s, p, uv_rect, color, ...) \
|
||||
swgl_commitTextureLinear(R8, s, p, uv_rect, color, __VA_ARGS__)
|
||||
|
||||
// Commit a single chunk from a linear texture fetch
|
||||
#define swgl_commitTextureLinearChunk(format, s, p, color, ...) \
|
||||
swgl_commitChunk(format, applyColor(textureLinearUnpacked##format( \
|
||||
s, ivec2(p), __VA_ARGS__), \
|
||||
packColor(swgl_Out##format, color)))
|
||||
#define swgl_commitTextureLinearChunkRGBA8(s, p, ...) \
|
||||
swgl_commitTextureLinearChunk(RGBA8, s, p, NoColor(), __VA_ARGS__)
|
||||
#define swgl_commitTextureLinearChunkR8(s, p, ...) \
|
||||
swgl_commitTextureLinearChunk(R8, s, p, NoColor(), __VA_ARGS__)
|
||||
// Blends an entire span of texture with linear filtering and repeating UVs.
|
||||
template <bool BLEND, typename S, typename C, typename P>
|
||||
static int blendTextureLinearRepeat(S sampler, vec2 uv, int span,
|
||||
const vec4_scalar& uv_repeat,
|
||||
const vec4_scalar& uv_rect, C color, P* buf,
|
||||
float z = 0) {
|
||||
if (!matchTextureFormat(sampler, buf)) {
|
||||
return 0;
|
||||
}
|
||||
// We need to step UVs unscaled and unquantized so that we can modulo them
|
||||
// with fract. We use uv_scale and uv_offset to map them into the correct
|
||||
// range.
|
||||
vec2_scalar uv_step =
|
||||
float(swgl_StepSize) * vec2_scalar{uv.x.y - uv.x.x, uv.y.y - uv.y.x};
|
||||
vec2_scalar uv_scale = swgl_linearQuantizeStep(
|
||||
sampler,
|
||||
vec2_scalar{uv_repeat.z - uv_repeat.x, uv_repeat.w - uv_repeat.y});
|
||||
vec2_scalar uv_offset =
|
||||
swgl_linearQuantize(sampler, vec2_scalar{uv_repeat.x, uv_repeat.y});
|
||||
vec2_scalar min_uv =
|
||||
swgl_linearQuantize(sampler, vec2_scalar{uv_rect.x, uv_rect.y});
|
||||
vec2_scalar max_uv =
|
||||
swgl_linearQuantize(sampler, vec2_scalar{uv_rect.z, uv_rect.w});
|
||||
int zoffset = swgl_textureLayerOffset(sampler, z);
|
||||
for (P* end = buf + span; buf < end; buf += swgl_StepSize, uv += uv_step) {
|
||||
vec2 repeated_uv = clamp(fract(uv) * uv_scale + uv_offset, min_uv, max_uv);
|
||||
commit_blend_span<BLEND>(
|
||||
buf, applyColor(textureLinearUnpacked(buf, sampler, ivec2(repeated_uv),
|
||||
zoffset),
|
||||
color));
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
// Commit a single chunk from a linear texture fetch that is scaled by a color
|
||||
#define swgl_commitTextureLinearChunkColorRGBA8(s, p, color, ...) \
|
||||
swgl_commitTextureLinearChunk(RGBA8, s, p, color, __VA_ARGS__)
|
||||
#define swgl_commitTextureLinearChunkColorR8(s, p, color, ...) \
|
||||
swgl_commitTextureLinearChunk(R8, s, p, color, __VA_ARGS__)
|
||||
// Commit an entire span with linear filtering and repeating UVs
|
||||
#define swgl_commitTextureLinearRepeat(format, s, p, uv_repeat, uv_rect, \
|
||||
color, ...) \
|
||||
do { \
|
||||
auto packed_color = packColor(swgl_Out##format, color); \
|
||||
int drawn = 0; \
|
||||
if (blend_key) { \
|
||||
drawn = blendTextureLinearRepeat<true>(s, p, swgl_SpanLength, uv_repeat, \
|
||||
uv_rect, packed_color, \
|
||||
swgl_Out##format, __VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureLinearRepeat<false>( \
|
||||
s, p, swgl_SpanLength, uv_repeat, uv_rect, packed_color, \
|
||||
swgl_Out##format, __VA_ARGS__); \
|
||||
} \
|
||||
swgl_Out##format += drawn; \
|
||||
swgl_SpanLength -= drawn; \
|
||||
} while (0)
|
||||
#define swgl_commitTextureLinearRepeatRGBA8(s, p, uv_repeat, uv_rect, ...) \
|
||||
swgl_commitTextureLinearRepeat(RGBA8, s, p, uv_repeat, uv_rect, NoColor(), \
|
||||
__VA_ARGS__)
|
||||
#define swgl_commitTextureLinearRepeatColorRGBA8(s, p, uv_repeat, uv_rect, \
|
||||
color, ...) \
|
||||
swgl_commitTextureLinearRepeat(RGBA8, s, p, uv_repeat, uv_rect, color, \
|
||||
__VA_ARGS__)
|
||||
|
||||
template <typename S>
|
||||
static ALWAYS_INLINE PackedRGBA8 textureNearestPacked(UNUSED uint32_t* buf,
|
||||
S sampler, ivec2 i,
|
||||
int zoffset) {
|
||||
return textureNearestPackedRGBA8(sampler, i, zoffset);
|
||||
}
|
||||
|
||||
// Blends an entire span of texture with nearest filtering and either
|
||||
// repeated or clamped UVs.
|
||||
template <bool BLEND, bool REPEAT, typename S, typename C, typename P>
|
||||
static int blendTextureNearestRepeat(S sampler, vec2 uv, int span,
|
||||
const vec4_scalar& uv_rect, C color,
|
||||
P* buf, float z = 0) {
|
||||
if (!matchTextureFormat(sampler, buf)) {
|
||||
return 0;
|
||||
}
|
||||
if (!REPEAT) {
|
||||
// If clamping, then we step pre-scaled to the sampler. For repeat modes,
|
||||
// this will be accomplished via uv_scale instead.
|
||||
uv = samplerScale(sampler, uv);
|
||||
}
|
||||
vec2_scalar uv_step =
|
||||
float(swgl_StepSize) * vec2_scalar{uv.x.y - uv.x.x, uv.y.y - uv.y.x};
|
||||
vec2_scalar min_uv = samplerScale(sampler, vec2_scalar{uv_rect.x, uv_rect.y});
|
||||
vec2_scalar max_uv = samplerScale(sampler, vec2_scalar{uv_rect.z, uv_rect.w});
|
||||
vec2_scalar uv_scale = max_uv - min_uv;
|
||||
int zoffset = swgl_textureLayerOffset(sampler, z);
|
||||
// If the effective sampling area of this texture is only a single pixel, then
|
||||
// treat it as a solid span. For repeat modes, the bounds are specified on
|
||||
// pixel boundaries, whereas for clamp modes, bounds are on pixel centers, so
|
||||
// the test varies depending on which. If the sample range on an axis is
|
||||
// greater than one pixel, we can still check if we don't move far enough from
|
||||
// the pixel center on that axis to hit the next pixel.
|
||||
if ((int(min_uv.x) + (REPEAT ? 1 : 0) >= int(max_uv.x) ||
|
||||
(uv_step.x * span * (REPEAT ? uv_scale.x : 1.0f) < 0.5f)) &&
|
||||
(int(min_uv.y) + (REPEAT ? 1 : 0) >= int(max_uv.y) ||
|
||||
(uv_step.y * span * (REPEAT ? uv_scale.y : 1.0f) < 0.5f))) {
|
||||
vec2 repeated_uv =
|
||||
REPEAT ? fract(uv) * uv_scale + min_uv : clamp(uv, min_uv, max_uv);
|
||||
commit_solid_span<BLEND>(
|
||||
buf,
|
||||
applyColor(unpack(textureNearestPacked(buf, sampler, ivec2(repeated_uv),
|
||||
zoffset)),
|
||||
color),
|
||||
span);
|
||||
} else {
|
||||
for (P* end = buf + span; buf < end; buf += swgl_StepSize, uv += uv_step) {
|
||||
vec2 repeated_uv =
|
||||
REPEAT ? fract(uv) * uv_scale + min_uv : clamp(uv, min_uv, max_uv);
|
||||
commit_blend_span<BLEND>(
|
||||
buf, applyColor(textureNearestPacked(buf, sampler, ivec2(repeated_uv),
|
||||
zoffset),
|
||||
color));
|
||||
}
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
// Determine if we can use the fast nearest filter for the given nearest mode.
|
||||
// If the Y coordinate varies more than half a pixel over
|
||||
// the span (which might cause the texel to alias to the next one), or the span
|
||||
// needs X scaling, then we have to use the fallback.
|
||||
template <typename S, typename T>
|
||||
static ALWAYS_INLINE bool needsNearestFallback(S sampler, T P, int span) {
|
||||
P = samplerScale(sampler, P);
|
||||
return (P.y.y - P.y.x) * span >= 0.5f || spanNeedsScale(span, P);
|
||||
}
|
||||
|
||||
// Commit an entire span with nearest filtering and either clamped or repeating
|
||||
// UVs
|
||||
#define swgl_commitTextureNearest(format, repeat, s, p, uv_rect, color, ...) \
|
||||
do { \
|
||||
auto packed_color = packColor(swgl_Out##format, color); \
|
||||
int drawn = 0; \
|
||||
if (repeat || needsNearestFallback(s, p, swgl_SpanLength)) { \
|
||||
if (blend_key) { \
|
||||
drawn = blendTextureNearestRepeat<true, repeat>( \
|
||||
s, p, swgl_SpanLength, uv_rect, packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureNearestRepeat<false, repeat>( \
|
||||
s, p, swgl_SpanLength, uv_rect, packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
} else if (blend_key) { \
|
||||
drawn = blendTextureNearestFast<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendTextureNearestFast<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||
packed_color, swgl_Out##format, \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
swgl_Out##format += drawn; \
|
||||
swgl_SpanLength -= drawn; \
|
||||
} while (0)
|
||||
#define swgl_commitTextureNearestRGBA8(s, p, uv_rect, ...) \
|
||||
swgl_commitTextureNearest(RGBA8, false, s, p, uv_rect, NoColor(), __VA_ARGS__)
|
||||
#define swgl_commitTextureNearestColorRGBA8(s, p, uv_rect, color, ...) \
|
||||
swgl_commitTextureNearest(RGBA8, false, s, p, uv_rect, color, __VA_ARGS__)
|
||||
#define swgl_commitTextureNearestRepeatRGBA8(s, p, uv_repeat, uv_rect, ...) \
|
||||
swgl_commitTextureNearest(RGBA8, true, s, p, uv_repeat, NoColor(), \
|
||||
__VA_ARGS__)
|
||||
#define swgl_commitTextureNearestRepeatColorRGBA8(s, p, uv_repeat, uv_rect, \
|
||||
color, ...) \
|
||||
swgl_commitTextureNearest(RGBA8, true, s, p, uv_repeat, color, __VA_ARGS__)
|
||||
|
||||
// Commit an entire span of texture with filtering determined by sampler state.
|
||||
#define swgl_commitTexture(format, s, ...) \
|
||||
do { \
|
||||
if (s->filter == TextureFilter::LINEAR) { \
|
||||
swgl_commitTextureLinear##format(s, __VA_ARGS__); \
|
||||
} else { \
|
||||
swgl_commitTextureNearest##format(s, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define swgl_commitTextureRGBA8(...) swgl_commitTexture(RGBA8, __VA_ARGS__)
|
||||
#define swgl_commitTextureColorRGBA8(...) \
|
||||
swgl_commitTexture(ColorRGBA8, __VA_ARGS__)
|
||||
#define swgl_commitTextureRepeatRGBA8(...) \
|
||||
swgl_commitTexture(RepeatRGBA8, __VA_ARGS__)
|
||||
#define swgl_commitTextureRepeatColorRGBA8(...) \
|
||||
swgl_commitTexture(RepeatColorRGBA8, __VA_ARGS__)
|
||||
|
||||
// Commit an entire span of a separable pass of a Gaussian blur that falls
|
||||
// within the given radius scaled by supplied coefficients, clamped to uv_rect
|
||||
|
@ -792,9 +985,12 @@ static ALWAYS_INLINE PackedRGBA8 sampleYUV(S0 sampler0, ivec2 uv0, int layer0,
|
|||
}
|
||||
|
||||
template <bool BLEND, typename S0, typename P, typename C = NoColor>
|
||||
static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||
const vec4_scalar uv_rect0, float z0, int colorSpace,
|
||||
int rescaleFactor, C color = C()) {
|
||||
static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||
const vec4_scalar uv_rect0, float z0, int colorSpace,
|
||||
int rescaleFactor, C color = C()) {
|
||||
if (!swgl_isTextureLinear(sampler0)) {
|
||||
return 0;
|
||||
}
|
||||
LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0, z0,
|
||||
layer0);
|
||||
auto c = packColor(buf, color);
|
||||
|
@ -805,6 +1001,7 @@ static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
|||
layer0, colorSpace, rescaleFactor),
|
||||
c));
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
template <typename S0, typename S1>
|
||||
|
@ -833,10 +1030,13 @@ static ALWAYS_INLINE PackedRGBA8 sampleYUV(S0 sampler0, ivec2 uv0, int layer0,
|
|||
|
||||
template <bool BLEND, typename S0, typename S1, typename P,
|
||||
typename C = NoColor>
|
||||
static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||
const vec4_scalar uv_rect0, float z0, S1 sampler1,
|
||||
vec2 uv1, const vec4_scalar uv_rect1, float z1,
|
||||
int colorSpace, int rescaleFactor, C color = C()) {
|
||||
static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||
const vec4_scalar uv_rect0, float z0, S1 sampler1, vec2 uv1,
|
||||
const vec4_scalar uv_rect1, float z1, int colorSpace,
|
||||
int rescaleFactor, C color = C()) {
|
||||
if (!swgl_isTextureLinear(sampler0) || !swgl_isTextureLinear(sampler1)) {
|
||||
return 0;
|
||||
}
|
||||
LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0, z0,
|
||||
layer0);
|
||||
LINEAR_QUANTIZE_UV(sampler1, uv1, uv_step1, uv_rect1, min_uv1, max_uv1, z1,
|
||||
|
@ -851,6 +1051,7 @@ static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
|||
colorSpace, rescaleFactor),
|
||||
c));
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
template <typename S0, typename S1, typename S2>
|
||||
|
@ -890,12 +1091,15 @@ static ALWAYS_INLINE PackedRGBA8 sampleYUV(S0 sampler0, ivec2 uv0, int layer0,
|
|||
|
||||
template <bool BLEND, typename S0, typename S1, typename S2, typename P,
|
||||
typename C = NoColor>
|
||||
static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||
const vec4_scalar uv_rect0, float z0, S1 sampler1,
|
||||
vec2 uv1, const vec4_scalar uv_rect1, float z1,
|
||||
S2 sampler2, vec2 uv2, const vec4_scalar uv_rect2,
|
||||
float z2, int colorSpace, int rescaleFactor,
|
||||
C color = C()) {
|
||||
static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||
const vec4_scalar uv_rect0, float z0, S1 sampler1, vec2 uv1,
|
||||
const vec4_scalar uv_rect1, float z1, S2 sampler2, vec2 uv2,
|
||||
const vec4_scalar uv_rect2, float z2, int colorSpace,
|
||||
int rescaleFactor, C color = C()) {
|
||||
if (!swgl_isTextureLinear(sampler0) || !swgl_isTextureLinear(sampler1) ||
|
||||
!swgl_isTextureLinear(sampler2)) {
|
||||
return 0;
|
||||
}
|
||||
LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0, z0,
|
||||
layer0);
|
||||
LINEAR_QUANTIZE_UV(sampler1, uv1, uv_step1, uv_rect1, min_uv1, max_uv1, z1,
|
||||
|
@ -914,6 +1118,7 @@ static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
|||
layer2, colorSpace, rescaleFactor),
|
||||
c));
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
// Commit a single chunk of a YUV surface represented by multiple planar
|
||||
|
@ -922,15 +1127,16 @@ static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
|||
// selects how many bits of precision must be utilized on conversion. See the
|
||||
// sampleYUV dispatcher functions for the various supported plane
|
||||
// configurations this intrinsic accepts.
|
||||
#define swgl_commitTextureLinearYUV(...) \
|
||||
do { \
|
||||
if (blend_key) { \
|
||||
blendYUV<true>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
||||
} else { \
|
||||
blendYUV<false>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
||||
} \
|
||||
swgl_OutRGBA8 += swgl_SpanLength; \
|
||||
swgl_SpanLength = 0; \
|
||||
#define swgl_commitTextureLinearYUV(...) \
|
||||
do { \
|
||||
int drawn = 0; \
|
||||
if (blend_key) { \
|
||||
drawn = blendYUV<true>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
||||
} else { \
|
||||
drawn = blendYUV<false>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
||||
} \
|
||||
swgl_OutRGBA8 += drawn; \
|
||||
swgl_SpanLength -= drawn; \
|
||||
} while (0)
|
||||
|
||||
// Commit a single chunk of a YUV surface scaled by a color.
|
||||
|
|
|
@ -1054,6 +1054,17 @@ static PackedRGBA8 textureLinearPackedRGBA8(S sampler, ivec2 i,
|
|||
return pack(textureLinearUnpackedRGBA8(sampler, i, zoffset));
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static PackedRGBA8 textureNearestPackedRGBA8(S sampler, ivec2 i,
|
||||
int zoffset = 0) {
|
||||
assert(sampler->format == TextureFormat::RGBA8);
|
||||
I32 row = computeRow(sampler, i, zoffset, 0);
|
||||
return combine(unaligned_load<V4<uint8_t>>(&sampler->buf[row.x]),
|
||||
unaligned_load<V4<uint8_t>>(&sampler->buf[row.y]),
|
||||
unaligned_load<V4<uint8_t>>(&sampler->buf[row.z]),
|
||||
unaligned_load<V4<uint8_t>>(&sampler->buf[row.w]));
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static PackedR8 textureLinearPackedR8(S sampler, ivec2 i, int zoffset = 0) {
|
||||
return pack(textureLinearUnpackedR8(sampler, i, zoffset));
|
||||
|
|
|
@ -273,9 +273,10 @@ void brush_vs(
|
|||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
vec2 compute_repeated_uvs(float perspective_divisor) {
|
||||
#ifdef WR_FEATURE_REPETITION
|
||||
vec2 uv_size = v_uv_bounds.zw - v_uv_bounds.xy;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
#if defined(WR_FEATURE_ALPHA_PASS) && !defined(SWGL_ANTIALIAS)
|
||||
// This prevents the uv on the top and left parts of the primitive that was inflated
|
||||
// for anti-aliasing purposes from going beyound the range covered by the regular
|
||||
// (non-inflated) primitive.
|
||||
|
@ -293,21 +294,19 @@ vec2 compute_repeated_uvs(float perspective_divisor) {
|
|||
if (local_uv.y >= v_tile_repeat.y) {
|
||||
repeated_uv.y = v_uv_bounds.w;
|
||||
}
|
||||
#else
|
||||
#else
|
||||
vec2 repeated_uv = fract(v_uv * perspective_divisor) * uv_size + v_uv_bounds.xy;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return repeated_uv;
|
||||
#else
|
||||
return v_uv * perspective_divisor + v_uv_bounds.xy;
|
||||
#endif
|
||||
}
|
||||
|
||||
Fragment brush_fs() {
|
||||
float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_layer_and_perspective.y);
|
||||
|
||||
#ifdef WR_FEATURE_REPETITION
|
||||
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
|
||||
#else
|
||||
vec2 repeated_uv = v_uv * perspective_divisor + v_uv_bounds.xy;
|
||||
#endif
|
||||
|
||||
// Clamp the uvs to avoid sampling artifacts.
|
||||
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
|
||||
|
@ -341,7 +340,7 @@ Fragment brush_fs() {
|
|||
|
||||
#if defined(SWGL_DRAW_SPAN) && (!defined(WR_FEATURE_ALPHA_PASS) || !defined(WR_FEATURE_DUAL_SOURCE_BLENDING))
|
||||
void swgl_drawSpanRGBA8() {
|
||||
if (!swgl_isTextureRGBA8(sColor0) || !swgl_isTextureLinear(sColor0)) {
|
||||
if (!swgl_isTextureRGBA8(sColor0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -353,39 +352,29 @@ void swgl_drawSpanRGBA8() {
|
|||
|
||||
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_layer_and_perspective.y);
|
||||
|
||||
#ifndef WR_FEATURE_REPETITION
|
||||
vec2 uv = v_uv * perspective_divisor + v_uv_bounds.xy;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
if (v_color != vec4(1.0)) {
|
||||
swgl_commitTextureLinearColorRGBA8(sColor0, uv, v_uv_sample_bounds, v_color, v_layer_and_perspective.x);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
swgl_commitTextureLinearRGBA8(sColor0, uv, v_uv_sample_bounds, v_layer_and_perspective.x);
|
||||
#ifdef WR_FEATURE_REPETITION
|
||||
// Get the UVs before any repetition, scaling, or offsetting has occurred...
|
||||
vec2 uv = v_uv * perspective_divisor;
|
||||
#else
|
||||
int layer = swgl_textureLayerOffset(sColor0, v_layer_and_perspective.x);
|
||||
vec2 uv = compute_repeated_uvs(perspective_divisor);
|
||||
#endif
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
if (v_color != vec4(1.0)) {
|
||||
while (swgl_SpanLength > 0) {
|
||||
vec4 color = v_color;
|
||||
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
|
||||
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
|
||||
swgl_commitTextureLinearChunkColorRGBA8(sColor0, swgl_linearQuantize(sColor0, uv), color, layer);
|
||||
v_uv += swgl_interpStep(v_uv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// No clip or color scaling required, so just fall through to a normal textured span...
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
if (v_color != vec4(1.0)) {
|
||||
#ifdef WR_FEATURE_REPETITION
|
||||
swgl_commitTextureRepeatColorRGBA8(sColor0, uv, v_uv_bounds, v_uv_sample_bounds, v_color, v_layer_and_perspective.x);
|
||||
#else
|
||||
swgl_commitTextureColorRGBA8(sColor0, uv, v_uv_sample_bounds, v_color, v_layer_and_perspective.x);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// No color scaling required, so just fall through to a normal textured span...
|
||||
#endif
|
||||
|
||||
while (swgl_SpanLength > 0) {
|
||||
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
|
||||
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
|
||||
swgl_commitTextureLinearChunkRGBA8(sColor0, swgl_linearQuantize(sColor0, uv), layer);
|
||||
v_uv += swgl_interpStep(v_uv);
|
||||
}
|
||||
#ifdef WR_FEATURE_REPETITION
|
||||
swgl_commitTextureRepeatRGBA8(sColor0, uv, v_uv_bounds, v_uv_sample_bounds, v_layer_and_perspective.x);
|
||||
#else
|
||||
swgl_commitTextureRGBA8(sColor0, uv, v_uv_sample_bounds, v_layer_and_perspective.x);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -118,27 +118,15 @@ Fragment brush_fs() {
|
|||
#ifdef SWGL_DRAW_SPAN
|
||||
void swgl_drawSpanRGBA8() {
|
||||
if (vFormat == YUV_FORMAT_PLANAR) {
|
||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1) || !swgl_isTextureLinear(sColor2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
||||
sColor1, vUv_U, vUvBounds_U, vYuvLayers.y,
|
||||
sColor2, vUv_V, vUvBounds_V, vYuvLayers.z,
|
||||
vYuvColorSpace, vRescaleFactor);
|
||||
} else if (vFormat == YUV_FORMAT_NV12) {
|
||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
||||
sColor1, vUv_U, vUvBounds_U, vYuvLayers.y,
|
||||
vYuvColorSpace, vRescaleFactor);
|
||||
} else if (vFormat == YUV_FORMAT_INTERLEAVED) {
|
||||
if (!swgl_isTextureLinear(sColor0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
||||
vYuvColorSpace, vRescaleFactor);
|
||||
}
|
||||
|
|
|
@ -161,39 +161,23 @@ void main(void) {
|
|||
void swgl_drawSpanRGBA8() {
|
||||
#ifdef WR_FEATURE_YUV
|
||||
if (vYuvFormat == YUV_FORMAT_PLANAR) {
|
||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1) || !swgl_isTextureLinear(sColor2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
||||
sColor1, vUV_u, vUVBounds_u, vYuvLayers.y,
|
||||
sColor2, vUV_v, vUVBounds_v, vYuvLayers.z,
|
||||
vYuvColorSpace, vRescaleFactor);
|
||||
} else if (vYuvFormat == YUV_FORMAT_NV12) {
|
||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
||||
sColor1, vUV_u, vUVBounds_u, vYuvLayers.y,
|
||||
vYuvColorSpace, vRescaleFactor);
|
||||
} else if (vYuvFormat == YUV_FORMAT_INTERLEAVED) {
|
||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
||||
vYuvColorSpace, vRescaleFactor);
|
||||
}
|
||||
#else
|
||||
if (!swgl_isTextureLinear(sColor0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vColor != vec4(1.0)) {
|
||||
swgl_commitTextureLinearColorRGBA8(sColor0, vUv, vUVBounds, vColor, vLayer);
|
||||
swgl_commitTextureColorRGBA8(sColor0, vUv, vUVBounds, vColor, vLayer);
|
||||
} else {
|
||||
swgl_commitTextureLinearRGBA8(sColor0, vUv, vUVBounds, vLayer);
|
||||
swgl_commitTextureRGBA8(sColor0, vUv, vUVBounds, vLayer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ void write_gradient_vertex(
|
|||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
vec2 compute_repeated_pos() {
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
#if defined(WR_FEATURE_ALPHA_PASS) && !defined(SWGL_ANTIALIAS)
|
||||
// Handle top and left inflated edges (see brush_image).
|
||||
vec2 local_pos = max(v_pos, vec2(0.0));
|
||||
|
||||
|
|
|
@ -121,14 +121,10 @@ void main(void) {
|
|||
|
||||
#ifdef SWGL_DRAW_SPAN
|
||||
void swgl_drawSpanRGBA8() {
|
||||
if (!swgl_isTextureLinear(sColor0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, vPerspective);
|
||||
vec2 uv = vUv * perspective_divisor;
|
||||
|
||||
swgl_commitTextureLinearRGBA8(sColor0, uv, vUvSampleBounds, 0.0);
|
||||
swgl_commitTextureRGBA8(sColor0, uv, vUvSampleBounds, 0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ fuzzy(1,32) == multiply-2.yaml multiply-2-ref.yaml
|
|||
fuzzy(1,32) == color_targets(4) alpha_targets(0) multiply-3.yaml multiply-2-ref.yaml
|
||||
== difference.yaml difference-ref.yaml
|
||||
fuzzy(1,30000) == difference-transparent.yaml difference-transparent-ref.yaml
|
||||
== darken.yaml darken-ref.yaml
|
||||
== lighten.yaml lighten-ref.yaml
|
||||
fuzzy-if(platform(swgl),1,10000) == darken.yaml darken-ref.yaml
|
||||
fuzzy-if(platform(swgl),1,10000) == lighten.yaml lighten-ref.yaml
|
||||
|
||||
fuzzy(1,32) == repeated-difference.yaml repeated-difference-ref.yaml
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ platform(linux,mac) == draw_calls(7) color_targets(7) alpha_targets(0) filter-bl
|
|||
== invisible.yaml invisible-ref.yaml
|
||||
fuzzy-if(platform(swgl),1,10000) == opacity.yaml opacity-ref.yaml
|
||||
fuzzy-range(<=1,*10000) == opacity-combined.yaml opacity-combined-ref.yaml
|
||||
== opacity-overlap.yaml opacity-overlap-ref.yaml
|
||||
fuzzy-if(platform(swgl),1,10000) == opacity-overlap.yaml opacity-overlap-ref.yaml
|
||||
== filter-brightness.yaml filter-brightness-ref.yaml
|
||||
== filter-brightness-2.yaml filter-brightness-2-ref.yaml
|
||||
== filter-brightness-3.yaml filter-brightness-3-ref.yaml
|
||||
== filter-brightness-4.yaml filter-brightness-4-ref.yaml
|
||||
fuzzy-if(platform(swgl),1,10000) == filter-brightness-4.yaml filter-brightness-4-ref.yaml
|
||||
== filter-component-transfer.yaml filter-component-transfer-ref.yaml
|
||||
skip_on(android,device) == filter-color-matrix.yaml filter-color-matrix-ref.yaml # fails on Pixel2
|
||||
== filter-contrast-gray-alpha-1.yaml filter-contrast-gray-alpha-1-ref.yaml
|
||||
|
|
|
@ -1695,7 +1695,7 @@ fuzzy-if(skiaContent,0-1,0-1) == 751012-1a.html 751012-1-ref.html
|
|||
fuzzy-if(skiaContent,0-1,0-1) == 751012-1b.html 751012-1-ref.html
|
||||
== 753329-1.html about:blank
|
||||
== 758561-1.html 758561-1-ref.html
|
||||
fuzzy-if(true,0-1,0-90) fuzzy-if(skiaContent,0-1,0-320) fuzzy-if(webrender&&swgl,1-1,1382-1382) == 759036-1.html 759036-1-ref.html
|
||||
fuzzy-if(true,0-1,0-90) fuzzy-if(skiaContent,0-1,0-320) == 759036-1.html 759036-1-ref.html
|
||||
fuzzy-if(true,0-17,0-5886) fuzzy-if(skiaContent,0-9,0-5894) fuzzy-if(geckoview&&webrender&&device,3-3,5831-5855) == 759036-2.html 759036-2-ref.html
|
||||
== 776265-1a.html 776265-1-ref.html
|
||||
== 776265-1b.html 776265-1-ref.html
|
||||
|
@ -2037,7 +2037,7 @@ fuzzy(0-255,0-4054) == 1415987-1.html 1415987-1-ref.html # this is a large fuzz,
|
|||
== 1424680.html 1424680-ref.html
|
||||
== 1424798-1.html 1424798-ref.html
|
||||
fuzzy-if(!webrender,0-74,0-2234) == 1425243-1.html 1425243-1-ref.html
|
||||
fuzzy-if(Android,0-66,0-574) fuzzy-if(d2d,0-89,0-777) fuzzy-if(!Android&&!d2d,0-1,0-31380) fuzzy-if(webrender&&winWidget,1-1,31240-31320) fuzzy-if(webrender&&swgl,1-1,31452-31676) == 1425243-2.html 1425243-2-ref.html
|
||||
fuzzy-if(Android,0-66,0-574) fuzzy-if(d2d,0-89,0-777) fuzzy-if(!Android&&!d2d,0-1,0-31380) fuzzy-if(webrender&&winWidget&&!swgl,1-1,31240-31320) == 1425243-2.html 1425243-2-ref.html
|
||||
== 1430869.html 1430869-ref.html
|
||||
== 1432541.html 1432541-ref.html
|
||||
== 1446470.html 1035091-ref.html
|
||||
|
|
|
@ -272,7 +272,7 @@ fuzzy-if(webrender&&winWidget,0-1,0-5) == grid-fragmentation-dyn5-027.html grid-
|
|||
== grid-fragmentation-dyn1-029.html grid-fragmentation-029-ref.html
|
||||
== grid-fragmentation-dyn2-029.html grid-fragmentation-029-ref.html
|
||||
== grid-fragmentation-dyn2-030.html grid-fragmentation-030-ref.html
|
||||
== grid-fragmentation-dyn2-031.html grid-fragmentation-031-ref.html
|
||||
fuzzy-if(webrender&&winWidget&&swgl,0-2,0-30) == grid-fragmentation-dyn2-031.html grid-fragmentation-031-ref.html
|
||||
|
||||
== bug1306106.html bug1306106-ref.html
|
||||
== grid-percent-intrinsic-sizing-001.html grid-percent-intrinsic-sizing-001-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче