4251aae01a308a14ee15c164ddd1ec4f1370ba80
1 /* $Id: feedback.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
42 #include "GL/xf86glx.h"
52 #define FB_TEXTURE 0X10
57 gl_FeedbackBuffer( GLcontext
*ctx
, GLsizei size
, GLenum type
, GLfloat
*buffer
)
59 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx
, "glFeedbackBuffer" );
61 if (ctx
->RenderMode
==GL_FEEDBACK
) {
62 gl_error( ctx
, GL_INVALID_OPERATION
, "glFeedbackBuffer" );
67 gl_error( ctx
, GL_INVALID_VALUE
, "glFeedbackBuffer(size<0)" );
71 gl_error( ctx
, GL_INVALID_VALUE
, "glFeedbackBuffer(buffer==NULL)" );
72 ctx
->Feedback
.BufferSize
= 0;
78 ctx
->Feedback
.Mask
= 0;
79 ctx
->Feedback
.Type
= type
;
82 ctx
->Feedback
.Mask
= FB_3D
;
83 ctx
->Feedback
.Type
= type
;
86 ctx
->Feedback
.Mask
= FB_3D
87 | (ctx
->Visual
->RGBAflag
? FB_COLOR
: FB_INDEX
);
88 ctx
->Feedback
.Type
= type
;
90 case GL_3D_COLOR_TEXTURE
:
91 ctx
->Feedback
.Mask
= FB_3D
92 | (ctx
->Visual
->RGBAflag
? FB_COLOR
: FB_INDEX
)
94 ctx
->Feedback
.Type
= type
;
96 case GL_4D_COLOR_TEXTURE
:
97 ctx
->Feedback
.Mask
= FB_3D
| FB_4D
98 | (ctx
->Visual
->RGBAflag
? FB_COLOR
: FB_INDEX
)
100 ctx
->Feedback
.Type
= type
;
103 ctx
->Feedback
.Mask
= 0;
104 gl_error( ctx
, GL_INVALID_ENUM
, "glFeedbackBuffer" );
107 ctx
->Feedback
.BufferSize
= size
;
108 ctx
->Feedback
.Buffer
= buffer
;
109 ctx
->Feedback
.Count
= 0;
114 void gl_PassThrough( GLcontext
*ctx
, GLfloat token
)
116 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glPassThrough");
118 if (ctx
->RenderMode
==GL_FEEDBACK
) {
119 FEEDBACK_TOKEN( ctx
, (GLfloat
) (GLint
) GL_PASS_THROUGH_TOKEN
);
120 FEEDBACK_TOKEN( ctx
, token
);
127 * Put a vertex into the feedback buffer.
129 void gl_feedback_vertex( GLcontext
*ctx
,
130 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
,
131 const GLfloat color
[4], GLfloat index
,
132 const GLfloat texcoord
[4] )
134 FEEDBACK_TOKEN( ctx
, x
);
135 FEEDBACK_TOKEN( ctx
, y
);
136 if (ctx
->Feedback
.Mask
& FB_3D
) {
137 FEEDBACK_TOKEN( ctx
, z
);
139 if (ctx
->Feedback
.Mask
& FB_4D
) {
140 FEEDBACK_TOKEN( ctx
, w
);
142 if (ctx
->Feedback
.Mask
& FB_INDEX
) {
143 FEEDBACK_TOKEN( ctx
, index
);
145 if (ctx
->Feedback
.Mask
& FB_COLOR
) {
146 FEEDBACK_TOKEN( ctx
, color
[0] );
147 FEEDBACK_TOKEN( ctx
, color
[1] );
148 FEEDBACK_TOKEN( ctx
, color
[2] );
149 FEEDBACK_TOKEN( ctx
, color
[3] );
151 if (ctx
->Feedback
.Mask
& FB_TEXTURE
) {
152 FEEDBACK_TOKEN( ctx
, texcoord
[0] );
153 FEEDBACK_TOKEN( ctx
, texcoord
[1] );
154 FEEDBACK_TOKEN( ctx
, texcoord
[2] );
155 FEEDBACK_TOKEN( ctx
, texcoord
[3] );
161 /**********************************************************************/
163 /**********************************************************************/
167 * NOTE: this function can't be put in a display list.
169 void gl_SelectBuffer( GLcontext
*ctx
, GLsizei size
, GLuint
*buffer
)
171 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glSelectBuffer");
172 if (ctx
->RenderMode
==GL_SELECT
) {
173 gl_error( ctx
, GL_INVALID_OPERATION
, "glSelectBuffer" );
175 ctx
->Select
.Buffer
= buffer
;
176 ctx
->Select
.BufferSize
= size
;
177 ctx
->Select
.BufferCount
= 0;
179 ctx
->Select
.HitFlag
= GL_FALSE
;
180 ctx
->Select
.HitMinZ
= 1.0;
181 ctx
->Select
.HitMaxZ
= 0.0;
185 #define WRITE_RECORD( CTX, V ) \
186 if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \
187 CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \
189 CTX->Select.BufferCount++;
193 void gl_update_hitflag( GLcontext
*ctx
, GLfloat z
)
195 ctx
->Select
.HitFlag
= GL_TRUE
;
196 if (z
< ctx
->Select
.HitMinZ
) {
197 ctx
->Select
.HitMinZ
= z
;
199 if (z
> ctx
->Select
.HitMaxZ
) {
200 ctx
->Select
.HitMaxZ
= z
;
206 static void write_hit_record( GLcontext
*ctx
)
209 GLuint zmin
, zmax
, zscale
= (~0u);
211 /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */
212 /* 2^32-1 and round to nearest unsigned integer. */
214 assert( ctx
!= NULL
); /* this line magically fixes a SunOS 5.x/gcc bug */
215 zmin
= (GLuint
) ((GLfloat
) zscale
* ctx
->Select
.HitMinZ
);
216 zmax
= (GLuint
) ((GLfloat
) zscale
* ctx
->Select
.HitMaxZ
);
218 WRITE_RECORD( ctx
, ctx
->Select
.NameStackDepth
);
219 WRITE_RECORD( ctx
, zmin
);
220 WRITE_RECORD( ctx
, zmax
);
221 for (i
=0;i
<ctx
->Select
.NameStackDepth
;i
++) {
222 WRITE_RECORD( ctx
, ctx
->Select
.NameStack
[i
] );
226 ctx
->Select
.HitFlag
= GL_FALSE
;
227 ctx
->Select
.HitMinZ
= 1.0;
228 ctx
->Select
.HitMaxZ
= -1.0;
233 void gl_InitNames( GLcontext
*ctx
)
235 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glInitNames");
236 /* Record the hit before the HitFlag is wiped out again. */
237 if (ctx
->RenderMode
==GL_SELECT
) {
238 if (ctx
->Select
.HitFlag
) {
239 write_hit_record( ctx
);
242 ctx
->Select
.NameStackDepth
= 0;
243 ctx
->Select
.HitFlag
= GL_FALSE
;
244 ctx
->Select
.HitMinZ
= 1.0;
245 ctx
->Select
.HitMaxZ
= 0.0;
250 void gl_LoadName( GLcontext
*ctx
, GLuint name
)
252 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLoadName");
253 if (ctx
->RenderMode
!=GL_SELECT
) {
256 if (ctx
->Select
.NameStackDepth
==0) {
257 gl_error( ctx
, GL_INVALID_OPERATION
, "glLoadName" );
260 if (ctx
->Select
.HitFlag
) {
261 write_hit_record( ctx
);
263 if (ctx
->Select
.NameStackDepth
<MAX_NAME_STACK_DEPTH
) {
264 ctx
->Select
.NameStack
[ctx
->Select
.NameStackDepth
-1] = name
;
267 ctx
->Select
.NameStack
[MAX_NAME_STACK_DEPTH
-1] = name
;
272 void gl_PushName( GLcontext
*ctx
, GLuint name
)
274 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glPushName");
275 if (ctx
->RenderMode
!=GL_SELECT
) {
278 if (ctx
->Select
.HitFlag
) {
279 write_hit_record( ctx
);
281 if (ctx
->Select
.NameStackDepth
<MAX_NAME_STACK_DEPTH
) {
282 ctx
->Select
.NameStack
[ctx
->Select
.NameStackDepth
++] = name
;
285 gl_error( ctx
, GL_STACK_OVERFLOW
, "glPushName" );
291 void gl_PopName( GLcontext
*ctx
)
293 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glPopName");
294 if (ctx
->RenderMode
!=GL_SELECT
) {
297 if (ctx
->Select
.HitFlag
) {
298 write_hit_record( ctx
);
300 if (ctx
->Select
.NameStackDepth
>0) {
301 ctx
->Select
.NameStackDepth
--;
304 gl_error( ctx
, GL_STACK_UNDERFLOW
, "glPopName" );
310 /**********************************************************************/
312 /**********************************************************************/
317 * NOTE: this function can't be put in a display list.
319 GLint
gl_RenderMode( GLcontext
*ctx
, GLenum mode
)
323 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx
, "glRenderMode", 0);
325 if (MESA_VERBOSE
& VERBOSE_API
)
326 fprintf(stderr
, "glRenderMode %s\n", gl_lookup_enum_by_nr(mode
));
328 ctx
->TriangleCaps
&= ~(DD_FEEDBACK
|DD_SELECT
);
330 switch (ctx
->RenderMode
) {
335 if (ctx
->Select
.HitFlag
) {
336 write_hit_record( ctx
);
338 if (ctx
->Select
.BufferCount
> ctx
->Select
.BufferSize
) {
341 gl_warning(ctx
, "Feedback buffer overflow");
346 result
= ctx
->Select
.Hits
;
348 ctx
->Select
.BufferCount
= 0;
349 ctx
->Select
.Hits
= 0;
350 ctx
->Select
.NameStackDepth
= 0;
353 if (ctx
->Feedback
.Count
> ctx
->Feedback
.BufferSize
) {
358 result
= ctx
->Feedback
.Count
;
360 ctx
->Feedback
.Count
= 0;
363 gl_error( ctx
, GL_INVALID_ENUM
, "glRenderMode" );
371 ctx
->TriangleCaps
|= DD_SELECT
;
372 if (ctx
->Select
.BufferSize
==0) {
373 /* haven't called glSelectBuffer yet */
374 gl_error( ctx
, GL_INVALID_OPERATION
, "glRenderMode" );
378 ctx
->TriangleCaps
|= DD_FEEDBACK
;
379 if (ctx
->Feedback
.BufferSize
==0) {
380 /* haven't called glFeedbackBuffer yet */
381 gl_error( ctx
, GL_INVALID_OPERATION
, "glRenderMode" );
385 gl_error( ctx
, GL_INVALID_ENUM
, "glRenderMode" );
390 ctx
->RenderMode
= mode
;
391 ctx
->NewState
|= NEW_ALL
;