Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  7.1
4
 *
5
 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
 
26
/**
27
 * \file clear.c
28
 * glClearColor, glClearIndex, glClear() functions.
29
 */
30
 
31
 
32
 
33
#include "glheader.h"
34
#include "clear.h"
35
#include "context.h"
36
#include "colormac.h"
37
#include "enums.h"
38
#include "macros.h"
39
#include "state.h"
40
 
41
 
42
 
43
#if _HAVE_FULL_GL
44
void GLAPIENTRY
45
_mesa_ClearIndex( GLfloat c )
46
{
47
   GET_CURRENT_CONTEXT(ctx);
48
   ASSERT_OUTSIDE_BEGIN_END(ctx);
49
 
50
   if (ctx->Color.ClearIndex == (GLuint) c)
51
      return;
52
 
53
   FLUSH_VERTICES(ctx, _NEW_COLOR);
54
   ctx->Color.ClearIndex = (GLuint) c;
55
}
56
#endif
57
 
58
 
59
/**
60
 * Specify the clear values for the color buffers.
61
 *
62
 * \param red red color component.
63
 * \param green green color component.
64
 * \param blue blue color component.
65
 * \param alpha alpha component.
66
 *
67
 * \sa glClearColor().
68
 *
69
 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor.  On a
70
 * change, flushes the vertices and notifies the driver via the
71
 * dd_function_table::ClearColor callback.
72
 */
73
void GLAPIENTRY
74
_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
75
{
76
   GLfloat tmp[4];
77
   GET_CURRENT_CONTEXT(ctx);
78
   ASSERT_OUTSIDE_BEGIN_END(ctx);
79
 
80
   tmp[0] = CLAMP(red,   0.0F, 1.0F);
81
   tmp[1] = CLAMP(green, 0.0F, 1.0F);
82
   tmp[2] = CLAMP(blue,  0.0F, 1.0F);
83
   tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
84
 
85
   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
86
      return; /* no change */
87
 
88
   FLUSH_VERTICES(ctx, _NEW_COLOR);
89
   COPY_4V(ctx->Color.ClearColor, tmp);
90
 
91
   if (ctx->Driver.ClearColor) {
92
      /* it's OK to call glClearColor in CI mode but it should be a NOP */
93
      (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
94
   }
95
}
96
 
97
 
98
/**
99
 * GL_EXT_texture_integer
100
 */
101
void GLAPIENTRY
102
_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
103
{
104
   GLfloat tmp[4];
105
   GET_CURRENT_CONTEXT(ctx);
106
   ASSERT_OUTSIDE_BEGIN_END(ctx);
107
 
108
   tmp[0] = (GLfloat) r;
109
   tmp[1] = (GLfloat) g;
110
   tmp[2] = (GLfloat) b;
111
   tmp[3] = (GLfloat) a;
112
 
113
   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
114
      return; /* no change */
115
 
116
   FLUSH_VERTICES(ctx, _NEW_COLOR);
117
 
118
   /* XXX we should eventually have a float/int/uint union for
119
    * the ctx->Color.ClearColor state.
120
    */
121
   COPY_4V(ctx->Color.ClearColor, tmp);
122
 
123
   if (ctx->Driver.ClearColor) {
124
      ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
125
   }
126
}
127
 
128
 
129
/**
130
 * GL_EXT_texture_integer
131
 */
132
void GLAPIENTRY
133
_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
134
{
135
   GLfloat tmp[4];
136
   GET_CURRENT_CONTEXT(ctx);
137
   ASSERT_OUTSIDE_BEGIN_END(ctx);
138
 
139
   tmp[0] = (GLfloat) r;
140
   tmp[1] = (GLfloat) g;
141
   tmp[2] = (GLfloat) b;
142
   tmp[3] = (GLfloat) a;
143
 
144
   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
145
      return; /* no change */
146
 
147
   FLUSH_VERTICES(ctx, _NEW_COLOR);
148
 
149
   /* XXX we should eventually have a float/int/uint union for
150
    * the ctx->Color.ClearColor state.
151
    */
152
   COPY_4V(ctx->Color.ClearColor, tmp);
153
 
154
   if (ctx->Driver.ClearColor) {
155
      ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
156
   }
157
}
158
 
159
 
160
/**
161
 * Clear buffers.
162
 *
163
 * \param mask bit-mask indicating the buffers to be cleared.
164
 *
165
 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
166
 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
167
 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
168
 * to clear the buffers, via the dd_function_table::Clear callback.
169
 */
170
void GLAPIENTRY
171
_mesa_Clear( GLbitfield mask )
172
{
173
   GET_CURRENT_CONTEXT(ctx);
174
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
175
 
176
   FLUSH_CURRENT(ctx, 0);
177
 
178
   if (MESA_VERBOSE & VERBOSE_API)
179
      _mesa_debug(ctx, "glClear 0x%x\n", mask);
180
 
181
   if (mask & ~(GL_COLOR_BUFFER_BIT |
182
                GL_DEPTH_BUFFER_BIT |
183
                GL_STENCIL_BUFFER_BIT |
184
                GL_ACCUM_BUFFER_BIT)) {
185
      /* invalid bit set */
186
      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
187
      return;
188
   }
189
 
190
   if (ctx->NewState) {
191
      _mesa_update_state( ctx );	/* update _Xmin, etc */
192
   }
193
 
194
   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
195
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
196
                  "glClear(incomplete framebuffer)");
197
      return;
198
   }
