summaryrefslogtreecommitdiff
path: root/src/glitz_program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glitz_program.c')
-rw-r--r--src/glitz_program.c283
1 files changed, 194 insertions, 89 deletions
diff --git a/src/glitz_program.c b/src/glitz_program.c
index 7caebc1..0578674 100644
--- a/src/glitz_program.c
+++ b/src/glitz_program.c
@@ -45,24 +45,24 @@
#define EXPAND_SRC_DECL "TEMP src;"
#define EXPAND_SRC_2D_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], 2D;", \
- "DP4 color.a, color, fragment.color;", \
- "MUL result.color, src, color.a;" }
+ "DP4 color.a, color, fragment.color;", \
+ "MUL result.color, src, color.a;" }
#define EXPAND_SRC_RECT_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], RECT;", \
- "DP4 color.a, color, fragment.color;", \
- "MUL result.color, src, color.a;" }
+ "DP4 color.a, color, fragment.color;", \
+ "MUL result.color, src, color.a;" }
#define EXPAND_MASK_DECL "TEMP mask;"
-#define EXPAND_MASK_2D_IN_OP \
- { "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
- "DP4 mask.a, mask, fragment.color;", \
- "MUL result.color, color, mask.a;" }
+#define EXPAND_MASK_2D_IN_OP \
+ { "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
+ "DP4 mask.a, mask, fragment.color;", \
+ "MUL result.color, color, mask.a;" }
#define EXPAND_MASK_RECT_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], RECT;", \
- "DP4 mask.a, mask, fragment.color;", \
- "MUL result.color, color, mask.a;" }
+ "DP4 mask.a, mask, fragment.color;", \
+ "MUL result.color, color, mask.a;" }
#define EXPAND_IN_NA \
{ "NA", "NA", "NA" }
@@ -140,6 +140,18 @@ static const struct _glitz_program_expand_t {
};
/*
+ * perspective divide.
+ */
+static const char *_perspective_divide[] = {
+ "RCP position.w, pos.w;",
+ "MUL position, pos, position.w;", NULL
+};
+
+static const char *_no_perspective_divide[] = {
+ "MOV position, pos;", NULL
+};
+
+/*
* general convolution filter.
*/
static const char *_convolution_header[] = {
@@ -148,79 +160,73 @@ static const char *_convolution_header[] = {
"TEMP color, in, coord, position;",
/* extra declarations */
- "%s"
-
- /* perspective divide */
- "RCP position.w, pos.w;",
- "MUL position, pos, position.w;", NULL
+ "%s", NULL
};
static const char *_convolution_sample_first[] = {
"MOV coord, 0.0;",
- "ADD coord.x, position.x, p[0].x;",
- "ADD coord.y, position.y, p[0].y;",
+ "ADD coord.xy, position.xyxx, p[0].xyxx;",
"TEX in, coord, texture[%s], %s;",
"MUL color, in, p[0].z;", NULL
};
static const char *_convolution_sample[] = {
- "ADD coord.x, position.x, p[%d].x;",
- "ADD coord.y, position.y, p[%d].y;",
+ "ADD coord.xy, position.xyxx, p[%d].xyxx;",
"TEX in, coord, texture[%s], %s;",
"MAD color, in, p[%d].z, color;", NULL
};
-
/*
* gradient filters.
*/
static const char *_gradient_header[] = {
- "PARAM gradient = program.local[0];",
- "PARAM stops[%d] = { program.local[1..%d] };",
+ "PARAM gradient[%d] = { program.local[0..%d] };",
+ "PARAM stops[%d] = { program.local[%d..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, second_color, stop0, stop1, position;",
/* extra declarations */
- "%s",
-
- /* perspective divide */
- "RCP position.w, pos.w;",
- "MUL position, pos, position.w;", NULL
+ "%s", NULL
};
/*
* linear gradient filter.
*
- * gradient.x = start offset
- * gradient.y = 1 / length
- * gradient.z = cos (angle)
- * gradient.w = -sin (angle)
+ * gradient.x = a
+ * gradient.y = b
+ * gradient.z = offset
*/
static const char *_linear_gradient_calculations[] = {
- "MUL position.x, gradient.z, position.x;",
- "MAD position.x, gradient.w, position.y, position.x;",
- "SUB position.z, position.x, gradient.x;",
- "MUL position.z, position.z, gradient.y;", NULL
+ "MUL position.xy, gradient[0], position;",
+ "ADD position.x, position.x, position.y;",
+ "ADD position.z, position.x, gradient[0].z;", NULL
};
/*
* radial gradient filter.
*
- * gradient.x = center point X coordinate
- * gradient.y = center point Y coordinate
- * gradient.z = radius0
- * gradient.w = 1 / (radius1 - radius0)
+ * gradient[0].x = fx
+ * gradient[0].y = fy
+ * gradient[0].z = dx
+ * gradient[0].w = dy
+ *
+ * gradient[1].x = m
+ * gradient[1].y = b
+ * gradient[1].z = 4a
+ * gradient[1].w = 1 / 2a
*/
static const char *_radial_gradient_calculations[] = {
- "SUB position, position, gradient;",
- "MUL position.x, position.x, position.x;",
- "MAD position.x, position.y, position.y, position.x;",
- "RSQ position.y, position.x;",
- "RCP position.x, position.y;",
- "MUL position.x, position.x, position.x;",
- "MUL position.x, position.x, position.y;",
- "SUB position.x, position.x, gradient.z;",
- "MUL position.z, position.x, gradient.w;", NULL
+ "SUB position, position.xyxx, gradient[0].xyxx;",
+ "MUL position.zw, position.xxxy, gradient[0];",
+ "ADD position.w, position.w, position.z;",
+ "MUL position.xyz, position.xyww, position.xyww;",
+ "ADD position.x, position.x, position.y;",
+ "MAD position.z, position.x, gradient[1].z, position.z;",
+ "RSQ position.z, position.z;",
+ "RCP position.z, position.z;",
+ "SUB position.x, position.z, position.w;",
+ "MUL position.x, position.x, gradient[1].w;",
+ "MAD position.z, position.x, gradient[1].x, gradient[1].y;", NULL
};
static const char *_gradient_fill_repeat[] = {
@@ -228,15 +234,12 @@ static const char *_gradient_fill_repeat[] = {
};
static const char *_gradient_fill_reflect[] = {
- "FLR position.w, position.z;",
- "MUL position.w, position.w, 0.5;",
- "FLR position.w, position.w;",
- "MUL position.y, position.w, 2.0;",
- "FLR position.x, position.z;",
- "SUB position.y, position.x, position.y;",
- "FRC position.x, position.z;",
- "SUB position.x, position.x, position.y;",
- "ABS position.z, position.x;", NULL
+ "MUL position.z, position.z, 0.5;"
+ "FRC position.z, position.z;"
+ "MUL position.z, position.z, 2.0;"
+ "SUB position.z, 1.0, position.z;"
+ "ABS position.z, position.z;"
+ "SUB position.z, 1.0, position.z;", NULL
};
static const char *_gradient_init_stops[] = {
@@ -263,7 +266,37 @@ static const char *_gradient_fetch_and_interpolate[] = {
"MUL_SAT position.z, position.z, stop0.w;",
/* linear interpolation */
- "LRP color, position.z, second_color, color;", NULL
+ "LRP color, position.z, second_color, color;",
+
+ /* multiply alpha */
+ "MUL color.rgb, color.rgba, color.a;", NULL
+};
+
+/*
+ * color conversion filters
+ */
+static const char *_colorspace_yv12_header[] = {
+ "PARAM offset = program.local[0];",
+ "PARAM minmax = program.local[1];",
+ "ATTRIB pos = fragment.texcoord[%s];",
+ "TEMP color, tmp, position;",
+
+ /* extra declarations */
+ "%s", NULL
+};
+
+static const char *_colorspace_yv12[] = {
+ "MAX position, position, minmax;",
+ "MIN position, position, minmax.zwww;",
+ "TEX color, position, texture[%s], %s;",
+ "MAD position, position, .5, offset.xyww;",
+ "TEX tmp.x, position, texture[%s], %s;",
+ "MAD color, color, 1.164, -0.073;", /* -1.164 * 16 / 255 */
+ "ADD position.x, position.x, offset.z;",
+ "TEX tmp.y, position, texture[%s], %s;",
+ "SUB tmp, tmp, { .5, .5 };",
+ "MAD color.xyz, { 1.596, -.813, 0 }, tmp.xxxw, color;",
+ "MAD color.xyz, { 0, -.391, 2.018 }, tmp.yyyw, color;", NULL
};
static struct _glitz_program_query {
@@ -276,9 +309,9 @@ static struct _glitz_program_query {
{ GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_PARAMETERS,
- GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 },
+ GLITZ_GL_MAX_PROGRAM_PARAMETERS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_PARAMETERS,
- GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 },
+ GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 0 },
{ GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS,
@@ -321,10 +354,10 @@ _glitz_program_under_limits (glitz_gl_proc_address_list_t *gl)
static glitz_gl_int_t
_glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
- char *program_string,
- int n_parameters)
+ char *string,
+ int n_parameters)
{
- glitz_gl_int_t error, pid = -1;
+ glitz_gl_int_t error = 0, pid = -1;
glitz_gl_uint_t program;
/* clear error flags */
@@ -334,11 +367,9 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program);
gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_FORMAT_ASCII,
- strlen (program_string),
- program_string);
+ strlen (string), string);
if (gl->get_error () == GLITZ_GL_NO_ERROR) {
gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
-
if (error == -1) {
glitz_gl_int_t value;
@@ -358,6 +389,14 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
}
}
}
+#ifdef DEBUG
+ else {
+ gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
+ }
+ if (error != -1)
+ fprintf (stderr, "fp error at pos %d beginning with '%.40s'\n",
+ error, string+error);
+#endif
if (pid == -1) {
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0);
@@ -368,7 +407,8 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
}
static void
-_string_array_to_char_array (char *dst, const char *src[])
+_string_array_to_char_array (char *dst,
+ const char *src[])
{
int i, n;
@@ -387,17 +427,26 @@ _string_array_to_char_array (char *dst, const char *src[])
#define GRADIENT_BASE_SIZE 2048
#define GRADIENT_STOP_SIZE 256
+#define COLORSPACE_BASE_SIZE 2048
+
static glitz_gl_uint_t
_glitz_create_fragment_program (glitz_composite_op_t *op,
int fp_type,
int id,
+ int p_divide,
const glitz_program_expand_t *expand)
{
- char buffer[1024], *program = NULL, *tex, *p = NULL;
- char *texture_type, *extra_declarations;
+ char buffer[1024], *program = NULL, *tex, *p = NULL;
+ char *texture_type, *extra_declarations;
+ const char **pos_to_position;
const glitz_in_op_t *in;
- glitz_gl_uint_t fp;
- int i;
+ glitz_gl_uint_t fp;
+ int i;
+
+ if (p_divide)
+ pos_to_position = _perspective_divide;
+ else
+ pos_to_position = _no_perspective_divide;
switch (op->type) {
case GLITZ_COMBINE_TYPE_ARGBF:
@@ -438,12 +487,15 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
_string_array_to_char_array (buffer, _convolution_header);
p += sprintf (p, buffer, id, id - 1, tex, extra_declarations);
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
_string_array_to_char_array (buffer, _convolution_sample_first);
p += sprintf (p, buffer, tex, texture_type);
_string_array_to_char_array (buffer, _convolution_sample);
for (i = 1; i < id; i++)
- p += sprintf (p, buffer, i, i, tex, texture_type, i);
+ p += sprintf (p, buffer, i, tex, texture_type, i);
break;
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
@@ -465,17 +517,27 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _gradient_header);
- p += sprintf (p, buffer, id, id, tex, extra_declarations);
switch (fp_type) {
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
case GLITZ_FP_LINEAR_GRADIENT_NEAREST:
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
+ p += sprintf (p, buffer, 1, 0, id, 1, id, tex, extra_declarations);
+
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
_string_array_to_char_array (buffer,
_linear_gradient_calculations);
break;
default:
+ p += sprintf (p, buffer, 2, 1, id, 2, id + 1, tex,
+ extra_declarations);
+
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
_string_array_to_char_array (buffer,
_radial_gradient_calculations);
break;
@@ -514,6 +576,25 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
id++;
break;
+ case GLITZ_FP_COLORSPACE_YV12:
+ program = malloc (COLORSPACE_BASE_SIZE);
+ if (program == NULL)
+ return 0;
+
+ p = program;
+
+ p += sprintf (p, "!!ARBfp1.0");
+
+ _string_array_to_char_array (buffer, _colorspace_yv12_header);
+ p += sprintf (p, buffer, tex, extra_declarations);
+
+ _string_array_to_char_array (buffer, pos_to_position);
+ p += sprintf (p, buffer);
+
+ _string_array_to_char_array (buffer, _colorspace_yv12);
+ p += sprintf (p, buffer, tex, texture_type, tex, texture_type,
+ tex, texture_type);
+ break;
default:
return 0;
}
@@ -525,8 +606,12 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
if (op->per_component)
p += sprintf (p, "%s", in->dot_product);
p += sprintf (p, "%s", in->mult);
+
sprintf (p, "END");
+#ifdef DEBUG
+ fprintf (stderr, "***** fp %d:\n%s\n\n", id, program);
+#endif
fp = _glitz_compile_arb_fragment_program (op->gl, program, id);
free (program);
@@ -545,22 +630,24 @@ glitz_program_map_fini (glitz_gl_proc_address_list_t *gl,
glitz_program_map_t *map)
{
glitz_gl_uint_t program;
- int i, j, k, x, y;
+ int i, j, k, x, y, z;
for (i = 0; i < GLITZ_COMBINE_TYPES; i++) {
for (j = 0; j < GLITZ_FP_TYPES; j++) {
for (x = 0; x < GLITZ_TEXTURE_LAST; x++) {
for (y = 0; y < GLITZ_TEXTURE_LAST; y++) {
- glitz_program_t *p = &map->filters[i][j].fp[x][y];
-
- if (p->name) {
- for (k = 0; k < p->size; k++)
- if (p->name[k] > 0) {
- program = p->name[k];
- gl->delete_programs (1, &program);
- }
-
- free (p->name);
+ for (z = 0; z < 2; z++) {
+ glitz_program_t *p = &map->filters[i][j].fp[x][y][z];
+
+ if (p->name) {
+ for (k = 0; k < p->size; k++)
+ if (p->name[k] > 0) {
+ program = p->name[k];
+ gl->delete_programs (1, &program);
+ }
+
+ free (p->name);
+ }
}
}
}
@@ -583,12 +670,30 @@ glitz_get_fragment_program (glitz_composite_op_t *op,
int id)
{
glitz_program_map_t *map;
- glitz_program_t *program;
- int t0 = TEXTURE_INDEX (op->src);
- int t1 = TEXTURE_INDEX (op->mask);
+ glitz_program_t *program;
+ int t0 = TEXTURE_INDEX (op->src);
+ int t1 = TEXTURE_INDEX (op->mask);
+ int p_divide = 1;
+
+ switch (op->type) {
+ case GLITZ_COMBINE_TYPE_ARGBF:
+ case GLITZ_COMBINE_TYPE_ARGBF_SOLID:
+ case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC:
+ case GLITZ_COMBINE_TYPE_ARGBF_ARGB:
+ case GLITZ_COMBINE_TYPE_ARGBF_ARGBC:
+ if (!SURFACE_PROJECTIVE_TRANSFORM (op->src))
+ p_divide = 0;
+ break;
+ case GLITZ_COMBINE_TYPE_ARGB_ARGBF:
+ case GLITZ_COMBINE_TYPE_SOLID_ARGBF:
+ if (!SURFACE_PROJECTIVE_TRANSFORM (op->mask))
+ p_divide = 0;
+ default:
+ break;
+ }
map = op->dst->drawable->backend->program_map;
- program = &map->filters[op->type][fp_type].fp[t0][t1];
+ program = &map->filters[op->type][fp_type].fp[t0][t1][p_divide];
if (program->size < id) {
int old_size;
@@ -609,7 +714,7 @@ glitz_get_fragment_program (glitz_composite_op_t *op,
glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT);
program->name[id - 1] =
- _glitz_create_fragment_program (op, fp_type, id,
+ _glitz_create_fragment_program (op, fp_type, id, p_divide,
_program_expand_map[t0][t1]);
glitz_surface_pop_current (op->dst);