buffers.c revision cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290
1/* $Id: buffers.c,v 1.21 2000/12/26 05:09:27 keithw Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2000  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#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "accum.h"
33#include "buffers.h"
34#include "context.h"
35#include "depth.h"
36#include "enums.h"
37#include "macros.h"
38#include "masking.h"
39#include "mem.h"
40#include "stencil.h"
41#include "state.h"
42#include "mtypes.h"
43#include "swrast/swrast.h"
44#endif
45
46
47
48void
49_mesa_ClearIndex( GLfloat c )
50{
51   GET_CURRENT_CONTEXT(ctx);
52   ASSERT_OUTSIDE_BEGIN_END(ctx);
53
54   if (ctx->Color.ClearIndex == (GLuint)c)
55      return;
56
57
58   FLUSH_VERTICES(ctx, _NEW_COLOR);
59   ctx->Color.ClearIndex = (GLuint) c;
60
61   if (!ctx->Visual.RGBAflag) {
62      /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
63      (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
64   }
65}
66
67
68
69void
70_mesa_ClearColor( GLclampf red, GLclampf green,
71                  GLclampf blue, GLclampf alpha )
72{
73   GLfloat tmp[4];
74   GET_CURRENT_CONTEXT(ctx);
75   ASSERT_OUTSIDE_BEGIN_END(ctx);
76
77   tmp[0] = CLAMP( red,   0.0, 1.0 );
78   tmp[1] = CLAMP( green, 0.0, 1.0 );
79   tmp[2] = CLAMP( blue,  0.0, 1.0 );
80   tmp[3] = CLAMP( alpha, 0.0, 1.0 );
81
82   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
83      return;
84
85   FLUSH_VERTICES(ctx, _NEW_COLOR);
86   COPY_4FV( ctx->Color.ClearColor, tmp );
87
88   if (ctx->Visual.RGBAflag) {
89      GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF);
90      GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF);
91      GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF);
92      GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF);
93      (*ctx->Driver.ClearColor)( ctx, r, g, b, a );
94   }
95}
96
97
98
99
100
101
102void
103_mesa_Clear( GLbitfield mask )
104{
105   GET_CURRENT_CONTEXT(ctx);
106   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
107
108   if (MESA_VERBOSE & VERBOSE_API)
109      fprintf(stderr, "glClear 0x%x\n", mask);
110
111   if (ctx->NewState) {
112      gl_update_state( ctx );	/* update _Xmin, etc */
113   }
114
115   if (ctx->RenderMode==GL_RENDER) {
116      const GLint x = ctx->DrawBuffer->_Xmin;
117      const GLint y = ctx->DrawBuffer->_Ymin;
118      const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
119      const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
120      GLbitfield ddMask;
121      GLbitfield newMask;
122
123      /* don't clear depth buffer if depth writing disabled */
124      if (!ctx->Depth.Mask)
125         CLEAR_BITS(mask, GL_DEPTH_BUFFER_BIT);
126
127      /* Build bitmask to send to driver Clear function */
128      ddMask = mask & (GL_DEPTH_BUFFER_BIT |
129                       GL_STENCIL_BUFFER_BIT |
130                       GL_ACCUM_BUFFER_BIT);
131      if (mask & GL_COLOR_BUFFER_BIT) {
132         ddMask |= ctx->Color.DrawDestMask;
133      }
134
135      ASSERT(ctx->Driver.Clear);
136      newMask = (*ctx->Driver.Clear)( ctx, ddMask, !ctx->Scissor.Enabled,
137                                      x, y, width, height );
138
139#ifdef DEBUG
140      {
141         GLbitfield legalBits = DD_FRONT_LEFT_BIT |
142                                DD_FRONT_RIGHT_BIT |
143                                DD_BACK_LEFT_BIT |
144                                DD_BACK_RIGHT_BIT |
145                                DD_DEPTH_BIT |
146                                DD_STENCIL_BIT |
147                                DD_ACCUM_BIT;
148         assert((newMask & (~legalBits)) == 0);
149      }
150#endif
151
152      if (newMask)
153	 _swrast_Clear( ctx, newMask, !ctx->Scissor.Enabled,
154			x, y, width, height );
155   }
156}
157
158
159void
160_mesa_DrawBuffer( GLenum mode )
161{
162   GET_CURRENT_CONTEXT(ctx);
163   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */
164
165
166   if (MESA_VERBOSE & VERBOSE_API)
167      fprintf(stderr, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode));
168
169   switch (mode) {
170      case GL_AUX0:
171      case GL_AUX1:
172      case GL_AUX2:
173      case GL_AUX3:
174         /* AUX buffers not implemented in Mesa at this time */
175         gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
176         return;
177      case GL_RIGHT:
178         if (!ctx->Visual.StereoFlag) {
179            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
180            return;}
181         if (ctx->Visual.DBflag)
182            ctx->Color.DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
183         else
184            ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
185         break;
186      case GL_FRONT_RIGHT:
187         if (!ctx->Visual.StereoFlag) {
188            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
189            return;
190         }
191         ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
192         break;
193      case GL_BACK_RIGHT:
194         if (!ctx->Visual.StereoFlag) {
195            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
196            return;
197         }
198         if (!ctx->Visual.DBflag) {
199            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
200            return;
201         }
202         ctx->Color.DrawDestMask = BACK_RIGHT_BIT;
203         break;
204      case GL_BACK_LEFT:
205         if (!ctx->Visual.DBflag) {
206            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
207            return;
208         }
209         ctx->Color.DrawDestMask = BACK_LEFT_BIT;
210         break;
211      case GL_FRONT_AND_BACK:
212         if (!ctx->Visual.DBflag) {
213            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
214            return;
215         }
216         if (ctx->Visual.StereoFlag)
217            ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT
218                                    | FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
219         else
220            ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
221         break;
222      case GL_BACK:
223         if (!ctx->Visual.DBflag) {
224            gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
225            return;
226         }
227         if (ctx->Visual.StereoFlag)
228            ctx->Color.DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT;
229         else
230            ctx->Color.DrawDestMask = BACK_LEFT_BIT;
231         break;
232      case GL_LEFT:
233         /* never an error */
234         if (ctx->Visual.DBflag)
235            ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
236         else
237            ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
238         break;
239      case GL_FRONT_LEFT:
240         /* never an error */
241         ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
242         break;
243      case GL_FRONT:
244         /* never an error */
245         if (ctx->Visual.StereoFlag)
246            ctx->Color.DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT;
247         else
248            ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
249         break;
250      case GL_NONE:
251         /* never an error */
252         ctx->Color.DrawDestMask = 0;
253         break;
254      default:
255         gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
256         return;
257   }
258
259   /*
260    * Make the dest buffer mode more precise if possible
261    */
262   if (mode == GL_LEFT && !ctx->Visual.DBflag)
263      ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
264   else if (mode == GL_RIGHT && !ctx->Visual.DBflag)
265      ctx->Color.DriverDrawBuffer = GL_FRONT_RIGHT;
266   else if (mode == GL_FRONT && !ctx->Visual.StereoFlag)
267      ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
268   else if (mode == GL_BACK && !ctx->Visual.StereoFlag)
269      ctx->Color.DriverDrawBuffer = GL_BACK_LEFT;
270   else
271      ctx->Color.DriverDrawBuffer = mode;
272
273   /*
274    * Set current alpha buffer pointer
275    */
276   if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
277      if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT)
278         ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
279      else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT)
280         ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
281      else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT)
282         ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
283      else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT)
284         ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
285   }
286
287   /*
288    * If we get here there can't have been an error.
289    * Now see if device driver can implement the drawing to the target
290    * buffer(s).  The driver may not be able to do GL_FRONT_AND_BACK mode
291    * for example.  We'll take care of that in the core code by looping
292    * over the individual buffers.
293    */
294   ASSERT(ctx->Driver.SetDrawBuffer);
295   if ( (*ctx->Driver.SetDrawBuffer)(ctx, ctx->Color.DriverDrawBuffer) ) {
296      /* All OK, the driver will do all buffer writes */
297      ctx->Color.MultiDrawBuffer = GL_FALSE;
298   }
299   else {
300      /* We'll have to loop over the multiple draw buffer targets */
301      ctx->Color.MultiDrawBuffer = GL_TRUE;
302      /* Set drawing buffer to front for now */
303      (void) (*ctx->Driver.SetDrawBuffer)(ctx, GL_FRONT_LEFT);
304   }
305
306   ctx->Color.DrawBuffer = mode;
307   ctx->NewState |= _NEW_COLOR;
308}
309
310
311
312void
313_mesa_ReadBuffer( GLenum mode )
314{
315   GET_CURRENT_CONTEXT(ctx);
316   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
317
318   if (MESA_VERBOSE & VERBOSE_API)
319      fprintf(stderr, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode));
320
321   switch (mode) {
322      case GL_AUX0:
323      case GL_AUX1:
324      case GL_AUX2:
325      case GL_AUX3:
326         /* AUX buffers not implemented in Mesa at this time */
327         gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
328         return;
329      case GL_LEFT:
330      case GL_FRONT:
331      case GL_FRONT_LEFT:
332         /* Front-Left buffer, always exists */
333         ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
334         break;
335      case GL_BACK:
336      case GL_BACK_LEFT:
337         /* Back-Left buffer, requires double buffering */
338         if (!ctx->Visual.DBflag) {
339            gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
340            return;
341         }
342         ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT;
343         break;
344      case GL_FRONT_RIGHT:
345      case GL_RIGHT:
346         if (!ctx->Visual.StereoFlag) {
347            gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
348            return;
349         }
350         ctx->Pixel.DriverReadBuffer = GL_FRONT_RIGHT;
351         break;
352      case GL_BACK_RIGHT:
353         if (!ctx->Visual.StereoFlag || !ctx->Visual.DBflag) {
354            gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
355            return;
356         }
357         ctx->Pixel.DriverReadBuffer = GL_BACK_RIGHT;
358         break;
359      default:
360         gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
361         return;
362   }
363
364   ctx->Pixel.ReadBuffer = mode;
365   ctx->NewState |= _NEW_PIXEL;
366}
367
368
369/*
370 * GL_MESA_resize_buffers extension
371 */
372void
373_mesa_ResizeBuffersMESA( void )
374{
375   GLcontext *ctx = _mesa_get_current_context();
376
377   GLuint buf_width, buf_height;
378
379   if (MESA_VERBOSE & VERBOSE_API)
380      fprintf(stderr, "glResizeBuffersMESA\n");
381
382   /* ask device driver for size of output buffer */
383   (*ctx->Driver.GetBufferSize)( ctx, &buf_width, &buf_height );
384
385   /* see if size of device driver's color buffer (window) has changed */
386   if (ctx->DrawBuffer->Width == (GLint) buf_width &&
387       ctx->DrawBuffer->Height == (GLint) buf_height)
388      return;
389
390   ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
391
392   /* save buffer size */
393   ctx->DrawBuffer->Width = buf_width;
394   ctx->DrawBuffer->Height = buf_height;
395
396   _swrast_alloc_buffers( ctx );
397}
398