[Glamor] [PATCH 1/2] Fix the bugs of linear gradient. Including nstops problem, p1 p2 location problem and memory corruption problem.

junyan.he at linux.intel.com junyan.he at linux.intel.com
Thu May 3 15:06:27 PDT 2012


From: Junyan He <junyan.he at linux.intel.com>

 1.Some gradient set the stops at the same position, like
 firstly 0.5 to red color and then set 0.5 to blue. This
 kind of setting will cause the shader work not
 correctly because the percentage caculating need to use
 the stop[i] - stop[i-1] as dividend. The previous patch
 we just kill some stop if the distance between them is
 0. But this cause the problem that the color for next
 stop is wrong. We now modify to handle it in the shader
 to avoid the 0 as dividend. 
 2.The P1 and P2 point may have the case that p1.y > p2.y,
 which will enter a wrong mode of vertical. Fix this bug.
 3.The macro like "#define LINEAR_SMALL_STOPS 6 + 2" causes
 the problem. When use it to define like "GLfloat
 stop_colors_st[LINEAR_SMALL_STOPS*4];" The array is
 small than what we supposed it to be. Cause memory
 corruption problem and cause the bug of render wrong
 result. Fix it.


Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 src/glamor_render.c |   41 ++++++++++++++++-------------------------
 1 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/src/glamor_render.c b/src/glamor_render.c
index b729e98..1e2f75e
--- a/src/glamor_render.c
+++ b/src/glamor_render.c
@@ -1365,9 +1365,12 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar
 	    "            break; \n"
 	    "    }\n"
 	    "    \n"
-	    "    percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n"
 	    "    if(stops[i] - stops[i-1] > 2.0)\n"
 	    "        percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow.
+	    "    else if(stops[i] - stops[i-1] < 0.000001)\n"
+	    "        percentage = 0.0;\n"
+	    "    else \n"
+	    "        percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n"
 	    "    new_alpha = percentage * stop_colors[i].a + \n"
 	    "                       (1.0-percentage) * stop_colors[i-1].a; \n"
 	    "    gradient_color = vec4((percentage * stop_colors[i].rgb \n"
@@ -1414,58 +1417,53 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar
 	    "        stop_color_after = stop_color0;\n"
 	    "        stop_after = stop0;\n"
 	    "        stop_before = stop0;\n"
-	    "        percentage = 0.0;\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"
-	    "        percentage = (stop_len - stop0)/(stop1 - 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"
-	    "        percentage = (stop_len - stop1)/(stop2 - 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"
-	    "        percentage = (stop_len - stop2)/(stop3 - 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"
-	    "        percentage = (stop_len - stop3)/(stop4 - 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"
-	    "        percentage = (stop_len - stop4)/(stop5 - 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"
-	    "        percentage = (stop_len - stop5)/(stop6 - 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"
-	    "        percentage = (stop_len - stop6)/(stop7 - stop6);\n"
 	    "    } else {\n"
 	    "        stop_color_before = stop_color7;\n"
 	    "        stop_color_after = stop_color7;\n"
 	    "        stop_after = stop7;\n"
 	    "        stop_before = stop7;\n"
-	    "        percentage = 0.0;\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"
@@ -1945,11 +1943,11 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy
 	glamor_put_dispatch(glamor_priv);
 }
 
-#define LINEAR_SMALL_STOPS 6 + 2
-#define LINEAR_LARGE_STOPS 16 + 2
+#define LINEAR_SMALL_STOPS (6 + 2)
+#define LINEAR_LARGE_STOPS (16 + 2)
 
-#define RADIAL_SMALL_STOPS 6 + 2
-#define RADIAL_LARGE_STOPS 16 + 2
+#define RADIAL_SMALL_STOPS (6 + 2)
+#define RADIAL_LARGE_STOPS (16 + 2)
 
 void
 glamor_init_gradient_shader(ScreenPtr screen)
@@ -2159,13 +2157,6 @@ _glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient,
 	int count = 1;
 
 	for (i = 0; i < pgradient->nstops; i++) {
-		/* We find some gradient picture set the stops at the same percentage, which
-		   will cause the shader problem because the (stops[i] - stops[i-1]) will
-		   be used as divisor. We just keep the later one if stops[i] == stops[i-1] */
-		if (i < pgradient->nstops - 1
-		         && pgradient->stops[i].x == pgradient->stops[i+1].x)
-			continue;
-
 		stop_colors[count*4] = pixman_fixed_to_double(
 		                                pgradient->stops[i].color.red);
 		stop_colors[count*4+1] = pixman_fixed_to_double(
@@ -2825,7 +2816,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 		dispatch->glUniform1i(n_stop_uniform_location, count);
 	}
 
-	if ((pt2[1] - pt1[1]) / yscale < 1.0) { // The horizontal case.
+	if (abs((pt2[1] - pt1[1]) / yscale) < 1.0) { // The horizontal case.
 		dispatch->glUniform1i(hor_ver_uniform_location, 1);
 		DEBUGF("p1.x: %f, p2.x: %f, enter the horizontal case\n", pt1[1], pt2[1]);
 
@@ -2833,7 +2824,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 		pt_distance = (pt2[0] - p1_distance);
 		dispatch->glUniform1f(p1_distance_uniform_location, p1_distance);
 		dispatch->glUniform1f(pt_distance_uniform_location, pt_distance);
-	} else if ((pt2[0] - pt1[0]) / xscale < 1.0) { //The vertical case.
+	} else if (abs((pt2[0] - pt1[0]) / xscale) < 1.0) { //The vertical case.
 		dispatch->glUniform1i(hor_ver_uniform_location, 2);
 		DEBUGF("p1.y: %f, p2.y: %f, enter the vertical case\n", pt1[0], pt2[0]);
 
@@ -2913,8 +2904,8 @@ GRADIENT_FAIL:
 	glamor_put_dispatch(glamor_priv);
 	return NULL;
 }
-#undef LINEAR_DEFAULT_STOPS
-#endif
+
+#endif /* End of GLAMOR_GRADIENT_SHADER */
 
 static PicturePtr
 glamor_convert_gradient_picture(ScreenPtr screen,
-- 
1.7.7.6



More information about the Glamor mailing list