Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: buffers.c,v 1.1 2003-02-28 11:41:58 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
 
27
 
28
#include "glheader.h"
29
#include "imports.h"
30
#include "accum.h"
31
#include "buffers.h"
32
#include "colormac.h"
33
#include "context.h"
34
#include "depth.h"
35
#include "enums.h"
36
#include "macros.h"
37
#include "stencil.h"
38
#include "state.h"
39
#include "mtypes.h"
40
 
41
 
42
 
43
void
44
_mesa_ClearIndex( GLfloat c )
45
{
46
   GET_CURRENT_CONTEXT(ctx);
47
   ASSERT_OUTSIDE_BEGIN_END(ctx);
48
 
49
   if (ctx->Color.ClearIndex == (GLuint) c)
50
      return;
51
 
52
   FLUSH_VERTICES(ctx, _NEW_COLOR);
53
   ctx->Color.ClearIndex = (GLuint) c;
54
 
55
   if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) {
56
      /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
57
      (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
58
   }
59
}
60
 
61
 
62
 
63
void
64
_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
65
{
66
   GLfloat tmp[4];
67
   GET_CURRENT_CONTEXT(ctx);
68
   ASSERT_OUTSIDE_BEGIN_END(ctx);
69
 
70
   tmp[0] = CLAMP(red,   0.0F, 1.0F);
71
   tmp[1] = CLAMP(green, 0.0F, 1.0F);
72
   tmp[2] = CLAMP(blue,  0.0F, 1.0F);
73
   tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
74
 
75
   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
76
      return; /* no change */
77
 
78
   FLUSH_VERTICES(ctx, _NEW_COLOR);
79
   COPY_4V(ctx->Color.ClearColor, tmp);
80
 
81
   if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) {
82
      /* it's OK to call glClearColor in CI mode but it should be a NOP */
83
      (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
84
   }
85
}
86
 
87
 
88
 
89
void
90
_mesa_Clear( GLbitfield mask )
91
{
92
   GET_CURRENT_CONTEXT(ctx);
93
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
94
 
95
   if (MESA_VERBOSE & VERBOSE_API)
96
      _mesa_debug(ctx, "glClear 0x%x\n", mask);
97
 
98
   if (mask & ~(GL_COLOR_BUFFER_BIT |
99
                GL_DEPTH_BUFFER_BIT |
100
                GL_STENCIL_BUFFER_BIT |
101
                GL_ACCUM_BUFFER_BIT)) {
102
      /* invalid bit set */
103
      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(mask)");
104
      return;
105
   }
106
 
107
   if (ctx->NewState) {
108
      _mesa_update_state( ctx );        /* update _Xmin, etc */
109
   }
110
 
111
   if (ctx->RenderMode==GL_RENDER) {
112
      const GLint x = ctx->DrawBuffer->_Xmin;
113
      const GLint y = ctx->DrawBuffer->_Ymin;
114
      const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
115
      const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
116
      GLbitfield ddMask;
117
 
118
      /* don't clear depth buffer if depth writing disabled */
119
      if (!ctx->Depth.Mask)
120
         mask &= ~GL_DEPTH_BUFFER_BIT;
121
 
122
      /* Build bitmask to send to driver Clear function */
123
      ddMask = mask & (GL_DEPTH_BUFFER_BIT |
124
                       GL_STENCIL_BUFFER_BIT |
125
                       GL_ACCUM_BUFFER_BIT);
126
      if (mask & GL_COLOR_BUFFER_BIT) {
127
         ddMask |= ctx->Color._DrawDestMask;
128
      }
129
 
130
      ASSERT(ctx->Driver.Clear);
131
      ctx->Driver.Clear( ctx, ddMask, (GLboolean) !ctx->Scissor.Enabled,
132
                         x, y, width, height );
133
   }
134
}
135
 
136
 
137
void
138
_mesa_DrawBuffer( GLenum mode )
139
{
140
   GET_CURRENT_CONTEXT(ctx);
141
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */
142
 
143
   if (MESA_VERBOSE & VERBOSE_API)
144
      _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(mode));
145
 
146
   /*
147
    * Do error checking and compute the _DrawDestMask bitfield.
148
    */
