[Glamor] [PATCH] Fix the problem of memory leak in gradient pixmap generating.

junyan.he at linux.intel.com junyan.he at linux.intel.com
Sun Apr 15 18:26:45 PDT 2012


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

 Fix the problem of memory leak in gradient pixmap
 generating. The problem caused by we do not call
 glDeleteShader when destroy a shader program. This patch
 will split the gradient pixmap generating to three
 category. If nstops < 6, we will use the no array version
 of the shader, which has the best performance. Else if
 nstops < 16, we use array version of the shader, which is
 compiled and linked at screen init stage. Else if nstops >
 16, we dynamically create a new shader program, and this
 program will be cached until bigger nstops.


Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 src/glamor_gl_dispatch.c |    1 +
 src/glamor_gl_dispatch.h |    1 +
 src/glamor_priv.h        |   28 ++++--
 src/glamor_render.c      |  238 ++++++++++++++++++++++++++++++++++------------
 4 files changed, 199 insertions(+), 69 deletions(-)

diff --git a/src/glamor_gl_dispatch.c b/src/glamor_gl_dispatch.c
index fc3c5c0..e6da94d
--- a/src/glamor_gl_dispatch.c
+++ b/src/glamor_gl_dispatch.c
@@ -76,6 +76,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch,
 	INIT_FUNC(dispatch, glCreateShader, get_proc_address);
 	INIT_FUNC(dispatch, glCompileShader, get_proc_address);
 	INIT_FUNC(dispatch, glAttachShader, get_proc_address);
+	INIT_FUNC(dispatch, glDeleteShader, get_proc_address);
 	INIT_FUNC(dispatch, glGetShaderiv, get_proc_address);
 	INIT_FUNC(dispatch, glGetShaderInfoLog, get_proc_address);
 	INIT_FUNC(dispatch, glGetProgramiv, get_proc_address);
diff --git a/src/glamor_gl_dispatch.h b/src/glamor_gl_dispatch.h
index 6adbde9..b3fc3a6
--- a/src/glamor_gl_dispatch.h
+++ b/src/glamor_gl_dispatch.h
@@ -108,6 +108,7 @@ typedef struct glamor_gl_dispatch {
 	GLuint (*glCreateShader) (GLenum type);
 	void (*glCompileShader) (GLuint shader);
 	void (*glAttachShader) (GLuint program, GLuint shader);
+	void (*glDeleteShader) (GLuint shader);
 	void (*glGetShaderiv) (GLuint shader, GLenum pname,
 			       GLint * params);
 	void (*glGetShaderInfoLog) (GLuint shader, GLsizei bufSize,
diff --git a/src/glamor_priv.h b/src/glamor_priv.h
index 961af47..dce9dd1
--- a/src/glamor_priv.h
+++ b/src/glamor_priv.h
@@ -123,11 +123,18 @@ enum shader_in {
 	SHADER_IN_COUNT,
 };
 
-enum gradient_shader_type {
-	GRADIENT_SHADER_LINEAR,
-	GRADIENT_SHADER_RADIAL,
-	GRADIENT_SHADER_CONICAL,
-	GRADIENT_SHADER_COUNT,
+enum gradient_shader {
+	SHADER_GRADIENT_LINEAR,
+	SHADER_GRADIENT_RADIAL,
+	SHADER_GRADIENT_CONICAL,
+	SHADER_GRADIENT_COUNT,
+};
+
+enum gradient_shader_prog {
+	SHADER_GRADIENT_VS_PROG,
+	SHADER_GRADIENT_FS_MAIN_PROG,
+	SHADER_GRADIENT_FS_GETCOLOR_PROG,
+	SHADER_GRADIENT_PROG_COUNT,
 };
 
 struct glamor_screen_private;
@@ -233,8 +240,13 @@ typedef struct glamor_screen_private {
 	GLint tile_prog;
 	GLint tile_wh;
 
-	/* glamor gradient */
-	GLint gradient_prog[GRADIENT_SHADER_COUNT];
+	/* glamor gradient, 0 for small nstops, 1 for
+	   large nstops and 2 for dynamic generate. */
+	GLint gradient_prog[SHADER_GRADIENT_COUNT][3];
+	GLint linear_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3];
+	int linear_max_nstops;
+	GLint radial_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3];
+	int radial_max_nstops;
 
 	/* glamor_putimage */
 	GLint put_image_xybitmap_prog;
@@ -747,7 +759,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
 
 #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD
 //#define GLAMOR_DELAYED_FILLING
-//#define GLAMOR_GRADIENT_SHADER
+#define GLAMOR_GRADIENT_SHADER
 
 
 
diff --git a/src/glamor_render.c b/src/glamor_render.c
index 9410adf..0421d42
--- a/src/glamor_render.c
+++ b/src/glamor_render.c
@@ -1425,11 +1425,12 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar
 	return fs_getcolor_prog;
 }
 
-static GLint
-_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int use_array)
+static void
+_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;
@@ -1577,12 +1578,35 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int us
 	    "}\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;
