1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2008  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 "main/glheader.h"
26848b8605Smrg#include "main/accum.h"
27848b8605Smrg#include "main/condrender.h"
28848b8605Smrg#include "main/format_pack.h"
29848b8605Smrg#include "main/macros.h"
30848b8605Smrg#include "main/imports.h"
31848b8605Smrg#include "main/mtypes.h"
32848b8605Smrg
33848b8605Smrg#include "s_context.h"
34848b8605Smrg#include "s_depth.h"
35848b8605Smrg#include "s_stencil.h"
36848b8605Smrg
37848b8605Smrg
38848b8605Smrg
39848b8605Smrg/**
40848b8605Smrg * Clear an rgba color buffer with masking if needed.
41848b8605Smrg */
42848b8605Smrgstatic void
43848b8605Smrgclear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
44848b8605Smrg                  const GLubyte colorMask[4])
45848b8605Smrg{
46848b8605Smrg   const GLint x = ctx->DrawBuffer->_Xmin;
47848b8605Smrg   const GLint y = ctx->DrawBuffer->_Ymin;
48848b8605Smrg   const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
49848b8605Smrg   const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
50848b8605Smrg   const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
51848b8605Smrg   const GLboolean doMasking = (colorMask[0] == 0 ||
52848b8605Smrg                                colorMask[1] == 0 ||
53848b8605Smrg                                colorMask[2] == 0 ||
54848b8605Smrg                                colorMask[3] == 0);
55848b8605Smrg   const GLfloat (*clearColor)[4] =
56848b8605Smrg      (const GLfloat (*)[4]) ctx->Color.ClearColor.f;
57848b8605Smrg   GLbitfield mapMode = GL_MAP_WRITE_BIT;
58848b8605Smrg   GLubyte *map;
59848b8605Smrg   GLint rowStride;
60848b8605Smrg   GLint i, j;
61848b8605Smrg
62848b8605Smrg   if (doMasking) {
63848b8605Smrg      /* we'll need to read buffer values too */
64848b8605Smrg      mapMode |= GL_MAP_READ_BIT;
65848b8605Smrg   }
66848b8605Smrg
67848b8605Smrg   /* map dest buffer */
68848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
69b8e80941Smrg                               mapMode, &map, &rowStride,
70b8e80941Smrg                               ctx->DrawBuffer->FlipY);
71848b8605Smrg   if (!map) {
72848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
73848b8605Smrg      return;
74848b8605Smrg   }
75848b8605Smrg
76848b8605Smrg   /* for 1, 2, 4-byte clearing */
77848b8605Smrg#define SIMPLE_TYPE_CLEAR(TYPE)                                         \
78848b8605Smrg   do {                                                                 \
79848b8605Smrg      TYPE pixel, pixelMask;                                            \
80848b8605Smrg      _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel);     \
81848b8605Smrg      if (doMasking) {                                                  \
82848b8605Smrg         _mesa_pack_colormask(rb->Format, colorMask, &pixelMask);       \
83848b8605Smrg         pixel &= pixelMask;                                            \
84848b8605Smrg         pixelMask = ~pixelMask;                                        \
85848b8605Smrg      }                                                                 \
86848b8605Smrg      for (i = 0; i < height; i++) {                                    \
87848b8605Smrg         TYPE *row = (TYPE *) map;                                      \
88848b8605Smrg         if (doMasking) {                                               \
89848b8605Smrg            for (j = 0; j < width; j++) {                               \
90848b8605Smrg               row[j] = (row[j] & pixelMask) | pixel;                   \
91848b8605Smrg            }                                                           \
92848b8605Smrg         }                                                              \
93848b8605Smrg         else {                                                         \
94848b8605Smrg            for (j = 0; j < width; j++) {                               \
95848b8605Smrg               row[j] = pixel;                                          \
96848b8605Smrg            }                                                           \
97848b8605Smrg         }                                                              \
98848b8605Smrg         map += rowStride;                                              \
99848b8605Smrg      }                                                                 \
100848b8605Smrg   } while (0)
101848b8605Smrg
102848b8605Smrg
103848b8605Smrg   /* for 3, 6, 8, 12, 16-byte clearing */
104848b8605Smrg#define MULTI_WORD_CLEAR(TYPE, N)                                       \
105848b8605Smrg   do {                                                                 \
106848b8605Smrg      TYPE pixel[N], pixelMask[N];                                      \
107848b8605Smrg      GLuint k;                                                         \
108848b8605Smrg      _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel);      \
109848b8605Smrg      if (doMasking) {                                                  \
110848b8605Smrg         _mesa_pack_colormask(rb->Format, colorMask, pixelMask);        \
111848b8605Smrg         for (k = 0; k < N; k++) {                                      \
112848b8605Smrg            pixel[k] &= pixelMask[k];                                   \
113848b8605Smrg            pixelMask[k] = ~pixelMask[k];                               \
114848b8605Smrg         }                                                              \
115848b8605Smrg      }                                                                 \
116848b8605Smrg      for (i = 0; i < height; i++) {                                    \
117848b8605Smrg         TYPE *row = (TYPE *) map;                                      \
118848b8605Smrg         if (doMasking) {                                               \
119848b8605Smrg            for (j = 0; j < width; j++) {                               \
120848b8605Smrg               for (k = 0; k < N; k++) {                                \
121848b8605Smrg                  row[j * N + k] =                                      \
122848b8605Smrg                     (row[j * N + k] & pixelMask[k]) | pixel[k];        \
123848b8605Smrg               }                                                        \
124848b8605Smrg            }                                                           \
125848b8605Smrg         }                                                              \
126848b8605Smrg         else {                                                         \
127848b8605Smrg            for (j = 0; j < width; j++) {                               \
128848b8605Smrg               for (k = 0; k < N; k++) {                                \
129848b8605Smrg                  row[j * N + k] = pixel[k];                            \
130848b8605Smrg               }                                                        \
131848b8605Smrg            }                                                           \
132848b8605Smrg         }                                                              \
133848b8605Smrg         map += rowStride;                                              \
134848b8605Smrg      }                                                                 \
135848b8605Smrg   } while(0)
136848b8605Smrg
137848b8605Smrg   switch (pixelSize) {
138848b8605Smrg   case 1:
139848b8605Smrg      SIMPLE_TYPE_CLEAR(GLubyte);
140848b8605Smrg      break;
141848b8605Smrg   case 2:
142848b8605Smrg      SIMPLE_TYPE_CLEAR(GLushort);
143848b8605Smrg      break;
144848b8605Smrg   case 3:
145848b8605Smrg      MULTI_WORD_CLEAR(GLubyte, 3);
146848b8605Smrg      break;
147848b8605Smrg   case 4:
148848b8605Smrg      SIMPLE_TYPE_CLEAR(GLuint);
149848b8605Smrg      break;
150848b8605Smrg   case 6:
151848b8605Smrg      MULTI_WORD_CLEAR(GLushort, 3);
152848b8605Smrg      break;
153848b8605Smrg   case 8:
154848b8605Smrg      MULTI_WORD_CLEAR(GLuint, 2);
155848b8605Smrg      break;
156848b8605Smrg   case 12:
157848b8605Smrg      MULTI_WORD_CLEAR(GLuint, 3);
158848b8605Smrg      break;
159848b8605Smrg   case 16:
160848b8605Smrg      MULTI_WORD_CLEAR(GLuint, 4);
161848b8605Smrg      break;
162848b8605Smrg   default:
163848b8605Smrg      _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
164848b8605Smrg   }
165848b8605Smrg
166848b8605Smrg   /* unmap buffer */
167848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
168848b8605Smrg}
169848b8605Smrg
170848b8605Smrg
171848b8605Smrg/**
172848b8605Smrg * Clear the front/back/left/right/aux color buffers.
173848b8605Smrg * This function is usually only called if the device driver can't
174848b8605Smrg * clear its own color buffers for some reason (such as with masking).
175848b8605Smrg */
176848b8605Smrgstatic void
177848b8605Smrgclear_color_buffers(struct gl_context *ctx)
178848b8605Smrg{
179848b8605Smrg   GLuint buf;
180848b8605Smrg
181848b8605Smrg   for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
182848b8605Smrg      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
183848b8605Smrg
184848b8605Smrg      /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
185848b8605Smrg       * the framebuffer can be complete with some attachments be missing.  In
186848b8605Smrg       * this case the _ColorDrawBuffers pointer will be NULL.
187848b8605Smrg       */
188848b8605Smrg      if (rb == NULL)
189848b8605Smrg	 continue;
190848b8605Smrg
191b8e80941Smrg      const GLubyte colormask[4] = {
192b8e80941Smrg         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
193b8e80941Smrg         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
194b8e80941Smrg         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
195b8e80941Smrg         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
196b8e80941Smrg      };
197b8e80941Smrg      clear_rgba_buffer(ctx, rb, colormask);
198848b8605Smrg   }
199848b8605Smrg}
200848b8605Smrg
201848b8605Smrg
202848b8605Smrg/**
203848b8605Smrg * Called via the device driver's ctx->Driver.Clear() function if the
204848b8605Smrg * device driver can't clear one or more of the buffers itself.
205848b8605Smrg * \param buffers  bitfield of BUFFER_BIT_* values indicating which
206848b8605Smrg *                 renderbuffers are to be cleared.
207848b8605Smrg * \param all  if GL_TRUE, clear whole buffer, else clear specified region.
208848b8605Smrg */
209848b8605Smrgvoid
210848b8605Smrg_swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
211848b8605Smrg{
212848b8605Smrg   const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL;
213848b8605Smrg
214848b8605Smrg#ifdef DEBUG_FOO
215848b8605Smrg   {
216848b8605Smrg      const GLbitfield legalBits =
217848b8605Smrg         BUFFER_BIT_FRONT_LEFT |
218848b8605Smrg	 BUFFER_BIT_FRONT_RIGHT |
219848b8605Smrg	 BUFFER_BIT_BACK_LEFT |
220848b8605Smrg	 BUFFER_BIT_BACK_RIGHT |
221848b8605Smrg	 BUFFER_BIT_DEPTH |
222848b8605Smrg	 BUFFER_BIT_STENCIL |
223848b8605Smrg	 BUFFER_BIT_ACCUM |
224848b8605Smrg         BUFFER_BIT_AUX0;
225848b8605Smrg      assert((buffers & (~legalBits)) == 0);
226848b8605Smrg   }
227848b8605Smrg#endif
228848b8605Smrg
229848b8605Smrg   if (!_mesa_check_conditional_render(ctx))
230848b8605Smrg      return; /* don't clear */
231848b8605Smrg
232848b8605Smrg   if (SWRAST_CONTEXT(ctx)->NewState)
233848b8605Smrg      _swrast_validate_derived(ctx);
234848b8605Smrg
235848b8605Smrg   if ((buffers & BUFFER_BITS_COLOR)
236848b8605Smrg       && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
237848b8605Smrg      clear_color_buffers(ctx);
238848b8605Smrg   }
239848b8605Smrg
240848b8605Smrg   if (buffers & BUFFER_BIT_ACCUM) {
241848b8605Smrg      _mesa_clear_accum_buffer(ctx);
242848b8605Smrg   }
243848b8605Smrg
244848b8605Smrg   if (buffers & BUFFER_DS) {
245848b8605Smrg      struct gl_renderbuffer *depthRb =
246848b8605Smrg         ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
247848b8605Smrg      struct gl_renderbuffer *stencilRb =
248848b8605Smrg         ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
249848b8605Smrg
250848b8605Smrg      if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) {
251848b8605Smrg         /* clear depth and stencil together */
252848b8605Smrg         _swrast_clear_depth_stencil_buffer(ctx);
253848b8605Smrg      }
254848b8605Smrg      else {
255848b8605Smrg         /* clear depth, stencil separately */
256848b8605Smrg         if (buffers & BUFFER_BIT_DEPTH) {
257848b8605Smrg            _swrast_clear_depth_buffer(ctx);
258848b8605Smrg         }
259848b8605Smrg         if (buffers & BUFFER_BIT_STENCIL) {
260848b8605Smrg            _swrast_clear_stencil_buffer(ctx);
261848b8605Smrg         }
262848b8605Smrg      }
263848b8605Smrg   }
264848b8605Smrg}
265