source: trunk/src/opengl/mesa/feedback.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 13.9 KB
Line 
1/* $Id: feedback.c,v 1.3 2000-05-23 20:40:33 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 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
29
30
31#ifdef PC_HEADER
32#include "all.h"
33#else
34#include "glheader.h"
35#include "types.h"
36#include "context.h"
37#include "enums.h"
38#include "feedback.h"
39#include "macros.h"
40#include "mmath.h"
41#include "triangle.h"
42#endif
43
44
45
46#define FB_3D 0x01
47#define FB_4D 0x02
48#define FB_INDEX 0x04
49#define FB_COLOR 0x08
50#define FB_TEXTURE 0X10
51
52
53
54void
55_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
56{
57 GET_CURRENT_CONTEXT(ctx);
58 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glFeedbackBuffer" );
59
60 if (ctx->RenderMode==GL_FEEDBACK) {
61 gl_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
62 return;
63 }
64
65 if (size<0) {
66 gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
67 return;
68 }
69 if (!buffer) {
70 gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
71 ctx->Feedback.BufferSize = 0;
72 return;
73 }
74
75 switch (type) {
76 case GL_2D:
77 ctx->Feedback.Mask = 0;
78 ctx->Feedback.Type = type;
79 break;
80 case GL_3D:
81 ctx->Feedback.Mask = FB_3D;
82 ctx->Feedback.Type = type;
83 break;
84 case GL_3D_COLOR:
85 ctx->Feedback.Mask = FB_3D
86 | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX);
87 ctx->Feedback.Type = type;
88 break;
89 case GL_3D_COLOR_TEXTURE:
90 ctx->Feedback.Mask = FB_3D
91 | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
92 | FB_TEXTURE;
93 ctx->Feedback.Type = type;
94 break;
95 case GL_4D_COLOR_TEXTURE:
96 ctx->Feedback.Mask = FB_3D | FB_4D
97 | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
98 | FB_TEXTURE;
99 ctx->Feedback.Type = type;
100 break;
101 default:
102 ctx->Feedback.Mask = 0;
103 gl_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
104 }
105
106 ctx->Feedback.BufferSize = size;
107 ctx->Feedback.Buffer = buffer;
108 ctx->Feedback.Count = 0;
109}
110
111
112
113void
114_mesa_PassThrough( GLfloat token )
115{
116 GET_CURRENT_CONTEXT(ctx);
117 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPassThrough");
118
119 if (ctx->RenderMode==GL_FEEDBACK) {
120 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
121 FEEDBACK_TOKEN( ctx, token );
122 }
123}
124
125
126
127/*
128 * Put a vertex into the feedback buffer.
129 */
130void gl_feedback_vertex( GLcontext *ctx,
131 const GLfloat win[4],
132 const GLfloat color[4],
133 GLuint index,
134 const GLfloat texcoord[4] )
135{
136 FEEDBACK_TOKEN( ctx, win[0] );
137 FEEDBACK_TOKEN( ctx, win[1] );
138 if (ctx->Feedback.Mask & FB_3D) {
139 FEEDBACK_TOKEN( ctx, win[2] );
140 }
141 if (ctx->Feedback.Mask & FB_4D) {
142 FEEDBACK_TOKEN( ctx, win[3] );
143 }
144 if (ctx->Feedback.Mask & FB_INDEX) {
145 FEEDBACK_TOKEN( ctx, (GLfloat) index );
146 }
147 if (ctx->Feedback.Mask & FB_COLOR) {
148 FEEDBACK_TOKEN( ctx, color[0] );
149 FEEDBACK_TOKEN( ctx, color[1] );
150 FEEDBACK_TOKEN( ctx, color[2] );
151 FEEDBACK_TOKEN( ctx, color[3] );
152 }
153 if (ctx->Feedback.Mask & FB_TEXTURE) {
154 FEEDBACK_TOKEN( ctx, texcoord[0] );
155 FEEDBACK_TOKEN( ctx, texcoord[1] );
156 FEEDBACK_TOKEN( ctx, texcoord[2] );
157 FEEDBACK_TOKEN( ctx, texcoord[3] );
158 }
159}
160
161
162
163static void feedback_vertex( GLcontext *ctx, GLuint v, GLuint pv )
164{
165 GLfloat win[4];
166 GLfloat color[4];
167 GLfloat tc[4];
168 GLuint texUnit = ctx->Texture.CurrentTransformUnit;
169 const struct vertex_buffer *VB = ctx->VB;
170 GLuint index;
171
172 win[0] = VB->Win.data[v][0];
173 win[1] = VB->Win.data[v][1];
174 win[2] = VB->Win.data[v][2] / ctx->Visual->DepthMaxF;
175 win[3] = 1.0 / VB->Win.data[v][3];
176
177 if (ctx->Light.ShadeModel == GL_SMOOTH)
178 pv = v;
179
180 UBYTE_RGBA_TO_FLOAT_RGBA( color, VB->ColorPtr->data[pv] );
181
182 if (VB->TexCoordPtr[texUnit]->size == 4 &&
183 VB->TexCoordPtr[texUnit]->data[v][3] != 0.0) {
184 GLfloat invq = 1.0F / VB->TexCoordPtr[texUnit]->data[v][3];
185 tc[0] = VB->TexCoordPtr[texUnit]->data[v][0] * invq;
186 tc[1] = VB->TexCoordPtr[texUnit]->data[v][1] * invq;
187 tc[2] = VB->TexCoordPtr[texUnit]->data[v][2] * invq;
188 tc[3] = VB->TexCoordPtr[texUnit]->data[v][3];
189 }
190 else {
191 ASSIGN_4V(tc, 0,0,0,1);
192 COPY_SZ_4V(tc,
193 VB->TexCoordPtr[texUnit]->size,
194 VB->TexCoordPtr[texUnit]->data[v]);
195 }
196
197 if (VB->IndexPtr)
198 index = VB->IndexPtr->data[v];
199 else
200 index = 0;
201
202 gl_feedback_vertex( ctx, win, color, index, tc );
203}
204
205
206
207/*
208 * Put triangle in feedback buffer.
209 */
210void gl_feedback_triangle( GLcontext *ctx,
211 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
212{
213 if (gl_cull_triangle( ctx, v0, v1, v2, 0 )) {
214 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN );
215 FEEDBACK_TOKEN( ctx, (GLfloat) 3 ); /* three vertices*/
216
217 feedback_vertex( ctx, v0, pv );
218 feedback_vertex( ctx, v1, pv );
219 feedback_vertex( ctx, v2, pv );
220 }
221}
222
223
224void gl_feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
225{
226 GLenum token = GL_LINE_TOKEN;
227
228 if (ctx->StippleCounter==0)
229 token = GL_LINE_RESET_TOKEN;
230
231 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) token );
232
233 feedback_vertex( ctx, v1, pv );
234 feedback_vertex( ctx, v2, pv );
235
236 ctx->StippleCounter++;
237}
238
239
240void gl_feedback_points( GLcontext *ctx, GLuint first, GLuint last )
241{
242 const struct vertex_buffer *VB = ctx->VB;
243 GLuint i;
244
245 for (i=first;i<=last;i++) {
246 if (VB->ClipMask[i]==0) {
247 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POINT_TOKEN );
248 feedback_vertex( ctx, i, i );
249 }
250 }
251}
252
253
254
255
256
257/**********************************************************************/
258/* Selection */
259/**********************************************************************/
260
261
262/*
263 * NOTE: this function can't be put in a display list.
264 */
265void
266_mesa_SelectBuffer( GLsizei size, GLuint *buffer )
267{
268 GET_CURRENT_CONTEXT(ctx);
269 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glSelectBuffer");
270 if (ctx->RenderMode==GL_SELECT) {
271 gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
272 }
273 ctx->Select.Buffer = buffer;
274 ctx->Select.BufferSize = size;
275 ctx->Select.BufferCount = 0;
276
277 ctx->Select.HitFlag = GL_FALSE;
278 ctx->Select.HitMinZ = 1.0;
279 ctx->Select.HitMaxZ = 0.0;
280}
281
282
283#define WRITE_RECORD( CTX, V ) \
284 if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \
285 CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \
286 } \
287 CTX->Select.BufferCount++;
288
289
290
291void gl_update_hitflag( GLcontext *ctx, GLfloat z )
292{
293 ctx->Select.HitFlag = GL_TRUE;
294 if (z < ctx->Select.HitMinZ) {
295 ctx->Select.HitMinZ = z;
296 }
297 if (z > ctx->Select.HitMaxZ) {
298 ctx->Select.HitMaxZ = z;
299 }
300}
301
302void gl_select_triangle( GLcontext *ctx,
303 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
304{
305 const struct vertex_buffer *VB = ctx->VB;
306
307 if (gl_cull_triangle( ctx, v0, v1, v2, 0 )) {
308 const GLfloat zs = 1.0F / ctx->Visual->DepthMaxF;
309 gl_update_hitflag( ctx, VB->Win.data[v0][2] * zs );
310 gl_update_hitflag( ctx, VB->Win.data[v1][2] * zs );
311 gl_update_hitflag( ctx, VB->Win.data[v2][2] * zs );
312 }
313}
314
315
316void gl_select_line( GLcontext *ctx,
317 GLuint v0, GLuint v1, GLuint pv )
318{
319 const struct vertex_buffer *VB = ctx->VB;
320 const GLfloat zs = 1.0F / ctx->Visual->DepthMaxF;
321 gl_update_hitflag( ctx, VB->Win.data[v0][2] * zs );
322 gl_update_hitflag( ctx, VB->Win.data[v1][2] * zs );
323}
324
325
326void gl_select_points( GLcontext *ctx, GLuint first, GLuint last )
327{
328 struct vertex_buffer *VB = ctx->VB;
329 const GLfloat zs = 1.0F / ctx->Visual->DepthMaxF;
330 GLuint i;
331
332 for (i=first;i<=last;i++) {
333 if (VB->ClipMask[i]==0) {
334 gl_update_hitflag( ctx, VB->Win.data[i][2] * zs );
335 }
336 }
337}
338
339
340static void write_hit_record( GLcontext *ctx )
341{
342 GLuint i;
343 GLuint zmin, zmax, zscale = (~0u);
344
345 /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */
346 /* 2^32-1 and round to nearest unsigned integer. */
347
348 ASSERT( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
349 zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
350 zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
351
352 WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
353 WRITE_RECORD( ctx, zmin );
354 WRITE_RECORD( ctx, zmax );
355 for (i = 0; i < ctx->Select.NameStackDepth; i++) {
356 WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
357 }
358
359 ctx->Select.Hits++;
360 ctx->Select.HitFlag = GL_FALSE;
361 ctx->Select.HitMinZ = 1.0;
362 ctx->Select.HitMaxZ = -1.0;
363}
364
365
366
367void
368_mesa_InitNames( void )
369{
370 GET_CURRENT_CONTEXT(ctx);
371 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glInitNames");
372 /* Record the hit before the HitFlag is wiped out again. */
373 if (ctx->RenderMode == GL_SELECT) {
374 if (ctx->Select.HitFlag) {
375 write_hit_record( ctx );
376 }
377 }
378 ctx->Select.NameStackDepth = 0;
379 ctx->Select.HitFlag = GL_FALSE;
380 ctx->Select.HitMinZ = 1.0;
381 ctx->Select.HitMaxZ = 0.0;
382}
383
384
385
386void
387_mesa_LoadName( GLuint name )
388{
389 GET_CURRENT_CONTEXT(ctx);
390 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLoadName");
391 if (ctx->RenderMode != GL_SELECT) {
392 return;
393 }
394 if (ctx->Select.NameStackDepth == 0) {
395 gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
396 return;
397 }
398 if (ctx->Select.HitFlag) {
399 write_hit_record( ctx );
400 }
401 if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) {
402 ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
403 }
404 else {
405 ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
406 }
407}
408
409
410void
411_mesa_PushName( GLuint name )
412{
413 GET_CURRENT_CONTEXT(ctx);
414 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushName");
415 if (ctx->RenderMode != GL_SELECT) {
416 return;
417 }
418 if (ctx->Select.HitFlag) {
419 write_hit_record( ctx );
420 }
421 if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) {
422 ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
423 }
424 else {
425 gl_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
426 }
427}
428
429
430
431void
432_mesa_PopName( void )
433{
434 GET_CURRENT_CONTEXT(ctx);
435 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopName");
436 if (ctx->RenderMode != GL_SELECT) {
437 return;
438 }
439 if (ctx->Select.HitFlag) {
440 write_hit_record( ctx );
441 }
442 if (ctx->Select.NameStackDepth > 0) {
443 ctx->Select.NameStackDepth--;
444 }
445 else {
446 gl_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
447 }
448}
449
450
451
452/**********************************************************************/
453/* Render Mode */
454/**********************************************************************/
455
456
457
458/*
459 * NOTE: this function can't be put in a display list.
460 */
461GLint
462_mesa_RenderMode( GLenum mode )
463{
464 GET_CURRENT_CONTEXT(ctx);
465 GLint result;
466
467 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glRenderMode", 0);
468
469 if (MESA_VERBOSE & VERBOSE_API)
470 fprintf(stderr, "glRenderMode %s\n", gl_lookup_enum_by_nr(mode));
471
472 ctx->TriangleCaps &= ~(DD_FEEDBACK|DD_SELECT);
473
474 switch (ctx->RenderMode) {
475 case GL_RENDER:
476 result = 0;
477 break;
478 case GL_SELECT:
479 if (ctx->Select.HitFlag) {
480 write_hit_record( ctx );
481 }
482 if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
483 /* overflow */
484#ifdef DEBUG
485 gl_warning(ctx, "Feedback buffer overflow");
486#endif
487 result = -1;
488 }
489 else {
490 result = ctx->Select.Hits;
491 }
492 ctx->Select.BufferCount = 0;
493 ctx->Select.Hits = 0;
494 ctx->Select.NameStackDepth = 0;
495 break;
496 case GL_FEEDBACK:
497 if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
498 /* overflow */
499 result = -1;
500 }
501 else {
502 result = ctx->Feedback.Count;
503 }
504 ctx->Feedback.Count = 0;
505 break;
506 default:
507 gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
508 return 0;
509 }
510
511 switch (mode) {
512 case GL_RENDER:
513 break;
514 case GL_SELECT:
515 ctx->TriangleCaps |= DD_SELECT;
516 if (ctx->Select.BufferSize==0) {
517 /* haven't called glSelectBuffer yet */
518 gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
519 }
520 break;
521 case GL_FEEDBACK:
522 ctx->TriangleCaps |= DD_FEEDBACK;
523 if (ctx->Feedback.BufferSize==0) {
524 /* haven't called glFeedbackBuffer yet */
525 gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
526 }
527 break;
528 default:
529 gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
530 return 0;
531 }
532
533 ctx->RenderMode = mode;
534 ctx->NewState |= NEW_ALL;
535
536 return result;
537}
538
Note: See TracBrowser for help on using the repository browser.