Mesa (master): postprocess: handle partial intialization failures.

Brian Paul brianp at kemper.freedesktop.org
Thu Jun 27 15:46:14 UTC 2013


Module: Mesa
Branch: master
Commit: e87fc11cac696881469a57955af2ac7b4929a2c7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e87fc11cac696881469a57955af2ac7b4929a2c7

Author: Matthew McClure <mcclurem at vmware.com>
Date:   Fri Jun 21 13:45:55 2013 -0700

postprocess: handle partial intialization failures.

This patch fixes segfaults observed when enabling the post processing
features. When the format is not supported, or a texture cannot be
created, the code must gracefully handle failure and report the error to
the calling code for proper failure handling.

To accomplish this the following changes were made to the filters.h
prototypes:

- bool return for pp_init_func
- Added pp_free_func for filter specific resource destruction

Fixes segfaults from backtraces:

* util_destroy_blit
  pp_free

* u_transfer_inline_write_vtbl
  pp_jimenezmlaa_init_run
  pp_init

This patch also uses tgsi_alloc_tokens to allocate temporary tokens in
pp_tgsi_to_state, instead of allocating the array on the stack. This
fixes the following stack corruption segfault in pp_run.c:

* _int_free
  aaline_delete_fs_state
  pp_free

Bug Number: 1021843
Reviewed-by: Brian Paul <brianp at vmware.com>

---

 src/gallium/auxiliary/postprocess/filters.h     |   18 ++--
 src/gallium/auxiliary/postprocess/postprocess.h |   22 +++-
 src/gallium/auxiliary/postprocess/pp_celshade.c |   10 ++-
 src/gallium/auxiliary/postprocess/pp_colors.c   |   21 +++-
 src/gallium/auxiliary/postprocess/pp_init.c     |  145 +++++++++++++++++------
 src/gallium/auxiliary/postprocess/pp_mlaa.c     |  121 ++++++++++++++------
 src/gallium/auxiliary/postprocess/pp_run.c      |   39 ++++++-
 7 files changed, 281 insertions(+), 95 deletions(-)

diff --git a/src/gallium/auxiliary/postprocess/filters.h b/src/gallium/auxiliary/postprocess/filters.h
index 9ea7462..1aa1e3a 100644
--- a/src/gallium/auxiliary/postprocess/filters.h
+++ b/src/gallium/auxiliary/postprocess/filters.h
@@ -30,8 +30,9 @@
 
 #include "postprocess/postprocess.h"
 
