This is an automated email from the git hooks/post-receive script.
git pushed a commit to reference refs/pull/114/head
in repository efl.
View the commit online.
commit 7765407feab71a57f11d3c96b04f4003cc213c78
Author: [email protected] <[email protected]>
AuthorDate: Mon Aug 10 20:34:36 2026 -0600
fix(evas_ector_gl): select fragment highp from a runtime probe
Fragment-stage highp is optional in GLSL ES 1.00. The span shaders use it
in every variant - _glsl_varyings_common and u_inv_tw/u_inv_th are shared by
all twelve - so on a GLES2 device without it, nothing compiles at all.
The choice cannot be made with #ifdef GL_FRAGMENT_PRECISION_HIGH, because
that macro exists only in the fragment language while a varying's precision
qualifier has to agree across both stages. Probe with
glGetShaderPrecisionFormat and inject a matching SPAN_HP macro into both.
Attributes and vertex-only locals keep highp unconditionally; the vertex
stage always supports it. On hardware that supports fragment highp,
SPAN_HP resolves to highp and the emitted shaders are unchanged.
Verified with forced mediump fallback (Step 6): all six -c 117-122 parity
tests still pass, with max per-pixel delta rising modestly on 119 (4->10)
and 120 (5->15); no blank renders or gross precision loss.
---
.../engines/gl_generic/evas_ector_gl_span_shader.c | 121 +++++++++++++--------
1 file changed, 74 insertions(+), 47 deletions(-)
diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c
index da12eb5df6..893e838d5b 100644
--- a/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c
+++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c
@@ -37,13 +37,13 @@
/* Common varyings present in all variants. */
static const char _glsl_varyings_common[] =
- "varying highp vec2 v_fbo_off;\n"
- "varying highp vec2 v_fill_off;\n"
- "varying highp vec2 v_stroke_off;\n"
- "varying highp float v_max_spans;\n"
- "varying highp float v_has_flags;\n" /* (has_fill | has_stroke<<1) as float */
- "varying highp float v_fill_x_min;\n"
- "varying highp float v_stroke_x_min;\n"
+ "varying SPAN_HP vec2 v_fbo_off;\n"
+ "varying SPAN_HP vec2 v_fill_off;\n"
+ "varying SPAN_HP vec2 v_stroke_off;\n"
+ "varying SPAN_HP float v_max_spans;\n"
+ "varying SPAN_HP float v_has_flags;\n" /* (has_fill | has_stroke<<1) as float */
+ "varying SPAN_HP float v_fill_x_min;\n"
+ "varying SPAN_HP float v_stroke_x_min;\n"
"varying mediump vec4 v_mul_col;\n";
static const char _glsl_varyings_solid[] =
@@ -51,15 +51,15 @@ static const char _glsl_varyings_solid[] =
"varying mediump vec4 v_stroke_col;\n";
static const char _glsl_varyings_gradient[] =
- "varying highp vec4 v_fill_grad_abc_y;\n"
- "varying highp vec4 v_fill_grad_def;\n"
- "varying highp vec4 v_fill_grad_radial;\n"
- "varying highp vec4 v_stroke_grad_abc_y;\n"
- "varying highp vec4 v_stroke_grad_def;\n"
- "varying highp vec4 v_stroke_grad_radial;\n";
+ "varying SPAN_HP vec4 v_fill_grad_abc_y;\n"
+ "varying SPAN_HP vec4 v_fill_grad_def;\n"
+ "varying SPAN_HP vec4 v_fill_grad_radial;\n"
+ "varying SPAN_HP vec4 v_stroke_grad_abc_y;\n"
+ "varying SPAN_HP vec4 v_stroke_grad_def;\n"
+ "varying SPAN_HP vec4 v_stroke_grad_radial;\n";
static const char _glsl_varyings_mask[] =
- "varying highp vec4 v_mask_off_size;\n"
+ "varying SPAN_HP vec4 v_mask_off_size;\n"
"varying mediump vec2 v_mask_comp_inv;\n";
/* ------------------------------------------------------------------ */
@@ -192,6 +192,31 @@ static const char _glsl_vs_main_gradient_mask[] =
/* Shared GLSL fragment shader source fragments */
/* ------------------------------------------------------------------ */
+/* Fragment-stage highp is optional in GLSL ES 1.00. glGetShaderPrecisionFormat
+ * reports range == 0 and precision == 0 when a format is unsupported, which is
+ * how we detect it. The result is injected as the SPAN_HP macro into *both*
+ * stages, because a varying's precision qualifier has to agree across them. */
+static int _span_fs_highp = -1; /* -1 unprobed, 0 unsupported, 1 supported */
+
+static int
+_span_fragment_highp_supported(void)
+{
+ GLint range[2] = { 0, 0 };
+ GLint precision = 0;
+
+ if (_span_fs_highp >= 0) return _span_fs_highp;
+
+ glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
+ range, &precision);
+ _span_fs_highp = (range[0] != 0 || range[1] != 0 || precision != 0) ? 1 : 0;
+ if (!_span_fs_highp)
+ INF("span shader: fragment highp unsupported, falling back to mediump");
+ return _span_fs_highp;
+}
+
+static const char _glsl_hp_highp[] = "#define SPAN_HP highp\n";
+static const char _glsl_hp_mediump[] = "#define SPAN_HP mediump\n";
+
/* Default precision: mediump for register pressure on tilers (V3D 4.2 / Mali).
* Locals and uniforms that need fp32 (gradient coefficients, gl_FragCoord
* arithmetic) are explicitly qualified highp at their declaration site. */
@@ -215,8 +240,8 @@ typedef enum {
* only the shared pool reciprocals and atlas sampler remain as uniforms.
* u_mask_tex is also a uniform (sampler); only present in mask variants. */
static const char _glsl_uniforms_shared[] =
- "uniform highp float u_inv_tw;\n"
- "uniform highp float u_inv_th;\n"
+ "uniform SPAN_HP float u_inv_tw;\n"
+ "uniform SPAN_HP float u_inv_th;\n"
"uniform sampler2D u_grad_ramp_atlas;\n"
"#define MAX_SPANS 64\n";
@@ -265,12 +290,12 @@ static const char _glsl_scan_spans[] =
"\n"
"/* Scan one span texture row, accumulating coverage-weighted base_col\n"
" * via premultiplied-alpha src-over into result. */\n"
- "vec4 scan_spans(sampler2D tex, highp vec2 off, vec4 base_col, highp float px,\n"
- " highp float fy, highp float inv_tw, int max_s, int x_min, vec4 res) {\n"
+ "vec4 scan_spans(sampler2D tex, SPAN_HP vec2 off, vec4 base_col, SPAN_HP float px,\n"
+ " SPAN_HP float fy, SPAN_HP float inv_tw, int max_s, int x_min, vec4 res) {\n"
" int sx = x_min;\n"
" for (int i = 0; i < MAX_SPANS; i++) {\n"
" if (i >= max_s) break;\n"
- " highp float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
+ " SPAN_HP float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
" vec4 t = texture2D(tex, vec2(fx, fy));\n"
" int gap = int(t.r * 255.0 + 0.5);\n"
" int len = int(t.g * 255.0 + 0.5);\n"
@@ -297,15 +322,15 @@ static const char _glsl_scan_spans[] =
static const char _glsl_grad_spread[] =
"\n"
"/* Apply gradient spread mode to t in [-inf, +inf] -> [0, 1].\n"
- " * Parameter and return type are highp to preserve precision for\n"
+ " * Parameter and return type are SPAN_HP to preserve precision for\n"
" * REFLECT/REPEAT on surfaces wider than ~1024 px (mediump fract\n"
" * loses mantissa bits once t > 1024). */\n"
- "highp float grad_spread(highp float t, int spread) {\n"
+ "SPAN_HP float grad_spread(SPAN_HP float t, int spread) {\n"
" if (spread == 1) {\n"
- " /* REFLECT: mirror at 0 and 1; arithmetic stays highp */\n"
+ " /* REFLECT: mirror at 0 and 1; arithmetic stays SPAN_HP */\n"
" t = 1.0 - abs(fract(t * 0.5) * 2.0 - 1.0);\n"
" } else if (spread == 2) {\n"
- " /* REPEAT; fract in highp */\n"
+ " /* REPEAT; fract in SPAN_HP */\n"
" t = fract(t);\n"
" } else {\n"
" /* PAD (default) */\n"
@@ -325,18 +350,18 @@ static const char _glsl_scan_gradient_spans[] =
"/* Scan one gradient span texture row. On hit, compute t per-pixel\n"
" * (linear or radial) and sample the gradient ramp atlas at ramp_v,\n"
" * then src-over blend into result. */\n"
- "vec4 scan_gradient_spans(sampler2D span_tex, highp vec2 off,\n"
- " highp float ramp_v,\n"
- " highp float ga, highp float gb, highp float gc,\n"
+ "vec4 scan_gradient_spans(sampler2D span_tex, SPAN_HP vec2 off,\n"
+ " SPAN_HP float ramp_v,\n"
+ " SPAN_HP float ga, SPAN_HP float gb, SPAN_HP float gc,\n"
" int gspread, int gtype,\n"
- " highp float gd, highp float ge, highp float gf,\n"
- " highp float gra, highp float grdx, highp float grdy,\n"
- " highp float px, highp float py,\n"
- " highp float fy, highp float inv_tw, int max_s, int x_min, vec4 res) {\n"
+ " SPAN_HP float gd, SPAN_HP float ge, SPAN_HP float gf,\n"
+ " SPAN_HP float gra, SPAN_HP float grdx, SPAN_HP float grdy,\n"
+ " SPAN_HP float px, SPAN_HP float py,\n"
+ " SPAN_HP float fy, SPAN_HP float inv_tw, int max_s, int x_min, vec4 res) {\n"
" int sx = x_min;\n"
" for (int i = 0; i < MAX_SPANS; i++) {\n"
" if (i >= max_s) break;\n"
- " highp float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
+ " SPAN_HP float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
" vec4 s = texture2D(span_tex, vec2(fx, fy));\n"
" int gap = int(s.r * 255.0 + 0.5);\n"
" int len = int(s.g * 255.0 + 0.5);\n"
@@ -344,22 +369,22 @@ static const char _glsl_scan_gradient_spans[] =
" if (len == 0) break;\n"
" sx += gap;\n"
" if (int(px) >= sx && int(px) < sx + len) {\n"
- " highp float t;\n"
+ " SPAN_HP float t;\n"
" if (gtype == 1) {\n"
" /* Radial gradient: quadratic solve in gradient space */\n"
- " highp float rx = ga * px + gb * py + gc;\n"
- " highp float ry = gd * px + ge * py + gf;\n"
- " highp float b_val = 2.0 * (rx * grdx + ry * grdy);\n"
+ " SPAN_HP float rx = ga * px + gb * py + gc;\n"
+ " SPAN_HP float ry = gd * px + ge * py + gf;\n"
+ " SPAN_HP float b_val = 2.0 * (rx * grdx + ry * grdy);\n"
" /* gra = inv2a = 0.5/a, precomputed on CPU to avoid\n"
" * per-fragment division. Pre-scale b and det like\n"
" * the software forward-differencing path does. */\n"
- " highp float b_s = b_val * gra;\n"
- " highp float det = b_s * b_s + (rx * rx + ry * ry) * 2.0 * gra;\n"
+ " SPAN_HP float b_s = b_val * gra;\n"
+ " SPAN_HP float det = b_s * b_s + (rx * rx + ry * ry) * 2.0 * gra;\n"
" t = sqrt(max(det, 0.0)) - b_s;\n"
" } else {\n"
" /* Linear gradient: affine dot product.\n"
" * All operands (ga, gb, gc, px, py) and destination t\n"
- " * are highp; result lands in highp t. */\n"
+ " * are SPAN_HP; result lands in SPAN_HP t. */\n"
" t = ga * px + gb * py + gc;\n"
" }\n"
" t = grad_spread(t, gspread);\n"
@@ -384,17 +409,17 @@ static const char _glsl_main_solid_body[] =
" int has_s = int(v_has_flags + 0.5) / 2;\n"
" int fill_xm = int(v_fill_x_min + 0.5);\n"
" int stk_xm = int(v_stroke_x_min + 0.5);\n"
- " highp float px = gl_FragCoord.x - v_fbo_off.x;\n"
- " highp float py = gl_FragCoord.y - v_fbo_off.y;\n"
+ " SPAN_HP float px = gl_FragCoord.x - v_fbo_off.x;\n"
+ " SPAN_HP float py = gl_FragCoord.y - v_fbo_off.y;\n"
" vec4 result = vec4(0.0);\n"
"\n"
" if (has_f == 1) {\n"
- " highp float fy = (v_fill_off.y + py) * u_inv_th;\n"
+ " SPAN_HP float fy = (v_fill_off.y + py) * u_inv_th;\n"
" result = scan_spans(u_fill_spans, v_fill_off, v_fill_col,\n"
" px, fy, u_inv_tw, max_s, fill_xm, result);\n"
" }\n"
" if (has_s == 1) {\n"
- " highp float fy = (v_stroke_off.y + py) * u_inv_th;\n"
+ " SPAN_HP float fy = (v_stroke_off.y + py) * u_inv_th;\n"
" result = scan_spans(u_stroke_spans, v_stroke_off, v_stroke_col,\n"
" px, fy, u_inv_tw, max_s, stk_xm, result);\n"
" }\n";
@@ -414,12 +439,12 @@ static const char _glsl_main_gradient_body[] =
" int fill_gspread = int(v_fill_grad_radial.w + 0.5);\n"
" int stk_gtype = int(v_stroke_grad_def.w + 0.5);\n"
" int stk_gspread = int(v_stroke_grad_radial.w + 0.5);\n"
- " highp float px = gl_FragCoord.x - v_fbo_off.x;\n"
- " highp float py = gl_FragCoord.y - v_fbo_off.y;\n"
+ " SPAN_HP float px = gl_FragCoord.x - v_fbo_off.x;\n"
+ " SPAN_HP float py = gl_FragCoord.y - v_fbo_off.y;\n"
" vec4 result = vec4(0.0);\n"
"\n"
" if (has_f == 1) {\n"
- " highp float fy = (v_fill_off.y + py) * u_inv_th;\n"
+ " SPAN_HP float fy = (v_fill_off.y + py) * u_inv_th;\n"
" result = scan_gradient_spans(\n"
" u_fill_spans, v_fill_off,\n"
" v_fill_grad_abc_y.w,\n"
@@ -430,7 +455,7 @@ static const char _glsl_main_gradient_body[] =
" px, py, fy, u_inv_tw, max_s, fill_xm, result);\n"
" }\n"
" if (has_s == 1) {\n"
- " highp float fy = (v_stroke_off.y + py) * u_inv_th;\n"
+ " SPAN_HP float fy = (v_stroke_off.y + py) * u_inv_th;\n"
" result = scan_gradient_spans(\n"
" u_stroke_spans, v_stroke_off,\n"
" v_stroke_grad_abc_y.w,\n"
@@ -497,6 +522,7 @@ _span_shader_parts_build(int kind, Span_Bind_Set bind, int mask, int *out_count)
const char *parts[20];
int n = 0;
+ parts[n++] = _span_fragment_highp_supported() ? _glsl_hp_highp : _glsl_hp_mediump;
parts[n++] = _glsl_precision;
/* Shared uniforms: pool reciprocals + atlas sampler. */
parts[n++] = _glsl_uniforms_shared;
@@ -531,9 +557,10 @@ _span_shader_parts_build(int kind, Span_Bind_Set bind, int mask, int *out_count)
static const char **
_span_vs_parts_build(int kind, int mask, int *out_count)
{
- const char *parts[12];
+ const char *parts[13];
int n = 0;
+ parts[n++] = _span_fragment_highp_supported() ? _glsl_hp_highp : _glsl_hp_mediump;
parts[n++] = _glsl_precision;
/* Attribute declarations. */
parts[n++] = _glsl_attributes_common;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.