149
   switch (mode) {
150
      case GL_RIGHT:
151
         if (!ctx->Visual.stereoMode) {
152
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
153
            return;}
154
         if (ctx->Visual.doubleBufferMode)
155
            ctx->Color._DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
156
         else
157
            ctx->Color._DrawDestMask = FRONT_RIGHT_BIT;
158
         break;
159
      case GL_FRONT_RIGHT:
160
         if (!ctx->Visual.stereoMode) {
161
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
162
            return;
163
         }
164
         ctx->Color._DrawDestMask = FRONT_RIGHT_BIT;
165
         break;
166
      case GL_BACK_RIGHT:
167
         if (!ctx->Visual.stereoMode || !ctx->Visual.doubleBufferMode) {
168
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
169
            return;
170
         }
171
         ctx->Color._DrawDestMask = BACK_RIGHT_BIT;
172
         break;
173
      case GL_BACK_LEFT:
174
         if (!ctx->Visual.doubleBufferMode) {
175
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
176
            return;
177
         }
178
         ctx->Color._DrawDestMask = BACK_LEFT_BIT;
179
         break;
180
      case GL_FRONT_AND_BACK:
181
         if (!ctx->Visual.doubleBufferMode) {
182
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
183
            return;
184
         }
185
         if (ctx->Visual.stereoMode)
186
            ctx->Color._DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT
187
                                    | FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
188
         else
189
            ctx->Color._DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
190
         break;
191
      case GL_BACK:
192
         if (!ctx->Visual.doubleBufferMode) {
193
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
194
            return;
195
         }
196
         if (ctx->Visual.stereoMode)
197
            ctx->Color._DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT;
198
         else
199
            ctx->Color._DrawDestMask = BACK_LEFT_BIT;
200
         break;
201
      case GL_LEFT:
202
         /* never an error */
203
         if (ctx->Visual.doubleBufferMode)
204
            ctx->Color._DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
205
         else
206
            ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
207
         break;
208
      case GL_FRONT_LEFT:
209
         /* never an error */
210
         ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
211
         break;
212
      case GL_FRONT:
213
         /* never an error */
214
         if (ctx->Visual.stereoMode)
215
            ctx->Color._DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT;
216
         else
217
            ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
218
         break;
219
      case GL_NONE:
220
         /* never an error */
221
         ctx->Color._DrawDestMask = 0;
222
         break;
223
      case GL_AUX0:
224
         if (ctx->Const.NumAuxBuffers >= 1) {
225
            ctx->Color._DrawDestMask = AUX0_BIT;
226
         }
227
         else {
228
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer(GL_AUX0)" );
229
            return;
230
         }
231
         break;
232
      case GL_AUX1:
233
         if (ctx->Const.NumAuxBuffers >= 2) {
234
            ctx->Color._DrawDestMask = AUX1_BIT;
235
         }
236
         else {
237
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer(GL_AUX1)" );
238
            return;
239
         }
240
         break;
241
      case GL_AUX2:
242
         if (ctx->Const.NumAuxBuffers >= 3) {
243
            ctx->Color._DrawDestMask = AUX2_BIT;
244
         }
245
         else {
246
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer(GL_AUX2)" );
247
            return;
248
         }
249
         break;
250
      case GL_AUX3:
251
         if (ctx->Const.NumAuxBuffers >= 4) {
252
            ctx->Color._DrawDestMask = AUX3_BIT;
253
         }
254
         else {
255
            _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer(GL_AUX3)" );
256
            return;
257
         }
258
         break;
259
      default:
260
         _mesa_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
261
         return;
262
   }
263
 
264
   ctx->Color.DrawBuffer = mode;
265
   ctx->NewState |= _NEW_COLOR;
266
 
267
   /*
268
    * Call device driver function.
269
    */
270
   if (ctx->Driver.DrawBuffer)
271
      (*ctx->Driver.DrawBuffer)(ctx, mode);
272
}
273
 
274
 
275
 
276
void
277
_mesa_ReadBuffer( GLenum mode )
278
{
279
   GET_CURRENT_CONTEXT(ctx);
280
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
281
 
282
   if (MESA_VERBOSE & VERBOSE_API)
283
      _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(mode));
284
 
285
   /*
286
    * Do error checking and compute ctx->Pixel._ReadSrcMask.
287
    */
288
   switch (mode) {
289
      case GL_LEFT:
290
      case GL_FRONT:
291
      case GL_FRONT_LEFT:
292
         /* Front-Left buffer, always exists */
293
         ctx->Pixel._ReadSrcMask = FRONT_LEFT_BIT;
294
         break;
295
      case GL_BACK:
296
      case GL_BACK_LEFT:
297
         /* Back-Left buffer, requires double buffering */
298
         if (!ctx->Visual.doubleBufferMode) {
299
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
300
            return;
301
         }
302
         ctx->Pixel._ReadSrcMask = BACK_LEFT_BIT;
303
         break;
304
      case GL_FRONT_RIGHT:
305
      case GL_RIGHT:
306
         if (!ctx->Visual.stereoMode) {
307
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
308
            return;
309
         }
310
         ctx->Pixel._ReadSrcMask = FRONT_RIGHT_BIT;
311
         break;
312
      case GL_BACK_RIGHT:
313
         if (!ctx->Visual.stereoMode || !ctx->Visual.doubleBufferMode) {
314
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
315
            return;
316
         }
317
         ctx->Pixel._ReadSrcMask = BACK_RIGHT_BIT;
318
         break;
319
      case GL_AUX0:
320
         if (ctx->Const.NumAuxBuffers >= 1) {
321
            ctx->Pixel._ReadSrcMask = AUX0_BIT;
322
         }
323
         else {
324
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer(GL_AUX0)" );
325
            return;
326
         }
327
         break;
328
      case GL_AUX1:
329
         if (ctx->Const.NumAuxBuffers >= 2) {
330
            ctx->Pixel._ReadSrcMask = AUX1_BIT;
331
         }
332
         else {
333
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer(GL_AUX1)" );
334
            return;
335
         }
336
         break;
337
      case GL_AUX2:
338
         if (ctx->Const.NumAuxBuffers >= 3) {
339
            ctx->Pixel._ReadSrcMask = AUX2_BIT;
340
         }
341
         else {
342
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer(GL_AUX2)" );
343
            return;
344
         }
345
         break;
346
      case GL_AUX3:
347
         if (ctx->Const.NumAuxBuffers >= 4) {
348
            ctx->Pixel._ReadSrcMask = AUX3_BIT;
349
         }
350
         else {
351
            _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer(GL_AUX3)" );
352
            return;
353
         }
354
         break;
355
      default:
356
         _mesa_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
357
         return;
358
   }