199
 
200
   if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
201
       ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
202
       ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
203
      return;
204
 
205
   if (ctx->RenderMode == GL_RENDER) {
206
      GLbitfield bufferMask;
207
 
208
      /* don't clear depth buffer if depth writing disabled */
209
      if (!ctx->Depth.Mask)
210
         mask &= ~GL_DEPTH_BUFFER_BIT;
211
 
212
      /* Build the bitmask to send to device driver's Clear function.
213
       * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
214
       * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
215
       * BUFFER_BIT_COLORn flags.
216
       */
217
      bufferMask = 0;
218
      if (mask & GL_COLOR_BUFFER_BIT) {
219
         GLuint i;
220
         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
221
            bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
222
         }
223
      }
224
 
225
      if ((mask & GL_DEPTH_BUFFER_BIT)
226
          && ctx->DrawBuffer->Visual.haveDepthBuffer) {
227
         bufferMask |= BUFFER_BIT_DEPTH;
228
      }
229
 
230
      if ((mask & GL_STENCIL_BUFFER_BIT)
231
          && ctx->DrawBuffer->Visual.haveStencilBuffer) {
232
         bufferMask |= BUFFER_BIT_STENCIL;
233
      }
234
 
235
      if ((mask & GL_ACCUM_BUFFER_BIT)
236
          && ctx->DrawBuffer->Visual.haveAccumBuffer) {
237
         bufferMask |= BUFFER_BIT_ACCUM;
238
      }
239
 
240
      ASSERT(ctx->Driver.Clear);
241
      ctx->Driver.Clear(ctx, bufferMask);
242
   }
243
}
244
 
245
 
246
/** Returned by make_color_buffer_mask() for errors */
247
#define INVALID_MASK ~0x0
248
 
249
 
250
/**
251
 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
252
 * BUFFER_BIT_x values.
253
 * Return INVALID_MASK if the drawbuffer value is invalid.
254
 */
255
static GLbitfield
256
make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
257
{
258
   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
259
   GLbitfield mask = 0x0;
260
 
261
   switch (drawbuffer) {
262
   case GL_FRONT:
263
      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
264
         mask |= BUFFER_BIT_FRONT_LEFT;
265
      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
266
         mask |= BUFFER_BIT_FRONT_RIGHT;
267
      break;
268
   case GL_BACK:
269
      if (att[BUFFER_BACK_LEFT].Renderbuffer)
270
         mask |= BUFFER_BIT_BACK_LEFT;
271
      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
272
         mask |= BUFFER_BIT_BACK_RIGHT;
273
      break;
274
   case GL_LEFT:
275
      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
276
         mask |= BUFFER_BIT_FRONT_LEFT;
277
      if (att[BUFFER_BACK_LEFT].Renderbuffer)
278
         mask |= BUFFER_BIT_BACK_LEFT;
279
      break;
280
   case GL_RIGHT:
281
      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
282
         mask |= BUFFER_BIT_FRONT_RIGHT;
283
      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
284
         mask |= BUFFER_BIT_BACK_RIGHT;
285
      break;
286
   case GL_FRONT_AND_BACK:
287
      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
288
         mask |= BUFFER_BIT_FRONT_LEFT;
289
      if (att[BUFFER_BACK_LEFT].Renderbuffer)
290
         mask |= BUFFER_BIT_BACK_LEFT;
291
      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
292
         mask |= BUFFER_BIT_FRONT_RIGHT;
293
      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
294
         mask |= BUFFER_BIT_BACK_RIGHT;
295
      break;
296
   default:
297
      if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
298
         mask = INVALID_MASK;
299
      }
300
      else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) {
301
         mask |= (BUFFER_BIT_COLOR0 << drawbuffer);
302
      }
