Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
#include "main/glheader.h"
26
#include "main/accum.h"
27
#include "main/condrender.h"
28
#include "main/format_pack.h"
29
#include "main/macros.h"
30
#include "main/imports.h"
31
#include "main/mtypes.h"
32
 
33
#include "s_context.h"
34
#include "s_depth.h"
35
#include "s_stencil.h"
36
 
37
 
38
 
39
/**
40
 * Clear an rgba color buffer with masking if needed.
41
 */
42
static void
43
clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
44
                  const GLubyte colorMask[4])
45
{
46
   const GLint x = ctx->DrawBuffer->_Xmin;
47
   const GLint y = ctx->DrawBuffer->_Ymin;
48
   const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
49
   const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
50
   const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
51
   const GLboolean doMasking = (colorMask[0] == 0 ||
52
                                colorMask[1] == 0 ||
53
                                colorMask[2] == 0 ||
54
                                colorMask[3] == 0);
55
   const GLfloat (*clearColor)[4] =
56
      (const GLfloat (*)[4]) ctx->Color.ClearColor.f;
57
   GLbitfield mapMode = GL_MAP_WRITE_BIT;
58
   GLubyte *map;
59
   GLint rowStride;
60
   GLint i, j;
61
 
62
   if (doMasking) {
63
      /* we'll need to read buffer values too */
64
      mapMode |= GL_MAP_READ_BIT;
65
   }
66
 
67
   /* map dest buffer */
68
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
69
                               mapMode, &map, &rowStride);
70
   if (!map) {
71
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
72
      return;
73
   }
74
 
75
   /* for 1, 2, 4-byte clearing */
76
#define SIMPLE_TYPE_CLEAR(TYPE)                                         \
77
   do {                                                                 \
78
      TYPE pixel, pixelMask;                                            \
79
      _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel);     \
80
      if (doMasking) {                                                  \
81
         _mesa_pack_colormask(rb->Format, colorMask, &pixelMask);       \
82
         pixel &= pixelMask;                                            \
83
         pixelMask = ~pixelMask;                                        \
84
      }                                                                 \
85
      for (i = 0; i < height; i++) {                                    \
86
         TYPE *row = (TYPE *) map;                                      \
87
         if (doMasking) {                                               \
88
            for (j = 0; j < width; j++) {                               \
89
               row[j] = (row[j] & pixelMask) | pixel;                   \
90
            }                                                           \
91
         }                                                              \
92
         else {                                                         \
93
            for (j = 0; j < width; j++) {                               \
94
               row[j] = pixel;                                          \
95
            }                                                           \
96
         }                                                              \
97
         map += rowStride;                                              \
98
      }                                                                 \
99
   } while (0)
100
 
101
 
102
   /* for 3, 6, 8, 12, 16-byte clearing */
103
#define MULTI_WORD_CLEAR(TYPE, N)                                       \
104
   do {                                                                 \
105
      TYPE pixel[N], pixelMask[N];                                      \
106
      GLuint k;                                                         \
107
      _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel);      \
108
      if (doMasking) {                                                  \
109
         _mesa_pack_colormask(rb->Format, colorMask, pixelMask);        \
110
         for (k = 0; k < N; k++) {                                      \
111
            pixel[k] &= pixelMask[k];                                   \
112
            pixelMask[k] = ~pixelMask[k];                               \
113
         }                                                              \
114
      }                                                                 \
115
      for (i = 0; i < height; i++) {                                    \
116
         TYPE *row = (TYPE *) map;                                      \
117
         if (doMasking) {                                               \
118
            for (j = 0; j < width; j++) {                               \
119
               for (k = 0; k < N; k++) {                                \
120
                  row[j * N + k] =                                      \
121
                     (row[j * N + k] & pixelMask[k]) | pixel[k];        \
122
               }                                                        \
123
            }                                                           \
124
         }                                                              \
125
         else {                                                         \
126
            for (j = 0; j < width; j++) {                               \
127
               for (k = 0; k < N; k++) {                                \
128
                  row[j * N + k] = pixel[k];                            \
129
               }                                                        \
130
            }                                                           \
131
         }                                                              \
132
         map += rowStride;                                              \
133
      }                                                                 \