359
 
360
   ctx->Pixel.ReadBuffer = mode;
361
   ctx->NewState |= _NEW_PIXEL;
362
 
363
   /*
364
    * Call device driver function.
365
    */
366
   if (ctx->Driver.ReadBuffer)
367
      (*ctx->Driver.ReadBuffer)(ctx, mode);
368
}
369
 
370
 
371
/*
372
 * GL_MESA_resize_buffers extension
373
 * When this function is called, we'll ask the window system how large
374
 * the current window is.  If it's not what we expect, we'll have to
375
 * resize/reallocate the software accum/stencil/depth/alpha buffers.
376
 */
377
void
378
_mesa_ResizeBuffersMESA( void )
379
{
380
   GLcontext *ctx = _mesa_get_current_context();
381
 
382
   if (MESA_VERBOSE & VERBOSE_API)
383
      _mesa_debug(ctx, "glResizeBuffersMESA\n");
384
 
385
   if (ctx) {
386
      ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
387
 
388
      if (ctx->DrawBuffer) {
389
         GLuint buf_width, buf_height;
390
         GLframebuffer *buffer = ctx->DrawBuffer;
391
 
392
         /* ask device driver for size of output buffer */
393
         (*ctx->Driver.GetBufferSize)( buffer, &buf_width, &buf_height );
394
 
395
         /* see if size of device driver's color buffer (window) has changed */
396
         if (buffer->Width == buf_width && buffer->Height == buf_height)
397
            return; /* size is as expected */
398
 
399
         buffer->Width = buf_width;
400
         buffer->Height = buf_height;
401
 
402
         ctx->Driver.ResizeBuffers( buffer );
403
      }
404
 
405
      if (ctx->ReadBuffer && ctx->ReadBuffer != ctx->DrawBuffer) {
406
         GLuint buf_width, buf_height;
407
         GLframebuffer *buffer = ctx->DrawBuffer;
408
 
409
         /* ask device driver for size of output buffer */
410
         (*ctx->Driver.GetBufferSize)( buffer, &buf_width, &buf_height );
411
 
412
         /* see if size of device driver's color buffer (window) has changed */
413
         if (buffer->Width == buf_width && buffer->Height == buf_height)
414
            return; /* size is as expected */
415
 
416
         buffer->Width = buf_width;
417
         buffer->Height = buf_height;
418
 
419
         ctx->Driver.ResizeBuffers( buffer );
420
      }
421
 
422
      ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
423
   }
424
}
425
 
426
 
427
void
428
_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
429
{
430
   GET_CURRENT_CONTEXT(ctx);
431
   ASSERT_OUTSIDE_BEGIN_END(ctx);
432
 
433
   if (width < 0 || height < 0) {
434
      _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
435
      return;
436
   }
437
 
438
   if (MESA_VERBOSE & VERBOSE_API)
439
      _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
440
 
441
   if (x == ctx->Scissor.X &&
442
       y == ctx->Scissor.Y &&
443
       width == ctx->Scissor.Width &&
444
       height == ctx->Scissor.Height)
445
      return;
446
 
447
   FLUSH_VERTICES(ctx, _NEW_SCISSOR);
448
   ctx->Scissor.X = x;
449
   ctx->Scissor.Y = y;
450
   ctx->Scissor.Width = width;
451
   ctx->Scissor.Height = height;
452
 
453
   if (ctx->Driver.Scissor)
454
      ctx->Driver.Scissor( ctx, x, y, width, height );
455
}
456
 
457
 
458
/*
459
 * XXX move somewhere else someday?
460
 */
461
void
462
_mesa_SampleCoverageARB(GLclampf value, GLboolean invert)
463
{
464
   GLcontext *ctx = _mesa_get_current_context();
465
 
466
   if (!ctx->Extensions.ARB_multisample) {
467
      _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB");
468
      return;
469
   }
470
 
471
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
472
   ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
473
   ctx->Multisample.SampleCoverageInvert = invert;
474
   ctx->NewState |= _NEW_MULTISAMPLE;
475
}
476