summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunyan He <junyan.he@linux.intel.com>2012-04-25 14:25:39 +0800
committerZhigang Gong <zhigang.gong@linux.intel.com>2012-04-27 15:53:37 +0800
commita6d2e02afa15b014622fb169d66b66d66daf3d4a (patch)
tree22f9801f89c48a9880254854dc2f962ab5bc2d3c
parent8e9595f99075bf476390ba726da23c63c91ac4f5 (diff)
Fix the problem of memory leak in gradient pixmap generating.
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: Zhigang Gong <zhigang.gong@linux.intel.com>
-rw-r--r--src/glamor_gl_dispatch.c1
-rw-r--r--src/glamor_gl_dispatch.h1
-rw-r--r--src/glamor_priv.h28
-rw-r--r--src/glamor_render.c238
4 files changed, 199 insertions, 69 deletions
diff --git a/src/glamor_gl_dispatch.c b/src/glamor_gl_dispatch.c
index fc3c5c0..e6da94d 100644
--- 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 100644
--- 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 68d3617..a7d89a9 100644
--- 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;
@@ -228,8 +235,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;
@@ -729,7 +741,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 0e82e98..21186a8 100644
--- a/src/glamor_render.c
+++ b/src/glamor_render.c
@@ -1412,11 +1412,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;
@@ -1564,12 +1565,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,
@@ -1580,8 +1604,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);
@@ -1594,16 +1618,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;
@@ -1757,7 +1795,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();
@@ -1773,8 +1835,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);
@@ -1787,26 +1849,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
@@ -1814,14 +1906,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);
}
@@ -2053,8 +2175,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;
@@ -2110,15 +2232,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 .*/
@@ -2141,7 +2265,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 =
@@ -2204,7 +2328,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");
@@ -2224,7 +2348,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]);
@@ -2309,7 +2433,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);
}
@@ -2321,9 +2445,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;
@@ -2332,7 +2453,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)
@@ -2345,8 +2466,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;
}
@@ -2381,8 +2500,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;
@@ -2438,16 +2557,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 .*/
@@ -2472,7 +2593,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 =
@@ -2555,7 +2676,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");
@@ -2575,7 +2696,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]);
@@ -2670,7 +2791,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);
}
@@ -2682,9 +2803,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;
@@ -2693,7 +2811,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)
@@ -2706,8 +2824,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;
}