gallium: accum buffer fixes
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 7 Apr 2008 20:53:49 +0000 (14:53 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 7 Apr 2008 20:53:49 +0000 (14:53 -0600)
If the driver can't create a PIPE_FORMAT_R16G16B16A16_SNORM surface, create
an accum surface using a shallower format and taller height.  Since only the
accum buffer code accesses the surface the actual format doesn't really
matter, just that there's enough memory.

src/mesa/state_tracker/st_cb_accum.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_cb_fbo.h
src/mesa/state_tracker/st_framebuffer.c

index a623d0bcc06088076e33d6cc128779d9d39ded24..35352351d5a5d96d1ba2758c305f716b51df8147 100644 (file)
  */
 
 
+/**
+ * Wrapper for pipe_get_tile_rgba().  Do format/cpp override to make the
+ * tile util function think the surface is 16bit/channel, even if it's not.
+ * See also: st_renderbuffer_alloc_storage()
+ */
+static void
+acc_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
+                  uint x, uint y, uint w, uint h, float *p)
+{
+   const enum pipe_format f = acc_ps->format;
+   const int cpp = acc_ps->cpp;
+
+   acc_ps->format = DEFAULT_ACCUM_PIPE_FORMAT;
+   acc_ps->cpp = 8;
+
+   pipe_get_tile_rgba(pipe, acc_ps, x, y, w, h, p);
+
+   acc_ps->format = f;
+   acc_ps->cpp = cpp;
+}
+
+
+/**
+ * Wrapper for pipe_put_tile_rgba().  Do format/cpp override to make the
+ * tile util function think the surface is 16bit/channel, even if it's not.
+ * See also: st_renderbuffer_alloc_storage()
+ */
+static void
+acc_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
+                  uint x, uint y, uint w, uint h, const float *p)
+{
+   enum pipe_format f = acc_ps->format;
+   const int cpp = acc_ps->cpp;
+
+   acc_ps->format = DEFAULT_ACCUM_PIPE_FORMAT;
+   acc_ps->cpp = 8;
+
+   pipe_put_tile_rgba(pipe, acc_ps, x, y, w, h, p);
+
+   acc_ps->format = f;
+   acc_ps->cpp = cpp;
+}
+
+
+
 void
 st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
 {
@@ -80,7 +125,9 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
       accBuf[i*4+3] = a;
    }
 
-   pipe_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
+   acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
+
+   free(accBuf);
 }
 
 
@@ -95,13 +142,13 @@ accum_mad(struct pipe_context *pipe, GLfloat scale, GLfloat bias,
 
    accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
-   pipe_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
+   acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
 
    for (i = 0; i < 4 * width * height; i++) {
       accBuf[i] = accBuf[i] * scale + bias;
    }
 
-   pipe_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
+   acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
 
    free(accBuf);
 }
@@ -120,13 +167,13 @@ accum_accum(struct pipe_context *pipe, GLfloat value,
    accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
    pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, colorBuf);
-   pipe_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
+   acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
 
    for (i = 0; i < 4 * width * height; i++) {
       accBuf[i] = accBuf[i] + colorBuf[i] * value;
    }
 
-   pipe_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
+   acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
 
    free(colorBuf);
    free(accBuf);
@@ -150,7 +197,7 @@ accum_load(struct pipe_context *pipe, GLfloat value,
       buf[i] = buf[i] * value;
    }
 
-   pipe_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, buf);
+   acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, buf);
 
    free(buf);
 }
@@ -169,7 +216,7 @@ accum_return(GLcontext *ctx, GLfloat value,
 
    abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
-   pipe_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, abuf);
+   acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, abuf);
 
    if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) {
       cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
index e55281a4308eab9b9e2f9c455c856d717e47b146..b1a56f3ca638a71209e4387f0e83826fd0849510 100644 (file)
@@ -127,14 +127,37 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
                                              pipeFormat,
                                              flags);
    if (ret || !strb->surface->buffer) {
-      return GL_FALSE; /* out of memory, try s/w buffer? */
+      if (pipeFormat == DEFAULT_ACCUM_PIPE_FORMAT) {
+         /* Accum buffer.  Try a different surface format.  Since accum
+          * buffers are s/w only for now, the surface pixel format doesn't
+          * really matter, only that the buffer is large enough.
+          */
+         int sz, mult;
+         enum pipe_format accum_format;
+
+         /* allocate a buffer of (typically) double height to get 64bpp */
+         accum_format = st_choose_renderbuffer_format(pipe, GL_RGBA);
+         sz = pf_get_size(accum_format);
+         mult = pf_get_size(DEFAULT_ACCUM_PIPE_FORMAT) / sz;
+
+         ret = pipe->winsys->surface_alloc_storage(pipe->winsys,
+                                                   strb->surface,
+                                                   width, height * mult,
+                                                   accum_format, flags);
+         if (ret)
+            return GL_FALSE; /* we've _really_ failed */
+
+      }
+      else {
+         return GL_FALSE; /* out of memory, try s/w buffer? */
+      }
    }
 
    ASSERT(strb->surface->buffer);
    ASSERT(strb->surface->format);
    ASSERT(strb->surface->cpp);
    ASSERT(strb->surface->width == width);
-   ASSERT(strb->surface->height == height);
+   /*ASSERT(strb->surface->height == height);*/
    ASSERT(strb->surface->pitch);
 
    strb->Base.Width  = width;
@@ -252,7 +275,7 @@ st_new_renderbuffer_fb(enum pipe_format format)
       strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
       strb->Base._BaseFormat = GL_STENCIL_INDEX;
       break;
-   case PIPE_FORMAT_R16G16B16A16_SNORM:
+   case DEFAULT_ACCUM_PIPE_FORMAT: /*PIPE_FORMAT_R16G16B16A16_SNORM*/
       strb->Base.InternalFormat = GL_RGBA16;
       strb->Base._BaseFormat = GL_RGBA;
       break;
index 21e531d1d068235ea7ab647b91f950ea8568d464..c1aa14f9b22ceeef99098c7ba5d13da6a7480b94 100644 (file)
@@ -30,6 +30,9 @@
 #define ST_CB_FBO_H
 
 
+#define DEFAULT_ACCUM_PIPE_FORMAT PIPE_FORMAT_R16G16B16A16_SNORM
+
+
 
 /**
  * Derived renderbuffer class.  Just need to add a pointer to the
index 075e9d1bd68508e679d88a87c62db5aac084b269..ea09d9234cdf1a8b00b74484d85b0e424e8a51bb 100644 (file)
@@ -107,7 +107,7 @@ st_create_framebuffer( const __GLcontextModes *visual,
       if (visual->accumRedBits > 0) {
          /* 16-bit/channel accum */
          struct gl_renderbuffer *accumRb
-            = st_new_renderbuffer_fb(PIPE_FORMAT_R16G16B16A16_SNORM);
+            = st_new_renderbuffer_fb(DEFAULT_ACCUM_PIPE_FORMAT);
          _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb);
       }