3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 #define FB_TEXTURE 0X10
46 _mesa_FeedbackBuffer( GLsizei size
, GLenum type
, GLfloat
*buffer
)
48 GET_CURRENT_CONTEXT(ctx
);
49 ASSERT_OUTSIDE_BEGIN_END(ctx
);
51 if (ctx
->RenderMode
==GL_FEEDBACK
) {
52 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glFeedbackBuffer" );
56 _mesa_error( ctx
, GL_INVALID_VALUE
, "glFeedbackBuffer(size<0)" );
60 _mesa_error( ctx
, GL_INVALID_VALUE
, "glFeedbackBuffer(buffer==NULL)" );
61 ctx
->Feedback
.BufferSize
= 0;
67 ctx
->Feedback
._Mask
= 0;
70 ctx
->Feedback
._Mask
= FB_3D
;
73 ctx
->Feedback
._Mask
= (FB_3D
|
74 (ctx
->Visual
.rgbMode
? FB_COLOR
: FB_INDEX
));
76 case GL_3D_COLOR_TEXTURE
:
77 ctx
->Feedback
._Mask
= (FB_3D
|
78 (ctx
->Visual
.rgbMode
? FB_COLOR
: FB_INDEX
) |
81 case GL_4D_COLOR_TEXTURE
:
82 ctx
->Feedback
._Mask
= (FB_3D
| FB_4D
|
83 (ctx
->Visual
.rgbMode
? FB_COLOR
: FB_INDEX
) |
87 _mesa_error( ctx
, GL_INVALID_ENUM
, "glFeedbackBuffer" );
91 FLUSH_VERTICES(ctx
, _NEW_RENDERMODE
); /* Always flush */
92 ctx
->Feedback
.Type
= type
;
93 ctx
->Feedback
.BufferSize
= size
;
94 ctx
->Feedback
.Buffer
= buffer
;
95 ctx
->Feedback
.Count
= 0; /* Becaues of this. */
100 _mesa_PassThrough( GLfloat token
)
102 GET_CURRENT_CONTEXT(ctx
);
103 ASSERT_OUTSIDE_BEGIN_END(ctx
);
105 if (ctx
->RenderMode
==GL_FEEDBACK
) {
106 FLUSH_VERTICES(ctx
, 0);
107 FEEDBACK_TOKEN( ctx
, (GLfloat
) (GLint
) GL_PASS_THROUGH_TOKEN
);
108 FEEDBACK_TOKEN( ctx
, token
);
115 * Put a vertex into the feedback buffer.
117 void _mesa_feedback_vertex( GLcontext
*ctx
,
118 const GLfloat win
[4],
119 const GLfloat color
[4],
121 const GLfloat texcoord
[4] )
123 FEEDBACK_TOKEN( ctx
, win
[0] );
124 FEEDBACK_TOKEN( ctx
, win
[1] );
125 if (ctx
->Feedback
._Mask
& FB_3D
) {
126 FEEDBACK_TOKEN( ctx
, win
[2] );
128 if (ctx
->Feedback
._Mask
& FB_4D
) {
129 FEEDBACK_TOKEN( ctx
, win
[3] );
131 if (ctx
->Feedback
._Mask
& FB_INDEX
) {
132 FEEDBACK_TOKEN( ctx
, (GLfloat
) index
);
134 if (ctx
->Feedback
._Mask
& FB_COLOR
) {
135 FEEDBACK_TOKEN( ctx
, color
[0] );
136 FEEDBACK_TOKEN( ctx
, color
[1] );
137 FEEDBACK_TOKEN( ctx
, color
[2] );
138 FEEDBACK_TOKEN( ctx
, color
[3] );
140 if (ctx
->Feedback
._Mask
& FB_TEXTURE
) {
141 FEEDBACK_TOKEN( ctx
, texcoord
[0] );
142 FEEDBACK_TOKEN( ctx
, texcoord
[1] );
143 FEEDBACK_TOKEN( ctx
, texcoord
[2] );
144 FEEDBACK_TOKEN( ctx
, texcoord
[3] );
149 /**********************************************************************/
151 /**********************************************************************/
155 * NOTE: this function can't be put in a display list.
158 _mesa_SelectBuffer( GLsizei size
, GLuint
*buffer
)
160 GET_CURRENT_CONTEXT(ctx
);
161 ASSERT_OUTSIDE_BEGIN_END(ctx
);
163 if (ctx
->RenderMode
==GL_SELECT
) {
164 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glSelectBuffer" );
165 return; /* KW: added return */
168 FLUSH_VERTICES(ctx
, _NEW_RENDERMODE
); /* why bother? */
169 ctx
->Select
.Buffer
= buffer
;
170 ctx
->Select
.BufferSize
= size
;
171 ctx
->Select
.BufferCount
= 0;
172 ctx
->Select
.HitFlag
= GL_FALSE
;
173 ctx
->Select
.HitMinZ
= 1.0;
174 ctx
->Select
.HitMaxZ
= 0.0;
178 #define WRITE_RECORD( CTX, V ) \
179 if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \
180 CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \
182 CTX->Select.BufferCount++;
186 void _mesa_update_hitflag( GLcontext
*ctx
, GLfloat z
)
188 ctx
->Select
.HitFlag
= GL_TRUE
;
189 if (z
< ctx
->Select
.HitMinZ
) {
190 ctx
->Select
.HitMinZ
= z
;
192 if (z
> ctx
->Select
.HitMaxZ
) {
193 ctx
->Select
.HitMaxZ
= z
;
198 static void write_hit_record( GLcontext
*ctx
)
201 GLuint zmin
, zmax
, zscale
= (~0u);
203 /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */
204 /* 2^32-1 and round to nearest unsigned integer. */
206 assert( ctx
!= NULL
); /* this line magically fixes a SunOS 5.x/gcc bug */
207 zmin
= (GLuint
) ((GLfloat
) zscale
* ctx
->Select
.HitMinZ
);
208 zmax
= (GLuint
) ((GLfloat
) zscale
* ctx
->Select
.HitMaxZ
);
210 WRITE_RECORD( ctx
, ctx
->Select
.NameStackDepth
);
211 WRITE_RECORD( ctx
, zmin
);
212 WRITE_RECORD( ctx
, zmax
);
213 for (i
= 0; i
< ctx
->Select
.NameStackDepth
; i
++) {
214 WRITE_RECORD( ctx
, ctx
->Select
.NameStack
[i
] );
218 ctx
->Select
.HitFlag
= GL_FALSE
;
219 ctx
->Select
.HitMinZ
= 1.0;
220 ctx
->Select
.HitMaxZ
= -1.0;
226 _mesa_InitNames( void )
228 GET_CURRENT_CONTEXT(ctx
);
229 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
231 /* Record the hit before the HitFlag is wiped out again. */
232 if (ctx
->RenderMode
== GL_SELECT
) {
233 if (ctx
->Select
.HitFlag
) {
234 write_hit_record( ctx
);
237 ctx
->Select
.NameStackDepth
= 0;
238 ctx
->Select
.HitFlag
= GL_FALSE
;
239 ctx
->Select
.HitMinZ
= 1.0;
240 ctx
->Select
.HitMaxZ
= 0.0;
241 ctx
->NewState
|= _NEW_RENDERMODE
;
247 _mesa_LoadName( GLuint name
)
249 GET_CURRENT_CONTEXT(ctx
);
250 ASSERT_OUTSIDE_BEGIN_END(ctx
);
252 if (ctx
->RenderMode
!= GL_SELECT
) {
255 if (ctx
->Select
.NameStackDepth
== 0) {
256 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glLoadName" );
260 FLUSH_VERTICES(ctx
, _NEW_RENDERMODE
);
262 if (ctx
->Select
.HitFlag
) {
263 write_hit_record( ctx
);
265 if (ctx
->Select
.NameStackDepth
< MAX_NAME_STACK_DEPTH
) {
266 ctx
->Select
.NameStack
[ctx
->Select
.NameStackDepth
-1] = name
;
269 ctx
->Select
.NameStack
[MAX_NAME_STACK_DEPTH
-1] = name
;
275 _mesa_PushName( GLuint name
)
277 GET_CURRENT_CONTEXT(ctx
);
278 ASSERT_OUTSIDE_BEGIN_END(ctx
);
280 if (ctx
->RenderMode
!= GL_SELECT
) {
284 FLUSH_VERTICES(ctx
, _NEW_RENDERMODE
);
285 if (ctx
->Select
.HitFlag
) {
286 write_hit_record( ctx
);
288 if (ctx
->Select
.NameStackDepth
>= MAX_NAME_STACK_DEPTH
) {
289 _mesa_error( ctx
, GL_STACK_OVERFLOW
, "glPushName" );
292 ctx
->Select
.NameStack
[ctx
->Select
.NameStackDepth
++] = name
;
298 _mesa_PopName( void )
300 GET_CURRENT_CONTEXT(ctx
);
301 ASSERT_OUTSIDE_BEGIN_END(ctx
);
303 if (ctx
->RenderMode
!= GL_SELECT
) {
307 FLUSH_VERTICES(ctx
, _NEW_RENDERMODE
);
308 if (ctx
->Select
.HitFlag
) {
309 write_hit_record( ctx
);
311 if (ctx
->Select
.NameStackDepth
== 0) {
312 _mesa_error( ctx
, GL_STACK_UNDERFLOW
, "glPopName" );
315 ctx
->Select
.NameStackDepth
--;
320 /**********************************************************************/
322 /**********************************************************************/
327 * NOTE: this function can't be put in a display list.
330 _mesa_RenderMode( GLenum mode
)
332 GET_CURRENT_CONTEXT(ctx
);
334 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, 0);
336 if (MESA_VERBOSE
& VERBOSE_API
)
337 _mesa_debug(ctx
, "glRenderMode %s\n", _mesa_lookup_enum_by_nr(mode
));
339 FLUSH_VERTICES(ctx
, _NEW_RENDERMODE
);
341 switch (ctx
->RenderMode
) {
346 if (ctx
->Select
.HitFlag
) {
347 write_hit_record( ctx
);
349 if (ctx
->Select
.BufferCount
> ctx
->Select
.BufferSize
) {
352 _mesa_warning(ctx
, "Feedback buffer overflow");
357 result
= ctx
->Select
.Hits
;
359 ctx
->Select
.BufferCount
= 0;
360 ctx
->Select
.Hits
= 0;
361 ctx
->Select
.NameStackDepth
= 0;
364 if (ctx
->Feedback
.Count
> ctx
->Feedback
.BufferSize
) {
369 result
= ctx
->Feedback
.Count
;
371 ctx
->Feedback
.Count
= 0;
374 _mesa_error( ctx
, GL_INVALID_ENUM
, "glRenderMode" );
382 if (ctx
->Select
.BufferSize
==0) {
383 /* haven't called glSelectBuffer yet */
384 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glRenderMode" );
388 if (ctx
->Feedback
.BufferSize
==0) {
389 /* haven't called glFeedbackBuffer yet */
390 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glRenderMode" );
394 _mesa_error( ctx
, GL_INVALID_ENUM
, "glRenderMode" );
398 ctx
->RenderMode
= mode
;
399 if (ctx
->Driver
.RenderMode
)
400 ctx
->Driver
.RenderMode( ctx
, mode
);