+	}
+
+	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;
+	}
+
 	dispatch = glamor_get_dispatch(glamor_priv);
 
 	gradient_prog = dispatch->glCreateProgram();
 
 	vs_prog = glamor_compile_glsl_prog(dispatch,
-	          GL_VERTEX_SHADER, gradient_vs);
+	                                   GL_VERTEX_SHADER, gradient_vs);
 
 	XNFasprintf(&gradient_fs,
 	            gradient_fs_template,
@@ -1593,8 +1617,8 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int us
 
 	free(gradient_fs);
 
-	fs_getcolor_prog = _glamor_create_getcolor_fs_program(screen,
-	                                                      stops_count, use_array);
+	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);
@@ -1607,16 +1631,30 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int us
 
 	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);
-	return gradient_prog;
 }
 
-static GLint
-_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int use_array)
+static void
+_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;
@@ -1770,7 +1808,31 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us
 	    "    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;
+	}
+
+	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;
+	}
+
 	dispatch = glamor_get_dispatch(glamor_priv);
 
 	gradient_prog = dispatch->glCreateProgram();
@@ -1786,8 +1848,8 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us
 	                                        GL_FRAGMENT_SHADER, gradient_fs);
 	free(gradient_fs);
 
-	fs_getcolor_prog = _glamor_create_getcolor_fs_program(screen,
-	                                                      stops_count, use_array);
+	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);
@@ -1800,26 +1862,56 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us
 
 	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);
-	return gradient_prog;
 }
 
-#define LINEAR_DEFAULT_STOPS 6 + 2
-#define RADIAL_DEFAULT_STOPS 6 + 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
 
 void
 glamor_init_gradient_shader(ScreenPtr screen)
 {
 	glamor_screen_private *glamor_priv;
+	int i;
 
 	glamor_priv = glamor_get_screen_private(screen);
 
-	glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR] =
-	    _glamor_create_linear_gradient_program(screen,
-	            LINEAR_DEFAULT_STOPS, 0);
-	glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL] =
-	    _glamor_create_radial_gradient_program(screen,
-	            RADIAL_DEFAULT_STOPS, 0);
+	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
@@ -1827,14 +1919,44 @@ 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);
 
-	dispatch->glDeleteProgram(
-	    glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR]);
-	dispatch->glDeleteProgram(
-	    glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL]);
+	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);
 }
@@ -2066,8 +2188,8 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 	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_DEFAULT_STOPS*4];
-	GLfloat n_stops_st[RADIAL_DEFAULT_STOPS];
+	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;
@@ -2123,15 +2245,17 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 
 	ValidatePicture(dst_picture);
 
-	stops_count = src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS ?
-	              src_picture->pSourcePict->radial.nstops + 2 : RADIAL_DEFAULT_STOPS;
+	stops_count = src_picture->pSourcePict->radial.nstops + 2;
 
-	/* Because the max value of nstops is unkown, so create a programwhen nstops > default.*/
-	if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_DEFAULT_STOPS) {
-		gradient_prog = glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL];
+	/* 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 {
-		gradient_prog = _glamor_create_radial_gradient_program(screen,
-		                          src_picture->pSourcePict->radial.nstops + 2, 1);
+		_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 .*/
@@ -2154,7 +2278,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 	r2_uniform_location =
 	    dispatch->glGetUniformLocation(gradient_prog, "r2");
 
-	if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_DEFAULT_STOPS) {
+	if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) {
 		stop0_uniform_location =
 		    dispatch->glGetUniformLocation(gradient_prog, "stop0");
 		stop1_uniform_location =
@@ -2217,7 +2341,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 		goto GRADIENT_FAIL;
 
 	/* Set all the stops and colors to shader. */
-	if (stops_count > RADIAL_DEFAULT_STOPS) {
+	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");
@@ -2237,7 +2361,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 	count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient,
 	                                   stop_colors, n_stops);
 
-	if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_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]);
@@ -2322,7 +2446,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 
 
 	/* Do the clear logic.*/
