From 0dd596fbc7f88b88467529a7f176aca70d70f731 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 7 Apr 2008 14:53:49 -0600 Subject: [PATCH] gallium: accum buffer fixes 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 | 61 ++++++++++++++++++++++--- src/mesa/state_tracker/st_cb_fbo.c | 29 ++++++++++-- src/mesa/state_tracker/st_cb_fbo.h | 3 ++ src/mesa/state_tracker/st_framebuffer.c | 2 +- 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index a623d0bcc06..35352351d5a 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -56,6 +56,51 @@ */ +/** + * 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)); diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index e55281a4308..b1a56f3ca63 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -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; diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index 21e531d1d06..c1aa14f9b22 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -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 diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index 075e9d1bd68..ea09d9234cd 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -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); } -- 2.30.2