xref: /reactos/dll/opengl/mesa/misc.c (revision 02e84521)
1 /* $Id: misc.c,v 1.23 1997/12/06 18:07:13 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.6
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: misc.c,v $
26  * Revision 1.23  1997/12/06 18:07:13  brianp
27  * changed version to 2.6
28  *
29  * Revision 1.22  1997/12/05 04:38:55  brianp
30  * added ClearColorAndDepth() function pointer (David Bucciarelli)
31  *
32  * Revision 1.21  1997/10/29 01:29:09  brianp
33  * added GL_EXT_point_parameters extension from Daniel Barrero
34  *
35  * Revision 1.20  1997/10/16 02:32:19  brianp
36  * added GL_EXT_shared_texture_palette extension
37  *
38  * Revision 1.19  1997/10/14 00:17:48  brianp
39  * added 3DFX_set_global_palette to extension string for 3Dfx
40  *
41  * Revision 1.18  1997/09/27 00:13:44  brianp
42  * added GL_EXT_paletted_texture extension
43  *
44  * Revision 1.17  1997/08/13 01:26:40  brianp
45  * changed version string to 2.4
46  *
47  * Revision 1.16  1997/07/24 01:23:16  brianp
48  * changed precompiled header symbol from PCH to PC_HEADER
49  *
50  * Revision 1.15  1997/06/20 02:21:36  brianp
51  * don't clear buffers if RenderMode != GL_RENDER
52  *
53  * Revision 1.14  1997/05/28 03:25:43  brianp
54  * added precompiled header (PCH) support
55  *
56  * Revision 1.13  1997/04/12 12:31:18  brianp
57  * removed gl_Rectf()
58  *
59  * Revision 1.12  1997/03/21 01:58:54  brianp
60  * now call Driver.RendererString() in gl_GetString()
61  *
62  * Revision 1.11  1997/02/10 20:40:51  brianp
63  * added GL_MESA_resize_buffers to extensions string
64  *
65  * Revision 1.10  1997/02/09 18:44:35  brianp
66  * added GL_EXT_texture3D support
67  *
68  * Revision 1.9  1997/01/08 20:55:02  brianp
69  * added GL_EXT_texture_object
70  *
71  * Revision 1.8  1996/11/05 01:41:45  brianp
72  * fixed potential scissor/clear color buffer bug
73  *
74  * Revision 1.7  1996/10/30 03:14:02  brianp
75  * incremented version to 2.1
76  *
77  * Revision 1.6  1996/10/11 03:42:17  brianp
78  * added GL_EXT_polygon_offset to extensions string
79  *
80  * Revision 1.5  1996/10/02 02:51:44  brianp
81  * created clear_color_buffers() which handles draw mode GL_FRONT_AND_BACK
82  *
83  * Revision 1.4  1996/09/25 03:22:14  brianp
84  * glDrawBuffer(GL_NONE) works now
85  *
86  * Revision 1.3  1996/09/24 00:16:10  brianp
87  * set NewState flag in glRead/DrawBuffer() and glHint()
88  * fixed display list bug in gl_Hint()
89  *
90  * Revision 1.2  1996/09/15 14:18:37  brianp
91  * now use GLframebuffer and GLvisual
92  *
93  * Revision 1.1  1996/09/13 01:38:16  brianp
94  * Initial revision
95  *
96  */
97 
98 
99 #ifdef PC_HEADER
100 #include "all.h"
101 #else
102 #include <stdlib.h>
103 #include <string.h>
104 #include "accum.h"
105 #include "alphabuf.h"
106 #include "context.h"
107 #include "depth.h"
108 #include "macros.h"
109 #include "masking.h"
110 #include "misc.h"
111 #include "stencil.h"
112 #include "types.h"
113 #endif
114 
115 
116 
117 void gl_ClearIndex( GLcontext *ctx, GLfloat c )
118 {
119    if (INSIDE_BEGIN_END(ctx)) {
120       gl_error( ctx, GL_INVALID_OPERATION, "glClearIndex" );
121       return;
122    }
123    ctx->Color.ClearIndex = (GLuint) c;
124    if (!ctx->Visual->RGBAflag) {
125       /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
126       (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
127    }
128 }
129 
130 
131 
132 void gl_ClearColor( GLcontext *ctx, GLclampf red, GLclampf green,
133                     GLclampf blue, GLclampf alpha )
134 {
135    if (INSIDE_BEGIN_END(ctx)) {
136       gl_error( ctx, GL_INVALID_OPERATION, "glClearColor" );
137       return;
138    }
139 
140    ctx->Color.ClearColor[0] = CLAMP( red,   0.0F, 1.0F );
141    ctx->Color.ClearColor[1] = CLAMP( green, 0.0F, 1.0F );
142    ctx->Color.ClearColor[2] = CLAMP( blue,  0.0F, 1.0F );
143    ctx->Color.ClearColor[3] = CLAMP( alpha, 0.0F, 1.0F );
144 
145    if (ctx->Visual->RGBAflag) {
146       GLubyte r = (GLint) (ctx->Color.ClearColor[0] * ctx->Visual->RedScale);
147       GLubyte g = (GLint) (ctx->Color.ClearColor[1] * ctx->Visual->GreenScale);
148       GLubyte b = (GLint) (ctx->Color.ClearColor[2] * ctx->Visual->BlueScale);
149       GLubyte a = (GLint) (ctx->Color.ClearColor[3] * ctx->Visual->AlphaScale);
150       (*ctx->Driver.ClearColor)( ctx, r, g, b, a );
151    }
152 }
153 
154 
155 
156 
157 /*
158  * Clear the color buffer when glColorMask or glIndexMask is in effect.
159  */
160 static void clear_color_buffer_with_masking( GLcontext *ctx )
161 {
162    GLint x, y, height, width;
163 
164    /* Compute region to clear */
165    if (ctx->Scissor.Enabled) {
166       x = ctx->Buffer->Xmin;
167       y = ctx->Buffer->Ymin;
168       height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
169       width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
170    }
171    else {
172       x = 0;
173       y = 0;
174       height = ctx->Buffer->Height;
175       width  = ctx->Buffer->Width;
176    }
177 
178    if (ctx->Visual->RGBAflag) {
179       /* RGBA mode */
180       GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
181       GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
182       GLubyte r = ctx->Color.ClearColor[0] * ctx->Visual->RedScale;
183       GLubyte g = ctx->Color.ClearColor[1] * ctx->Visual->GreenScale;
184       GLubyte b = ctx->Color.ClearColor[2] * ctx->Visual->BlueScale;
185       GLubyte a = ctx->Color.ClearColor[3] * ctx->Visual->AlphaScale;
186       GLint i;
187       for (i=0;i<height;i++,y++) {
188          MEMSET( red,   (int) r, width );
189          MEMSET( green, (int) g, width );
190          MEMSET( blue,  (int) b, width );
191          MEMSET( alpha, (int) a, width );
192          gl_mask_color_span( ctx, width, x, y, red, green, blue, alpha );
193          (*ctx->Driver.WriteColorSpan)( ctx,
194                                  width, x, y, red, green, blue, alpha, NULL );
195          if (ctx->RasterMask & ALPHABUF_BIT) {
196             gl_write_alpha_span( ctx, width, x, y, alpha, NULL );
197          }
198       }
199    }
200    else {
201       /* Color index mode */
202       GLuint indx[MAX_WIDTH];
203       GLubyte mask[MAX_WIDTH];
204       GLint i, j;
205       MEMSET( mask, 1, width );
206       for (i=0;i<height;i++,y++) {
207          for (j=0;j<width;j++) {
208             indx[j] = ctx->Color.ClearIndex;
209          }
210          gl_mask_index_span( ctx, width, x, y, indx );
211          (*ctx->Driver.WriteIndexSpan)( ctx, width, x, y, indx, mask );
212       }
213    }
214 }
215 
216 
217 
218 /*
219  * Clear the front and/or back color buffers.  Also clear the alpha
220  * buffer(s) if present.
221  */
222 static void clear_color_buffers( GLcontext *ctx )
223 {
224    if (ctx->Color.SWmasking) {
225       clear_color_buffer_with_masking( ctx );
226    }
227    else {
228       GLint x = ctx->Buffer->Xmin;
229       GLint y = ctx->Buffer->Ymin;
230       GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
231       GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
232       (*ctx->Driver.Clear)( ctx, !ctx->Scissor.Enabled,
233                             x, y, width, height );
234       if (ctx->RasterMask & ALPHABUF_BIT) {
235          /* front and/or back alpha buffers will be cleared here */
236          gl_clear_alpha_buffers( ctx );
237       }
238    }
239 
240    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
241       /*** Also clear the back buffer ***/
242       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
243       if (ctx->Color.SWmasking) {
244          clear_color_buffer_with_masking( ctx );
245       }
246       else {
247          GLint x = ctx->Buffer->Xmin;
248          GLint y = ctx->Buffer->Ymin;
249          GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
250          GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
251          (*ctx->Driver.Clear)( ctx, !ctx->Scissor.Enabled,
252                                x, y, width, height );
253       }
254       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
255    }
256 }
257 
258 
259 
260 void gl_Clear( GLcontext *ctx, GLbitfield mask )
261 {
262 #ifdef PROFILE
263    GLdouble t0 = gl_time();
264 #endif
265 
266    if (INSIDE_BEGIN_END(ctx)) {
267       gl_error( ctx, GL_INVALID_OPERATION, "glClear" );
268       return;
269    }
270 
271    if (ctx->RenderMode==GL_RENDER) {
272       if (ctx->NewState) {
273          gl_update_state( ctx );
274       }
275 
276       /* See if we can call device driver function to clear both the
277        * color and depth buffers.
278        */
279       if (ctx->Driver.ClearColorAndDepth &&
280           (mask & GL_COLOR_BUFFER_BIT) && (mask & GL_DEPTH_BUFFER_BIT)) {
281          GLint x = ctx->Buffer->Xmin;
282          GLint y = ctx->Buffer->Ymin;
283          GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
284          GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
285          (*ctx->Driver.ClearColorAndDepth)( ctx, !ctx->Scissor.Enabled,
286                                             x, y, width, height );
287          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
288             /*** Also clear the back buffer ***/
289             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
290             (*ctx->Driver.ClearColorAndDepth)( ctx, !ctx->Scissor.Enabled,
291                                                x, y, width, height );
292             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
293          }
294       }
295       else {
296          /* normal procedure for clearing buffers */
297          if (mask & GL_COLOR_BUFFER_BIT)  clear_color_buffers( ctx );
298          if (mask & GL_DEPTH_BUFFER_BIT)  (*ctx->Driver.ClearDepthBuffer)(ctx);
299          if (mask & GL_ACCUM_BUFFER_BIT)   gl_clear_accum_buffer( ctx );
300          if (mask & GL_STENCIL_BUFFER_BIT) gl_clear_stencil_buffer( ctx );
301       }
302 
303 #ifdef PROFILE
304       ctx->ClearTime += gl_time() - t0;
305       ctx->ClearCount++;
306 #endif
307    }
308 }
309 
310 
311 
312 const GLubyte *gl_GetString( GLcontext *ctx, GLenum name )
313 {
314    static char renderer[1000];
315    static char *vendor = "Brian Paul & ReactOS Developers";
316    static char *version = "1.1";
317    static char *extensions = "GL_EXT_paletted_texture GL_EXT_bgra GL_WIN_swap_hint";
318 
319    if (INSIDE_BEGIN_END(ctx)) {
320       gl_error( ctx, GL_INVALID_OPERATION, "glGetString" );
321       return (GLubyte *) 0;
322    }
323 
324    switch (name) {
325       case GL_VENDOR:
326          return (GLubyte *) vendor;
327       case GL_RENDERER:
328          strcpy(renderer, "Mesa");
329          if (ctx->Driver.RendererString) {
330             strcat(renderer, " ");
331             strcat(renderer, (*ctx->Driver.RendererString)());
332          }
333          return (GLubyte *) renderer;
334       case GL_VERSION:
335          return (GLubyte *) version;
336       case GL_EXTENSIONS:
337          return (GLubyte *) extensions;
338       default:
339          gl_error( ctx, GL_INVALID_ENUM, "glGetString" );
340          return (GLubyte *) 0;
341    }
342 }
343 
344 
345 
346 void gl_Finish( GLcontext *ctx )
347 {
348    /* Don't compile into display list */
349    if (INSIDE_BEGIN_END(ctx)) {
350       gl_error( ctx, GL_INVALID_OPERATION, "glFinish" );
351       return;
352    }
353    if (ctx->Driver.Finish) {
354       (*ctx->Driver.Finish)( ctx );
355    }
356 }
357 
358 
359 
360 void gl_Flush( GLcontext *ctx )
361 {
362    /* Don't compile into display list */
363    if (INSIDE_BEGIN_END(ctx)) {
364       gl_error( ctx, GL_INVALID_OPERATION, "glFlush" );
365       return;
366    }
367    if (ctx->Driver.Flush) {
368       (*ctx->Driver.Flush)( ctx );
369    }
370 }
371 
372 
373 
374 void gl_Hint( GLcontext *ctx, GLenum target, GLenum mode )
375 {
376    if (INSIDE_BEGIN_END(ctx)) {
377       gl_error( ctx, GL_INVALID_OPERATION, "glHint" );
378       return;
379    }
380    if (mode!=GL_DONT_CARE && mode!=GL_FASTEST && mode!=GL_NICEST) {
381       gl_error( ctx, GL_INVALID_ENUM, "glHint(mode)" );
382       return;
383    }
384    switch (target) {
385       case GL_FOG_HINT:
386          ctx->Hint.Fog = mode;
387          break;
388       case GL_LINE_SMOOTH_HINT:
389          ctx->Hint.LineSmooth = mode;
390          break;
391       case GL_PERSPECTIVE_CORRECTION_HINT:
392          ctx->Hint.PerspectiveCorrection = mode;
393          break;
394       case GL_POINT_SMOOTH_HINT:
395          ctx->Hint.PointSmooth = mode;
396          break;
397       case GL_POLYGON_SMOOTH_HINT:
398          ctx->Hint.PolygonSmooth = mode;
399          break;
400       default:
401          gl_error( ctx, GL_INVALID_ENUM, "glHint(target)" );
402    }
403    ctx->NewState |= NEW_ALL;   /* just to be safe */
404 }
405 
406 
407 
408 void gl_DrawBuffer( GLcontext *ctx, GLenum mode )
409 {
410    if (INSIDE_BEGIN_END(ctx)) {
411       gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
412       return;
413    }
414    switch (mode) {
415       case GL_FRONT:
416       case GL_FRONT_LEFT:
417       case GL_FRONT_AND_BACK:
418          if ( (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ) == GL_FALSE ) {
419             gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
420             return;
421          }
422          ctx->Color.DrawBuffer = mode;
423          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
424 	 ctx->NewState |= NEW_RASTER_OPS;
425          break;
426       case GL_BACK:
427       case GL_BACK_LEFT:
428          if ( (*ctx->Driver.SetBuffer)( ctx, GL_BACK ) == GL_FALSE) {
429             gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
430             return;
431          }
432          ctx->Color.DrawBuffer = mode;
433          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
434 	 ctx->NewState |= NEW_RASTER_OPS;
435          break;
436       case GL_NONE:
437          ctx->Color.DrawBuffer = mode;
438          ctx->Buffer->Alpha = NULL;
439          ctx->NewState |= NEW_RASTER_OPS;
440          break;
441       case GL_FRONT_RIGHT:
442       case GL_BACK_RIGHT:
443       case GL_LEFT:
444       case GL_RIGHT:
445       case GL_AUX0:
446          gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
447          break;
448       default:
449          gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
450    }
451 }
452 
453 
454 
455 void gl_ReadBuffer( GLcontext *ctx, GLenum mode )
456 {
457    if (INSIDE_BEGIN_END(ctx)) {
458       gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
459       return;
460    }
461    switch (mode) {
462       case GL_FRONT:
463       case GL_FRONT_LEFT:
464          if ( (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ) == GL_FALSE) {
465             gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
466             return;
467          }
468          ctx->Pixel.ReadBuffer = mode;
469          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
470          ctx->NewState |= NEW_RASTER_OPS;
471          break;
472       case GL_BACK:
473       case GL_BACK_LEFT:
474          if ( (*ctx->Driver.SetBuffer)( ctx, GL_BACK ) == GL_FALSE) {
475             gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
476             return;
477          }
478          ctx->Pixel.ReadBuffer = mode;
479          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
480          ctx->NewState |= NEW_RASTER_OPS;
481          break;
482       case GL_FRONT_RIGHT:
483       case GL_BACK_RIGHT:
484       case GL_LEFT:
485       case GL_RIGHT:
486       case GL_AUX0:
487          gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
488          break;
489       default:
490          gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
491    }
492 
493    /* Remember, the draw buffer is the default state */
494    (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
495 }
496