134
   } while(0)
135
 
136
   switch (pixelSize) {
137
   case 1:
138
      SIMPLE_TYPE_CLEAR(GLubyte);
139
      break;
140
   case 2:
141
      SIMPLE_TYPE_CLEAR(GLushort);
142
      break;
143
   case 3:
144
      MULTI_WORD_CLEAR(GLubyte, 3);
145
      break;
146
   case 4:
147
      SIMPLE_TYPE_CLEAR(GLuint);
148
      break;
149
   case 6:
150
      MULTI_WORD_CLEAR(GLushort, 3);
151
      break;
152
   case 8:
153
      MULTI_WORD_CLEAR(GLuint, 2);
154
      break;
155
   case 12:
156
      MULTI_WORD_CLEAR(GLuint, 3);
157
      break;
158
   case 16:
159
      MULTI_WORD_CLEAR(GLuint, 4);
160
      break;
161
   default:
162
      _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
163
   }
164
 
165
   /* unmap buffer */
166
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
167
}
168
 
169
 
170
/**
171
 * Clear the front/back/left/right/aux color buffers.
172
 * This function is usually only called if the device driver can't
173
 * clear its own color buffers for some reason (such as with masking).
174
 */
175
static void
176
clear_color_buffers(struct gl_context *ctx)
177
{
178
   GLuint buf;
179
 
180
   for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
181
      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
182
 
183
      /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
184
       * the framebuffer can be complete with some attachments be missing.  In
185
       * this case the _ColorDrawBuffers pointer will be NULL.
186
       */
187
      if (rb == NULL)
188
	 continue;
189
 
190
      clear_rgba_buffer(ctx, rb, ctx->Color.ColorMask[buf]);
191
   }
192
}
193
 
194
 
195
/**
196
 * Called via the device driver's ctx->Driver.Clear() function if the
197
 * device driver can't clear one or more of the buffers itself.
198
 * \param buffers  bitfield of BUFFER_BIT_* values indicating which
199
 *                 renderbuffers are to be cleared.
200
 * \param all  if GL_TRUE, clear whole buffer, else clear specified region.
201
 */
202
void
203
_swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
204
{
205
   const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL;
206
 
207
#ifdef DEBUG_FOO
208
   {
209
      const GLbitfield legalBits =
210
         BUFFER_BIT_FRONT_LEFT |
211
	 BUFFER_BIT_FRONT_RIGHT |
212
	 BUFFER_BIT_BACK_LEFT |
213
	 BUFFER_BIT_BACK_RIGHT |
214
	 BUFFER_BIT_DEPTH |
215
	 BUFFER_BIT_STENCIL |
216
	 BUFFER_BIT_ACCUM |
217
         BUFFER_BIT_AUX0;
218
      assert((buffers & (~legalBits)) == 0);
219
   }
220
#endif
221
 
222
   if (!_mesa_check_conditional_render(ctx))
223
      return; /* don't clear */
224
 
225
   if (SWRAST_CONTEXT(ctx)->NewState)
226
      _swrast_validate_derived(ctx);
227
 
228
   if ((buffers & BUFFER_BITS_COLOR)
229
       && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
230
      clear_color_buffers(ctx);
231
   }
232
 
233
   if (buffers & BUFFER_BIT_ACCUM) {
234
      _mesa_clear_accum_buffer(ctx);
235
   }
236
 
237
   if (buffers & BUFFER_DS) {
238
      struct gl_renderbuffer *depthRb =
239
         ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
240
      struct gl_renderbuffer *stencilRb =
241
         ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
242
 
243
      if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) {
244
         /* clear depth and stencil together */
245
         _swrast_clear_depth_stencil_buffer(ctx);
246
      }
247
      else {
248
         /* clear depth, stencil separately */
249
         if (buffers & BUFFER_BIT_DEPTH) {
250
            _swrast_clear_depth_buffer(ctx);
251
         }
252
         if (buffers & BUFFER_BIT_STENCIL) {
253
            _swrast_clear_stencil_buffer(ctx);
254
         }
255
      }
256
   }
257
}