st_cb_accum.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028  /*
00029   * Authors:
00030   *   Brian Paul
00031   */
00032 
00033 #include "main/imports.h"
00034 #include "main/image.h"
00035 #include "main/macros.h"
00036 
00037 #include "st_context.h"
00038 #include "st_cb_accum.h"
00039 #include "st_cb_fbo.h"
00040 #include "st_draw.h"
00041 #include "st_public.h"
00042 #include "st_format.h"
00043 #include "pipe/p_context.h"
00044 #include "pipe/p_defines.h"
00045 #include "pipe/p_inlines.h"
00046 #include "util/u_tile.h"
00047 
00048 
00049 #define UNCLAMPED_FLOAT_TO_SHORT(us, f)  \
00050    us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
00051 
00052 
00065 static void
00066 acc_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
00067                   uint x, uint y, uint w, uint h, float *p)
00068 {
00069    const enum pipe_format f = acc_ps->format;
00070    const struct pipe_format_block b = acc_ps->block;
00071 
00072    acc_ps->format = DEFAULT_ACCUM_PIPE_FORMAT;
00073    acc_ps->block.size = 8;
00074    acc_ps->block.width = 1;
00075    acc_ps->block.height = 1;
00076 
00077    pipe_get_tile_rgba(acc_ps, x, y, w, h, p);
00078 
00079    acc_ps->format = f;
00080    acc_ps->block = b;
00081 }
00082 
00083 
00089 static void
00090 acc_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
00091                   uint x, uint y, uint w, uint h, const float *p)
00092 {
00093    enum pipe_format f = acc_ps->format;
00094    const struct pipe_format_block b = acc_ps->block;
00095 
00096    acc_ps->format = DEFAULT_ACCUM_PIPE_FORMAT;
00097    acc_ps->block.size = 8;
00098    acc_ps->block.width = 1;
00099    acc_ps->block.height = 1;
00100 
00101    pipe_put_tile_rgba(acc_ps, x, y, w, h, p);
00102 
00103    acc_ps->format = f;
00104    acc_ps->block = b;
00105 }
00106 
00107 
00108 
00109 void
00110 st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
00111 {
00112    struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
00113    struct pipe_surface *acc_ps;
00114    struct pipe_screen *screen = ctx->st->pipe->screen;
00115    const GLint xpos = ctx->DrawBuffer->_Xmin;
00116    const GLint ypos = ctx->DrawBuffer->_Ymin;
00117    const GLint width = ctx->DrawBuffer->_Xmax - xpos;
00118    const GLint height = ctx->DrawBuffer->_Ymax - ypos;
00119    GLubyte *map;
00120 
00121    acc_ps = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
00122                                     PIPE_BUFFER_USAGE_CPU_WRITE);
00123    map = screen->surface_map(screen, acc_ps,
00124                              PIPE_BUFFER_USAGE_CPU_WRITE);
00125 
00126    /* note acc_strb->format might not equal acc_ps->format */
00127    switch (acc_strb->format) {
00128    case PIPE_FORMAT_R16G16B16A16_SNORM:
00129       {
00130          GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
00131          GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
00132          GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
00133          GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
00134          int i, j;
00135          for (i = 0; i < height; i++) {
00136             GLshort *dst = (GLshort *) (map + (ypos + i) * acc_ps->stride + xpos * 8);
00137             for (j = 0; j < width; j++) {
00138                dst[0] = r;
00139                dst[1] = g;
00140                dst[2] = b;
00141                dst[3] = a;
00142                dst += 4;
00143             }
00144          }
00145       }
00146       break;
00147    default:
00148       _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
00149    }
00150 
00151    screen->surface_unmap(screen, acc_ps);
00152    pipe_surface_reference(&acc_ps, NULL);
00153 }
00154 
00155 
00157 static void
00158 accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
00159           GLint xpos, GLint ypos, GLint width, GLint height,
00160           struct st_renderbuffer *acc_strb)
00161 {
00162    struct pipe_screen *screen = ctx->st->pipe->screen;
00163    struct pipe_surface *acc_ps = acc_strb->surface;
00164    GLubyte *map;
00165 
00166    map = screen->surface_map(screen, acc_ps, 
00167                              PIPE_BUFFER_USAGE_CPU_WRITE);
00168 
00169    /* note acc_strb->format might not equal acc_ps->format */
00170    switch (acc_strb->format) {
00171    case PIPE_FORMAT_R16G16B16A16_SNORM:
00172       {
00173          int i, j;
00174          for (i = 0; i < height; i++) {
00175             GLshort *acc = (GLshort *) (map + (ypos + i) * acc_ps->stride + xpos * 8);
00176             for (j = 0; j < width * 4; j++) {
00177                float val = SHORT_TO_FLOAT(acc[j]) * scale + bias;
00178                acc[j] = FLOAT_TO_SHORT(val);
00179             }
00180          }
00181       }
00182       break;
00183    default:
00184       _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
00185    }
00186 
00187    screen->surface_unmap(screen, acc_ps);
00188 }
00189 
00190 
00191 static void
00192 accum_accum(struct pipe_context *pipe, GLfloat value,
00193             GLint xpos, GLint ypos, GLint width, GLint height,
00194             struct st_renderbuffer *acc_strb,
00195             struct st_renderbuffer *color_strb)
00196 {
00197    struct pipe_screen *screen = pipe->screen;
00198    struct pipe_surface *acc_surf, *color_surf;
00199    GLfloat *colorBuf, *accBuf;
00200    GLint i;
00201 
00202    acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
00203                                       (PIPE_BUFFER_USAGE_CPU_WRITE |
00204                                        PIPE_BUFFER_USAGE_CPU_READ));
00205 
00206    color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
00207                                         PIPE_BUFFER_USAGE_CPU_READ);
00208 
00209    colorBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00210    accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00211 
00212    pipe_get_tile_rgba(color_surf, xpos, ypos, width, height, colorBuf);
00213    acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
00214 
00215    for (i = 0; i < 4 * width * height; i++) {
00216       accBuf[i] = accBuf[i] + colorBuf[i] * value;
00217    }
00218 
00219    acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
00220 
00221    free(colorBuf);
00222    free(accBuf);
00223    pipe_surface_reference(&acc_surf, NULL);
00224    pipe_surface_reference(&color_surf, NULL);
00225 }
00226 
00227 
00228 static void
00229 accum_load(struct pipe_context *pipe, GLfloat value,
00230            GLint xpos, GLint ypos, GLint width, GLint height,
00231            struct st_renderbuffer *acc_strb,
00232            struct st_renderbuffer *color_strb)
00233 {
00234    struct pipe_screen *screen = pipe->screen;
00235    struct pipe_surface *acc_surf, *color_surf;
00236    GLfloat *buf;
00237    GLint i;
00238 
00239    acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
00240                                       PIPE_BUFFER_USAGE_CPU_WRITE);
00241 
00242    color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
00243                                         PIPE_BUFFER_USAGE_CPU_READ);
00244 
00245    buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00246 
00247    pipe_get_tile_rgba(color_surf, xpos, ypos, width, height, buf);
00248 
00249    for (i = 0; i < 4 * width * height; i++) {
00250       buf[i] = buf[i] * value;
00251    }
00252 
00253    acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, buf);
00254 
00255    free(buf);
00256    pipe_surface_reference(&acc_surf, NULL);
00257    pipe_surface_reference(&color_surf, NULL);
00258 }
00259 
00260 
00261 static void
00262 accum_return(GLcontext *ctx, GLfloat value,
00263              GLint xpos, GLint ypos, GLint width, GLint height,
00264              struct st_renderbuffer *acc_strb,
00265              struct st_renderbuffer *color_strb)
00266 {
00267    struct pipe_context *pipe = ctx->st->pipe;
00268    struct pipe_screen *screen = pipe->screen;
00269    const GLubyte *colormask = ctx->Color.ColorMask;
00270    struct pipe_surface *acc_surf, *color_surf;
00271    GLfloat *abuf, *cbuf = NULL;
00272    GLint i, ch;
00273 
00274    abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00275 
00276    acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
00277                                       PIPE_BUFFER_USAGE_CPU_READ);
00278 
00279    color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
00280                                         (PIPE_BUFFER_USAGE_CPU_READ |
00281                                          PIPE_BUFFER_USAGE_CPU_WRITE));
00282 
00283    acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, abuf);
00284 
00285    if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) {
00286       cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00287       pipe_get_tile_rgba(color_surf, xpos, ypos, width, height, cbuf);
00288    }
00289 
00290    for (i = 0; i < width * height; i++) {
00291       for (ch = 0; ch < 4; ch++) {
00292          if (colormask[ch]) {
00293             GLfloat val = abuf[i * 4 + ch] * value;
00294             abuf[i * 4 + ch] = CLAMP(val, 0.0f, 1.0f);
00295          }
00296          else {
00297             abuf[i * 4 + ch] = cbuf[i * 4 + ch];
00298          }
00299       }
00300    }
00301 
00302    pipe_put_tile_rgba(color_surf, xpos, ypos, width, height, abuf);
00303 
00304    free(abuf);
00305    if (cbuf)
00306       free(cbuf);
00307    pipe_surface_reference(&acc_surf, NULL);
00308    pipe_surface_reference(&color_surf, NULL);
00309 }
00310 
00311 
00312 static void
00313 st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
00314 {
00315    struct st_context *st = ctx->st;
00316    struct pipe_context *pipe = st->pipe;
00317    struct st_renderbuffer *acc_strb
00318      = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
00319    struct st_renderbuffer *color_strb
00320       = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
00321 
00322    const GLint xpos = ctx->DrawBuffer->_Xmin;
00323    const GLint ypos = ctx->DrawBuffer->_Ymin;
00324    const GLint width = ctx->DrawBuffer->_Xmax - xpos;
00325    const GLint height = ctx->DrawBuffer->_Ymax - ypos;
00326 
00327    /* make sure color bufs aren't cached */
00328    st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL );
00329 
00330    switch (op) {
00331    case GL_ADD:
00332       if (value != 0.0F) {
00333          accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb);
00334       }
00335       break;
00336    case GL_MULT:
00337       if (value != 1.0F) {
00338          accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb);
00339       }
00340       break;
00341    case GL_ACCUM:
00342       if (value != 0.0F) {
00343          accum_accum(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
00344       }
00345       break;
00346    case GL_LOAD:
00347       accum_load(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
00348       break;
00349    case GL_RETURN:
00350       accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
00351       break;
00352    default:
00353       assert(0);
00354    }
00355 }
00356 
00357 
00358 
00359 void st_init_accum_functions(struct dd_function_table *functions)
00360 {
00361    functions->Accum = st_Accum;
00362 }

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4