303
   }
304
 
305
   return mask;
306
}
307
 
308
 
309
 
310
/**
311
 * New in GL 3.0
312
 * Clear signed integer color buffer or stencil buffer (not depth).
313
 */
314
void GLAPIENTRY
315
_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
316
{
317
   GET_CURRENT_CONTEXT(ctx);
318
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
319
 
320
   FLUSH_CURRENT(ctx, 0);
321
 
322
   if (ctx->NewState) {
323
      _mesa_update_state( ctx );
324
   }
325
 
326
   switch (buffer) {
327
   case GL_STENCIL:
328
      if (drawbuffer != 0) {
329
         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
330
                     drawbuffer);
331
         return;
332
      }
333
      else {
334
         /* Save current stencil clear value, set to 'value', do the
335
          * stencil clear and restore the clear value.
336
          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
337
          * hook instead.
338
          */
339
         const GLuint clearSave = ctx->Stencil.Clear;
340
         ctx->Stencil.Clear = *value;
341
         if (ctx->Driver.ClearStencil)
342
            ctx->Driver.ClearStencil(ctx, *value);
343
         ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
344
         ctx->Stencil.Clear = clearSave;
345
         if (ctx->Driver.ClearStencil)
346
            ctx->Driver.ClearStencil(ctx, clearSave);
347
      }
348
      break;
349
   case GL_COLOR:
350
      {
351
         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
352
         if (mask == INVALID_MASK) {
353
            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
354
                        drawbuffer);
355
            return;
356
         }
357
         else if (mask) {
358
            /* XXX note: we're putting the integer clear values into the
359
             * floating point state var.  This will not always work.  We'll
360
             * need a new ctx->Driver.ClearBuffer() hook....
361
             */
362
            GLclampf clearSave[4];
363
            /* save color */
364
            COPY_4V(clearSave, ctx->Color.ClearColor);
365
            /* set color */
366
            COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
367
            if (ctx->Driver.ClearColor)
368
               ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
369
            /* clear buffer(s) */
370
            ctx->Driver.Clear(ctx, mask);
371
            /* restore color */
372
            COPY_4V(ctx->Color.ClearColor, clearSave);
373
            if (ctx->Driver.ClearColor)
374
               ctx->Driver.ClearColor(ctx, clearSave);
375
         }
376
      }
377
      break;
378
   default:
379
      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
380
                  _mesa_lookup_enum_by_nr(buffer));
381
      return;
382
   }
383
}
384
 
385
 
386
/**
387
 * New in GL 3.0
388
 * Clear unsigned integer color buffer (not depth, not stencil).
389
 */
390
void GLAPIENTRY
391
_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
392
{
393
   GET_CURRENT_CONTEXT(ctx);
394
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
395
 
396
   FLUSH_CURRENT(ctx, 0);
397
 
398
   if (ctx->NewState) {
399
      _mesa_update_state( ctx );
400
   }
401
 
402
   switch (buffer) {
403
   case GL_COLOR:
404
      {
405
         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
406
         if (mask == INVALID_MASK) {
407
            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
408
                        drawbuffer);
409
            return;
410
         }
411
         else if (mask) {
412
            /* XXX note: we're putting the uint clear values into the
413
             * floating point state var.  This will not always work.  We'll
414
             * need a new ctx->Driver.ClearBuffer() hook....
415
             */
416
            GLclampf clearSave[4];
417
            /* save color */
418
            COPY_4V(clearSave, ctx->Color.ClearColor);
419
            /* set color */
420
            COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
421
            if (ctx->Driver.ClearColor)
422
               ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
423
            /* clear buffer(s) */
424
            ctx->Driver.Clear(ctx, mask);
425
            /* restore color */
426
            COPY_4V(ctx->Color.ClearColor, clearSave);
427
            if (ctx->Driver.ClearColor)
428
               ctx->Driver.ClearColor(ctx, clearSave);
429
         }
430
      }
431
      break;
432
   default:
433
      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
434
                  _mesa_lookup_enum_by_nr(buffer));
