accum.c revision 848b8605
1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg#include "glheader.h" 26848b8605Smrg#include "accum.h" 27848b8605Smrg#include "condrender.h" 28848b8605Smrg#include "context.h" 29848b8605Smrg#include "format_unpack.h" 30848b8605Smrg#include "format_pack.h" 31848b8605Smrg#include "imports.h" 32848b8605Smrg#include "macros.h" 33848b8605Smrg#include "state.h" 34848b8605Smrg#include "mtypes.h" 35848b8605Smrg#include "main/dispatch.h" 36848b8605Smrg 37848b8605Smrg 38848b8605Smrgvoid GLAPIENTRY 39848b8605Smrg_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) 40848b8605Smrg{ 41848b8605Smrg GLfloat tmp[4]; 42848b8605Smrg GET_CURRENT_CONTEXT(ctx); 43848b8605Smrg 44848b8605Smrg tmp[0] = CLAMP( red, -1.0F, 1.0F ); 45848b8605Smrg tmp[1] = CLAMP( green, -1.0F, 1.0F ); 46848b8605Smrg tmp[2] = CLAMP( blue, -1.0F, 1.0F ); 47848b8605Smrg tmp[3] = CLAMP( alpha, -1.0F, 1.0F ); 48848b8605Smrg 49848b8605Smrg if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor)) 50848b8605Smrg return; 51848b8605Smrg 52848b8605Smrg COPY_4FV( ctx->Accum.ClearColor, tmp ); 53848b8605Smrg} 54848b8605Smrg 55848b8605Smrg 56848b8605Smrgvoid GLAPIENTRY 57848b8605Smrg_mesa_Accum( GLenum op, GLfloat value ) 58848b8605Smrg{ 59848b8605Smrg GET_CURRENT_CONTEXT(ctx); 60848b8605Smrg FLUSH_VERTICES(ctx, 0); 61848b8605Smrg 62848b8605Smrg switch (op) { 63848b8605Smrg case GL_ADD: 64848b8605Smrg case GL_MULT: 65848b8605Smrg case GL_ACCUM: 66848b8605Smrg case GL_LOAD: 67848b8605Smrg case GL_RETURN: 68848b8605Smrg /* OK */ 69848b8605Smrg break; 70848b8605Smrg default: 71848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glAccum(op)"); 72848b8605Smrg return; 73848b8605Smrg } 74848b8605Smrg 75848b8605Smrg if (ctx->DrawBuffer->Visual.haveAccumBuffer == 0) { 76848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glAccum(no accum buffer)"); 77848b8605Smrg return; 78848b8605Smrg } 79848b8605Smrg 80848b8605Smrg if (ctx->DrawBuffer != ctx->ReadBuffer) { 81848b8605Smrg /* See GLX_SGI_make_current_read or WGL_ARB_make_current_read, 82848b8605Smrg * or GL_EXT_framebuffer_blit. 83848b8605Smrg */ 84848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 85848b8605Smrg "glAccum(different read/draw buffers)"); 86848b8605Smrg return; 87848b8605Smrg } 88848b8605Smrg 89848b8605Smrg if (ctx->NewState) 90848b8605Smrg _mesa_update_state(ctx); 91848b8605Smrg 92848b8605Smrg if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 93848b8605Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 94848b8605Smrg "glAccum(incomplete framebuffer)"); 95848b8605Smrg return; 96848b8605Smrg } 97848b8605Smrg 98848b8605Smrg if (ctx->RasterDiscard) 99848b8605Smrg return; 100848b8605Smrg 101848b8605Smrg if (ctx->RenderMode == GL_RENDER) { 102848b8605Smrg _mesa_accum(ctx, op, value); 103848b8605Smrg } 104848b8605Smrg} 105848b8605Smrg 106848b8605Smrg 107848b8605Smrg/** 108848b8605Smrg * Clear the accumulation buffer by mapping the renderbuffer and 109848b8605Smrg * writing the clear color to it. Called by the driver's implementation 110848b8605Smrg * of the glClear function. 111848b8605Smrg */ 112848b8605Smrgvoid 113848b8605Smrg_mesa_clear_accum_buffer(struct gl_context *ctx) 114848b8605Smrg{ 115848b8605Smrg GLuint x, y, width, height; 116848b8605Smrg GLubyte *accMap; 117848b8605Smrg GLint accRowStride; 118848b8605Smrg struct gl_renderbuffer *accRb; 119848b8605Smrg 120848b8605Smrg if (!ctx->DrawBuffer) 121848b8605Smrg return; 122848b8605Smrg 123848b8605Smrg accRb = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer; 124848b8605Smrg if (!accRb) 125848b8605Smrg return; /* missing accum buffer, not an error */ 126848b8605Smrg 127848b8605Smrg /* bounds, with scissor */ 128848b8605Smrg x = ctx->DrawBuffer->_Xmin; 129848b8605Smrg y = ctx->DrawBuffer->_Ymin; 130848b8605Smrg width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 131848b8605Smrg height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 132848b8605Smrg 133848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, accRb, x, y, width, height, 134848b8605Smrg GL_MAP_WRITE_BIT, &accMap, &accRowStride); 135848b8605Smrg 136848b8605Smrg if (!accMap) { 137848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 138848b8605Smrg return; 139848b8605Smrg } 140848b8605Smrg 141848b8605Smrg if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) { 142848b8605Smrg const GLshort clearR = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]); 143848b8605Smrg const GLshort clearG = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]); 144848b8605Smrg const GLshort clearB = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]); 145848b8605Smrg const GLshort clearA = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]); 146848b8605Smrg GLuint i, j; 147848b8605Smrg 148848b8605Smrg for (j = 0; j < height; j++) { 149848b8605Smrg GLshort *row = (GLshort *) accMap; 150848b8605Smrg 151848b8605Smrg for (i = 0; i < width; i++) { 152848b8605Smrg row[i * 4 + 0] = clearR; 153848b8605Smrg row[i * 4 + 1] = clearG; 154848b8605Smrg row[i * 4 + 2] = clearB; 155848b8605Smrg row[i * 4 + 3] = clearA; 156848b8605Smrg } 157848b8605Smrg accMap += accRowStride; 158848b8605Smrg } 159848b8605Smrg } 160848b8605Smrg else { 161848b8605Smrg /* other types someday? */ 162848b8605Smrg _mesa_warning(ctx, "unexpected accum buffer type"); 163848b8605Smrg } 164848b8605Smrg 165848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, accRb); 166848b8605Smrg} 167848b8605Smrg 168848b8605Smrg 169848b8605Smrg/** 170848b8605Smrg * if (bias) 171848b8605Smrg * Accum += value 172848b8605Smrg * else 173848b8605Smrg * Accum *= value 174848b8605Smrg */ 175848b8605Smrgstatic void 176848b8605Smrgaccum_scale_or_bias(struct gl_context *ctx, GLfloat value, 177848b8605Smrg GLint xpos, GLint ypos, GLint width, GLint height, 178848b8605Smrg GLboolean bias) 179848b8605Smrg{ 180848b8605Smrg struct gl_renderbuffer *accRb = 181848b8605Smrg ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer; 182848b8605Smrg GLubyte *accMap; 183848b8605Smrg GLint accRowStride; 184848b8605Smrg 185848b8605Smrg assert(accRb); 186848b8605Smrg 187848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height, 188848b8605Smrg GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, 189848b8605Smrg &accMap, &accRowStride); 190848b8605Smrg 191848b8605Smrg if (!accMap) { 192848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 193848b8605Smrg return; 194848b8605Smrg } 195848b8605Smrg 196848b8605Smrg if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) { 197848b8605Smrg const GLshort incr = (GLshort) (value * 32767.0f); 198848b8605Smrg GLint i, j; 199848b8605Smrg if (bias) { 200848b8605Smrg for (j = 0; j < height; j++) { 201848b8605Smrg GLshort *acc = (GLshort *) accMap; 202848b8605Smrg for (i = 0; i < 4 * width; i++) { 203848b8605Smrg acc[i] += incr; 204848b8605Smrg } 205848b8605Smrg accMap += accRowStride; 206848b8605Smrg } 207848b8605Smrg } 208848b8605Smrg else { 209848b8605Smrg /* scale */ 210848b8605Smrg for (j = 0; j < height; j++) { 211848b8605Smrg GLshort *acc = (GLshort *) accMap; 212848b8605Smrg for (i = 0; i < 4 * width; i++) { 213848b8605Smrg acc[i] = (GLshort) (acc[i] * value); 214848b8605Smrg } 215848b8605Smrg accMap += accRowStride; 216848b8605Smrg } 217848b8605Smrg } 218848b8605Smrg } 219848b8605Smrg else { 220848b8605Smrg /* other types someday? */ 221848b8605Smrg } 222848b8605Smrg 223848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, accRb); 224848b8605Smrg} 225848b8605Smrg 226848b8605Smrg 227848b8605Smrg/** 228848b8605Smrg * if (load) 229848b8605Smrg * Accum = ColorBuf * value 230848b8605Smrg * else 231848b8605Smrg * Accum += ColorBuf * value 232848b8605Smrg */ 233848b8605Smrgstatic void 234848b8605Smrgaccum_or_load(struct gl_context *ctx, GLfloat value, 235848b8605Smrg GLint xpos, GLint ypos, GLint width, GLint height, 236848b8605Smrg GLboolean load) 237848b8605Smrg{ 238848b8605Smrg struct gl_renderbuffer *accRb = 239848b8605Smrg ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer; 240848b8605Smrg struct gl_renderbuffer *colorRb = ctx->ReadBuffer->_ColorReadBuffer; 241848b8605Smrg GLubyte *accMap, *colorMap; 242848b8605Smrg GLint accRowStride, colorRowStride; 243848b8605Smrg GLbitfield mappingFlags; 244848b8605Smrg 245848b8605Smrg if (!colorRb) { 246848b8605Smrg /* no read buffer - OK */ 247848b8605Smrg return; 248848b8605Smrg } 249848b8605Smrg 250848b8605Smrg assert(accRb); 251848b8605Smrg 252848b8605Smrg mappingFlags = GL_MAP_WRITE_BIT; 253848b8605Smrg if (!load) /* if we're accumulating */ 254848b8605Smrg mappingFlags |= GL_MAP_READ_BIT; 255848b8605Smrg 256848b8605Smrg /* Map accum buffer */ 257848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height, 258848b8605Smrg mappingFlags, &accMap, &accRowStride); 259848b8605Smrg if (!accMap) { 260848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 261848b8605Smrg return; 262848b8605Smrg } 263848b8605Smrg 264848b8605Smrg /* Map color buffer */ 265848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height, 266848b8605Smrg GL_MAP_READ_BIT, 267848b8605Smrg &colorMap, &colorRowStride); 268848b8605Smrg if (!colorMap) { 269848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, accRb); 270848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 271848b8605Smrg return; 272848b8605Smrg } 273848b8605Smrg 274848b8605Smrg if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) { 275848b8605Smrg const GLfloat scale = value * 32767.0f; 276848b8605Smrg GLint i, j; 277848b8605Smrg GLfloat (*rgba)[4]; 278848b8605Smrg 279848b8605Smrg rgba = malloc(width * 4 * sizeof(GLfloat)); 280848b8605Smrg if (rgba) { 281848b8605Smrg for (j = 0; j < height; j++) { 282848b8605Smrg GLshort *acc = (GLshort *) accMap; 283848b8605Smrg 284848b8605Smrg /* read colors from source color buffer */ 285848b8605Smrg _mesa_unpack_rgba_row(colorRb->Format, width, colorMap, rgba); 286848b8605Smrg 287848b8605Smrg if (load) { 288848b8605Smrg for (i = 0; i < width; i++) { 289848b8605Smrg acc[i * 4 + 0] = (GLshort) (rgba[i][RCOMP] * scale); 290848b8605Smrg acc[i * 4 + 1] = (GLshort) (rgba[i][GCOMP] * scale); 291848b8605Smrg acc[i * 4 + 2] = (GLshort) (rgba[i][BCOMP] * scale); 292848b8605Smrg acc[i * 4 + 3] = (GLshort) (rgba[i][ACOMP] * scale); 293848b8605Smrg } 294848b8605Smrg } 295848b8605Smrg else { 296848b8605Smrg /* accumulate */ 297848b8605Smrg for (i = 0; i < width; i++) { 298848b8605Smrg acc[i * 4 + 0] += (GLshort) (rgba[i][RCOMP] * scale); 299848b8605Smrg acc[i * 4 + 1] += (GLshort) (rgba[i][GCOMP] * scale); 300848b8605Smrg acc[i * 4 + 2] += (GLshort) (rgba[i][BCOMP] * scale); 301848b8605Smrg acc[i * 4 + 3] += (GLshort) (rgba[i][ACOMP] * scale); 302848b8605Smrg } 303848b8605Smrg } 304848b8605Smrg 305848b8605Smrg colorMap += colorRowStride; 306848b8605Smrg accMap += accRowStride; 307848b8605Smrg } 308848b8605Smrg 309848b8605Smrg free(rgba); 310848b8605Smrg } 311848b8605Smrg else { 312848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 313848b8605Smrg } 314848b8605Smrg } 315848b8605Smrg else { 316848b8605Smrg /* other types someday? */ 317848b8605Smrg } 318848b8605Smrg 319848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, accRb); 320848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, colorRb); 321848b8605Smrg} 322848b8605Smrg 323848b8605Smrg 324848b8605Smrg/** 325848b8605Smrg * ColorBuffer = Accum * value 326848b8605Smrg */ 327848b8605Smrgstatic void 328848b8605Smrgaccum_return(struct gl_context *ctx, GLfloat value, 329848b8605Smrg GLint xpos, GLint ypos, GLint width, GLint height) 330848b8605Smrg{ 331848b8605Smrg struct gl_framebuffer *fb = ctx->DrawBuffer; 332848b8605Smrg struct gl_renderbuffer *accRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer; 333848b8605Smrg GLubyte *accMap, *colorMap; 334848b8605Smrg GLint accRowStride, colorRowStride; 335848b8605Smrg GLuint buffer; 336848b8605Smrg 337848b8605Smrg /* Map accum buffer */ 338848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height, 339848b8605Smrg GL_MAP_READ_BIT, 340848b8605Smrg &accMap, &accRowStride); 341848b8605Smrg if (!accMap) { 342848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 343848b8605Smrg return; 344848b8605Smrg } 345848b8605Smrg 346848b8605Smrg /* Loop over destination buffers */ 347848b8605Smrg for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) { 348848b8605Smrg struct gl_renderbuffer *colorRb = fb->_ColorDrawBuffers[buffer]; 349848b8605Smrg const GLboolean masking = (!ctx->Color.ColorMask[buffer][RCOMP] || 350848b8605Smrg !ctx->Color.ColorMask[buffer][GCOMP] || 351848b8605Smrg !ctx->Color.ColorMask[buffer][BCOMP] || 352848b8605Smrg !ctx->Color.ColorMask[buffer][ACOMP]); 353848b8605Smrg GLbitfield mappingFlags = GL_MAP_WRITE_BIT; 354848b8605Smrg 355848b8605Smrg if (masking) 356848b8605Smrg mappingFlags |= GL_MAP_READ_BIT; 357848b8605Smrg 358848b8605Smrg /* Map color buffer */ 359848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height, 360848b8605Smrg mappingFlags, &colorMap, &colorRowStride); 361848b8605Smrg if (!colorMap) { 362848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 363848b8605Smrg continue; 364848b8605Smrg } 365848b8605Smrg 366848b8605Smrg if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) { 367848b8605Smrg const GLfloat scale = value / 32767.0f; 368848b8605Smrg GLint i, j; 369848b8605Smrg GLfloat (*rgba)[4], (*dest)[4]; 370848b8605Smrg 371848b8605Smrg rgba = malloc(width * 4 * sizeof(GLfloat)); 372848b8605Smrg dest = malloc(width * 4 * sizeof(GLfloat)); 373848b8605Smrg 374848b8605Smrg if (rgba && dest) { 375848b8605Smrg for (j = 0; j < height; j++) { 376848b8605Smrg GLshort *acc = (GLshort *) accMap; 377848b8605Smrg 378848b8605Smrg for (i = 0; i < width; i++) { 379848b8605Smrg rgba[i][0] = acc[i * 4 + 0] * scale; 380848b8605Smrg rgba[i][1] = acc[i * 4 + 1] * scale; 381848b8605Smrg rgba[i][2] = acc[i * 4 + 2] * scale; 382848b8605Smrg rgba[i][3] = acc[i * 4 + 3] * scale; 383848b8605Smrg } 384848b8605Smrg 385848b8605Smrg if (masking) { 386848b8605Smrg 387848b8605Smrg /* get existing colors from dest buffer */ 388848b8605Smrg _mesa_unpack_rgba_row(colorRb->Format, width, colorMap, dest); 389848b8605Smrg 390848b8605Smrg /* use the dest colors where mask[channel] = 0 */ 391848b8605Smrg if (ctx->Color.ColorMask[buffer][RCOMP] == 0) { 392848b8605Smrg for (i = 0; i < width; i++) 393848b8605Smrg rgba[i][RCOMP] = dest[i][RCOMP]; 394848b8605Smrg } 395848b8605Smrg if (ctx->Color.ColorMask[buffer][GCOMP] == 0) { 396848b8605Smrg for (i = 0; i < width; i++) 397848b8605Smrg rgba[i][GCOMP] = dest[i][GCOMP]; 398848b8605Smrg } 399848b8605Smrg if (ctx->Color.ColorMask[buffer][BCOMP] == 0) { 400848b8605Smrg for (i = 0; i < width; i++) 401848b8605Smrg rgba[i][BCOMP] = dest[i][BCOMP]; 402848b8605Smrg } 403848b8605Smrg if (ctx->Color.ColorMask[buffer][ACOMP] == 0) { 404848b8605Smrg for (i = 0; i < width; i++) 405848b8605Smrg rgba[i][ACOMP] = dest[i][ACOMP]; 406848b8605Smrg } 407848b8605Smrg } 408848b8605Smrg 409848b8605Smrg _mesa_pack_float_rgba_row(colorRb->Format, width, 410848b8605Smrg (const GLfloat (*)[4]) rgba, colorMap); 411848b8605Smrg 412848b8605Smrg accMap += accRowStride; 413848b8605Smrg colorMap += colorRowStride; 414848b8605Smrg } 415848b8605Smrg } 416848b8605Smrg else { 417848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum"); 418848b8605Smrg } 419848b8605Smrg free(rgba); 420848b8605Smrg free(dest); 421848b8605Smrg } 422848b8605Smrg else { 423848b8605Smrg /* other types someday? */ 424848b8605Smrg } 425848b8605Smrg 426848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, colorRb); 427848b8605Smrg } 428848b8605Smrg 429848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, accRb); 430848b8605Smrg} 431848b8605Smrg 432848b8605Smrg 433848b8605Smrg 434848b8605Smrg/** 435848b8605Smrg * Software fallback for glAccum. A hardware driver that supports 436848b8605Smrg * signed 16-bit color channels could implement hardware accumulation 437848b8605Smrg * operations, but no driver does so at this time. 438848b8605Smrg */ 439848b8605Smrgvoid 440848b8605Smrg_mesa_accum(struct gl_context *ctx, GLenum op, GLfloat value) 441848b8605Smrg{ 442848b8605Smrg GLint xpos, ypos, width, height; 443848b8605Smrg 444848b8605Smrg if (!ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer) { 445848b8605Smrg _mesa_warning(ctx, "Calling glAccum() without an accumulation buffer"); 446848b8605Smrg return; 447848b8605Smrg } 448848b8605Smrg 449848b8605Smrg if (!_mesa_check_conditional_render(ctx)) 450848b8605Smrg return; 451848b8605Smrg 452848b8605Smrg xpos = ctx->DrawBuffer->_Xmin; 453848b8605Smrg ypos = ctx->DrawBuffer->_Ymin; 454848b8605Smrg width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 455848b8605Smrg height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 456848b8605Smrg 457848b8605Smrg switch (op) { 458848b8605Smrg case GL_ADD: 459848b8605Smrg if (value != 0.0F) { 460848b8605Smrg accum_scale_or_bias(ctx, value, xpos, ypos, width, height, GL_TRUE); 461848b8605Smrg } 462848b8605Smrg break; 463848b8605Smrg case GL_MULT: 464848b8605Smrg if (value != 1.0F) { 465848b8605Smrg accum_scale_or_bias(ctx, value, xpos, ypos, width, height, GL_FALSE); 466848b8605Smrg } 467848b8605Smrg break; 468848b8605Smrg case GL_ACCUM: 469848b8605Smrg if (value != 0.0F) { 470848b8605Smrg accum_or_load(ctx, value, xpos, ypos, width, height, GL_FALSE); 471848b8605Smrg } 472848b8605Smrg break; 473848b8605Smrg case GL_LOAD: 474848b8605Smrg accum_or_load(ctx, value, xpos, ypos, width, height, GL_TRUE); 475848b8605Smrg break; 476848b8605Smrg case GL_RETURN: 477848b8605Smrg accum_return(ctx, value, xpos, ypos, width, height); 478848b8605Smrg break; 479848b8605Smrg default: 480848b8605Smrg _mesa_problem(ctx, "invalid mode in _mesa_accum()"); 481848b8605Smrg break; 482848b8605Smrg } 483848b8605Smrg} 484848b8605Smrg 485848b8605Smrg 486848b8605Smrgvoid 487848b8605Smrg_mesa_init_accum( struct gl_context *ctx ) 488848b8605Smrg{ 489848b8605Smrg /* Accumulate buffer group */ 490848b8605Smrg ASSIGN_4V( ctx->Accum.ClearColor, 0.0, 0.0, 0.0, 0.0 ); 491848b8605Smrg} 492