-	if (stops_count > RADIAL_DEFAULT_STOPS) {
+	if (stops_count > RADIAL_SMALL_STOPS) {
 		free(n_stops);
 		free(stop_colors);
 	}
@@ -2334,9 +2458,6 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen,
 	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 	dispatch->glUseProgram(0);
 
-	if (src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS)
-		dispatch->glDeleteProgram(gradient_prog);
-
 	glamor_put_dispatch(glamor_priv);
 	return dst_picture;
 
@@ -2345,7 +2466,7 @@ GRADIENT_FAIL:
 		FreePicture(dst_picture, 0);
 	}
 
-	if (stops_count > RADIAL_DEFAULT_STOPS) {
+	if (stops_count > RADIAL_SMALL_STOPS) {
 		if (n_stops)
 			free(n_stops);
 		if (stop_colors)
@@ -2358,8 +2479,6 @@ GRADIENT_FAIL:
 	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 	dispatch->glUseProgram(0);
-	if (src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS)
-		dispatch->glDeleteProgram(gradient_prog);
 	glamor_put_dispatch(glamor_priv);
 	return NULL;
 }
@@ -2394,8 +2513,8 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 	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_DEFAULT_STOPS*4];
-	GLfloat n_stops_st[LINEAR_DEFAULT_STOPS];
+	GLfloat stop_colors_st[LINEAR_SMALL_STOPS*4];
+	GLfloat n_stops_st[LINEAR_SMALL_STOPS];
 
 	GLint transform_mat_uniform_location;
 	GLint pt1_uniform_location;
@@ -2451,16 +2570,18 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 
 	ValidatePicture(dst_picture);
 
-	stops_count = src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS ?
-	              src_picture->pSourcePict->linear.nstops + 2 : LINEAR_DEFAULT_STOPS;
+	stops_count = src_picture->pSourcePict->linear.nstops + 2;
 
 	/* Because the max value of nstops is unkown, so create a program
-	   when nstops > default.*/
-	if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) {
-		gradient_prog = glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR];
+	   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 {
-		gradient_prog = _glamor_create_linear_gradient_program(screen,
-		                        src_picture->pSourcePict->linear.nstops + 2, 1);
+		_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 .*/
@@ -2485,7 +2606,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 	pt_distance_uniform_location =
 	    dispatch->glGetUniformLocation(gradient_prog, "pt_distance");
 
-	if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) {
+	if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) {
 		stop0_uniform_location =
 		    dispatch->glGetUniformLocation(gradient_prog, "stop0");
 		stop1_uniform_location =
@@ -2568,7 +2689,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 	DEBUGF("pt2:(%f %f)\n", pt2[0], pt2[1]);
 
 	/* Set all the stops and colors to shader. */
-	if (stops_count > LINEAR_DEFAULT_STOPS) {
+	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");
@@ -2588,7 +2709,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 	count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient,
 	                                   stop_colors, n_stops);
 
-	if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_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]);
@@ -2683,7 +2804,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 	}
 
 	/* Do the clear logic.*/
-	if (stops_count > LINEAR_DEFAULT_STOPS) {
+	if (stops_count > LINEAR_SMALL_STOPS) {
 		free(n_stops);
 		free(stop_colors);
 	}
@@ -2695,9 +2816,6 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen,
 	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 	dispatch->glUseProgram(0);
 
-	if (src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS)
-		dispatch->glDeleteProgram(gradient_prog);
-
 	glamor_put_dispatch(glamor_priv);
 	return dst_picture;
 
@@ -2706,7 +2824,7 @@ GRADIENT_FAIL:
 		FreePicture(dst_picture, 0);
 	}
 
-	if (stops_count > LINEAR_DEFAULT_STOPS) {
+	if (stops_count > LINEAR_SMALL_STOPS) {
 		if (n_stops)
 			free(n_stops);
 		if (stop_colors)
@@ -2719,8 +2837,6 @@ GRADIENT_FAIL:
 	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 	dispatch->glUseProgram(0);
-	if (src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS)
-		dispatch->glDeleteProgram(gradient_prog);
 	glamor_put_dispatch(glamor_priv);
 	return NULL;
 }
-- 
1.7.7.6



More information about the Glamor mailing list