-typedef void (*pp_init_func) (struct pp_queue_t *, unsigned int,
+typedef bool (*pp_init_func) (struct pp_queue_t *, unsigned int,
                               unsigned int);
+typedef void (*pp_free_func) (struct pp_queue_t *, unsigned int);
 
 struct pp_filter_t
 {
@@ -41,18 +42,19 @@ struct pp_filter_t
    unsigned int verts;          /* How many are vertex shaders */
    pp_init_func init;           /* Init function */
    pp_func main;                /* Run function */
+   pp_free_func free;           /* Free function */
 };
 
 /*	Order matters. Put new filters in a suitable place. */
 
 static const struct pp_filter_t pp_filters[PP_FILTERS] = {
-/*    name			inner	shaders	verts	init			run */
-   { "pp_noblue",		0,	2,	1,	pp_noblue_init,		pp_nocolor },
-   { "pp_nogreen",		0,	2,	1,	pp_nogreen_init,	pp_nocolor },
-   { "pp_nored",		0,	2,	1,	pp_nored_init,		pp_nocolor },
-   { "pp_celshade",		0,	2,	1,	pp_celshade_init,	pp_nocolor },
-   { "pp_jimenezmlaa",		2,	5,	2,	pp_jimenezmlaa_init,	pp_jimenezmlaa },
-   { "pp_jimenezmlaa_color",	2,	5,	2,	pp_jimenezmlaa_init_color, pp_jimenezmlaa_color },
+/*    name			inner	shaders	verts	init			run                       free   */
+   { "pp_noblue",		0,	2,	1,	pp_noblue_init,		pp_nocolor,               pp_nocolor_free },
+   { "pp_nogreen",		0,	2,	1,	pp_nogreen_init,	pp_nocolor,               pp_nocolor_free },
+   { "pp_nored",		0,	2,	1,	pp_nored_init,		pp_nocolor,               pp_nocolor_free },
+   { "pp_celshade",		0,	2,	1,	pp_celshade_init,	pp_nocolor,               pp_celshade_free },
+   { "pp_jimenezmlaa",		2,	5,	2,	pp_jimenezmlaa_init,	pp_jimenezmlaa,           pp_jimenezmlaa_free },
+   { "pp_jimenezmlaa_color",	2,	5,	2,	pp_jimenezmlaa_init_color, pp_jimenezmlaa_color,  pp_jimenezmlaa_free },
 };
 
 #endif
diff --git a/src/gallium/auxiliary/postprocess/postprocess.h b/src/gallium/auxiliary/postprocess/postprocess.h
index 9ae1896..52c6c75 100644
--- a/src/gallium/auxiliary/postprocess/postprocess.h
+++ b/src/gallium/auxiliary/postprocess/postprocess.h
@@ -53,11 +53,13 @@ struct pp_queue_t
 
    struct pipe_resource *depth; /* depth of original input */
    struct pipe_resource *stencil;       /* stencil shared by inner_tmps */
+   struct pipe_resource *constbuf;      /* MLAA constant buffer */
+   struct pipe_resource *areamaptex;    /* MLAA area map texture */
 
    struct pipe_surface *tmps[2], *inner_tmps[3], *stencils;
 
    void ***shaders;             /* Shaders in TGSI form */
-   unsigned int *verts;
+   unsigned int *filters;       /* Active filter to filters.h mapping. */
    struct program *p;
 
    bool fbos_init;
@@ -88,14 +90,20 @@ void pp_jimenezmlaa_color(struct pp_queue_t *, struct pipe_resource *,
 
 /* The filter init functions */
 
-void pp_celshade_init(struct pp_queue_t *, unsigned int, unsigned int);
+bool pp_celshade_init(struct pp_queue_t *, unsigned int, unsigned int);
 
-void pp_nored_init(struct pp_queue_t *, unsigned int, unsigned int);
-void pp_nogreen_init(struct pp_queue_t *, unsigned int, unsigned int);
-void pp_noblue_init(struct pp_queue_t *, unsigned int, unsigned int);
+bool pp_nored_init(struct pp_queue_t *, unsigned int, unsigned int);
+bool pp_nogreen_init(struct pp_queue_t *, unsigned int, unsigned int);
+bool pp_noblue_init(struct pp_queue_t *, unsigned int, unsigned int);
 
-void pp_jimenezmlaa_init(struct pp_queue_t *, unsigned int, unsigned int);
-void pp_jimenezmlaa_init_color(struct pp_queue_t *, unsigned int,
+bool pp_jimenezmlaa_init(struct pp_queue_t *, unsigned int, unsigned int);
+bool pp_jimenezmlaa_init_color(struct pp_queue_t *, unsigned int,
                                unsigned int);
 
+/* The filter free functions */
+
+void pp_celshade_free(struct pp_queue_t *, unsigned int);
+void pp_nocolor_free(struct pp_queue_t *, unsigned int);
+void pp_jimenezmlaa_free(struct pp_queue_t *, unsigned int);
+
 #endif
diff --git a/src/gallium/auxiliary/postprocess/pp_celshade.c b/src/gallium/auxiliary/postprocess/pp_celshade.c
index 447b401..471ec38 100644
--- a/src/gallium/auxiliary/postprocess/pp_celshade.c
+++ b/src/gallium/auxiliary/postprocess/pp_celshade.c
@@ -30,9 +30,17 @@
 #include "postprocess/pp_filters.h"
 
 /** Init function */
-void
+bool
 pp_celshade_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
 {
    ppq->shaders[n][1] =
       pp_tgsi_to_state(ppq->p->pipe, celshade, false, "celshade");
+
+   return (ppq->shaders[n][1] != NULL) ? TRUE : FALSE;
+}
+
+/** Free function */
+void
+pp_celshade_free(struct pp_queue_t *ppq, unsigned int n)
+{
 }
diff --git a/src/gallium/auxiliary/postprocess/pp_colors.c b/src/gallium/auxiliary/postprocess/pp_colors.c
index 82576a7..c30e92e 100644
--- a/src/gallium/auxiliary/postprocess/pp_colors.c
+++ b/src/gallium/auxiliary/postprocess/pp_colors.c
@@ -57,24 +57,37 @@ pp_nocolor(struct pp_queue_t *ppq, struct pipe_resource *in,
 
 /* Init functions */
 
-void
+bool
 pp_nored_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
 {
-   ppq->shaders[n][1] = pp_tgsi_to_state(ppq->p->pipe, nored, false, "nored");
+   ppq->shaders[n][1] =
+      pp_tgsi_to_state(ppq->p->pipe, nored, false, "nored");
+
+   return (ppq->shaders[n][1] != NULL) ? TRUE : FALSE;
 }
 
 
-void
+bool
 pp_nogreen_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
 {
    ppq->shaders[n][1] =
       pp_tgsi_to_state(ppq->p->pipe, nogreen, false, "nogreen");
+
+   return (ppq->shaders[n][1] != NULL) ? TRUE : FALSE;
 }
 
 
-void
+bool
 pp_noblue_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
 {
    ppq->shaders[n][1] =
       pp_tgsi_to_state(ppq->p->pipe, noblue, false, "noblue");
+
+   return (ppq->shaders[n][1] != NULL) ? TRUE : FALSE;
+}
+
+/* Free functions */
+void
+pp_nocolor_free(struct pp_queue_t *ppq, unsigned int n)
+{
 }
diff --git a/src/gallium/auxiliary/postprocess/pp_init.c b/src/gallium/auxiliary/postprocess/pp_init.c
index 137c82b..1130248 100644
--- a/src/gallium/auxiliary/postprocess/pp_init.c
+++ b/src/gallium/auxiliary/postprocess/pp_init.c
@@ -42,57 +42,81 @@ struct pp_queue_t *
 pp_init(struct pipe_context *pipe, const unsigned int *enabled,
         struct cso_context *cso)
 {
-
+   unsigned int num_filters = 0;
    unsigned int curpos = 0, i, tmp_req = 0;
    struct pp_queue_t *ppq;
-   pp_func *tmp_q;
 
    pp_debug("Initializing the post-processing queue.\n");
 
    /* How many filters were requested? */
    for (i = 0; i < PP_FILTERS; i++) {
       if (enabled[i])
-         curpos++;
+         num_filters++;
    }
-   if (!curpos)
+   if (num_filters == 0)
       return NULL;
 
    ppq = CALLOC(1, sizeof(struct pp_queue_t));
-   tmp_q = CALLOC(curpos, sizeof(pp_func));
-   ppq->shaders = CALLOC(curpos, sizeof(void *));
-   ppq->verts = CALLOC(curpos, sizeof(unsigned int));
 
-   if (!tmp_q || !ppq || !ppq->shaders || !ppq->verts)
+   if (ppq == NULL) {
+      pp_debug("Unable to allocate memory for ppq.\n");
       goto error;
+   }
+
+   ppq->pp_queue = CALLOC(num_filters, sizeof(pp_func));
+   if (ppq->pp_queue == NULL) {
+      pp_debug("Unable to allocate memory for pp_queue.\n");
+      goto error;
+   }
+
+   ppq->shaders = CALLOC(num_filters, sizeof(void *));
+   ppq->filters = CALLOC(num_filters, sizeof(unsigned int));
+
+   if ((ppq->shaders == NULL) ||
+       (ppq->filters == NULL)) {
+      pp_debug("Unable to allocate memory for shaders and filter arrays.\n");
+      goto error;
+   }
 
    ppq->p = pp_init_prog(ppq, pipe, cso);
-   if (!ppq->p)
+   if (ppq->p == NULL) {
+      pp_debug("pp_init_prog returned NULL.\n");
       goto error;
+   }
 
    /* Add the enabled filters to the queue, in order */
    curpos = 0;
-   ppq->pp_queue = tmp_q;
    for (i = 0; i < PP_FILTERS; i++) {
       if (enabled[i]) {
          ppq->pp_queue[curpos] = pp_filters[i].main;
          tmp_req = MAX2(tmp_req, pp_filters[i].inner_tmps);
+         ppq->filters[curpos] = i;
 
          if (pp_filters[i].shaders) {
             ppq->shaders[curpos] =
                CALLOC(pp_filters[i].shaders + 1, sizeof(void *));
-            ppq->verts[curpos] = pp_filters[i].verts;
-            if (!ppq->shaders[curpos])
+            if (!ppq->shaders[curpos]) {
+               pp_debug("Unable to allocate memory for shader list.\n");
                goto error;
+            }
          }
-         pp_filters[i].init(ppq, curpos, enabled[i]);
+
+         /* Call the initialization function for the filter. */
+         if (!pp_filters[i].init(ppq, curpos, enabled[i])) {
+            pp_debug("Initialization for filter %u failed.\n", i);
+            goto error;
+         }           
 
          curpos++;
       }
    }
 
    ppq->p->blitctx = util_create_blit(ppq->p->pipe, cso);
-   if (!ppq->p->blitctx)
+
+   if (ppq->p->blitctx == NULL) {
+      pp_debug("Unable to create a blit context.\n");
       goto error;
+   }
 
    ppq->n_filters = curpos;
    ppq->n_tmp = (curpos > 2 ? 2 : 1);
@@ -104,16 +128,18 @@ pp_init(struct pipe_context *pipe, const unsigned int *enabled,
       ppq->shaders[i][0] = ppq->p->passvs;
 
    pp_debug("Queue successfully allocated. %u filter(s).\n", curpos);
-
+   
    return ppq;
 
  error:
-   pp_debug("Error setting up pp\n");
 
-   if (ppq)
-      FREE(ppq->p);
-   FREE(ppq);
-   FREE(tmp_q);
+   if (ppq) {
+      /* Assign curpos, since we only need to destroy initialized filters. */
+      ppq->n_filters = curpos;
+
+      /* Call the common free function which must handle partial initialization. */
+      pp_free(ppq);
+   }
 
    return NULL;
 }
@@ -142,33 +168,81 @@ pp_free_fbos(struct pp_queue_t *ppq)
    ppq->fbos_init = false;
 }
 
-/** Free the pp queue. Called on context termination. */
+/** 
+ * Free the pp queue. Called on context termination and failure in
+ * pp_init.
+ */
 void
 pp_free(struct pp_queue_t *ppq)
 {
-
    unsigned int i, j;
 
    pp_free_fbos(ppq);
 
-   util_destroy_blit(ppq->p->blitctx);
+   if (ppq && ppq->p) {
+      /* Only destroy created contexts. */
+      if (ppq->p->blitctx) {
+         util_destroy_blit(ppq->p->blitctx);
+      }
 
-   for (i = 0; i < ppq->n_filters; i++) {
-      for (j = 0; j < PP_MAX_PASSES && ppq->shaders[i][j]; j++) {
-         if (j >= ppq->verts[i]) {
-            ppq->p->pipe->delete_fs_state(ppq->p->pipe, ppq->shaders[i][j]);
-            ppq->shaders[i][j] = NULL;
-         }
-         else if (ppq->shaders[i][j] != ppq->p->passvs) {
-            ppq->p->pipe->delete_vs_state(ppq->p->pipe, ppq->shaders[i][j]);
-            ppq->shaders[i][j] = NULL;
+      if (ppq->p->pipe && ppq->filters && ppq->shaders) {
+         for (i = 0; i < ppq->n_filters; i++) {
+            unsigned int filter = ppq->filters[i];
+
+            if (ppq->shaders[i] == NULL) {
+               continue;
+            }
+
+            /*
+             * Common shader destruction code for all postprocessing
+             * filters.
+             */
+            for (j = 0; j < pp_filters[filter].shaders; j++) {
+               if (ppq->shaders[i][j] == NULL) {
+                  /* We reached the end of initialized shaders. */
+                  break;
+               }
+
+               if (ppq->shaders[i][j] == ppq->p->passvs) {
+                  continue;
+               }
+
+               assert(ppq);
+               assert(ppq->p);
+               assert(ppq->p->pipe);
+ 
+               if (j >= pp_filters[filter].verts) {
+                  assert(ppq->p->pipe->delete_fs_state);
+                  ppq->p->pipe->delete_fs_state(ppq->p->pipe,
+                                                ppq->shaders[i][j]);
+                  ppq->shaders[i][j] = NULL;
+               } else {
+                  assert(ppq->p->pipe->delete_vs_state);
+                  ppq->p->pipe->delete_vs_state(ppq->p->pipe,
+                                                ppq->shaders[i][j]);
+                  ppq->shaders[i][j] = NULL;
+               }
+            }
+
+            /* Finally call each filter type's free functionality. */
+            pp_filters[filter].free(ppq, i);
          }
       }
+
+      FREE(ppq->p);
    }
 
-   FREE(ppq->p);
-   FREE(ppq->pp_queue);
-   FREE(ppq);
+   if (ppq) {
+      /*
+       * Handle partial initialization for common resource destruction
+       * in the create path.
+       */
+      FREE(ppq->filters);
+      FREE(ppq->shaders);
+      FREE(ppq->pp_queue);
+  
+      FREE(ppq);
+   }
 
    pp_debug("Queue taken down.\n");
 }
@@ -256,7 +330,6 @@ pp_init_fbos(struct pp_queue_t *ppq, unsigned int w,
    if (!ppq->stencil || !ppq->stencils)
       goto error;
 
-
    p->framebuffer.width = w;
    p->framebuffer.height = h;
 
diff --git a/src/gallium/auxiliary/postprocess/pp_mlaa.c b/src/gallium/auxiliary/postprocess/pp_mlaa.c
index 6d9fa9a..503749b 100644
--- a/src/gallium/auxiliary/postprocess/pp_mlaa.c
+++ b/src/gallium/auxiliary/postprocess/pp_mlaa.c
@@ -56,16 +56,16 @@
 static float constants[] = { 1, 1, 0, 0 };
 static unsigned int dimensions[2] = { 0, 0 };
 
-static struct pipe_resource *constbuf, *areamaptex;
-
 /** Upload the constants. */
 static void
-up_consts(struct pipe_context *pipe)
+up_consts(struct pp_queue_t *ppq)
 {
+   struct pipe_context *pipe = ppq->p->pipe;
    struct pipe_box box;
 
    u_box_2d(0, 0, sizeof(constants), 1, &box);
-   pipe->transfer_inline_write(pipe, constbuf, 0, PIPE_TRANSFER_WRITE,
+
+   pipe->transfer_inline_write(pipe, ppq->constbuf, 0, PIPE_TRANSFER_WRITE,
                                &box, constants, sizeof(constants),
                                sizeof(constants));
 }
@@ -81,11 +81,24 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
    struct pipe_depth_stencil_alpha_state mstencil;
    struct pipe_sampler_view v_tmp, *arr[3];
 
-   unsigned int w = p->framebuffer.width;
-   unsigned int h = p->framebuffer.height;
+   unsigned int w = 0;
+   unsigned int h = 0;
 
    const struct pipe_stencil_ref ref = { {1} };
+
+   /* Insufficient initialization checks. */
+   assert(p);
+   assert(ppq);
+   assert(ppq->constbuf);
+   assert(ppq->areamaptex);
+   assert(ppq->inner_tmp);
+   assert(ppq->shaders[n]);
+
+   w = p->framebuffer.width;
+   h = p->framebuffer.height;
+
    memset(&mstencil, 0, sizeof(mstencil));
+
    cso_set_stencil_ref(p->cso, &ref);
 
    /* Init the pixel size constant */
@@ -94,13 +107,15 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
       constants[0] = 1.0f / p->framebuffer.width;
       constants[1] = 1.0f / p->framebuffer.height;
 
-      up_consts(p->pipe);
+      up_consts(ppq);
       dimensions[0] = p->framebuffer.width;
       dimensions[1] = p->framebuffer.height;
    }
 
-   cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_VERTEX, 0, constbuf);
-   cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_FRAGMENT, 0, constbuf);
+   cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_VERTEX,
+                                    0, ppq->constbuf);
+   cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_FRAGMENT,
+                                    0, ppq->constbuf);
 
    mstencil.stencil[0].enabled = 1;
    mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0;
@@ -142,7 +157,7 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
    mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP;
    cso_set_depth_stencil_alpha(p->cso, &mstencil);
 
-   pp_filter_setup_in(p, areamaptex);
+   pp_filter_setup_in(p, ppq->areamaptex);
    pp_filter_setup_out(p, ppq->inner_tmp[1]);
 
    u_sampler_view_default_template(&v_tmp, ppq->inner_tmp[0],
@@ -206,32 +221,34 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
 }
 
 /** The init function of the MLAA filter. */
-static void
+static bool
 pp_jimenezmlaa_init_run(struct pp_queue_t *ppq, unsigned int n,
                         unsigned int val, bool iscolor)
 {
 
    struct pipe_box box;
    struct pipe_resource res;
-   char *tmp_text;
-
-   constbuf = pipe_buffer_create(ppq->p->screen, PIPE_BIND_CONSTANT_BUFFER,
-                                 PIPE_USAGE_STATIC, sizeof(constants));
-   if (!constbuf) {
-      pp_debug("Failed to allocate constant buffer\n");
-      return;
-   }
-
-
-   pp_debug("mlaa: using %u max search steps\n", val);
+   char *tmp_text = NULL;
 
    tmp_text = CALLOC(sizeof(blend2fs_1) + sizeof(blend2fs_2) +
                      IMM_SPACE, sizeof(char));
 
-   if (!tmp_text) {
+   if (tmp_text == NULL) {
       pp_debug("Failed to allocate shader space\n");
-      return;
+      return FALSE;
+   }
+
+   ppq->constbuf = pipe_buffer_create(ppq->p->screen,
+                                      PIPE_BIND_CONSTANT_BUFFER,
+                                      PIPE_USAGE_STATIC,
+                                      sizeof(constants));
+   if (ppq->constbuf == NULL) {
+      pp_debug("Failed to allocate constant buffer\n");
+      goto fail;
    }
+
+   pp_debug("mlaa: using %u max search steps\n", val);
+
    util_sprintf(tmp_text, "%s"
                 "IMM FLT32 {    %.8f,     0.0000,     0.0000,     0.0000}\n"
                 "%s\n", blend2fs_1, (float) val, blend2fs_2);
@@ -249,15 +266,19 @@ pp_jimenezmlaa_init_run(struct pp_queue_t *ppq, unsigned int n,
                                             res.target, 1, res.bind))
       pp_debug("Areamap format not supported\n");
 
-   areamaptex = ppq->p->screen->resource_create(ppq->p->screen, &res);
+   ppq->areamaptex = ppq->p->screen->resource_create(ppq->p->screen, &res);
+   
+   if (ppq->areamaptex == NULL) {
+      pp_debug("Failed to allocate area map texture\n");
+      goto fail;
+   }
+   
    u_box_2d(0, 0, 165, 165, &box);
 
-   ppq->p->pipe->transfer_inline_write(ppq->p->pipe, areamaptex, 0,
+   ppq->p->pipe->transfer_inline_write(ppq->p->pipe, ppq->areamaptex, 0,
                                        PIPE_TRANSFER_WRITE, &box,
                                        areamap, 165 * 2, sizeof(areamap));
 
-
-
    ppq->shaders[n][1] = pp_tgsi_to_state(ppq->p->pipe, offsetvs, true,
                                          "offsetvs");
    if (iscolor)
@@ -272,23 +293,35 @@ pp_jimenezmlaa_init_run(struct pp_queue_t *ppq, unsigned int n,
                                          "neigh3fs");
 
    FREE(tmp_text);
+
+   return TRUE;
+
+ fail:
+   
+   FREE(tmp_text);
+
+   /*
+    * Call the common free function for destruction of partially initialized
+    * resources.
+    */
+   pp_jimenezmlaa_free(ppq, n);
+
+   return FALSE;
 }
 
 /** Short wrapper to init the depth version. */
-void
+bool
 pp_jimenezmlaa_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
 {
-
-   pp_jimenezmlaa_init_run(ppq, n, val, false);
+   return pp_jimenezmlaa_init_run(ppq, n, val, false);
 }
 
 /** Short wrapper to init the color version. */
-void
+bool
 pp_jimenezmlaa_init_color(struct pp_queue_t *ppq, unsigned int n,
                           unsigned int val)
 {
-
-   pp_jimenezmlaa_init_run(ppq, n, val, true);
+   return pp_jimenezmlaa_init_run(ppq, n, val, true);
 }
 
 /** Short wrapper to run the depth version. */
@@ -306,3 +339,23 @@ pp_jimenezmlaa_color(struct pp_queue_t *ppq, struct pipe_resource *in,
 {
    pp_jimenezmlaa_run(ppq, in, out, n, true);
 }
+
+
+/**
+ * Short wrapper to free the mlaa filter resources. Shaders are freed in
+ * the common code in pp_free.
+ */
+void
+pp_jimenezmlaa_free(struct pp_queue_t *ppq, unsigned int n)
+{
+   if (ppq->areamaptex) {
+      ppq->p->screen->resource_destroy(ppq->p->screen, ppq->areamaptex);
+      ppq->areamaptex = NULL;
+   }
+
+   if (ppq->constbuf) {
+      ppq->p->screen->resource_destroy(ppq->p->screen, ppq->constbuf);
+      ppq->constbuf = NULL;
+   }
+}
+
diff --git a/src/gallium/auxiliary/postprocess/pp_run.c b/src/gallium/auxiliary/postprocess/pp_run.c
index 54253f4..9bd977b 100644
--- a/src/gallium/auxiliary/postprocess/pp_run.c
+++ b/src/gallium/auxiliary/postprocess/pp_run.c
@@ -32,6 +32,8 @@
 #include "util/u_inlines.h"
 #include "util/u_sampler.h"
 
+#include "tgsi/tgsi_parse.h"
+
 /**
 *	Main run function of the PP queue. Called on swapbuffers/flush.
 *
@@ -46,6 +48,13 @@ pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
    unsigned int i;
    struct cso_context *cso = ppq->p->cso;
 
+   if (ppq->n_filters == 0)
+      return;
+
+   assert(ppq->pp_queue);
+   assert(ppq->tmp[0]);
+   assert(ppq->tmp[1]);
+ 
    if (in->width0 != ppq->p->framebuffer.width ||
        in->height0 != ppq->p->framebuffer.height) {
       pp_debug("Resizing the temp pp buffers\n");
@@ -98,6 +107,9 @@ pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
    pipe_resource_reference(&refout, out);
 
    switch (ppq->n_filters) {
+   case 0:
+      /* Failsafe, but never reached. */
+      break;
    case 1:                     /* No temp buf */
       ppq->pp_queue[0] (ppq, in, out, 0);
       break;
@@ -192,7 +204,19 @@ pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
                  const char *name)
 {
    struct pipe_shader_state state;
-   struct tgsi_token tokens[PP_MAX_TOKENS];
+   struct tgsi_token *tokens = NULL;
+   void *ret_state = NULL;
+ 
+   /*
+    * Allocate temporary token storage. State creation will duplicate
+    * tokens so we must free them on exit.
+    */ 
+   tokens = tgsi_alloc_tokens(PP_MAX_TOKENS);
+
+   if (tokens == NULL) {
+      pp_debug("Failed to allocate temporary token storage.\n");
+      return NULL;
+   }
 
    if (tgsi_text_translate(text, tokens, Elements(tokens)) == FALSE) {
       pp_debug("Failed to translate %s\n", name);
@@ -202,10 +226,15 @@ pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
    state.tokens = tokens;
    memset(&state.stream_output, 0, sizeof(state.stream_output));
 
-   if (isvs)
-      return pipe->create_vs_state(pipe, &state);
-   else
-      return pipe->create_fs_state(pipe, &state);
+   if (isvs) {
+      ret_state = pipe->create_vs_state(pipe, &state);
+      FREE(tokens);
+   } else {
+      ret_state = pipe->create_fs_state(pipe, &state);
+      FREE(tokens);
+   }
+
+   return ret_state;
 }
 
 /** Setup misc state for the filter. */




More information about the mesa-commit mailing list