diff options
author | Eric Anholt <eric@anholt.net> | 2013-12-18 11:59:07 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2014-01-27 09:30:47 -0800 |
commit | d84d71029ae9e462559d64eff7259e2cc7732fac (patch) | |
tree | 119ae8ccb9342833148f4ad754d1a08764df126a /glamor/glamor_gradient.c | |
parent | e8e9a54c47deedbc13b8969ed29e16463b0314a0 (diff) |
glamor: Apply x-indent.sh.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Zhigang Gong <zhigang.gong@linux.intel.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'glamor/glamor_gradient.c')
-rw-r--r-- | glamor/glamor_gradient.c | 2531 |
1 files changed, 1270 insertions, 1261 deletions
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index 4abc82d74..df6c3bbca 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -43,15 +43,16 @@ #ifdef GLAMOR_GRADIENT_SHADER static GLint -_glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_array) +_glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, + int use_array) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; - char *gradient_fs = NULL; - GLint fs_getcolor_prog; + char *gradient_fs = NULL; + GLint fs_getcolor_prog; - #define gradient_fs_getcolor\ +#define gradient_fs_getcolor\ GLAMOR_DEFAULT_PRECISION\ "uniform int n_stop;\n"\ "uniform float stops[%d];\n"\ @@ -82,163 +83,86 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar " return gradient_color;\n"\ "}\n" - /* Because the array access for shader is very slow, the performance is very low - if use array. So use global uniform to replace for it if the number of n_stops is small.*/ - const char *gradient_fs_getcolor_no_array = - GLAMOR_DEFAULT_PRECISION - "uniform int n_stop;\n" - "uniform float stop0;\n" - "uniform float stop1;\n" - "uniform float stop2;\n" - "uniform float stop3;\n" - "uniform float stop4;\n" - "uniform float stop5;\n" - "uniform float stop6;\n" - "uniform float stop7;\n" - "uniform vec4 stop_color0;\n" - "uniform vec4 stop_color1;\n" - "uniform vec4 stop_color2;\n" - "uniform vec4 stop_color3;\n" - "uniform vec4 stop_color4;\n" - "uniform vec4 stop_color5;\n" - "uniform vec4 stop_color6;\n" - "uniform vec4 stop_color7;\n" - "\n" - "vec4 get_color(float stop_len)\n" - "{\n" - " float stop_after;\n" - " float stop_before;\n" - " vec4 stop_color_before;\n" - " vec4 stop_color_after;\n" - " float new_alpha; \n" - " vec4 gradient_color;\n" - " float percentage; \n" - " \n" - " if((stop_len < stop0) && (n_stop >= 1)) {\n" - " stop_color_before = stop_color0;\n" - " stop_color_after = stop_color0;\n" - " stop_after = stop0;\n" - " stop_before = stop0;\n" - " } else if((stop_len < stop1) && (n_stop >= 2)) {\n" - " stop_color_before = stop_color0;\n" - " stop_color_after = stop_color1;\n" - " stop_after = stop1;\n" - " stop_before = stop0;\n" - " } else if((stop_len < stop2) && (n_stop >= 3)) {\n" - " stop_color_before = stop_color1;\n" - " stop_color_after = stop_color2;\n" - " stop_after = stop2;\n" - " stop_before = stop1;\n" - " } else if((stop_len < stop3) && (n_stop >= 4)){\n" - " stop_color_before = stop_color2;\n" - " stop_color_after = stop_color3;\n" - " stop_after = stop3;\n" - " stop_before = stop2;\n" - " } else if((stop_len < stop4) && (n_stop >= 5)){\n" - " stop_color_before = stop_color3;\n" - " stop_color_after = stop_color4;\n" - " stop_after = stop4;\n" - " stop_before = stop3;\n" - " } else if((stop_len < stop5) && (n_stop >= 6)){\n" - " stop_color_before = stop_color4;\n" - " stop_color_after = stop_color5;\n" - " stop_after = stop5;\n" - " stop_before = stop4;\n" - " } else if((stop_len < stop6) && (n_stop >= 7)){\n" - " stop_color_before = stop_color5;\n" - " stop_color_after = stop_color6;\n" - " stop_after = stop6;\n" - " stop_before = stop5;\n" - " } else if((stop_len < stop7) && (n_stop >= 8)){\n" - " stop_color_before = stop_color6;\n" - " stop_color_after = stop_color7;\n" - " stop_after = stop7;\n" - " stop_before = stop6;\n" - " } else {\n" - " stop_color_before = stop_color7;\n" - " stop_color_after = stop_color7;\n" - " stop_after = stop7;\n" - " stop_before = stop7;\n" - " }\n" - " if(stop_after - stop_before > 2.0)\n" - " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. - " else if(stop_after - stop_before < 0.000001)\n" - " percentage = 0.0;\n" - " else \n" - " percentage = (stop_len - stop_before)/(stop_after - stop_before);\n" - " new_alpha = percentage * stop_color_after.a + \n" - " (1.0-percentage) * stop_color_before.a; \n" - " gradient_color = vec4((percentage * stop_color_after.rgb \n" - " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" - " new_alpha);\n" - " \n" - " return gradient_color;\n" - "}\n"; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - if(use_array) { - XNFasprintf(&gradient_fs, - gradient_fs_getcolor, stops_count, stops_count); - fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - gradient_fs); - free(gradient_fs); - } else { - fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - gradient_fs_getcolor_no_array); - } - - return fs_getcolor_prog; + /* Because the array access for shader is very slow, the performance is very low + if use array. So use global uniform to replace for it if the number of n_stops is small. */ + const char *gradient_fs_getcolor_no_array = GLAMOR_DEFAULT_PRECISION "uniform int n_stop;\n" "uniform float stop0;\n" "uniform float stop1;\n" "uniform float stop2;\n" "uniform float stop3;\n" "uniform float stop4;\n" "uniform float stop5;\n" "uniform float stop6;\n" "uniform float stop7;\n" "uniform vec4 stop_color0;\n" "uniform vec4 stop_color1;\n" "uniform vec4 stop_color2;\n" "uniform vec4 stop_color3;\n" "uniform vec4 stop_color4;\n" "uniform vec4 stop_color5;\n" "uniform vec4 stop_color6;\n" "uniform vec4 stop_color7;\n" "\n" "vec4 get_color(float stop_len)\n" "{\n" " float stop_after;\n" " float stop_before;\n" " vec4 stop_color_before;\n" " vec4 stop_color_after;\n" " float new_alpha; \n" " vec4 gradient_color;\n" " float percentage; \n" " \n" " if((stop_len < stop0) && (n_stop >= 1)) {\n" " stop_color_before = stop_color0;\n" " stop_color_after = stop_color0;\n" " stop_after = stop0;\n" " stop_before = stop0;\n" " } else if((stop_len < stop1) && (n_stop >= 2)) {\n" " stop_color_before = stop_color0;\n" " stop_color_after = stop_color1;\n" " stop_after = stop1;\n" " stop_before = stop0;\n" " } else if((stop_len < stop2) && (n_stop >= 3)) {\n" " stop_color_before = stop_color1;\n" " stop_color_after = stop_color2;\n" " stop_after = stop2;\n" " stop_before = stop1;\n" " } else if((stop_len < stop3) && (n_stop >= 4)){\n" " stop_color_before = stop_color2;\n" " stop_color_after = stop_color3;\n" " stop_after = stop3;\n" " stop_before = stop2;\n" " } else if((stop_len < stop4) && (n_stop >= 5)){\n" " stop_color_before = stop_color3;\n" " stop_color_after = stop_color4;\n" " stop_after = stop4;\n" " stop_before = stop3;\n" " } else if((stop_len < stop5) && (n_stop >= 6)){\n" " stop_color_before = stop_color4;\n" " stop_color_after = stop_color5;\n" " stop_after = stop5;\n" " stop_before = stop4;\n" " } else if((stop_len < stop6) && (n_stop >= 7)){\n" " stop_color_before = stop_color5;\n" " stop_color_after = stop_color6;\n" " stop_after = stop6;\n" " stop_before = stop5;\n" " } else if((stop_len < stop7) && (n_stop >= 8)){\n" " stop_color_before = stop_color6;\n" " stop_color_after = stop_color7;\n" " stop_after = stop7;\n" " stop_before = stop6;\n" " } else {\n" " stop_color_before = stop_color7;\n" " stop_color_after = stop_color7;\n" " stop_after = stop7;\n" " stop_before = stop7;\n" " }\n" " if(stop_after - stop_before > 2.0)\n" " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. + " else if(stop_after - stop_before < 0.000001)\n" + " percentage = 0.0;\n" + " else \n" + " percentage = (stop_len - stop_before)/(stop_after - stop_before);\n" + " new_alpha = percentage * stop_color_after.a + \n" + " (1.0-percentage) * stop_color_before.a; \n" + " gradient_color = vec4((percentage * stop_color_after.rgb \n" + " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" " return gradient_color;\n" "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + if (use_array) { + XNFasprintf(&gradient_fs, + gradient_fs_getcolor, stops_count, stops_count); + fs_getcolor_prog = + glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, gradient_fs); + free(gradient_fs); + } + else { + fs_getcolor_prog = + glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + gradient_fs_getcolor_no_array); + } + + return fs_getcolor_prog; } static void -_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) +_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, + int dyn_gen) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - int index; - - GLint gradient_prog = 0; - char *gradient_fs = NULL; - GLint fs_main_prog, fs_getcolor_prog, vs_prog; - - const char *gradient_vs = - GLAMOR_DEFAULT_PRECISION - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord;\n" - "varying vec2 source_texture;\n" - "\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - " source_texture = v_texcoord.xy;\n" - "}\n"; - - /* - * Refer to pixman radial gradient. - * - * The problem is given the two circles of c1 and c2 with the radius of r1 and - * r1, we need to caculate the t, which is used to do interpolate with stops, - * using the fomula: - * length((1-t)*c1 + t*c2 - p) = (1-t)*r1 + t*r2 - * expand the fomula with xy coond, get the following: - * sqrt(sqr((1-t)*c1.x + t*c2.x - p.x) + sqr((1-t)*c1.y + t*c2.y - p.y)) - * = (1-t)r1 + t*r2 - * <====> At*t- 2Bt + C = 0 - * where A = sqr(c2.x - c1.x) + sqr(c2.y - c1.y) - sqr(r2 -r1) - * B = (p.x - c1.x)*(c2.x - c1.x) + (p.y - c1.y)*(c2.y - c1.y) + r1*(r2 -r1) - * C = sqr(p.x - c1.x) + sqr(p.y - c1.y) - r1*r1 - * - * solve the fomula and we get the result of - * t = (B + sqrt(B*B - A*C)) / A or - * t = (B - sqrt(B*B - A*C)) / A (quadratic equation have two solutions) - * - * The solution we are going to prefer is the bigger one, unless the - * radius associated to it is negative (or it falls outside the valid t range) - */ - - #define gradient_radial_fs_template\ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + int index; + + GLint gradient_prog = 0; + char *gradient_fs = NULL; + GLint fs_main_prog, fs_getcolor_prog, vs_prog; + + const char *gradient_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" "}\n"; + + /* + * Refer to pixman radial gradient. + * + * The problem is given the two circles of c1 and c2 with the radius of r1 and + * r1, we need to caculate the t, which is used to do interpolate with stops, + * using the fomula: + * length((1-t)*c1 + t*c2 - p) = (1-t)*r1 + t*r2 + * expand the fomula with xy coond, get the following: + * sqrt(sqr((1-t)*c1.x + t*c2.x - p.x) + sqr((1-t)*c1.y + t*c2.y - p.y)) + * = (1-t)r1 + t*r2 + * <====> At*t- 2Bt + C = 0 + * where A = sqr(c2.x - c1.x) + sqr(c2.y - c1.y) - sqr(r2 -r1) + * B = (p.x - c1.x)*(c2.x - c1.x) + (p.y - c1.y)*(c2.y - c1.y) + r1*(r2 -r1) + * C = sqr(p.x - c1.x) + sqr(p.y - c1.y) - r1*r1 + * + * solve the fomula and we get the result of + * t = (B + sqrt(B*B - A*C)) / A or + * t = (B - sqrt(B*B - A*C)) / A (quadratic equation have two solutions) + * + * The solution we are going to prefer is the bigger one, unless the + * radius associated to it is negative (or it falls outside the valid t range) + */ + +#define gradient_radial_fs_template\ GLAMOR_DEFAULT_PRECISION\ "uniform mat3 transform_mat;\n"\ "uniform int repeat_type;\n"\ @@ -344,149 +268,164 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dy " }\n"\ "}\n" - glamor_priv = glamor_get_screen_private(screen); - - if ((glamor_priv->radial_max_nstops >= stops_count) && (dyn_gen)) { - /* Very Good, not to generate again. */ - return; - } - - dispatch = glamor_get_dispatch(glamor_priv); - - if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) { - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; - - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]); - glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0; - } - - gradient_prog = dispatch->glCreateProgram(); - - vs_prog = glamor_compile_glsl_prog(dispatch, - GL_VERTEX_SHADER, gradient_vs); - - XNFasprintf(&gradient_fs, - gradient_radial_fs_template, - PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); - - fs_main_prog = glamor_compile_glsl_prog(dispatch, - GL_FRAGMENT_SHADER, gradient_fs); - - free(gradient_fs); - - fs_getcolor_prog = - _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); - - dispatch->glAttachShader(gradient_prog, vs_prog); - dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); - dispatch->glAttachShader(gradient_prog, fs_main_prog); - - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_positionsition"); - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); - - glamor_link_glsl_prog(dispatch, gradient_prog); - - dispatch->glUseProgram(0); - - if (dyn_gen) { - index = 2; - glamor_priv->radial_max_nstops = stops_count; - } else if (stops_count) { - index = 1; - } else { - index = 0; - } - - glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; - - glamor_put_dispatch(glamor_priv); + glamor_priv = glamor_get_screen_private(screen); + + if ((glamor_priv->radial_max_nstops >= stops_count) && (dyn_gen)) { + /* Very Good, not to generate again. */ + return; + } + + dispatch = glamor_get_dispatch(glamor_priv); + + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) { + dispatch->glDeleteShader(glamor_priv-> + radial_gradient_shaders + [SHADER_GRADIENT_VS_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; + + dispatch->glDeleteShader(glamor_priv-> + radial_gradient_shaders + [SHADER_GRADIENT_FS_MAIN_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = + 0; + + dispatch->glDeleteShader(glamor_priv-> + radial_gradient_shaders + [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); + glamor_priv-> + radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; + + dispatch->glDeleteProgram(glamor_priv-> + gradient_prog[SHADER_GRADIENT_RADIAL][2]); + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0; + } + + gradient_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, gradient_vs); + + XNFasprintf(&gradient_fs, + gradient_radial_fs_template, + PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL, + PIXMAN_REPEAT_REFLECT); + + fs_main_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); + + free(gradient_fs); + + fs_getcolor_prog = + _glamor_create_getcolor_fs_program(screen, stops_count, + (stops_count > 0)); + + dispatch->glAttachShader(gradient_prog, vs_prog); + dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); + dispatch->glAttachShader(gradient_prog, fs_main_prog); + + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, + "v_positionsition"); + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, + "v_texcoord"); + + glamor_link_glsl_prog(dispatch, gradient_prog); + + dispatch->glUseProgram(0); + + if (dyn_gen) { + index = 2; + glamor_priv->radial_max_nstops = stops_count; + } + else if (stops_count) { + index = 1; + } + else { + index = 0; + } + + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = + vs_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = + fs_main_prog; + glamor_priv-> + radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = + fs_getcolor_prog; + + glamor_put_dispatch(glamor_priv); } static void -_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) +_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, + int dyn_gen) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - - int index = 0; - GLint gradient_prog = 0; - char *gradient_fs = NULL; - GLint fs_main_prog, fs_getcolor_prog, vs_prog; - - const char *gradient_vs = - GLAMOR_DEFAULT_PRECISION - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord;\n" - "varying vec2 source_texture;\n" - "\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - " source_texture = v_texcoord.xy;\n" - "}\n"; - - /* - * | - * |\ - * | \ - * | \ - * | \ - * |\ \ - * | \ \ - * cos_val = |\ p1d \ / - * sqrt(1/(slope*slope+1.0)) ------>\ \ \ / - * | \ \ \ - * | \ \ / \ - * | \ *Pt1\ - * *p1 | \ \ *P - * \ | / \ \ / - * \ | / \ \ / - * \ | pd \ - * \ | \ / \ - * p2* | \ / \ / - * slope = (p2.y - p1.y) / | / p2d / - * (p2.x - p1.x) | / \ / - * | / \ / - * | / / - * | / / - * | / *Pt2 - * | / - * | / - * | / - * | / - * | / - * -------+--------------------------------- - * O| - * | - * | - * - * step 1: compute the distance of p, pt1 and pt2 in the slope direction. - * Caculate the distance on Y axis first and multiply cos_val to - * get the value on slope direction(pd, p1d and p2d represent the - * distance of p, pt1, and pt2 respectively). - * - * step 2: caculate the percentage of (pd - p1d)/(p2d - p1d). - * If (pd - p1d) > (p2d - p1d) or < 0, then sub or add (p2d - p1d) - * to make it in the range of [0, (p2d - p1d)]. - * - * step 3: compare the percentage to every stop and find the stpos just - * before and after it. Use the interpolation fomula to compute RGBA. - */ - - #define gradient_fs_template \ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + int index = 0; + GLint gradient_prog = 0; + char *gradient_fs = NULL; + GLint fs_main_prog, fs_getcolor_prog, vs_prog; + + const char *gradient_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" "}\n"; + + /* + * | + * |\ + * | \ + * | \ + * | \ + * |\ \ + * | \ \ + * cos_val = |\ p1d \ / + * sqrt(1/(slope*slope+1.0)) ------>\ \ \ / + * | \ \ \ + * | \ \ / \ + * | \ *Pt1\ + * *p1 | \ \ *P + * \ | / \ \ / + * \ | / \ \ / + * \ | pd \ + * \ | \ / \ + * p2* | \ / \ / + * slope = (p2.y - p1.y) / | / p2d / + * (p2.x - p1.x) | / \ / + * | / \ / + * | / / + * | / / + * | / *Pt2 + * | / + * | / + * | / + * | / + * | / + * -------+--------------------------------- + * O| + * | + * | + * + * step 1: compute the distance of p, pt1 and pt2 in the slope direction. + * Caculate the distance on Y axis first and multiply cos_val to + * get the value on slope direction(pd, p1d and p2d represent the + * distance of p, pt1, and pt2 respectively). + * + * step 2: caculate the percentage of (pd - p1d)/(p2d - p1d). + * If (pd - p1d) > (p2d - p1d) or < 0, then sub or add (p2d - p1d) + * to make it in the range of [0, (p2d - p1d)]. + * + * step 3: compare the percentage to every stop and find the stpos just + * before and after it. Use the interpolation fomula to compute RGBA. + */ + +#define gradient_fs_template \ GLAMOR_DEFAULT_PRECISION\ "uniform mat3 transform_mat;\n"\ "uniform int repeat_type;\n"\ @@ -569,1016 +508,1086 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy " gl_FragColor = get_color(stop_len);\n"\ "}\n" - glamor_priv = glamor_get_screen_private(screen); - - if ((glamor_priv->linear_max_nstops >= stops_count) && (dyn_gen)) { - /* Very Good, not to generate again. */ - return; - } - - dispatch = glamor_get_dispatch(glamor_priv); - if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) { - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; - - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]); - glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0; - } - - gradient_prog = dispatch->glCreateProgram(); - - vs_prog = glamor_compile_glsl_prog(dispatch, - GL_VERTEX_SHADER, gradient_vs); - - XNFasprintf(&gradient_fs, - gradient_fs_template, - PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); - - fs_main_prog = glamor_compile_glsl_prog(dispatch, - GL_FRAGMENT_SHADER, gradient_fs); - free(gradient_fs); - - fs_getcolor_prog = - _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); - - dispatch->glAttachShader(gradient_prog, vs_prog); - dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); - dispatch->glAttachShader(gradient_prog, fs_main_prog); - - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position"); - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); - - glamor_link_glsl_prog(dispatch, gradient_prog); - - dispatch->glUseProgram(0); - - if (dyn_gen) { - index = 2; - glamor_priv->linear_max_nstops = stops_count; - } else if (stops_count) { - index = 1; - } else { - index = 0; - } - - glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; - - glamor_put_dispatch(glamor_priv); + glamor_priv = glamor_get_screen_private(screen); + + if ((glamor_priv->linear_max_nstops >= stops_count) && (dyn_gen)) { + /* Very Good, not to generate again. */ + return; + } + + dispatch = glamor_get_dispatch(glamor_priv); + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) { + dispatch->glDeleteShader(glamor_priv-> + linear_gradient_shaders + [SHADER_GRADIENT_VS_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; + + dispatch->glDeleteShader(glamor_priv-> + linear_gradient_shaders + [SHADER_GRADIENT_FS_MAIN_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = + 0; + + dispatch->glDeleteShader(glamor_priv-> + linear_gradient_shaders + [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); + glamor_priv-> + linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; + + dispatch->glDeleteProgram(glamor_priv-> + gradient_prog[SHADER_GRADIENT_LINEAR][2]); + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0; + } + + gradient_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, gradient_vs); + + XNFasprintf(&gradient_fs, + gradient_fs_template, + PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + + fs_main_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); + free(gradient_fs); + + fs_getcolor_prog = + _glamor_create_getcolor_fs_program(screen, stops_count, + (stops_count > 0)); + + dispatch->glAttachShader(gradient_prog, vs_prog); + dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); + dispatch->glAttachShader(gradient_prog, fs_main_prog); + + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, + "v_position"); + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, + "v_texcoord"); + + glamor_link_glsl_prog(dispatch, gradient_prog); + + dispatch->glUseProgram(0); + + if (dyn_gen) { + index = 2; + glamor_priv->linear_max_nstops = stops_count; + } + else if (stops_count) { + index = 1; + } + else { + index = 0; + } + + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = + vs_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = + fs_main_prog; + glamor_priv-> + linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = + fs_getcolor_prog; + + glamor_put_dispatch(glamor_priv); } void glamor_init_gradient_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv; - int i; - - glamor_priv = glamor_get_screen_private(screen); - - for (i = 0; i < 3; i++) { - glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i] = 0; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; - - glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i] = 0; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; - } - glamor_priv->linear_max_nstops = 0; - glamor_priv->radial_max_nstops = 0; - - _glamor_create_linear_gradient_program(screen, 0, 0); - _glamor_create_linear_gradient_program(screen, LINEAR_LARGE_STOPS, 0); - - _glamor_create_radial_gradient_program(screen, 0, 0); - _glamor_create_radial_gradient_program(screen, RADIAL_LARGE_STOPS, 0); + glamor_screen_private *glamor_priv; + int i; + + glamor_priv = glamor_get_screen_private(screen); + + for (i = 0; i < 3; i++) { + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = + 0; + glamor_priv-> + linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; + + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = + 0; + glamor_priv-> + radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; + } + glamor_priv->linear_max_nstops = 0; + glamor_priv->radial_max_nstops = 0; + + _glamor_create_linear_gradient_program(screen, 0, 0); + _glamor_create_linear_gradient_program(screen, LINEAR_LARGE_STOPS, 0); + + _glamor_create_radial_gradient_program(screen, 0, 0); + _glamor_create_radial_gradient_program(screen, RADIAL_LARGE_STOPS, 0); } void glamor_fini_gradient_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - int i = 0; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - for (i = 0; i < 3; i++) { - /* Linear Gradient */ - if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); - - if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); - - if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); - - if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]) - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]); - - /* Radial Gradient */ - if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); - - if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); - - if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); - - if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]) - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]); - } - - glamor_put_dispatch(glamor_priv); + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + int i = 0; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + for (i = 0; i < 3; i++) { + /* Linear Gradient */ + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) + dispatch->glDeleteShader(glamor_priv-> + linear_gradient_shaders + [SHADER_GRADIENT_VS_PROG][i]); + + if (glamor_priv-> + linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) + dispatch->glDeleteShader(glamor_priv-> + linear_gradient_shaders + [SHADER_GRADIENT_FS_MAIN_PROG][i]); + + if (glamor_priv-> + linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) + dispatch->glDeleteShader(glamor_priv-> + linear_gradient_shaders + [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); + + if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]) + dispatch->glDeleteProgram(glamor_priv-> + gradient_prog[SHADER_GRADIENT_LINEAR][i]); + + /* Radial Gradient */ + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) + dispatch->glDeleteShader(glamor_priv-> + radial_gradient_shaders + [SHADER_GRADIENT_VS_PROG][i]); + + if (glamor_priv-> + radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) + dispatch->glDeleteShader(glamor_priv-> + radial_gradient_shaders + [SHADER_GRADIENT_FS_MAIN_PROG][i]); + + if (glamor_priv-> + radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) + dispatch->glDeleteShader(glamor_priv-> + radial_gradient_shaders + [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); + + if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]) + dispatch->glDeleteProgram(glamor_priv-> + gradient_prog[SHADER_GRADIENT_RADIAL][i]); + } + + glamor_put_dispatch(glamor_priv); } static void -_glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], - int width, int height, int normalize) +_glamor_gradient_convert_trans_matrix(PictTransform * from, float to[3][3], + int width, int height, int normalize) { - /* - * Because in the shader program, we normalize all the pixel cood to [0, 1], - * so with the transform matrix, the correct logic should be: - * v_s = A*T*v - * v_s: point vector in shader after normalized. - * A: The transition matrix from width X height --> 1.0 X 1.0 - * T: The transform matrix. - * v: point vector in width X height space. - * - * result is OK if we use this fomula. But for every point in width X height space, - * we can just use their normalized point vector in shader, namely we can just - * use the result of A*v in shader. So we have no chance to insert T in A*v. - * We can just convert v_s = A*T*v to v_s = A*T*inv(A)*A*v, where inv(A) is the - * inverse matrix of A. Now, v_s = (A*T*inv(A)) * (A*v) - * So, to get the correct v_s, we need to cacula1 the matrix: (A*T*inv(A)), and - * we name this matrix T_s. - * - * Firstly, because A is for the scale convertion, we find - * -- -- - * |1/w 0 0 | - * A = | 0 1/h 0 | - * | 0 0 1.0| - * -- -- - * so T_s = A*T*inv(a) and result - * - * -- -- - * | t11 h*t12/w t13/w| - * T_s = | w*t21/h t22 t23/h| - * | w*t31 h*t32 t33 | - * -- -- - */ - - to[0][0] = (float)pixman_fixed_to_double(from->matrix[0][0]); - to[0][1] = (float)pixman_fixed_to_double(from->matrix[0][1]) - * (normalize ? (((float)height) / ((float)width)) : 1.0); - to[0][2] = (float)pixman_fixed_to_double(from->matrix[0][2]) - / (normalize ? ((float)width) : 1.0); - - to[1][0] = (float)pixman_fixed_to_double(from->matrix[1][0]) - * (normalize ? (((float)width) / ((float)height)) : 1.0); - to[1][1] = (float)pixman_fixed_to_double(from->matrix[1][1]); - to[1][2] = (float)pixman_fixed_to_double(from->matrix[1][2]) - / (normalize ? ((float)height) : 1.0); - - to[2][0] = (float)pixman_fixed_to_double(from->matrix[2][0]) - * (normalize ? ((float)width) : 1.0); - to[2][1] = (float)pixman_fixed_to_double(from->matrix[2][1]) - * (normalize ? ((float)height) : 1.0); - to[2][2] = (float)pixman_fixed_to_double(from->matrix[2][2]); - - DEBUGF("the transform matrix is:\n%f\t%f\t%f\n%f\t%f\t%f\n%f\t%f\t%f\n", - to[0][0], to[0][1], to[0][2], - to[1][0], to[1][1], to[1][2], - to[2][0], to[2][1], to[2][2]); + /* + * Because in the shader program, we normalize all the pixel cood to [0, 1], + * so with the transform matrix, the correct logic should be: + * v_s = A*T*v + * v_s: point vector in shader after normalized. + * A: The transition matrix from width X height --> 1.0 X 1.0 + * T: The transform matrix. + * v: point vector in width X height space. + * + * result is OK if we use this fomula. But for every point in width X height space, + * we can just use their normalized point vector in shader, namely we can just + * use the result of A*v in shader. So we have no chance to insert T in A*v. + * We can just convert v_s = A*T*v to v_s = A*T*inv(A)*A*v, where inv(A) is the + * inverse matrix of A. Now, v_s = (A*T*inv(A)) * (A*v) + * So, to get the correct v_s, we need to cacula1 the matrix: (A*T*inv(A)), and + * we name this matrix T_s. + * + * Firstly, because A is for the scale convertion, we find + * -- -- + * |1/w 0 0 | + * A = | 0 1/h 0 | + * | 0 0 1.0| + * -- -- + * so T_s = A*T*inv(a) and result + * + * -- -- + * | t11 h*t12/w t13/w| + * T_s = | w*t21/h t22 t23/h| + * | w*t31 h*t32 t33 | + * -- -- + */ + + to[0][0] = (float) pixman_fixed_to_double(from->matrix[0][0]); + to[0][1] = (float) pixman_fixed_to_double(from->matrix[0][1]) + * (normalize ? (((float) height) / ((float) width)) : 1.0); + to[0][2] = (float) pixman_fixed_to_double(from->matrix[0][2]) + / (normalize ? ((float) width) : 1.0); + + to[1][0] = (float) pixman_fixed_to_double(from->matrix[1][0]) + * (normalize ? (((float) width) / ((float) height)) : 1.0); + to[1][1] = (float) pixman_fixed_to_double(from->matrix[1][1]); + to[1][2] = (float) pixman_fixed_to_double(from->matrix[1][2]) + / (normalize ? ((float) height) : 1.0); + + to[2][0] = (float) pixman_fixed_to_double(from->matrix[2][0]) + * (normalize ? ((float) width) : 1.0); + to[2][1] = (float) pixman_fixed_to_double(from->matrix[2][1]) + * (normalize ? ((float) height) : 1.0); + to[2][2] = (float) pixman_fixed_to_double(from->matrix[2][2]); + + DEBUGF("the transform matrix is:\n%f\t%f\t%f\n%f\t%f\t%f\n%f\t%f\t%f\n", + to[0][0], to[0][1], to[0][2], + to[1][0], to[1][1], to[1][2], to[2][0], to[2][1], to[2][2]); } static int _glamor_gradient_set_pixmap_destination(ScreenPtr screen, - glamor_screen_private *glamor_priv, + glamor_screen_private * glamor_priv, PicturePtr dst_picture, - GLfloat *xscale, GLfloat *yscale, + GLfloat * xscale, GLfloat * yscale, int x_source, int y_source, float vertices[8], float tex_vertices[8], - int tex_normalize) + int tex_normalize) { - glamor_pixmap_private *pixmap_priv; - PixmapPtr pixmap = NULL; - glamor_gl_dispatch *dispatch = NULL; - - pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); - pixmap_priv = glamor_get_pixmap_private(pixmap); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ - return 0; - } - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - - pixmap_priv_get_dest_scale(pixmap_priv, xscale, yscale); - - DEBUGF("xscale = %f, yscale = %f," - " x_source = %d, y_source = %d, width = %d, height = %d\n", - *xscale, *yscale, x_source, y_source, - dst_picture->pDrawable->width, dst_picture->pDrawable->height); - - glamor_set_normalize_vcoords_tri_strip(*xscale, *yscale, - 0, 0, - (INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - glamor_priv->yInverted, vertices); - - if (tex_normalize) { - glamor_set_normalize_tcoords_tri_stripe(*xscale, *yscale, - x_source, y_source, - (INT16)(dst_picture->pDrawable->width + x_source), - (INT16)(dst_picture->pDrawable->height + y_source), - glamor_priv->yInverted, tex_vertices); - } else { - glamor_set_tcoords_tri_strip((INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - x_source, y_source, - (INT16)(dst_picture->pDrawable->width) + x_source, - (INT16)(dst_picture->pDrawable->height) + y_source, - glamor_priv->yInverted, tex_vertices); - } - - DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," - "rightbottom: %f X %f, leftbottom : %f X %f\n", - vertices[0], vertices[1], vertices[2], vertices[3], - vertices[4], vertices[5], vertices[6], vertices[7]); - DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," - "rightbottom: %f X %f, leftbottom : %f X %f\n", - tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], - tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); - - dispatch = glamor_get_dispatch(glamor_priv); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 0, vertices); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 0, tex_vertices); - - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - glamor_put_dispatch(glamor_priv); - - return 1; + glamor_pixmap_private *pixmap_priv; + PixmapPtr pixmap = NULL; + glamor_gl_dispatch *dispatch = NULL; + + pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ + return 0; + } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + pixmap_priv_get_dest_scale(pixmap_priv, xscale, yscale); + + DEBUGF("xscale = %f, yscale = %f," + " x_source = %d, y_source = %d, width = %d, height = %d\n", + *xscale, *yscale, x_source, y_source, + dst_picture->pDrawable->width, dst_picture->pDrawable->height); + + glamor_set_normalize_vcoords_tri_strip(*xscale, *yscale, + 0, 0, + (INT16) (dst_picture->pDrawable-> + width), + (INT16) (dst_picture->pDrawable-> + height), + glamor_priv->yInverted, vertices); + + if (tex_normalize) { + glamor_set_normalize_tcoords_tri_stripe(*xscale, *yscale, + x_source, y_source, + (INT16) (dst_picture-> + pDrawable->width + + x_source), + (INT16) (dst_picture-> + pDrawable->height + + y_source), + glamor_priv->yInverted, + tex_vertices); + } + else { + glamor_set_tcoords_tri_strip((INT16) (dst_picture->pDrawable->width), + (INT16) (dst_picture->pDrawable->height), + x_source, y_source, + (INT16) (dst_picture->pDrawable->width) + + x_source, + (INT16) (dst_picture->pDrawable->height) + + y_source, glamor_priv->yInverted, + tex_vertices); + } + + DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + vertices[0], vertices[1], vertices[2], vertices[3], + vertices[4], vertices[5], vertices[6], vertices[7]); + DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], + tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); + + dispatch = glamor_get_dispatch(glamor_priv); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 0, vertices); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 0, tex_vertices); + + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + glamor_put_dispatch(glamor_priv); + + return 1; } static int _glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, - GLfloat *stop_colors, GLfloat *n_stops) + GLfloat * stop_colors, GLfloat * n_stops) { - int i; - int count = 1; - - for (i = 0; i < pgradient->nstops; i++) { - stop_colors[count*4] = pixman_fixed_to_double( - pgradient->stops[i].color.red); - stop_colors[count*4+1] = pixman_fixed_to_double( - pgradient->stops[i].color.green); - stop_colors[count*4+2] = pixman_fixed_to_double( - pgradient->stops[i].color.blue); - stop_colors[count*4+3] = pixman_fixed_to_double( - pgradient->stops[i].color.alpha); - - n_stops[count] = (GLfloat)pixman_fixed_to_double( - pgradient->stops[i].x); - count++; - } - - /* for the end stop. */ - count++; - - switch (src_picture->repeatType) { + int i; + int count = 1; + + for (i = 0; i < pgradient->nstops; i++) { + stop_colors[count * 4] = + pixman_fixed_to_double(pgradient->stops[i].color.red); + stop_colors[count * 4 + 1] = + pixman_fixed_to_double(pgradient->stops[i].color.green); + stop_colors[count * 4 + 2] = + pixman_fixed_to_double(pgradient->stops[i].color.blue); + stop_colors[count * 4 + 3] = + pixman_fixed_to_double(pgradient->stops[i].color.alpha); + + n_stops[count] = + (GLfloat) pixman_fixed_to_double(pgradient->stops[i].x); + count++; + } + + /* for the end stop. */ + count++; + + switch (src_picture->repeatType) { #define REPEAT_FILL_STOPS(m, n) \ stop_colors[(m)*4 + 0] = stop_colors[(n)*4 + 0]; \ stop_colors[(m)*4 + 1] = stop_colors[(n)*4 + 1]; \ stop_colors[(m)*4 + 2] = stop_colors[(n)*4 + 2]; \ stop_colors[(m)*4 + 3] = stop_colors[(n)*4 + 3]; - default: - case PIXMAN_REPEAT_NONE: - stop_colors[0] = 0.0; //R - stop_colors[1] = 0.0; //G - stop_colors[2] = 0.0; //B - stop_colors[3] = 0.0; //Alpha - n_stops[0] = -(float)INT_MAX; //should be small enough. - - stop_colors[0 + (count-1)*4] = 0.0; //R - stop_colors[1 + (count-1)*4] = 0.0; //G - stop_colors[2 + (count-1)*4] = 0.0; //B - stop_colors[3 + (count-1)*4] = 0.0; //Alpha - n_stops[count-1] = (float)INT_MAX; //should be large enough. - break; - case PIXMAN_REPEAT_NORMAL: - REPEAT_FILL_STOPS(0, count - 2); - n_stops[0] = n_stops[count-2] - 1.0; - - REPEAT_FILL_STOPS(count - 1, 1); - n_stops[count-1] = n_stops[1] + 1.0; - break; - case PIXMAN_REPEAT_REFLECT: - REPEAT_FILL_STOPS(0, 1); - n_stops[0] = -n_stops[1]; - - REPEAT_FILL_STOPS(count - 1, count - 2); - n_stops[count-1] = 1.0 + 1.0 - n_stops[count-2]; - break; - case PIXMAN_REPEAT_PAD: - REPEAT_FILL_STOPS(0, 1); - n_stops[0] = -(float)INT_MAX; - - REPEAT_FILL_STOPS(count - 1, count - 2); - n_stops[count-1] = (float)INT_MAX; - break; + default: + case PIXMAN_REPEAT_NONE: + stop_colors[0] = 0.0; //R + stop_colors[1] = 0.0; //G + stop_colors[2] = 0.0; //B + stop_colors[3] = 0.0; //Alpha + n_stops[0] = -(float) INT_MAX; //should be small enough. + + stop_colors[0 + (count - 1) * 4] = 0.0; //R + stop_colors[1 + (count - 1) * 4] = 0.0; //G + stop_colors[2 + (count - 1) * 4] = 0.0; //B + stop_colors[3 + (count - 1) * 4] = 0.0; //Alpha + n_stops[count - 1] = (float) INT_MAX; //should be large enough. + break; + case PIXMAN_REPEAT_NORMAL: + REPEAT_FILL_STOPS(0, count - 2); + n_stops[0] = n_stops[count - 2] - 1.0; + + REPEAT_FILL_STOPS(count - 1, 1); + n_stops[count - 1] = n_stops[1] + 1.0; + break; + case PIXMAN_REPEAT_REFLECT: + REPEAT_FILL_STOPS(0, 1); + n_stops[0] = -n_stops[1]; + + REPEAT_FILL_STOPS(count - 1, count - 2); + n_stops[count - 1] = 1.0 + 1.0 - n_stops[count - 2]; + break; + case PIXMAN_REPEAT_PAD: + REPEAT_FILL_STOPS(0, 1); + n_stops[0] = -(float) INT_MAX; + + REPEAT_FILL_STOPS(count - 1, count - 2); + n_stops[count - 1] = (float) INT_MAX; + break; #undef REPEAT_FILL_STOPS - } + } - for (i = 0; i < count; i++) { - DEBUGF("n_stops[%d] = %f, color = r:%f g:%f b:%f a:%f\n", - i, n_stops[i], - stop_colors[i*4], stop_colors[i*4+1], - stop_colors[i*4+2], stop_colors[i*4+3]); - } + for (i = 0; i < count; i++) { + DEBUGF("n_stops[%d] = %f, color = r:%f g:%f b:%f a:%f\n", + i, n_stops[i], + stop_colors[i * 4], stop_colors[i * 4 + 1], + stop_colors[i * 4 + 2], stop_colors[i * 4 + 3]); + } - return count; + return count; } PicturePtr glamor_generate_radial_gradient_picture(ScreenPtr screen, - PicturePtr src_picture, - int x_source, int y_source, - int width, int height, - PictFormatShort format) + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - PicturePtr dst_picture = NULL; - PixmapPtr pixmap = NULL; - GLint gradient_prog = 0; - int error; - float tex_vertices[8]; - int stops_count = 0; - int count = 0; - GLfloat *stop_colors = NULL; - GLfloat *n_stops = NULL; - GLfloat xscale, yscale; - float vertices[8]; - float transform_mat[3][3]; - static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0}}; - GLfloat stop_colors_st[RADIAL_SMALL_STOPS*4]; - GLfloat n_stops_st[RADIAL_SMALL_STOPS]; - GLfloat A_value; - GLfloat cxy[4]; - float c1x, c1y, c2x, c2y, r1, r2; - - GLint transform_mat_uniform_location = 0; - GLint repeat_type_uniform_location = 0; - GLint n_stop_uniform_location = 0; - GLint stops_uniform_location = 0; - GLint stop_colors_uniform_location = 0; - GLint stop0_uniform_location = 0; - GLint stop1_uniform_location = 0; - GLint stop2_uniform_location = 0; - GLint stop3_uniform_location = 0; - GLint stop4_uniform_location = 0; - GLint stop5_uniform_location = 0; - GLint stop6_uniform_location = 0; - GLint stop7_uniform_location = 0; - GLint stop_color0_uniform_location = 0; - GLint stop_color1_uniform_location = 0; - GLint stop_color2_uniform_location = 0; - GLint stop_color3_uniform_location = 0; - GLint stop_color4_uniform_location = 0; - GLint stop_color5_uniform_location = 0; - GLint stop_color6_uniform_location = 0; - GLint stop_color7_uniform_location = 0; - GLint A_value_uniform_location = 0; - GLint c1_uniform_location = 0; - GLint r1_uniform_location = 0; - GLint c2_uniform_location = 0; - GLint r2_uniform_location = 0; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - /* Create a pixmap with VBO. */ - pixmap = glamor_create_pixmap(screen, - width, height, - PIXMAN_FORMAT_DEPTH(format), - 0); - if (!pixmap) - goto GRADIENT_FAIL; - - dst_picture = CreatePicture(0, &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), format), - 0, 0, serverClient, &error); - - /* Release the reference, picture will hold the last one. */ - glamor_destroy_pixmap(pixmap); - - if (!dst_picture) - goto GRADIENT_FAIL; - - ValidatePicture(dst_picture); - - stops_count = src_picture->pSourcePict->radial.nstops + 2; - - /* Because the max value of nstops is unkown, so create a program - when nstops > LINEAR_LARGE_STOPS.*/ - if (stops_count <= RADIAL_SMALL_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][0]; - } else if (stops_count <= RADIAL_LARGE_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][1]; - } else { - _glamor_create_radial_gradient_program(screen, - src_picture->pSourcePict->linear.nstops + 2, - 1); - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]; - } - - /* Bind all the uniform vars .*/ - transform_mat_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); - repeat_type_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); - n_stop_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "n_stop"); - A_value_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "A_value"); - repeat_type_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); - c1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "c1"); - r1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "r1"); - c2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "c2"); - r2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "r2"); - - if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) { - stop0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop0"); - stop1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop1"); - stop2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop2"); - stop3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop3"); - stop4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop4"); - stop5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop5"); - stop6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop6"); - stop7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop7"); - - stop_color0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); - stop_color1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); - stop_color2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); - stop_color3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); - stop_color4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); - stop_color5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); - stop_color6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); - stop_color7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); - } else { - stops_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stops"); - stop_colors_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); - } - - dispatch->glUseProgram(gradient_prog); - - dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); - - - if (src_picture->transform) { - _glamor_gradient_convert_trans_matrix(src_picture->transform, - transform_mat, - width, height, 0); - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &transform_mat[0][0]); - } else { - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &identity_mat[0][0]); - } - - if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, - &xscale, &yscale, x_source, y_source, - vertices, tex_vertices, 0)) - goto GRADIENT_FAIL; - - /* Set all the stops and colors to shader. */ - if (stops_count > RADIAL_SMALL_STOPS) { - stop_colors = malloc(4 * stops_count * sizeof(float)); - if (stop_colors == NULL) { - ErrorF("Failed to allocate stop_colors memory.\n"); - goto GRADIENT_FAIL; - } - - n_stops = malloc(stops_count * sizeof(float)); - if (n_stops == NULL) { - ErrorF("Failed to allocate n_stops memory.\n"); - goto GRADIENT_FAIL; - } - } else { - stop_colors = stop_colors_st; - n_stops = n_stops_st; - } - - count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, - stop_colors, n_stops); - - if (src_picture->pSourcePict->linear.nstops + 2 <= RADIAL_SMALL_STOPS) { - int j = 0; - dispatch->glUniform4f(stop_color0_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color1_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color2_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color3_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color4_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color5_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color6_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color7_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - - j = 0; - dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); - dispatch->glUniform1i(n_stop_uniform_location, count); - } else { - dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); - dispatch->glUniform1fv(stops_uniform_location, count, n_stops); - dispatch->glUniform1i(n_stop_uniform_location, count); - } - - c1x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.x); - c1y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.y); - c2x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.x); - c2y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.y); - - r1 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.radius); - r2 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.radius); - - glamor_set_circle_centre(width, height, c1x, c1y, glamor_priv->yInverted, cxy); - dispatch->glUniform2fv(c1_uniform_location, 1, cxy); - dispatch->glUniform1f(r1_uniform_location, r1); - - glamor_set_circle_centre(width, height, c2x, c2y, glamor_priv->yInverted, cxy); - dispatch->glUniform2fv(c2_uniform_location, 1, cxy); - dispatch->glUniform1f(r2_uniform_location, r2); - - A_value = (c2x - c1x) * (c2x - c1x) + (c2y - c1y) * (c2y - c1y) - (r2 - r1) * (r2 - r1); - dispatch->glUniform1f(A_value_uniform_location, A_value); - - DEBUGF("C1:(%f, %f) R1:%f\nC2:(%f, %f) R2:%f\nA = %f\n", - c1x, c1y, r1, c2x, c2y, r2, A_value); - - /* Now rendering. */ - dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - /* Do the clear logic.*/ - if (stops_count > RADIAL_SMALL_STOPS) { - free(n_stops); - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - - glamor_put_dispatch(glamor_priv); - return dst_picture; - -GRADIENT_FAIL: - if (dst_picture) { - FreePicture(dst_picture, 0); - } - - if (stops_count > RADIAL_SMALL_STOPS) { - if (n_stops) - free(n_stops); - if (stop_colors) - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - glamor_put_dispatch(glamor_priv); - return NULL; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + PicturePtr dst_picture = NULL; + PixmapPtr pixmap = NULL; + GLint gradient_prog = 0; + int error; + float tex_vertices[8]; + int stops_count = 0; + int count = 0; + GLfloat *stop_colors = NULL; + GLfloat *n_stops = NULL; + GLfloat xscale, yscale; + float vertices[8]; + float transform_mat[3][3]; + static const float identity_mat[3][3] = { {1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0} + }; + GLfloat stop_colors_st[RADIAL_SMALL_STOPS * 4]; + GLfloat n_stops_st[RADIAL_SMALL_STOPS]; + GLfloat A_value; + GLfloat cxy[4]; + float c1x, c1y, c2x, c2y, r1, r2; + + GLint transform_mat_uniform_location = 0; + GLint repeat_type_uniform_location = 0; + GLint n_stop_uniform_location = 0; + GLint stops_uniform_location = 0; + GLint stop_colors_uniform_location = 0; + GLint stop0_uniform_location = 0; + GLint stop1_uniform_location = 0; + GLint stop2_uniform_location = 0; + GLint stop3_uniform_location = 0; + GLint stop4_uniform_location = 0; + GLint stop5_uniform_location = 0; + GLint stop6_uniform_location = 0; + GLint stop7_uniform_location = 0; + GLint stop_color0_uniform_location = 0; + GLint stop_color1_uniform_location = 0; + GLint stop_color2_uniform_location = 0; + GLint stop_color3_uniform_location = 0; + GLint stop_color4_uniform_location = 0; + GLint stop_color5_uniform_location = 0; + GLint stop_color6_uniform_location = 0; + GLint stop_color7_uniform_location = 0; + GLint A_value_uniform_location = 0; + GLint c1_uniform_location = 0; + GLint r1_uniform_location = 0; + GLint c2_uniform_location = 0; + GLint r2_uniform_location = 0; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + /* Create a pixmap with VBO. */ + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), 0); + if (!pixmap) + goto GRADIENT_FAIL; + + dst_picture = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), 0, 0, serverClient, + &error); + + /* Release the reference, picture will hold the last one. */ + glamor_destroy_pixmap(pixmap); + + if (!dst_picture) + goto GRADIENT_FAIL; + + ValidatePicture(dst_picture); + + stops_count = src_picture->pSourcePict->radial.nstops + 2; + + /* Because the max value of nstops is unkown, so create a program + when nstops > LINEAR_LARGE_STOPS. */ + if (stops_count <= RADIAL_SMALL_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][0]; + } + else if (stops_count <= RADIAL_LARGE_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][1]; + } + else { + _glamor_create_radial_gradient_program(screen, + src_picture->pSourcePict->linear. + nstops + 2, 1); + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]; + } + + /* Bind all the uniform vars . */ + transform_mat_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + n_stop_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "n_stop"); + A_value_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "A_value"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + c1_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "c1"); + r1_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "r1"); + c2_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "c2"); + r2_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "r2"); + + if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) { + stop0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop0"); + stop1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop1"); + stop2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop2"); + stop3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop3"); + stop4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop4"); + stop5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop5"); + stop6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop6"); + stop7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop7"); + + stop_color0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); + stop_color1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); + stop_color2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); + stop_color3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); + stop_color4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); + stop_color5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); + stop_color6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); + stop_color7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); + } + else { + stops_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stops"); + stop_colors_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); + } + + dispatch->glUseProgram(gradient_prog); + + dispatch->glUniform1i(repeat_type_uniform_location, + src_picture->repeatType); + + if (src_picture->transform) { + _glamor_gradient_convert_trans_matrix(src_picture->transform, + transform_mat, width, height, 0); + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &transform_mat[0][0]); + } + else { + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &identity_mat[0][0]); + } + + if (!_glamor_gradient_set_pixmap_destination + (screen, glamor_priv, dst_picture, &xscale, &yscale, x_source, y_source, + vertices, tex_vertices, 0)) + goto GRADIENT_FAIL; + + /* Set all the stops and colors to shader. */ + if (stops_count > RADIAL_SMALL_STOPS) { + stop_colors = malloc(4 * stops_count * sizeof(float)); + if (stop_colors == NULL) { + ErrorF("Failed to allocate stop_colors memory.\n"); + goto GRADIENT_FAIL; + } + + n_stops = malloc(stops_count * sizeof(float)); + if (n_stops == NULL) { + ErrorF("Failed to allocate n_stops memory.\n"); + goto GRADIENT_FAIL; + } + } + else { + stop_colors = stop_colors_st; + n_stops = n_stops_st; + } + + count = + _glamor_gradient_set_stops(src_picture, + &src_picture->pSourcePict->gradient, + stop_colors, n_stops); + + if (src_picture->pSourcePict->linear.nstops + 2 <= RADIAL_SMALL_STOPS) { + int j = 0; + + dispatch->glUniform4f(stop_color0_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color1_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color2_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color3_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color4_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color5_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color6_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color7_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + + j = 0; + dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + else { + dispatch->glUniform4fv(stop_colors_uniform_location, count, + stop_colors); + dispatch->glUniform1fv(stops_uniform_location, count, n_stops); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + + c1x = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.x); + c1y = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.y); + c2x = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.x); + c2y = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.y); + + r1 = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c1. + radius); + r2 = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c2. + radius); + + glamor_set_circle_centre(width, height, c1x, c1y, glamor_priv->yInverted, + cxy); + dispatch->glUniform2fv(c1_uniform_location, 1, cxy); + dispatch->glUniform1f(r1_uniform_location, r1); + + glamor_set_circle_centre(width, height, c2x, c2y, glamor_priv->yInverted, + cxy); + dispatch->glUniform2fv(c2_uniform_location, 1, cxy); + dispatch->glUniform1f(r2_uniform_location, r2); + + A_value = + (c2x - c1x) * (c2x - c1x) + (c2y - c1y) * (c2y - c1y) - (r2 - + r1) * (r2 - + r1); + dispatch->glUniform1f(A_value_uniform_location, A_value); + + DEBUGF("C1:(%f, %f) R1:%f\nC2:(%f, %f) R2:%f\nA = %f\n", + c1x, c1y, r1, c2x, c2y, r2, A_value); + + /* Now rendering. */ + dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* Do the clear logic. */ + if (stops_count > RADIAL_SMALL_STOPS) { + free(n_stops); + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); + return dst_picture; + + GRADIENT_FAIL: + if (dst_picture) { + FreePicture(dst_picture, 0); + } + + if (stops_count > RADIAL_SMALL_STOPS) { + if (n_stops) + free(n_stops); + if (stop_colors) + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); + return NULL; } PicturePtr glamor_generate_linear_gradient_picture(ScreenPtr screen, - PicturePtr src_picture, - int x_source, int y_source, - int width, int height, - PictFormatShort format) + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - PicturePtr dst_picture = NULL; - PixmapPtr pixmap = NULL; - GLint gradient_prog = 0; - int error; - float pt_distance; - float p1_distance; - GLfloat cos_val; - float tex_vertices[8]; - int stops_count = 0; - GLfloat *stop_colors = NULL; - GLfloat *n_stops = NULL; - int count = 0; - float slope; - GLfloat xscale, yscale; - GLfloat pt1[2], pt2[2]; - float vertices[8]; - float transform_mat[3][3]; - static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0}}; - GLfloat stop_colors_st[LINEAR_SMALL_STOPS*4]; - GLfloat n_stops_st[LINEAR_SMALL_STOPS]; - - GLint transform_mat_uniform_location = 0; - GLint n_stop_uniform_location = 0; - GLint stops_uniform_location = 0; - GLint stop0_uniform_location = 0; - GLint stop1_uniform_location = 0; - GLint stop2_uniform_location = 0; - GLint stop3_uniform_location = 0; - GLint stop4_uniform_location = 0; - GLint stop5_uniform_location = 0; - GLint stop6_uniform_location = 0; - GLint stop7_uniform_location = 0; - GLint stop_colors_uniform_location = 0; - GLint stop_color0_uniform_location = 0; - GLint stop_color1_uniform_location = 0; - GLint stop_color2_uniform_location = 0; - GLint stop_color3_uniform_location = 0; - GLint stop_color4_uniform_location = 0; - GLint stop_color5_uniform_location = 0; - GLint stop_color6_uniform_location = 0; - GLint stop_color7_uniform_location = 0; - GLint pt_slope_uniform_location = 0; - GLint repeat_type_uniform_location = 0; - GLint hor_ver_uniform_location = 0; - GLint cos_val_uniform_location = 0; - GLint p1_distance_uniform_location = 0; - GLint pt_distance_uniform_location = 0; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - /* Create a pixmap with VBO. */ - pixmap = glamor_create_pixmap(screen, - width, height, - PIXMAN_FORMAT_DEPTH(format), - 0); - - if (!pixmap) - goto GRADIENT_FAIL; - - dst_picture = CreatePicture(0, &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), format), - 0, 0, serverClient, &error); - - /* Release the reference, picture will hold the last one. */ - glamor_destroy_pixmap(pixmap); - - if (!dst_picture) - goto GRADIENT_FAIL; - - ValidatePicture(dst_picture); - - stops_count = src_picture->pSourcePict->linear.nstops + 2; - - /* Because the max value of nstops is unkown, so create a program - when nstops > LINEAR_LARGE_STOPS.*/ - if (stops_count <= LINEAR_SMALL_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][0]; - } else if (stops_count <= LINEAR_LARGE_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][1]; - } else { - _glamor_create_linear_gradient_program(screen, - src_picture->pSourcePict->linear.nstops + 2, 1); - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]; - } - - /* Bind all the uniform vars .*/ - n_stop_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "n_stop"); - pt_slope_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt_slope"); - repeat_type_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); - hor_ver_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "hor_ver"); - transform_mat_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); - cos_val_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "cos_val"); - p1_distance_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "p1_distance"); - pt_distance_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt_distance"); - - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { - stop0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop0"); - stop1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop1"); - stop2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop2"); - stop3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop3"); - stop4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop4"); - stop5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop5"); - stop6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop6"); - stop7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop7"); - - stop_color0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); - stop_color1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); - stop_color2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); - stop_color3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); - stop_color4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); - stop_color5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); - stop_color6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); - stop_color7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); - } else { - stops_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stops"); - stop_colors_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); - } - - dispatch->glUseProgram(gradient_prog); - - dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); - - /* set the transform matrix. */ - if (src_picture->transform) { - _glamor_gradient_convert_trans_matrix(src_picture->transform, - transform_mat, - width, height, 1); - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &transform_mat[0][0]); - } else { - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &identity_mat[0][0]); - } - - if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, - &xscale, &yscale, x_source, y_source, - vertices, tex_vertices, 1)) - goto GRADIENT_FAIL; - - /* Normalize the PTs. */ - glamor_set_normalize_pt(xscale, yscale, - pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x), - pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y), - glamor_priv->yInverted, - pt1); - DEBUGF("pt1:(%f, %f) ---> (%f %f)\n", pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x), - pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y), pt1[0], pt1[1]); - - glamor_set_normalize_pt(xscale, yscale, - pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x), - pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y), - glamor_priv->yInverted, - pt2); - DEBUGF("pt2:(%f, %f) ---> (%f %f)\n", pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x), - pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y), pt2[0], pt2[1]); - - /* Set all the stops and colors to shader. */ - if (stops_count > LINEAR_SMALL_STOPS) { - stop_colors = malloc(4 * stops_count * sizeof(float)); - if (stop_colors == NULL) { - ErrorF("Failed to allocate stop_colors memory.\n"); - goto GRADIENT_FAIL; - } - - n_stops = malloc(stops_count * sizeof(float)); - if (n_stops == NULL) { - ErrorF("Failed to allocate n_stops memory.\n"); - goto GRADIENT_FAIL; - } - } else { - stop_colors = stop_colors_st; - n_stops = n_stops_st; - } - - count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, - stop_colors, n_stops); - - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { - int j = 0; - dispatch->glUniform4f(stop_color0_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color1_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color2_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color3_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color4_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color5_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color6_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color7_uniform_location, - stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - - j = 0; - dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); - - dispatch->glUniform1i(n_stop_uniform_location, count); - } else { - dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); - dispatch->glUniform1fv(stops_uniform_location, count, n_stops); - dispatch->glUniform1i(n_stop_uniform_location, count); - } - - if (src_picture->pSourcePict->linear.p2.y == - src_picture->pSourcePict->linear.p1.y) { // The horizontal case. - dispatch->glUniform1i(hor_ver_uniform_location, 1); - DEBUGF("p1.y: %f, p2.y: %f, enter the horizontal case\n", - pt1[1], pt2[1]); - - p1_distance = pt1[0]; - pt_distance = (pt2[0] - p1_distance); - dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); - dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); - } else { - /* The slope need to compute here. In shader, the viewport set will change - the orginal slope and the slope which is vertical to it will not be correct.*/ - slope = - (float)(src_picture->pSourcePict->linear.p2.x - - src_picture->pSourcePict->linear.p1.x) / - (float)(src_picture->pSourcePict->linear.p2.y - - src_picture->pSourcePict->linear.p1.y); - slope = slope * yscale / xscale; - dispatch->glUniform1f(pt_slope_uniform_location, slope); - dispatch->glUniform1i(hor_ver_uniform_location, 0); - - cos_val = sqrt(1.0 / (slope * slope + 1.0)); - dispatch->glUniform1f(cos_val_uniform_location, cos_val); - - p1_distance = (pt1[1] - pt1[0] * slope) * cos_val; - pt_distance = (pt2[1] - pt2[0] * slope) * cos_val - p1_distance; - dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); - dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); - } - - /* Now rendering. */ - dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - /* Do the clear logic.*/ - if (stops_count > LINEAR_SMALL_STOPS) { - free(n_stops); - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - - glamor_put_dispatch(glamor_priv); - return dst_picture; - -GRADIENT_FAIL: - if (dst_picture) { - FreePicture(dst_picture, 0); - } - - if (stops_count > LINEAR_SMALL_STOPS) { - if (n_stops) - free(n_stops); - if (stop_colors) - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - glamor_put_dispatch(glamor_priv); - return NULL; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + PicturePtr dst_picture = NULL; + PixmapPtr pixmap = NULL; + GLint gradient_prog = 0; + int error; + float pt_distance; + float p1_distance; + GLfloat cos_val; + float tex_vertices[8]; + int stops_count = 0; + GLfloat *stop_colors = NULL; + GLfloat *n_stops = NULL; + int count = 0; + float slope; + GLfloat xscale, yscale; + GLfloat pt1[2], pt2[2]; + float vertices[8]; + float transform_mat[3][3]; + static const float identity_mat[3][3] = { {1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0} + }; + GLfloat stop_colors_st[LINEAR_SMALL_STOPS * 4]; + GLfloat n_stops_st[LINEAR_SMALL_STOPS]; + + GLint transform_mat_uniform_location = 0; + GLint n_stop_uniform_location = 0; + GLint stops_uniform_location = 0; + GLint stop0_uniform_location = 0; + GLint stop1_uniform_location = 0; + GLint stop2_uniform_location = 0; + GLint stop3_uniform_location = 0; + GLint stop4_uniform_location = 0; + GLint stop5_uniform_location = 0; + GLint stop6_uniform_location = 0; + GLint stop7_uniform_location = 0; + GLint stop_colors_uniform_location = 0; + GLint stop_color0_uniform_location = 0; + GLint stop_color1_uniform_location = 0; + GLint stop_color2_uniform_location = 0; + GLint stop_color3_uniform_location = 0; + GLint stop_color4_uniform_location = 0; + GLint stop_color5_uniform_location = 0; + GLint stop_color6_uniform_location = 0; + GLint stop_color7_uniform_location = 0; + GLint pt_slope_uniform_location = 0; + GLint repeat_type_uniform_location = 0; + GLint hor_ver_uniform_location = 0; + GLint cos_val_uniform_location = 0; + GLint p1_distance_uniform_location = 0; + GLint pt_distance_uniform_location = 0; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + /* Create a pixmap with VBO. */ + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), 0); + + if (!pixmap) + goto GRADIENT_FAIL; + + dst_picture = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), 0, 0, serverClient, + &error); + + /* Release the reference, picture will hold the last one. */ + glamor_destroy_pixmap(pixmap); + + if (!dst_picture) + goto GRADIENT_FAIL; + + ValidatePicture(dst_picture); + + stops_count = src_picture->pSourcePict->linear.nstops + 2; + + /* Because the max value of nstops is unkown, so create a program + when nstops > LINEAR_LARGE_STOPS. */ + if (stops_count <= LINEAR_SMALL_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][0]; + } + else if (stops_count <= LINEAR_LARGE_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][1]; + } + else { + _glamor_create_linear_gradient_program(screen, + src_picture->pSourcePict->linear. + nstops + 2, 1); + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]; + } + + /* Bind all the uniform vars . */ + n_stop_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "n_stop"); + pt_slope_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt_slope"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + hor_ver_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "hor_ver"); + transform_mat_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); + cos_val_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "cos_val"); + p1_distance_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "p1_distance"); + pt_distance_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt_distance"); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { + stop0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop0"); + stop1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop1"); + stop2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop2"); + stop3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop3"); + stop4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop4"); + stop5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop5"); + stop6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop6"); + stop7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop7"); + + stop_color0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); + stop_color1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); + stop_color2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); + stop_color3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); + stop_color4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); + stop_color5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); + stop_color6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); + stop_color7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); + } + else { + stops_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stops"); + stop_colors_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); + } + + dispatch->glUseProgram(gradient_prog); + + dispatch->glUniform1i(repeat_type_uniform_location, + src_picture->repeatType); + + /* set the transform matrix. */ + if (src_picture->transform) { + _glamor_gradient_convert_trans_matrix(src_picture->transform, + transform_mat, width, height, 1); + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &transform_mat[0][0]); + } + else { + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &identity_mat[0][0]); + } + + if (!_glamor_gradient_set_pixmap_destination + (screen, glamor_priv, dst_picture, &xscale, &yscale, x_source, y_source, + vertices, tex_vertices, 1)) + goto GRADIENT_FAIL; + + /* Normalize the PTs. */ + glamor_set_normalize_pt(xscale, yscale, + pixman_fixed_to_double(src_picture->pSourcePict-> + linear.p1.x), + pixman_fixed_to_double(src_picture->pSourcePict-> + linear.p1.y), + glamor_priv->yInverted, pt1); + DEBUGF("pt1:(%f, %f) ---> (%f %f)\n", + pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x), + pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y), + pt1[0], pt1[1]); + + glamor_set_normalize_pt(xscale, yscale, + pixman_fixed_to_double(src_picture->pSourcePict-> + linear.p2.x), + pixman_fixed_to_double(src_picture->pSourcePict-> + linear.p2.y), + glamor_priv->yInverted, pt2); + DEBUGF("pt2:(%f, %f) ---> (%f %f)\n", + pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x), + pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y), + pt2[0], pt2[1]); + + /* Set all the stops and colors to shader. */ + if (stops_count > LINEAR_SMALL_STOPS) { + stop_colors = malloc(4 * stops_count * sizeof(float)); + if (stop_colors == NULL) { + ErrorF("Failed to allocate stop_colors memory.\n"); + goto GRADIENT_FAIL; + } + + n_stops = malloc(stops_count * sizeof(float)); + if (n_stops == NULL) { + ErrorF("Failed to allocate n_stops memory.\n"); + goto GRADIENT_FAIL; + } + } + else { + stop_colors = stop_colors_st; + n_stops = n_stops_st; + } + + count = + _glamor_gradient_set_stops(src_picture, + &src_picture->pSourcePict->gradient, + stop_colors, n_stops); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { + int j = 0; + + dispatch->glUniform4f(stop_color0_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color1_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color2_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color3_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color4_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color5_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color6_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + j++; + dispatch->glUniform4f(stop_color7_uniform_location, + stop_colors[4 * j + 0], stop_colors[4 * j + 1], + stop_colors[4 * j + 2], stop_colors[4 * j + 3]); + + j = 0; + dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); + + dispatch->glUniform1i(n_stop_uniform_location, count); + } + else { + dispatch->glUniform4fv(stop_colors_uniform_location, count, + stop_colors); + dispatch->glUniform1fv(stops_uniform_location, count, n_stops); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + + if (src_picture->pSourcePict->linear.p2.y == src_picture->pSourcePict->linear.p1.y) { // The horizontal case. + dispatch->glUniform1i(hor_ver_uniform_location, 1); + DEBUGF("p1.y: %f, p2.y: %f, enter the horizontal case\n", + pt1[1], pt2[1]); + + p1_distance = pt1[0]; + pt_distance = (pt2[0] - p1_distance); + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } + else { + /* The slope need to compute here. In shader, the viewport set will change + the orginal slope and the slope which is vertical to it will not be correct. */ + slope = -(float) (src_picture->pSourcePict->linear.p2.x + - src_picture->pSourcePict->linear.p1.x) / + (float) (src_picture->pSourcePict->linear.p2.y + - src_picture->pSourcePict->linear.p1.y); + slope = slope * yscale / xscale; + dispatch->glUniform1f(pt_slope_uniform_location, slope); + dispatch->glUniform1i(hor_ver_uniform_location, 0); + + cos_val = sqrt(1.0 / (slope * slope + 1.0)); + dispatch->glUniform1f(cos_val_uniform_location, cos_val); + + p1_distance = (pt1[1] - pt1[0] * slope) * cos_val; + pt_distance = (pt2[1] - pt2[0] * slope) * cos_val - p1_distance; + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } + + /* Now rendering. */ + dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* Do the clear logic. */ + if (stops_count > LINEAR_SMALL_STOPS) { + free(n_stops); + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); + return dst_picture; + + GRADIENT_FAIL: + if (dst_picture) { + FreePicture(dst_picture, 0); + } + + if (stops_count > LINEAR_SMALL_STOPS) { + if (n_stops) + free(n_stops); + if (stop_colors) + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); + return NULL; } -#endif /* End of GLAMOR_GRADIENT_SHADER */ +#endif /* End of GLAMOR_GRADIENT_SHADER */ -#endif /* End of RENDER */ +#endif /* End of RENDER */ |