зеркало из 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)],
|
vec![Type::new(*s)],
|
||||||
RunClass::Scalar,
|
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(
|
declare_function(
|
||||||
state,
|
state,
|
||||||
"swgl_commitTextureLinearRGBA8",
|
"swgl_commitTextureLinearRGBA8",
|
||||||
|
@ -3896,6 +3860,80 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio
|
||||||
Type::new(Void),
|
Type::new(Void),
|
||||||
vec![Type::new(*s), Type::new(Vec2), Type::new(Vec4), Type::new(Float), Type::new(Float)],
|
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(
|
declare_function(
|
||||||
state,
|
state,
|
||||||
"swgl_commitGaussianBlurRGBA8",
|
"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
|
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.
|
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
|
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
|
signed-distance field approximation. WR would normally try to discern the
|
||||||
2D local-space coordinates of a given destination pixel relative to 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
|
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
|
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.
|
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): {
|
case BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||||
WideRGBA8 secondary =
|
WideRGBA8 secondary =
|
||||||
muldiv256(dst,
|
muldiv256(dst,
|
||||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.0f));
|
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.49f));
|
||||||
return src + dst - secondary;
|
return src + dst - secondary;
|
||||||
}
|
}
|
||||||
case MASK_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
case MASK_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||||
WideRGBA8 secondary =
|
WideRGBA8 secondary =
|
||||||
muldiv256(dst,
|
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);
|
WideRGBA8 mask = load_clip_mask(buf, span);
|
||||||
return muldiv255(src, mask) + dst - muldiv255(secondary, mask);
|
return muldiv255(src, mask) + dst - muldiv255(secondary, mask);
|
||||||
}
|
}
|
||||||
case AA_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
case AA_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||||
WideRGBA8 secondary =
|
WideRGBA8 secondary =
|
||||||
muldiv256(dst,
|
muldiv256(dst,
|
||||||
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.0f));
|
pack_pixels_RGBA8(fragment_shader->gl_SecondaryFragColor, 256.49f));
|
||||||
DO_AA(RGBA8, {
|
DO_AA(RGBA8, {
|
||||||
src = muldiv256(src, aa);
|
src = muldiv256(src, aa);
|
||||||
secondary = muldiv256(secondary, 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): {
|
case AA_MASK_BLEND_KEY(GL_ONE, GL_ONE_MINUS_SRC1_COLOR): {
|
||||||
WideRGBA8 secondary =
|
WideRGBA8 secondary =
|
||||||
muldiv256(dst,
|
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);
|
WideRGBA8 mask = load_clip_mask(buf, span);
|
||||||
DO_AA(RGBA8, mask = muldiv256(mask, aa));
|
DO_AA(RGBA8, mask = muldiv256(mask, aa));
|
||||||
return muldiv255(src, mask) + dst - muldiv255(secondary, mask);
|
return muldiv255(src, mask) + dst - muldiv255(secondary, mask);
|
||||||
|
|
|
@ -1672,6 +1672,14 @@ struct vec4_scalar {
|
||||||
return *this;
|
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) {
|
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;
|
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;
|
w /= a.w;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
vec4& operator*=(vec4 a) {
|
||||||
|
x *= a.x;
|
||||||
|
y *= a.y;
|
||||||
|
z *= a.z;
|
||||||
|
w *= a.w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
vec4& operator*=(Float a) {
|
vec4& operator*=(Float a) {
|
||||||
x *= a;
|
x *= a;
|
||||||
y *= a;
|
y *= a;
|
||||||
|
|
|
@ -32,20 +32,22 @@ static ALWAYS_INLINE P applyColor(P src, P color) {
|
||||||
return muldiv256(src, color);
|
return muldiv256(src, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE PackedRGBA8 applyColor(PackedRGBA8 src, WideRGBA8 color) {
|
static ALWAYS_INLINE WideRGBA8 applyColor(PackedRGBA8 src, WideRGBA8 color) {
|
||||||
return pack(muldiv256(unpack(src), color));
|
return muldiv256(unpack(src), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE PackedR8 applyColor(PackedR8 src, WideR8 color) {
|
static ALWAYS_INLINE WideR8 applyColor(PackedR8 src, WideR8 color) {
|
||||||
return pack(muldiv256(unpack(src), color));
|
return muldiv256(unpack(src), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packs a color on a scale of 0..256 rather than 0..255 to allow faster scale
|
// 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
|
// 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>
|
template <typename P, typename C>
|
||||||
static ALWAYS_INLINE auto packColor(P* buf, C color) {
|
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>
|
template <typename P>
|
||||||
|
@ -57,6 +59,10 @@ static ALWAYS_INLINE void commit_span(uint32_t* buf, WideRGBA8 r) {
|
||||||
unaligned_store(buf, pack(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) {
|
static ALWAYS_INLINE WideRGBA8 blend_span(uint32_t* buf, WideRGBA8 r) {
|
||||||
return blend_pixels(buf, unaligned_load<PackedRGBA8>(buf), 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);
|
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) {
|
static ALWAYS_INLINE PackedRGBA8 blend_span(uint32_t* buf, PackedRGBA8 r) {
|
||||||
return pack(blend_span(buf, unpack(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) {
|
static ALWAYS_INLINE void commit_span(uint8_t* buf, WideR8 r) {
|
||||||
unaligned_store(buf, pack(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) {
|
static ALWAYS_INLINE WideR8 blend_span(uint8_t* buf, WideR8 r) {
|
||||||
return blend_pixels(buf, unpack(unaligned_load<PackedR8>(buf)), 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.
|
// Forces a value with vector run-class to have scalar run-class.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static ALWAYS_INLINE auto swgl_forceScalar(T v) -> decltype(force_scalar(v)) {
|
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
|
// bounds. This requires a pointer to the destination buffer. An optional color
|
||||||
// modulus can be supplied.
|
// modulus can be supplied.
|
||||||
template <bool BLEND, typename S, typename C, typename P>
|
template <bool BLEND, typename S, typename C, typename P>
|
||||||
static int blendTextureNearest(S sampler, vec2 uv, int span,
|
static int blendTextureNearestFast(S sampler, vec2 uv, int span,
|
||||||
const vec4_scalar& uv_rect, C color, P* buf,
|
const vec4_scalar& uv_rect, C color, P* buf,
|
||||||
float layer = 0) {
|
float layer = 0) {
|
||||||
if (!matchTextureFormat(sampler, buf)) {
|
if (!matchTextureFormat(sampler, buf)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -587,23 +615,15 @@ static int blendTextureNearest(S sampler, vec2 uv, int span,
|
||||||
int n = max(min(maxX + 1, endX) - curX, 0);
|
int n = max(min(maxX + 1, endX) - curX, 0);
|
||||||
// Try to process as many chunks as possible with full loads and stores.
|
// 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) {
|
for (int end = curX + (n & ~3); curX < end; curX += 4, buf += 4) {
|
||||||
auto src =
|
auto src = applyColor(unaligned_load<packed_type>(&row[curX]), color);
|
||||||
applyColor(unpack(unaligned_load<packed_type>(&row[curX])), color);
|
|
||||||
commit_blend_span<BLEND>(buf, src);
|
commit_blend_span<BLEND>(buf, src);
|
||||||
}
|
}
|
||||||
n &= 3;
|
n &= 3;
|
||||||
// If we have any leftover samples after processing chunks, use partial loads
|
// If we have any leftover samples after processing chunks, use partial loads
|
||||||
// and stores.
|
// and stores.
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
if (BLEND) {
|
auto src = applyColor(partial_load_span<packed_type>(&row[curX], n), color);
|
||||||
auto src = applyColor(
|
commit_blend_span<BLEND>(buf, src, n);
|
||||||
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);
|
|
||||||
}
|
|
||||||
buf += n;
|
buf += n;
|
||||||
curX += n;
|
curX += n;
|
||||||
}
|
}
|
||||||
|
@ -616,6 +636,16 @@ static int blendTextureNearest(S sampler, vec2 uv, int span,
|
||||||
return 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
|
// Helper function to decide whether we can safely apply 1:1 nearest filtering
|
||||||
// without diverging too much from the linear filter.
|
// without diverging too much from the linear filter.
|
||||||
template <typename S, typename T>
|
template <typename S, typename T>
|
||||||
|
@ -625,16 +655,11 @@ static inline LinearFilter needsTextureLinear(S sampler, T P, int span) {
|
||||||
return LINEAR_FILTER_FALLBACK;
|
return LINEAR_FILTER_FALLBACK;
|
||||||
}
|
}
|
||||||
P = samplerScale(sampler, P);
|
P = samplerScale(sampler, P);
|
||||||
// We need to verify that the pixel step reasonably approximates stepping
|
if (spanNeedsScale(span, P)) {
|
||||||
// by a single texel for every pixel we need to reproduce. Try to ensure
|
// If the source region is not flipped and smaller than the destination,
|
||||||
// that the margin of error is no more than approximately 2^-7.
|
// then we can use the upscaling filter since row Y is constant.
|
||||||
span &= ~(128 - 1);
|
return P.x.x <= P.x.y && P.x.y - P.x.x <= 1 ? LINEAR_FILTER_UPSCALE
|
||||||
span += 128;
|
: LINEAR_FILTER_FALLBACK;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// Also verify that we're reasonably close to the center of a texel
|
// 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
|
// 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;
|
return LINEAR_FILTER_NEAREST;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit a single chunk from a linear texture fetch
|
// Commit an entire span with linear filtering
|
||||||
#define swgl_commitTextureLinear(format, s, p, uv_rect, color, ...) \
|
#define swgl_commitTextureLinear(format, s, p, uv_rect, color, ...) \
|
||||||
do { \
|
do { \
|
||||||
auto packed_color = packColor(swgl_Out##format, color); \
|
auto packed_color = packColor(swgl_Out##format, color); \
|
||||||
int drawn = 0; \
|
int drawn = 0; \
|
||||||
if (LinearFilter filter = needsTextureLinear(s, p, swgl_SpanLength)) { \
|
if (LinearFilter filter = needsTextureLinear(s, p, swgl_SpanLength)) { \
|
||||||
if (blend_key) { \
|
if (blend_key) { \
|
||||||
drawn = blendTextureLinear<true>(s, p, swgl_SpanLength, uv_rect, \
|
drawn = blendTextureLinear<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||||
packed_color, swgl_Out##format, \
|
packed_color, swgl_Out##format, \
|
||||||
filter, __VA_ARGS__); \
|
filter, __VA_ARGS__); \
|
||||||
} else { \
|
} else { \
|
||||||
drawn = blendTextureLinear<false>(s, p, swgl_SpanLength, uv_rect, \
|
drawn = blendTextureLinear<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||||
packed_color, swgl_Out##format, \
|
packed_color, swgl_Out##format, \
|
||||||
filter, __VA_ARGS__); \
|
filter, __VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} else if (blend_key) { \
|
} else if (blend_key) { \
|
||||||
drawn = blendTextureNearest<true>(s, p, swgl_SpanLength, uv_rect, \
|
drawn = blendTextureNearestFast<true>(s, p, swgl_SpanLength, uv_rect, \
|
||||||
packed_color, swgl_Out##format, \
|
packed_color, swgl_Out##format, \
|
||||||
__VA_ARGS__); \
|
__VA_ARGS__); \
|
||||||
} else { \
|
} else { \
|
||||||
drawn = blendTextureNearest<false>(s, p, swgl_SpanLength, uv_rect, \
|
drawn = blendTextureNearestFast<false>(s, p, swgl_SpanLength, uv_rect, \
|
||||||
packed_color, swgl_Out##format, \
|
packed_color, swgl_Out##format, \
|
||||||
__VA_ARGS__); \
|
__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
swgl_Out##format += drawn; \
|
swgl_Out##format += drawn; \
|
||||||
swgl_SpanLength -= drawn; \
|
swgl_SpanLength -= drawn; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define swgl_commitTextureLinearRGBA8(s, p, uv_rect, ...) \
|
#define swgl_commitTextureLinearRGBA8(s, p, uv_rect, ...) \
|
||||||
swgl_commitTextureLinear(RGBA8, s, p, uv_rect, NoColor(), __VA_ARGS__)
|
swgl_commitTextureLinear(RGBA8, s, p, uv_rect, NoColor(), __VA_ARGS__)
|
||||||
#define swgl_commitTextureLinearR8(s, p, uv_rect, ...) \
|
#define swgl_commitTextureLinearR8(s, p, uv_rect, ...) \
|
||||||
swgl_commitTextureLinear(R8, s, p, uv_rect, NoColor(), __VA_ARGS__)
|
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, ...) \
|
#define swgl_commitTextureLinearColorRGBA8(s, p, uv_rect, color, ...) \
|
||||||
swgl_commitTextureLinear(RGBA8, s, p, uv_rect, color, __VA_ARGS__)
|
swgl_commitTextureLinear(RGBA8, s, p, uv_rect, color, __VA_ARGS__)
|
||||||
#define swgl_commitTextureLinearColorR8(s, p, uv_rect, color, ...) \
|
#define swgl_commitTextureLinearColorR8(s, p, uv_rect, color, ...) \
|
||||||
swgl_commitTextureLinear(R8, s, p, uv_rect, color, __VA_ARGS__)
|
swgl_commitTextureLinear(R8, s, p, uv_rect, color, __VA_ARGS__)
|
||||||
|
|
||||||
// Commit a single chunk from a linear texture fetch
|
// Blends an entire span of texture with linear filtering and repeating UVs.
|
||||||
#define swgl_commitTextureLinearChunk(format, s, p, color, ...) \
|
template <bool BLEND, typename S, typename C, typename P>
|
||||||
swgl_commitChunk(format, applyColor(textureLinearUnpacked##format( \
|
static int blendTextureLinearRepeat(S sampler, vec2 uv, int span,
|
||||||
s, ivec2(p), __VA_ARGS__), \
|
const vec4_scalar& uv_repeat,
|
||||||
packColor(swgl_Out##format, color)))
|
const vec4_scalar& uv_rect, C color, P* buf,
|
||||||
#define swgl_commitTextureLinearChunkRGBA8(s, p, ...) \
|
float z = 0) {
|
||||||
swgl_commitTextureLinearChunk(RGBA8, s, p, NoColor(), __VA_ARGS__)
|
if (!matchTextureFormat(sampler, buf)) {
|
||||||
#define swgl_commitTextureLinearChunkR8(s, p, ...) \
|
return 0;
|
||||||
swgl_commitTextureLinearChunk(R8, s, p, NoColor(), __VA_ARGS__)
|
}
|
||||||
|
// 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
|
// Commit an entire span with linear filtering and repeating UVs
|
||||||
#define swgl_commitTextureLinearChunkColorRGBA8(s, p, color, ...) \
|
#define swgl_commitTextureLinearRepeat(format, s, p, uv_repeat, uv_rect, \
|
||||||
swgl_commitTextureLinearChunk(RGBA8, s, p, color, __VA_ARGS__)
|
color, ...) \
|
||||||
#define swgl_commitTextureLinearChunkColorR8(s, p, color, ...) \
|
do { \
|
||||||
swgl_commitTextureLinearChunk(R8, s, p, color, __VA_ARGS__)
|
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
|
// 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
|
// 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>
|
template <bool BLEND, typename S0, typename P, typename C = NoColor>
|
||||||
static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||||
const vec4_scalar uv_rect0, float z0, int colorSpace,
|
const vec4_scalar uv_rect0, float z0, int colorSpace,
|
||||||
int rescaleFactor, C color = C()) {
|
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,
|
LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0, z0,
|
||||||
layer0);
|
layer0);
|
||||||
auto c = packColor(buf, color);
|
auto c = packColor(buf, color);
|
||||||
|
@ -805,6 +1001,7 @@ static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||||
layer0, colorSpace, rescaleFactor),
|
layer0, colorSpace, rescaleFactor),
|
||||||
c));
|
c));
|
||||||
}
|
}
|
||||||
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S0, typename S1>
|
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,
|
template <bool BLEND, typename S0, typename S1, typename P,
|
||||||
typename C = NoColor>
|
typename C = NoColor>
|
||||||
static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||||
const vec4_scalar uv_rect0, float z0, S1 sampler1,
|
const vec4_scalar uv_rect0, float z0, S1 sampler1, vec2 uv1,
|
||||||
vec2 uv1, const vec4_scalar uv_rect1, float z1,
|
const vec4_scalar uv_rect1, float z1, int colorSpace,
|
||||||
int colorSpace, int rescaleFactor, C color = C()) {
|
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,
|
LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0, z0,
|
||||||
layer0);
|
layer0);
|
||||||
LINEAR_QUANTIZE_UV(sampler1, uv1, uv_step1, uv_rect1, min_uv1, max_uv1, z1,
|
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),
|
colorSpace, rescaleFactor),
|
||||||
c));
|
c));
|
||||||
}
|
}
|
||||||
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S0, typename S1, typename S2>
|
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,
|
template <bool BLEND, typename S0, typename S1, typename S2, typename P,
|
||||||
typename C = NoColor>
|
typename C = NoColor>
|
||||||
static void blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0,
|
||||||
const vec4_scalar uv_rect0, float z0, S1 sampler1,
|
const vec4_scalar uv_rect0, float z0, S1 sampler1, vec2 uv1,
|
||||||
vec2 uv1, const vec4_scalar uv_rect1, float z1,
|
const vec4_scalar uv_rect1, float z1, S2 sampler2, vec2 uv2,
|
||||||
S2 sampler2, vec2 uv2, const vec4_scalar uv_rect2,
|
const vec4_scalar uv_rect2, float z2, int colorSpace,
|
||||||
float z2, int colorSpace, int rescaleFactor,
|
int rescaleFactor, C color = C()) {
|
||||||
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,
|
LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0, z0,
|
||||||
layer0);
|
layer0);
|
||||||
LINEAR_QUANTIZE_UV(sampler1, uv1, uv_step1, uv_rect1, min_uv1, max_uv1, z1,
|
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),
|
layer2, colorSpace, rescaleFactor),
|
||||||
c));
|
c));
|
||||||
}
|
}
|
||||||
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit a single chunk of a YUV surface represented by multiple planar
|
// 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
|
// selects how many bits of precision must be utilized on conversion. See the
|
||||||
// sampleYUV dispatcher functions for the various supported plane
|
// sampleYUV dispatcher functions for the various supported plane
|
||||||
// configurations this intrinsic accepts.
|
// configurations this intrinsic accepts.
|
||||||
#define swgl_commitTextureLinearYUV(...) \
|
#define swgl_commitTextureLinearYUV(...) \
|
||||||
do { \
|
do { \
|
||||||
if (blend_key) { \
|
int drawn = 0; \
|
||||||
blendYUV<true>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
if (blend_key) { \
|
||||||
} else { \
|
drawn = blendYUV<true>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
||||||
blendYUV<false>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
} else { \
|
||||||
} \
|
drawn = blendYUV<false>(swgl_OutRGBA8, swgl_SpanLength, __VA_ARGS__); \
|
||||||
swgl_OutRGBA8 += swgl_SpanLength; \
|
} \
|
||||||
swgl_SpanLength = 0; \
|
swgl_OutRGBA8 += drawn; \
|
||||||
|
swgl_SpanLength -= drawn; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Commit a single chunk of a YUV surface scaled by a color.
|
// 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));
|
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>
|
template <typename S>
|
||||||
static PackedR8 textureLinearPackedR8(S sampler, ivec2 i, int zoffset = 0) {
|
static PackedR8 textureLinearPackedR8(S sampler, ivec2 i, int zoffset = 0) {
|
||||||
return pack(textureLinearUnpackedR8(sampler, i, zoffset));
|
return pack(textureLinearUnpackedR8(sampler, i, zoffset));
|
||||||
|
|
|
@ -273,9 +273,10 @@ void brush_vs(
|
||||||
#ifdef WR_FRAGMENT_SHADER
|
#ifdef WR_FRAGMENT_SHADER
|
||||||
|
|
||||||
vec2 compute_repeated_uvs(float perspective_divisor) {
|
vec2 compute_repeated_uvs(float perspective_divisor) {
|
||||||
|
#ifdef WR_FEATURE_REPETITION
|
||||||
vec2 uv_size = v_uv_bounds.zw - v_uv_bounds.xy;
|
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
|
// 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
|
// for anti-aliasing purposes from going beyound the range covered by the regular
|
||||||
// (non-inflated) primitive.
|
// (non-inflated) primitive.
|
||||||
|
@ -293,21 +294,19 @@ vec2 compute_repeated_uvs(float perspective_divisor) {
|
||||||
if (local_uv.y >= v_tile_repeat.y) {
|
if (local_uv.y >= v_tile_repeat.y) {
|
||||||
repeated_uv.y = v_uv_bounds.w;
|
repeated_uv.y = v_uv_bounds.w;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
vec2 repeated_uv = fract(v_uv * perspective_divisor) * uv_size + v_uv_bounds.xy;
|
vec2 repeated_uv = fract(v_uv * perspective_divisor) * uv_size + v_uv_bounds.xy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return repeated_uv;
|
return repeated_uv;
|
||||||
|
#else
|
||||||
|
return v_uv * perspective_divisor + v_uv_bounds.xy;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment brush_fs() {
|
Fragment brush_fs() {
|
||||||
float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_layer_and_perspective.y);
|
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);
|
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.
|
// Clamp the uvs to avoid sampling artifacts.
|
||||||
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
|
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))
|
#if defined(SWGL_DRAW_SPAN) && (!defined(WR_FEATURE_ALPHA_PASS) || !defined(WR_FEATURE_DUAL_SOURCE_BLENDING))
|
||||||
void swgl_drawSpanRGBA8() {
|
void swgl_drawSpanRGBA8() {
|
||||||
if (!swgl_isTextureRGBA8(sColor0) || !swgl_isTextureLinear(sColor0)) {
|
if (!swgl_isTextureRGBA8(sColor0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,39 +352,29 @@ void swgl_drawSpanRGBA8() {
|
||||||
|
|
||||||
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_layer_and_perspective.y);
|
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_layer_and_perspective.y);
|
||||||
|
|
||||||
#ifndef WR_FEATURE_REPETITION
|
#ifdef WR_FEATURE_REPETITION
|
||||||
vec2 uv = v_uv * perspective_divisor + v_uv_bounds.xy;
|
// Get the UVs before any repetition, scaling, or offsetting has occurred...
|
||||||
|
vec2 uv = v_uv * perspective_divisor;
|
||||||
#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);
|
|
||||||
#else
|
#else
|
||||||
int layer = swgl_textureLayerOffset(sColor0, v_layer_and_perspective.x);
|
vec2 uv = compute_repeated_uvs(perspective_divisor);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WR_FEATURE_ALPHA_PASS
|
#ifdef WR_FEATURE_ALPHA_PASS
|
||||||
if (v_color != vec4(1.0)) {
|
if (v_color != vec4(1.0)) {
|
||||||
while (swgl_SpanLength > 0) {
|
#ifdef WR_FEATURE_REPETITION
|
||||||
vec4 color = v_color;
|
swgl_commitTextureRepeatColorRGBA8(sColor0, uv, v_uv_bounds, v_uv_sample_bounds, v_color, v_layer_and_perspective.x);
|
||||||
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
|
#else
|
||||||
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
|
swgl_commitTextureColorRGBA8(sColor0, uv, v_uv_sample_bounds, v_color, v_layer_and_perspective.x);
|
||||||
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...
|
|
||||||
#endif
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// No color scaling required, so just fall through to a normal textured span...
|
||||||
|
#endif
|
||||||
|
|
||||||
while (swgl_SpanLength > 0) {
|
#ifdef WR_FEATURE_REPETITION
|
||||||
vec2 repeated_uv = compute_repeated_uvs(perspective_divisor);
|
swgl_commitTextureRepeatRGBA8(sColor0, uv, v_uv_bounds, v_uv_sample_bounds, v_layer_and_perspective.x);
|
||||||
vec2 uv = clamp(repeated_uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
|
#else
|
||||||
swgl_commitTextureLinearChunkRGBA8(sColor0, swgl_linearQuantize(sColor0, uv), layer);
|
swgl_commitTextureRGBA8(sColor0, uv, v_uv_sample_bounds, v_layer_and_perspective.x);
|
||||||
v_uv += swgl_interpStep(v_uv);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -118,27 +118,15 @@ Fragment brush_fs() {
|
||||||
#ifdef SWGL_DRAW_SPAN
|
#ifdef SWGL_DRAW_SPAN
|
||||||
void swgl_drawSpanRGBA8() {
|
void swgl_drawSpanRGBA8() {
|
||||||
if (vFormat == YUV_FORMAT_PLANAR) {
|
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,
|
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
||||||
sColor1, vUv_U, vUvBounds_U, vYuvLayers.y,
|
sColor1, vUv_U, vUvBounds_U, vYuvLayers.y,
|
||||||
sColor2, vUv_V, vUvBounds_V, vYuvLayers.z,
|
sColor2, vUv_V, vUvBounds_V, vYuvLayers.z,
|
||||||
vYuvColorSpace, vRescaleFactor);
|
vYuvColorSpace, vRescaleFactor);
|
||||||
} else if (vFormat == YUV_FORMAT_NV12) {
|
} else if (vFormat == YUV_FORMAT_NV12) {
|
||||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
||||||
sColor1, vUv_U, vUvBounds_U, vYuvLayers.y,
|
sColor1, vUv_U, vUvBounds_U, vYuvLayers.y,
|
||||||
vYuvColorSpace, vRescaleFactor);
|
vYuvColorSpace, vRescaleFactor);
|
||||||
} else if (vFormat == YUV_FORMAT_INTERLEAVED) {
|
} else if (vFormat == YUV_FORMAT_INTERLEAVED) {
|
||||||
if (!swgl_isTextureLinear(sColor0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
swgl_commitTextureLinearYUV(sColor0, vUv_Y, vUvBounds_Y, vYuvLayers.x,
|
||||||
vYuvColorSpace, vRescaleFactor);
|
vYuvColorSpace, vRescaleFactor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,39 +161,23 @@ void main(void) {
|
||||||
void swgl_drawSpanRGBA8() {
|
void swgl_drawSpanRGBA8() {
|
||||||
#ifdef WR_FEATURE_YUV
|
#ifdef WR_FEATURE_YUV
|
||||||
if (vYuvFormat == YUV_FORMAT_PLANAR) {
|
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,
|
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
||||||
sColor1, vUV_u, vUVBounds_u, vYuvLayers.y,
|
sColor1, vUV_u, vUVBounds_u, vYuvLayers.y,
|
||||||
sColor2, vUV_v, vUVBounds_v, vYuvLayers.z,
|
sColor2, vUV_v, vUVBounds_v, vYuvLayers.z,
|
||||||
vYuvColorSpace, vRescaleFactor);
|
vYuvColorSpace, vRescaleFactor);
|
||||||
} else if (vYuvFormat == YUV_FORMAT_NV12) {
|
} else if (vYuvFormat == YUV_FORMAT_NV12) {
|
||||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
||||||
sColor1, vUV_u, vUVBounds_u, vYuvLayers.y,
|
sColor1, vUV_u, vUVBounds_u, vYuvLayers.y,
|
||||||
vYuvColorSpace, vRescaleFactor);
|
vYuvColorSpace, vRescaleFactor);
|
||||||
} else if (vYuvFormat == YUV_FORMAT_INTERLEAVED) {
|
} else if (vYuvFormat == YUV_FORMAT_INTERLEAVED) {
|
||||||
if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYuvLayers.x,
|
||||||
vYuvColorSpace, vRescaleFactor);
|
vYuvColorSpace, vRescaleFactor);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!swgl_isTextureLinear(sColor0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vColor != vec4(1.0)) {
|
if (vColor != vec4(1.0)) {
|
||||||
swgl_commitTextureLinearColorRGBA8(sColor0, vUv, vUVBounds, vColor, vLayer);
|
swgl_commitTextureColorRGBA8(sColor0, vUv, vUVBounds, vColor, vLayer);
|
||||||
} else {
|
} else {
|
||||||
swgl_commitTextureLinearRGBA8(sColor0, vUv, vUVBounds, vLayer);
|
swgl_commitTextureRGBA8(sColor0, vUv, vUVBounds, vLayer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ void write_gradient_vertex(
|
||||||
|
|
||||||
#ifdef WR_FRAGMENT_SHADER
|
#ifdef WR_FRAGMENT_SHADER
|
||||||
vec2 compute_repeated_pos() {
|
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).
|
// Handle top and left inflated edges (see brush_image).
|
||||||
vec2 local_pos = max(v_pos, vec2(0.0));
|
vec2 local_pos = max(v_pos, vec2(0.0));
|
||||||
|
|
||||||
|
|
|
@ -121,14 +121,10 @@ void main(void) {
|
||||||
|
|
||||||
#ifdef SWGL_DRAW_SPAN
|
#ifdef SWGL_DRAW_SPAN
|
||||||
void swgl_drawSpanRGBA8() {
|
void swgl_drawSpanRGBA8() {
|
||||||
if (!swgl_isTextureLinear(sColor0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, vPerspective);
|
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, vPerspective);
|
||||||
vec2 uv = vUv * perspective_divisor;
|
vec2 uv = vUv * perspective_divisor;
|
||||||
|
|
||||||
swgl_commitTextureLinearRGBA8(sColor0, uv, vUvSampleBounds, 0.0);
|
swgl_commitTextureRGBA8(sColor0, uv, vUvSampleBounds, 0.0);
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
fuzzy(1,32) == color_targets(4) alpha_targets(0) multiply-3.yaml multiply-2-ref.yaml
|
||||||
== difference.yaml difference-ref.yaml
|
== difference.yaml difference-ref.yaml
|
||||||
fuzzy(1,30000) == difference-transparent.yaml difference-transparent-ref.yaml
|
fuzzy(1,30000) == difference-transparent.yaml difference-transparent-ref.yaml
|
||||||
== darken.yaml darken-ref.yaml
|
fuzzy-if(platform(swgl),1,10000) == darken.yaml darken-ref.yaml
|
||||||
== lighten.yaml lighten-ref.yaml
|
fuzzy-if(platform(swgl),1,10000) == lighten.yaml lighten-ref.yaml
|
||||||
|
|
||||||
fuzzy(1,32) == repeated-difference.yaml repeated-difference-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
|
== invisible.yaml invisible-ref.yaml
|
||||||
fuzzy-if(platform(swgl),1,10000) == opacity.yaml opacity-ref.yaml
|
fuzzy-if(platform(swgl),1,10000) == opacity.yaml opacity-ref.yaml
|
||||||
fuzzy-range(<=1,*10000) == opacity-combined.yaml opacity-combined-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.yaml filter-brightness-ref.yaml
|
||||||
== filter-brightness-2.yaml filter-brightness-2-ref.yaml
|
== filter-brightness-2.yaml filter-brightness-2-ref.yaml
|
||||||
== filter-brightness-3.yaml filter-brightness-3-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
|
== 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
|
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
|
== 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
|
fuzzy-if(skiaContent,0-1,0-1) == 751012-1b.html 751012-1-ref.html
|
||||||
== 753329-1.html about:blank
|
== 753329-1.html about:blank
|
||||||
== 758561-1.html 758561-1-ref.html
|
== 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
|
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-1a.html 776265-1-ref.html
|
||||||
== 776265-1b.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
|
== 1424680.html 1424680-ref.html
|
||||||
== 1424798-1.html 1424798-ref.html
|
== 1424798-1.html 1424798-ref.html
|
||||||
fuzzy-if(!webrender,0-74,0-2234) == 1425243-1.html 1425243-1-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
|
== 1430869.html 1430869-ref.html
|
||||||
== 1432541.html 1432541-ref.html
|
== 1432541.html 1432541-ref.html
|
||||||
== 1446470.html 1035091-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-dyn1-029.html grid-fragmentation-029-ref.html
|
||||||
== grid-fragmentation-dyn2-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-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
|
== bug1306106.html bug1306106-ref.html
|
||||||
== grid-percent-intrinsic-sizing-001.html grid-percent-intrinsic-sizing-001-ref.html
|
== grid-percent-intrinsic-sizing-001.html grid-percent-intrinsic-sizing-001-ref.html
|
||||||
|
|
Загрузка…
Ссылка в новой задаче