435
      return;
436
   }
437
}
438
 
439
 
440
/**
441
 * New in GL 3.0
442
 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
443
 */
444
void GLAPIENTRY
445
_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
446
{
447
   GET_CURRENT_CONTEXT(ctx);
448
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
449
 
450
   FLUSH_CURRENT(ctx, 0);
451
 
452
   if (ctx->NewState) {
453
      _mesa_update_state( ctx );
454
   }
455
 
456
   switch (buffer) {
457
   case GL_DEPTH:
458
      if (drawbuffer != 0) {
459
         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
460
                     drawbuffer);
461
         return;
462
      }
463
      else {
464
         /* Save current depth clear value, set to 'value', do the
465
          * depth clear and restore the clear value.
466
          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
467
          * hook instead.
468
          */
469
         const GLclampd clearSave = ctx->Depth.Clear;
470
         ctx->Depth.Clear = *value;
471
         if (ctx->Driver.ClearDepth)
472
            ctx->Driver.ClearDepth(ctx, *value);
473
         ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
474
         ctx->Depth.Clear = clearSave;
475
         if (ctx->Driver.ClearDepth)
476
            ctx->Driver.ClearDepth(ctx, clearSave);
477
      }
478
      /* clear depth buffer to value */
479
      break;
480
   case GL_COLOR:
481
      {
482
         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
483
         if (mask == INVALID_MASK) {
484
            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
485
                        drawbuffer);
486
            return;
487
         }
488
         else if (mask) {
489
            GLclampf clearSave[4];
490
            /* save color */
491
            COPY_4V(clearSave, ctx->Color.ClearColor);
492
            /* set color */
493
            COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
494
            if (ctx->Driver.ClearColor)
495
               ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
496
            /* clear buffer(s) */
497
            ctx->Driver.Clear(ctx, mask);
498
            /* restore color */
499
            COPY_4V(ctx->Color.ClearColor, clearSave);
500
            if (ctx->Driver.ClearColor)
501
               ctx->Driver.ClearColor(ctx, clearSave);
502
         }
503
      }
504
      break;
505
   default:
506
      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
507
                  _mesa_lookup_enum_by_nr(buffer));
508
      return;
509
   }
510
}
511
 
512
 
513
/**
514
 * New in GL 3.0
515
 * Clear depth/stencil buffer only.
516
 */
517
void GLAPIENTRY
518
_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
519
                    GLfloat depth, GLint stencil)
520
{
521
   GET_CURRENT_CONTEXT(ctx);
522
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
523
 
524
   FLUSH_CURRENT(ctx, 0);
525
 
526
   if (buffer != GL_DEPTH_STENCIL) {
527
      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
528
                  _mesa_lookup_enum_by_nr(buffer));
529
      return;
530
   }
531
 
532
   if (drawbuffer != 0) {
533
      _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
534
                  drawbuffer);
535
      return;
536
   }
537
 
538
   if (ctx->NewState) {
539
      _mesa_update_state( ctx );
540
   }
541
 
542
   {
543
      /* save current clear values */
544
      const GLclampd clearDepthSave = ctx->Depth.Clear;
545
      const GLuint clearStencilSave = ctx->Stencil.Clear;
546
 
547
      /* set new clear values */
548
      ctx->Depth.Clear = depth;
549
      ctx->Stencil.Clear = stencil;
550
      if (ctx->Driver.ClearDepth)
551
         ctx->Driver.ClearDepth(ctx, depth);
552
      if (ctx->Driver.ClearStencil)
553
         ctx->Driver.ClearStencil(ctx, stencil);
554
 
555
      /* clear buffers */
556
      ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
557
 
558
      /* restore */
559
      ctx->Depth.Clear = clearDepthSave;
560
      ctx->Stencil.Clear = clearStencilSave;
561
      if (ctx->Driver.ClearDepth)
562
         ctx->Driver.ClearDepth(ctx, clearDepthSave);
563
      if (ctx->Driver.ClearStencil)
564
         ctx->Driver.ClearStencil(ctx, clearStencilSave);
565
   }
566
}