00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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_format.h"
00042 #include "pipe/p_context.h"
00043 #include "pipe/p_defines.h"
00044 #include "pipe/p_inlines.h"
00045 #include "util/p_tile.h"
00046
00047
00048 #define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
00049 us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
00050
00051
00059 static void
00060 acc_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
00061 uint x, uint y, uint w, uint h, float *p)
00062 {
00063 const enum pipe_format f = acc_ps->format;
00064 const int cpp = acc_ps->cpp;
00065
00066 acc_ps->format = PIPE_FORMAT_R16G16B16A16_SNORM;
00067 acc_ps->cpp = 8;
00068
00069 pipe_get_tile_rgba(pipe, acc_ps, x, y, w, h, p);
00070
00071 acc_ps->format = f;
00072 acc_ps->cpp = cpp;
00073 }
00074
00075
00076 static void
00077 acc_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
00078 uint x, uint y, uint w, uint h, const float *p)
00079 {
00080 enum pipe_format f = acc_ps->format;
00081 const int cpp = acc_ps->cpp;
00082
00083 acc_ps->format = PIPE_FORMAT_R16G16B16A16_SNORM;
00084 acc_ps->cpp = 8;
00085
00086 pipe_put_tile_rgba(pipe, acc_ps, x, y, w, h, p);
00087
00088 acc_ps->format = f;
00089 acc_ps->cpp = cpp;
00090 }
00091
00092
00093
00094 void
00095 st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
00096 {
00097 struct pipe_context *pipe = ctx->st->pipe;
00098 struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
00099 struct pipe_surface *acc_ps = acc_strb->surface;
00100 const GLint xpos = ctx->DrawBuffer->_Xmin;
00101 const GLint ypos = ctx->DrawBuffer->_Ymin;
00102 const GLint width = ctx->DrawBuffer->_Xmax - xpos;
00103 const GLint height = ctx->DrawBuffer->_Ymax - ypos;
00104 const GLfloat r = ctx->Accum.ClearColor[0];
00105 const GLfloat g = ctx->Accum.ClearColor[1];
00106 const GLfloat b = ctx->Accum.ClearColor[2];
00107 const GLfloat a = ctx->Accum.ClearColor[3];
00108 GLfloat *accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00109 int i;
00110
00111 #if 1
00112 GLvoid *map;
00113
00114 map = pipe_surface_map(acc_ps);
00115 switch (acc_strb->format) {
00116 case PIPE_FORMAT_R16G16B16A16_SNORM:
00117 {
00118 GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
00119 GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
00120 GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
00121 GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
00122 int i, j;
00123 for (i = 0; i < height; i++) {
00124 GLshort *dst = ((GLshort *) map
00125 + ((ypos + i) * acc_ps->pitch + xpos) * 4);
00126 for (j = 0; j < width; j++) {
00127 dst[0] = r;
00128 dst[1] = g;
00129 dst[2] = b;
00130 dst[3] = a;
00131 dst += 4;
00132 }
00133 }
00134 }
00135 break;
00136 default:
00137 _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
00138 }
00139
00140 pipe_surface_unmap(acc_ps);
00141
00142 #else
00143 for (i = 0; i < width * height; i++) {
00144 accBuf[i*4+0] = r;
00145 accBuf[i*4+1] = g;
00146 accBuf[i*4+2] = b;
00147 accBuf[i*4+3] = a;
00148 }
00149
00150 acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
00151 #endif
00152 }
00153
00154
00156 static void
00157 accum_mad(struct pipe_context *pipe, GLfloat scale, GLfloat bias,
00158 GLint xpos, GLint ypos, GLint width, GLint height,
00159 struct pipe_surface *acc_ps)
00160 {
00161 GLfloat *accBuf;
00162 GLint i;
00163
00164 accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00165
00166 pipe_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
00167
00168 for (i = 0; i < 4 * width * height; i++) {
00169 accBuf[i] = accBuf[i] * scale + bias;
00170 }
00171
00172 pipe_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
00173
00174 free(accBuf);
00175 }
00176
00177
00178 static void
00179 accum_accum(struct pipe_context *pipe, GLfloat value,
00180 GLint xpos, GLint ypos, GLint width, GLint height,
00181 struct pipe_surface *acc_ps,
00182 struct pipe_surface *color_ps)
00183 {
00184 GLfloat *colorBuf, *accBuf;
00185 GLint i;
00186
00187 colorBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00188 accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00189
00190 pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, colorBuf);
00191 acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
00192
00193 for (i = 0; i < 4 * width * height; i++) {
00194 accBuf[i] = accBuf[i] + colorBuf[i] * value;
00195 }
00196
00197 acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
00198
00199 free(colorBuf);
00200 free(accBuf);
00201 }
00202
00203
00204 static void
00205 accum_load(struct pipe_context *pipe, GLfloat value,
00206 GLint xpos, GLint ypos, GLint width, GLint height,
00207 struct pipe_surface *acc_ps,
00208 struct pipe_surface *color_ps)
00209 {
00210 GLfloat *buf;
00211 GLint i;
00212
00213 buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00214
00215 pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, buf);
00216
00217 for (i = 0; i < 4 * width * height; i++) {
00218 buf[i] = buf[i] * value;
00219 }
00220
00221 acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, buf);
00222
00223 free(buf);
00224 }
00225
00226
00227 static void
00228 accum_return(GLcontext *ctx, GLfloat value,
00229 GLint xpos, GLint ypos, GLint width, GLint height,
00230 struct pipe_surface *acc_ps,
00231 struct pipe_surface *color_ps)
00232 {
00233 struct pipe_context *pipe = ctx->st->pipe;
00234 const GLubyte *colormask = ctx->Color.ColorMask;
00235 GLfloat *abuf, *cbuf = NULL;
00236 GLint i, ch;
00237
00238 abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00239
00240 acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, abuf);
00241
00242 if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) {
00243 cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
00244 pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, cbuf);
00245 }
00246
00247 for (i = 0; i < width * height; i++) {
00248 for (ch = 0; ch < 4; ch++) {
00249 if (colormask[ch]) {
00250 GLfloat val = abuf[i * 4 + ch] * value;
00251 abuf[i * 4 + ch] = CLAMP(val, 0.0, 1.0);
00252 }
00253 else {
00254 abuf[i * 4 + ch] = cbuf[i * 4 + ch];
00255 }
00256 }
00257 }
00258
00259 pipe_put_tile_rgba(pipe, color_ps, xpos, ypos, width, height, abuf);
00260
00261 free(abuf);
00262 if (cbuf)
00263 free(cbuf);
00264 }
00265
00266
00267 static void
00268 st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
00269 {
00270 struct st_context *st = ctx->st;
00271 struct pipe_context *pipe = st->pipe;
00272 struct st_renderbuffer *acc_strb
00273 = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
00274 struct st_renderbuffer *color_strb
00275 = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
00276 struct pipe_surface *acc_ps = acc_strb->surface;
00277 struct pipe_surface *color_ps = color_strb->surface;
00278
00279 const GLint xpos = ctx->DrawBuffer->_Xmin;
00280 const GLint ypos = ctx->DrawBuffer->_Ymin;
00281 const GLint width = ctx->DrawBuffer->_Xmax - xpos;
00282 const GLint height = ctx->DrawBuffer->_Ymax - ypos;
00283
00284
00285 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
00286
00287 switch (op) {
00288 case GL_ADD:
00289 if (value != 0.0F) {
00290 accum_mad(pipe, 1.0, value, xpos, ypos, width, height, acc_ps);
00291 }
00292 break;
00293 case GL_MULT:
00294 if (value != 1.0F) {
00295 accum_mad(pipe, value, 0.0, xpos, ypos, width, height, acc_ps);
00296 }
00297 break;
00298 case GL_ACCUM:
00299 if (value != 0.0F) {
00300 accum_accum(pipe, value, xpos, ypos, width, height, acc_ps, color_ps);
00301 }
00302 break;
00303 case GL_LOAD:
00304 accum_load(pipe, value, xpos, ypos, width, height, acc_ps, color_ps);
00305 break;
00306 case GL_RETURN:
00307 accum_return(ctx, value, xpos, ypos, width, height, acc_ps, color_ps);
00308 break;
00309 default:
00310 assert(0);
00311 }
00312 }
00313
00314
00315
00316 void st_init_accum_functions(struct dd_function_table *functions)
00317 {
00318 functions->Accum = st_Accum;
00319 }