1afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach/*
2afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * Mesa 3-D graphics library
35e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
4e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
55e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
6afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * Permission is hereby granted, free of charge, to any person obtaining a
7afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * copy of this software and associated documentation files (the "Software"),
8afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * to deal in the Software without restriction, including without limitation
9afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * and/or sell copies of the Software, and to permit persons to whom the
11afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * Software is furnished to do so, subject to the following conditions:
125e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
13afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * The above copyright notice and this permission notice shall be included
14afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * in all copies or substantial portions of the Software.
155e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
16afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
193d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
203d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
213d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
223d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER DEALINGS IN THE SOFTWARE.
23afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach */
24afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
25fbd8f212c3866ec98c1d8c9d3db3ddb7e7c479a5Brian Paul#include "glheader.h"
26afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach#include "accum.h"
27122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul#include "condrender.h"
28afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach#include "context.h"
29122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul#include "format_unpack.h"
30122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul#include "format_pack.h"
313c63452e64df7e10aa073c6c3b9492b1d7dabbb8Brian Paul#include "imports.h"
32ebb248aa5c018dc676d389221d76ed329059789eBrian Paul#include "macros.h"
33ea39f042c378c234b573ceead4c5194020d949c4Brian Paul#include "state.h"
345e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen#include "mtypes.h"
352cf44390d1e819f23e1d7ceb3199276c9148c647Chia-I Wu#include "main/dispatch.h"
36a833ff0f53da6e365d917bb0081d909a809b6ec1Chia-I Wu
37a833ff0f53da6e365d917bb0081d909a809b6ec1Chia-I Wu
38c40d1dd62dd9bcbb97128e37a75d991a8d3b2d8cKendall Bennettvoid GLAPIENTRY
39fbd8f212c3866ec98c1d8c9d3db3ddb7e7c479a5Brian Paul_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
40afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach{
41cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell   GLfloat tmp[4];
42fbd8f212c3866ec98c1d8c9d3db3ddb7e7c479a5Brian Paul   GET_CURRENT_CONTEXT(ctx);
43afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
447c276329e815c84ea2403bb08c44ff60179c0cd6Brian Paul   tmp[0] = CLAMP( red,   -1.0F, 1.0F );
457c276329e815c84ea2403bb08c44ff60179c0cd6Brian Paul   tmp[1] = CLAMP( green, -1.0F, 1.0F );
467c276329e815c84ea2403bb08c44ff60179c0cd6Brian Paul   tmp[2] = CLAMP( blue,  -1.0F, 1.0F );
477c276329e815c84ea2403bb08c44ff60179c0cd6Brian Paul   tmp[3] = CLAMP( alpha, -1.0F, 1.0F );
48cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell
49cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell   if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor))
50cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell      return;
51afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
52cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell   COPY_4FV( ctx->Accum.ClearColor, tmp );
53cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell}
54afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
553a0e0b284fd74aa6cb7b380a59cf20e62f8f8ffdBrian Paul
56f7fa946d1da96178e63e42dd8d8739d3e0f66e1dPaul Berryvoid GLAPIENTRY
57fbd8f212c3866ec98c1d8c9d3db3ddb7e7c479a5Brian Paul_mesa_Accum( GLenum op, GLfloat value )
58afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach{
59fbd8f212c3866ec98c1d8c9d3db3ddb7e7c479a5Brian Paul   GET_CURRENT_CONTEXT(ctx);
60a9754793dab4b24c09cae21c29f902ce0e53319aEric Anholt   FLUSH_VERTICES(ctx, 0);
61afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
62e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   switch (op) {
63e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   case GL_ADD:
64e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   case GL_MULT:
65e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   case GL_ACCUM:
66e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   case GL_LOAD:
67e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   case GL_RETURN:
68e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* OK */
69e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      break;
70e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   default:
71e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glAccum(op)");
72e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      return;
73e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   }
74e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
75b4269c07f8fe51912a01a36ff6239f1565d0639cBrian Paul   if (ctx->DrawBuffer->Visual.haveAccumBuffer == 0) {
76dbd0fa920effdceacec34fa0d5ae9ab7a2f09614Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION, "glAccum(no accum buffer)");
77dbd0fa920effdceacec34fa0d5ae9ab7a2f09614Brian Paul      return;
78dbd0fa920effdceacec34fa0d5ae9ab7a2f09614Brian Paul   }
79dbd0fa920effdceacec34fa0d5ae9ab7a2f09614Brian Paul
8078b3b667b5fc7dbd7f723682f8ffaa0091286abbBrian Paul   if (ctx->DrawBuffer != ctx->ReadBuffer) {
819b8059e53610d6d9d217f331b0671354e62ad47fBrian Paul      /* See GLX_SGI_make_current_read or WGL_ARB_make_current_read,
829b8059e53610d6d9d217f331b0671354e62ad47fBrian Paul       * or GL_EXT_framebuffer_blit.
839b8059e53610d6d9d217f331b0671354e62ad47fBrian Paul       */
8478b3b667b5fc7dbd7f723682f8ffaa0091286abbBrian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
8578b3b667b5fc7dbd7f723682f8ffaa0091286abbBrian Paul                  "glAccum(different read/draw buffers)");
8678b3b667b5fc7dbd7f723682f8ffaa0091286abbBrian Paul      return;
8778b3b667b5fc7dbd7f723682f8ffaa0091286abbBrian Paul   }
8878b3b667b5fc7dbd7f723682f8ffaa0091286abbBrian Paul
89afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   if (ctx->NewState)
90d95000da2fdad78f25618fe9703f23806587b65aBrian Paul      _mesa_update_state(ctx);
91afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
92d95000da2fdad78f25618fe9703f23806587b65aBrian Paul   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
93d95000da2fdad78f25618fe9703f23806587b65aBrian Paul      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
94d95000da2fdad78f25618fe9703f23806587b65aBrian Paul                  "glAccum(incomplete framebuffer)");
953a0e0b284fd74aa6cb7b380a59cf20e62f8f8ffdBrian Paul      return;
963a0e0b284fd74aa6cb7b380a59cf20e62f8f8ffdBrian Paul   }
973a0e0b284fd74aa6cb7b380a59cf20e62f8f8ffdBrian Paul
98aee96806f049c17384a8edc11acce76257d98a57Paul Berry   if (ctx->RasterDiscard)
99e7c2b711a3b01cbeb0bf93d5442599457e7f8f51Eric Anholt      return;
100e7c2b711a3b01cbeb0bf93d5442599457e7f8f51Eric Anholt
101d95000da2fdad78f25618fe9703f23806587b65aBrian Paul   if (ctx->RenderMode == GL_RENDER) {
102122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_accum(ctx, op, value);
103afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
104afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach}
1056dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell
106e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
107122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul/**
108122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * Clear the accumulation buffer by mapping the renderbuffer and
109122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * writing the clear color to it.  Called by the driver's implementation
110122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * of the glClear function.
111122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul */
112122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulvoid
113122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul_mesa_clear_accum_buffer(struct gl_context *ctx)
114122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul{
115122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLuint x, y, width, height;
116122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLubyte *accMap;
117122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLint accRowStride;
118122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   struct gl_renderbuffer *accRb;
119122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
120122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!ctx->DrawBuffer)
121122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
122122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
123122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   accRb = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
124122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!accRb)
125122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;   /* missing accum buffer, not an error */
126122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
127122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   /* bounds, with scissor */
128122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   x = ctx->DrawBuffer->_Xmin;
129122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   y = ctx->DrawBuffer->_Ymin;
130122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
131122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
132122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
133122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.MapRenderbuffer(ctx, accRb, x, y, width, height,
134122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               GL_MAP_WRITE_BIT, &accMap, &accRowStride);
135122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
136122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!accMap) {
137122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
138122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
139122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
140122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
1418b47b6bc32b595ee1a37cde279d44a6ac84403c0Mark Mueller   if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) {
142122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLshort clearR = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
143122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLshort clearG = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
144122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLshort clearB = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
145122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLshort clearA = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
146122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      GLuint i, j;
147122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
148122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      for (j = 0; j < height; j++) {
149122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         GLshort *row = (GLshort *) accMap;
150122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
151122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         for (i = 0; i < width; i++) {
152122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            row[i * 4 + 0] = clearR;
153122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            row[i * 4 + 1] = clearG;
154122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            row[i * 4 + 2] = clearB;
155122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            row[i * 4 + 3] = clearA;
156122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         }
157122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         accMap += accRowStride;
158122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
159122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
160122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   else {
161122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      /* other types someday? */
162122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_warning(ctx, "unexpected accum buffer type");
163122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
164122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
165122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.UnmapRenderbuffer(ctx, accRb);
166122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul}
167122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
168122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
169122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul/**
170122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * if (bias)
171122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul *    Accum += value
172122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * else
173122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul *    Accum *= value
174122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul */
175122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulstatic void
176122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulaccum_scale_or_bias(struct gl_context *ctx, GLfloat value,
177122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                    GLint xpos, GLint ypos, GLint width, GLint height,
178122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                    GLboolean bias)
179122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul{
180122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   struct gl_renderbuffer *accRb =
181122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
182122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLubyte *accMap;
183122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLint accRowStride;
184122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
185122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   assert(accRb);
186122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
187122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height,
188122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
189122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               &accMap, &accRowStride);
190122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
191122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!accMap) {
192122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
193122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
194122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
195122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
1968b47b6bc32b595ee1a37cde279d44a6ac84403c0Mark Mueller   if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) {
197122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLshort incr = (GLshort) (value * 32767.0f);
19803503daa2118c760fb2963c6ac5a813f58941fa1Brian Paul      GLint i, j;
199122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (bias) {
200122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         for (j = 0; j < height; j++) {
201122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            GLshort *acc = (GLshort *) accMap;
202122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            for (i = 0; i < 4 * width; i++) {
203122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               acc[i] += incr;
204122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            }
205122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            accMap += accRowStride;
206122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         }
207122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
208122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      else {
209122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         /* scale */
210122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         for (j = 0; j < height; j++) {
211122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            GLshort *acc = (GLshort *) accMap;
212122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            for (i = 0; i < 4 * width; i++) {
213122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               acc[i] = (GLshort) (acc[i] * value);
214122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            }
215122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            accMap += accRowStride;
216122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         }
217122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
218122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
219122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   else {
220122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      /* other types someday? */
221122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
222122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
223122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.UnmapRenderbuffer(ctx, accRb);
224122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul}
225122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
226122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
227122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul/**
228122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * if (load)
229122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul *    Accum = ColorBuf * value
230122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * else
231122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul *    Accum += ColorBuf * value
232122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul */
233122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulstatic void
234122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulaccum_or_load(struct gl_context *ctx, GLfloat value,
235122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul              GLint xpos, GLint ypos, GLint width, GLint height,
236122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul              GLboolean load)
237122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul{
238122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   struct gl_renderbuffer *accRb =
239122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
240122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   struct gl_renderbuffer *colorRb = ctx->ReadBuffer->_ColorReadBuffer;
241122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLubyte *accMap, *colorMap;
242122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLint accRowStride, colorRowStride;
243122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLbitfield mappingFlags;
244122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
245122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!colorRb) {
246122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      /* no read buffer - OK */
247122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
248122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
249122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
250122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   assert(accRb);
251122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
252122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   mappingFlags = GL_MAP_WRITE_BIT;
253122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!load) /* if we're accumulating */
254122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      mappingFlags |= GL_MAP_READ_BIT;
255122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
256122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   /* Map accum buffer */
257122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height,
258122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               mappingFlags, &accMap, &accRowStride);
259122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!accMap) {
260122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
261122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
262122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
263122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
264122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   /* Map color buffer */
265122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height,
266122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               GL_MAP_READ_BIT,
267122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               &colorMap, &colorRowStride);
268122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!colorMap) {
269122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      ctx->Driver.UnmapRenderbuffer(ctx, accRb);
270122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
271122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
272122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
273122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
2748b47b6bc32b595ee1a37cde279d44a6ac84403c0Mark Mueller   if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) {
275122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLfloat scale = value * 32767.0f;
27603503daa2118c760fb2963c6ac5a813f58941fa1Brian Paul      GLint i, j;
277122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      GLfloat (*rgba)[4];
278122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
2792b7a972e3f36bfcdc6fbe2b59d7ffdcde49c9405Matt Turner      rgba = malloc(width * 4 * sizeof(GLfloat));
280122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (rgba) {
281122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         for (j = 0; j < height; j++) {
282122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            GLshort *acc = (GLshort *) accMap;
283122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
284122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            /* read colors from source color buffer */
285122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            _mesa_unpack_rgba_row(colorRb->Format, width, colorMap, rgba);
286122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
287122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            if (load) {
288122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               for (i = 0; i < width; i++) {
289122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 0] = (GLshort) (rgba[i][RCOMP] * scale);
290122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 1] = (GLshort) (rgba[i][GCOMP] * scale);
291122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 2] = (GLshort) (rgba[i][BCOMP] * scale);
292122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 3] = (GLshort) (rgba[i][ACOMP] * scale);
293122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               }
294122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            }
295122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            else {
296122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               /* accumulate */
297122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               for (i = 0; i < width; i++) {
298122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 0] += (GLshort) (rgba[i][RCOMP] * scale);
299122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 1] += (GLshort) (rgba[i][GCOMP] * scale);
300122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 2] += (GLshort) (rgba[i][BCOMP] * scale);
301122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  acc[i * 4 + 3] += (GLshort) (rgba[i][ACOMP] * scale);
302122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               }
303122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            }
304122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
305122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            colorMap += colorRowStride;
306122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            accMap += accRowStride;
307122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         }
308122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
309122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         free(rgba);
310122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
311122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      else {
312122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
313122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
314122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
315122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   else {
316122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      /* other types someday? */
317122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
318122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
319122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.UnmapRenderbuffer(ctx, accRb);
320122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.UnmapRenderbuffer(ctx, colorRb);
321122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul}
322122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
323122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
324122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul/**
325122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * ColorBuffer = Accum * value
326122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul */
327122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulstatic void
328122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulaccum_return(struct gl_context *ctx, GLfloat value,
329122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul             GLint xpos, GLint ypos, GLint width, GLint height)
330122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul{
331122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   struct gl_framebuffer *fb = ctx->DrawBuffer;
332122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   struct gl_renderbuffer *accRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer;
333122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLubyte *accMap, *colorMap;
334122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLint accRowStride, colorRowStride;
335122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLuint buffer;
336122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
337122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   /* Map accum buffer */
338122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.MapRenderbuffer(ctx, accRb, xpos, ypos, width, height,
339122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               GL_MAP_READ_BIT,
340122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                               &accMap, &accRowStride);
341122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!accMap) {
342122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
343122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
344122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
345122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
346122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   /* Loop over destination buffers */
347122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) {
348122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      struct gl_renderbuffer *colorRb = fb->_ColorDrawBuffers[buffer];
349122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      const GLboolean masking = (!ctx->Color.ColorMask[buffer][RCOMP] ||
350122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                                 !ctx->Color.ColorMask[buffer][GCOMP] ||
351122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                                 !ctx->Color.ColorMask[buffer][BCOMP] ||
352122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                                 !ctx->Color.ColorMask[buffer][ACOMP]);
353122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      GLbitfield mappingFlags = GL_MAP_WRITE_BIT;
354122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
355122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (masking)
356122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         mappingFlags |= GL_MAP_READ_BIT;
357122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
358122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      /* Map color buffer */
359122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height,
360122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                                  mappingFlags, &colorMap, &colorRowStride);
361122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (!colorMap) {
362122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
363122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         continue;
364122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
365122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
3668b47b6bc32b595ee1a37cde279d44a6ac84403c0Mark Mueller      if (accRb->Format == MESA_FORMAT_RGBA_SNORM16) {
367122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         const GLfloat scale = value / 32767.0f;
368122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         GLint i, j;
369122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         GLfloat (*rgba)[4], (*dest)[4];
370122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
3712b7a972e3f36bfcdc6fbe2b59d7ffdcde49c9405Matt Turner         rgba = malloc(width * 4 * sizeof(GLfloat));
3722b7a972e3f36bfcdc6fbe2b59d7ffdcde49c9405Matt Turner         dest = malloc(width * 4 * sizeof(GLfloat));
373122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
374122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         if (rgba && dest) {
375122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            for (j = 0; j < height; j++) {
376122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               GLshort *acc = (GLshort *) accMap;
377122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
378122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               for (i = 0; i < width; i++) {
379122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  rgba[i][0] = acc[i * 4 + 0] * scale;
380122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  rgba[i][1] = acc[i * 4 + 1] * scale;
381122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  rgba[i][2] = acc[i * 4 + 2] * scale;
382122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  rgba[i][3] = acc[i * 4 + 3] * scale;
383122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               }
384122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
385122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               if (masking) {
386122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
387122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  /* get existing colors from dest buffer */
388122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  _mesa_unpack_rgba_row(colorRb->Format, width, colorMap, dest);
389122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
390122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  /* use the dest colors where mask[channel] = 0 */
391122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  if (ctx->Color.ColorMask[buffer][RCOMP] == 0) {
392122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                     for (i = 0; i < width; i++)
393122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                        rgba[i][RCOMP] = dest[i][RCOMP];
394122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  }
395122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  if (ctx->Color.ColorMask[buffer][GCOMP] == 0) {
396122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                     for (i = 0; i < width; i++)
397122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                        rgba[i][GCOMP] = dest[i][GCOMP];
398122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  }
399122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  if (ctx->Color.ColorMask[buffer][BCOMP] == 0) {
400122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                     for (i = 0; i < width; i++)
401122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                        rgba[i][BCOMP] = dest[i][BCOMP];
402122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  }
403122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  if (ctx->Color.ColorMask[buffer][ACOMP] == 0) {
404122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                     for (i = 0; i < width; i++)
405122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                        rgba[i][ACOMP] = dest[i][ACOMP];
406122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                  }
407122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               }
408122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
409122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               _mesa_pack_float_rgba_row(colorRb->Format, width,
410122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul                                         (const GLfloat (*)[4]) rgba, colorMap);
411122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
412122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               accMap += accRowStride;
413122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul               colorMap += colorRowStride;
414122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            }
415122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         }
416122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         else {
417122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
418122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         }
419122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         free(rgba);
420122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         free(dest);
421122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
422122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      else {
423122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         /* other types someday? */
424122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
425122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
426122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      ctx->Driver.UnmapRenderbuffer(ctx, colorRb);
427122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
428122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
429122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ctx->Driver.UnmapRenderbuffer(ctx, accRb);
430122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul}
431122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
432122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
433122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
434122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul/**
435122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * Software fallback for glAccum.  A hardware driver that supports
436122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * signed 16-bit color channels could implement hardware accumulation
437122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul * operations, but no driver does so at this time.
438122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul */
439122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paulvoid
440122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul_mesa_accum(struct gl_context *ctx, GLenum op, GLfloat value)
441122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul{
442122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   GLint xpos, ypos, width, height;
443122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
444122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer) {
445122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_warning(ctx, "Calling glAccum() without an accumulation buffer");
446122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
447122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
448122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
449122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   if (!_mesa_check_conditional_render(ctx))
450122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      return;
451122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
452122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   xpos = ctx->DrawBuffer->_Xmin;
453122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   ypos = ctx->DrawBuffer->_Ymin;
454122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   width =  ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
455122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
456122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul
457122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   switch (op) {
458122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   case GL_ADD:
459122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (value != 0.0F) {
460122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         accum_scale_or_bias(ctx, value, xpos, ypos, width, height, GL_TRUE);
461122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
462122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      break;
463122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   case GL_MULT:
464122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (value != 1.0F) {
465122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         accum_scale_or_bias(ctx, value, xpos, ypos, width, height, GL_FALSE);
466122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
467122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      break;
468122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   case GL_ACCUM:
469122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      if (value != 0.0F) {
470122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul         accum_or_load(ctx, value, xpos, ypos, width, height, GL_FALSE);
471122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      }
472122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      break;
473122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   case GL_LOAD:
474122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      accum_or_load(ctx, value, xpos, ypos, width, height, GL_TRUE);
475122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      break;
476122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   case GL_RETURN:
477122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      accum_return(ctx, value, xpos, ypos, width, height);
478122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      break;
479122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   default:
480122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      _mesa_problem(ctx, "invalid mode in _mesa_accum()");
481122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul      break;
482122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul   }
483122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul}
4848fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul
4858fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul
4868fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paulvoid
4878fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul_mesa_init_accum( struct gl_context *ctx )
4888fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul{
4898fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul   /* Accumulate buffer group */
4908fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul   ASSIGN_4V( ctx->Accum.ClearColor, 0.0, 0.0, 0.0, 0.0 );
4918fe6755ed52acfb88a7a787c3406b64fcdd80e6eBrian Paul}
492