Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / glu / sgi / libnurbs / internals / nurbsinterfac.cc
1 /*
2 ** License Applicability. Except to the extent portions of this file are
3 ** made subject to an alternative license as permitted in the SGI Free
4 ** Software License B, Version 1.1 (the "License"), the contents of this
5 ** file are subject only to the provisions of the License. You may not use
6 ** this file except in compliance with the License. You may obtain a copy
7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9 **
10 ** http://oss.sgi.com/projects/FreeB
11 **
12 ** Note that, as provided in the License, the Software is distributed on an
13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17 **
18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21 ** Copyright in any portions created by third parties is as indicated
22 ** elsewhere herein. All Rights Reserved.
23 **
24 ** Additional Notice Provisions: The application programming interfaces
25 ** established by SGI in conjunction with the Original Code are The
26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31 ** published by SGI, but has not been independently verified as being
32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
33 */
34
35 /*
36  * nurbsinterfac.c++
37  *
38  */
39
40 #include "glimports.h"
41 #include "mystdio.h"
42 #include "nurbsconsts.h"
43 #include "nurbstess.h"
44 #include "bufpool.h"
45 #include "quilt.h"
46 #include "displaylist.h"
47 #include "knotvector.h"
48 #include "mapdesc.h"
49
50 #define THREAD( work, arg, cleanup ) \
51         if( dl ) {\
52             arg->save = 1;\
53             dl->append( (PFVS)&NurbsTessellator::work, (void *) arg, (PFVS)&NurbsTessellator::cleanup );\
54         } else {\
55             arg->save = 0;\
56             work( arg );\
57         }
58
59 #define THREAD2( work ) \
60         if( dl ) {\
61             dl->append( (PFVS)&NurbsTessellator::work, 0, 0 );\
62         } else {\
63             work( );\
64         }
65
66 NurbsTessellator::NurbsTessellator( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e) 
67         : maplist( backend ),
68           backend( c, e ),
69           subdivider( renderhints, backend ),
70           o_pwlcurvePool( sizeof( O_pwlcurve ), 32, "o_pwlcurvePool" ),
71           o_nurbscurvePool( sizeof( O_nurbscurve ), 32, "o_nurbscurvePool"),
72           o_curvePool( sizeof( O_curve ), 32,  "o_curvePool" ),
73           o_trimPool( sizeof( O_trim ), 32,  "o_trimPool" ),
74           o_surfacePool( sizeof( O_surface ), 1, "o_surfacePool" ),
75           o_nurbssurfacePool( sizeof( O_nurbssurface ), 4, "o_nurbssurfacePool" ),
76           propertyPool( sizeof( Property ), 32, "propertyPool" ),
77           quiltPool( sizeof( Quilt  ), 32, "quiltPool" )
78 {
79     dl          = 0;
80     inSurface   = 0;
81     inCurve     = 0;
82     inTrim      = 0;
83     playBack    = 0;
84     jumpbuffer  = newJumpbuffer();
85     subdivider.setJumpbuffer( jumpbuffer );
86 }
87
88 NurbsTessellator::~NurbsTessellator( void ) 
89 {
90     if( inTrim ) {
91         do_nurbserror( 12 );
92         endtrim();
93     }
94
95     if( inSurface ) {
96         *nextNurbssurface = 0;
97         do_freeall();
98     }
99
100     if (jumpbuffer) {
101         deleteJumpbuffer(jumpbuffer);
102         jumpbuffer= 0;
103     }   
104 }
105
106 /*-----------------------------------------------------------------------------
107  * bgnsurface - allocate and initialize an o_surface structure
108  *
109  * Client: GL user
110  *-----------------------------------------------------------------------------
111  */
112 void
113 NurbsTessellator::bgnsurface( long nuid )
114 {
115     O_surface *o_surface = new(o_surfacePool) O_surface;
116     o_surface->nuid = nuid;
117     THREAD( do_bgnsurface, o_surface, do_freebgnsurface );
118 }
119
120 /*-----------------------------------------------------------------------------
121  * bgncurve - allocate an initialize an o_curve structure
122  * 
123  * Client: GL user
124  *-----------------------------------------------------------------------------
125  */
126 void
127 NurbsTessellator::bgncurve( long nuid )
128 {
129     O_curve *o_curve = new(o_curvePool) O_curve;
130     o_curve->nuid = nuid;
131     THREAD( do_bgncurve, o_curve, do_freebgncurve );
132 }
133 /*-----------------------------------------------------------------------------
134  * endcurve -
135  * 
136  * Client:
137  *-----------------------------------------------------------------------------
138  */
139
140 void
141 NurbsTessellator::endcurve( void )
142 {
143     THREAD2( do_endcurve );
144 }
145
146 /*-----------------------------------------------------------------------------
147  * endsurface - user level end of surface call
148  *
149  * Client: GL user
150  *-----------------------------------------------------------------------------
151  */
152 void
153 NurbsTessellator::endsurface( void )
154 {
155     THREAD2( do_endsurface );
156 }
157
158
159 /*-----------------------------------------------------------------------------
160  * bgntrim - allocate and initialize a new trim loop structure (o_trim )
161  *
162  * Client: GL user
163  *-----------------------------------------------------------------------------
164  */
165 void
166 NurbsTessellator::bgntrim( void )
167 {
168     O_trim *o_trim = new(o_trimPool) O_trim;
169     THREAD( do_bgntrim, o_trim, do_freebgntrim );
170 }
171
172 /*-----------------------------------------------------------------------------
173  * endtrim -
174  *
175  * Client: GL user
176  *-----------------------------------------------------------------------------
177  */
178 void
179 NurbsTessellator::endtrim( void )
180 {
181     THREAD2( do_endtrim );
182 }
183
184
185 /*-----------------------------------------------------------------------------
186  * pwlcurve -
187  *
188  *      count        - number of points on curve
189  *      array        - array of points on curve
190  *      byte_stride  - distance between points in bytes
191  *      type         - valid data flag
192  *
193  * Client: Gl user
194  *-----------------------------------------------------------------------------
195  */
196 void
197 NurbsTessellator::pwlcurve( long count, INREAL array[], long byte_stride, long type )
198 {
199     Mapdesc *mapdesc = maplist.locate( type );
200
201     if( mapdesc == 0 ) {
202         do_nurbserror( 35 );
203         isDataValid = 0;
204         return;
205     }
206
207     if ( (type != N_P2D) && (type != N_P2DR) ) {
208         do_nurbserror( 22 );
209         isDataValid = 0;
210         return;
211     }
212     if( count < 0 ) {
213         do_nurbserror( 33 );
214         isDataValid = 0;
215         return;
216     }
217     if( byte_stride < 0 ) {
218         do_nurbserror( 34 );
219         isDataValid = 0;
220         return;
221     }
222
223 #ifdef NOTDEF
224     if( mapdesc->isRational() ) {
225         INREAL *p = array;
226         INREAL x = p[0]; INREAL y = p[1]; INREAL w = p[2];
227         p = (INREAL *) (((char *) p) + byte_stride);
228         for( long i = 1; i != count; i++ ) {
229             if( p[0] == x && p[1] == y && p[2] == w ) break;
230             x = p[0]; y = p[1]; w = p[2];
231             p = (INREAL *) (((char *) p) + byte_stride);
232         }
233         if( i != count ) {
234             do_nurbserror( 37 );
235             _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
236             isDataValid = 0;
237             return;
238         }
239     } else {
240         INREAL *p = array;
241         INREAL x = p[0]; INREAL y = p[1];
242         p = (INREAL *) (((char *) p) + byte_stride);
243         for( long i = 1; i != count; i++ ) {
244             if( p[0] == x && p[1] == y ) break;
245             x = p[0]; y = p[1];
246             p = (INREAL *) (((char *) p) + byte_stride);
247         }
248         if( i != count ) {
249             do_nurbserror( 37 );
250             _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
251             isDataValid = 0;
252             return;
253         }
254     }
255 #endif
256
257     O_pwlcurve  *o_pwlcurve = new(o_pwlcurvePool) O_pwlcurve( type, count, array, byte_stride, extTrimVertexPool.get((int)count) );
258     THREAD( do_pwlcurve, o_pwlcurve, do_freepwlcurve );
259 }
260
261
262 /*-----------------------------------------------------------------------------
263  * nurbscurve -
264  *
265  * Client: GL user
266  *-----------------------------------------------------------------------------
267  */
268 void
269 NurbsTessellator::nurbscurve(
270     long nknots,                /* number of p knots */
271     INREAL knot[],              /* nondecreasing knot values in p */
272     long byte_stride,           /* distance in bytes between control points */
273     INREAL ctlarray[],          /* pointer to first control point */
274     long order,                 /* order of spline */
275     long type )                 /* description of range space */
276 {
277
278     Mapdesc *mapdesc = maplist.locate( type );
279
280     if( mapdesc == 0 ) {
281         do_nurbserror( 35 );
282         isDataValid = 0;
283         return;
284     }
285
286     if( ctlarray == 0 ) {
287         do_nurbserror( 36 );
288         isDataValid = 0;
289         return;
290     }
291
292     if( byte_stride < 0 ) {
293         do_nurbserror( 34 );
294         isDataValid = 0;
295         return;
296     }
297
298     Knotvector knots;
299
300     knots.init( nknots, byte_stride, order, knot );
301     if( do_check_knots( &knots, "curve" ) ) return;
302     
303     O_nurbscurve *o_nurbscurve = new(o_nurbscurvePool) O_nurbscurve(type);
304     o_nurbscurve->bezier_curves = new(quiltPool) Quilt(mapdesc);
305     o_nurbscurve->bezier_curves->toBezier( knots,ctlarray, mapdesc->getNcoords() );
306  
307     THREAD( do_nurbscurve, o_nurbscurve, do_freenurbscurve );
308 }
309
310
311 /*-----------------------------------------------------------------------------
312  * nurbssurface -
313  *
314  * Client: User routine
315  *-----------------------------------------------------------------------------
316  */
317 void
318 NurbsTessellator::nurbssurface(
319     long sknot_count,           /* number of s knots */
320     INREAL sknot[],             /* nondecreasing knot values in s */
321     long tknot_count,           /* number of t knots */
322     INREAL tknot[],             /* nondecreasing knot values in t */
323     long s_byte_stride,         /* s step size in memory bytes */
324     long t_byte_stride,         /* t step size in memory bytes */
325     INREAL ctlarray[],          /* pointer to first control point */
326     long sorder,                /* order of the spline in s parameter */
327     long torder,                /* order of the spline in t parameter */
328     long type)                  /* description of range space */
329
330     Mapdesc *mapdesc = maplist.locate( type );
331
332     if( mapdesc == 0 ) {
333         do_nurbserror( 35 );
334         isDataValid = 0;
335         return;
336     }
337
338     if( s_byte_stride < 0 ) {
339         do_nurbserror( 34 );
340         isDataValid = 0;
341         return;
342     }
343
344     if( t_byte_stride < 0 ) {
345         do_nurbserror( 34 );
346         isDataValid = 0;
347         return;
348     }
349
350     Knotvector sknotvector, tknotvector;
351
352     sknotvector.init( sknot_count, s_byte_stride, sorder, sknot );
353     if( do_check_knots( &sknotvector, "surface" ) ) return;
354
355     tknotvector.init( tknot_count, t_byte_stride, torder, tknot );
356     if( do_check_knots( &tknotvector, "surface" ) ) return;
357
358     O_nurbssurface *o_nurbssurface = new(o_nurbssurfacePool) O_nurbssurface(type);
359     o_nurbssurface->bezier_patches = new(quiltPool) Quilt(mapdesc);
360
361     o_nurbssurface->bezier_patches->toBezier( sknotvector, tknotvector,
362         ctlarray, mapdesc->getNcoords() ); 
363     THREAD( do_nurbssurface, o_nurbssurface, do_freenurbssurface );
364 }
365
366
367 /*-----------------------------------------------------------------------------
368  * setnurbsproperty -
369  * 
370  *-----------------------------------------------------------------------------
371  */
372 void
373 NurbsTessellator::setnurbsproperty( long tag, INREAL value )
374 {
375     if( ! renderhints.isProperty( tag ) ) {
376         do_nurbserror( 26 );
377     } else {
378         Property *prop = new(propertyPool) Property( tag, value );
379         THREAD( do_setnurbsproperty, prop, do_freenurbsproperty );
380     }
381 }
382
383 /*-----------------------------------------------------------------------------
384  * setnurbsproperty -
385  * 
386  *-----------------------------------------------------------------------------
387  */
388 void
389 NurbsTessellator::setnurbsproperty( long type, long tag, INREAL value )
390 {
391     Mapdesc *mapdesc = maplist.locate( type );
392
393     if( mapdesc == 0 ) {
394         do_nurbserror( 35 );
395         return;
396     }
397
398     if( ! mapdesc->isProperty( tag ) ) {
399         do_nurbserror( 26 );
400         return;
401     }
402
403     Property *prop = new(propertyPool) Property( type, tag, value );
404     THREAD( do_setnurbsproperty2, prop, do_freenurbsproperty );
405 }
406
407
408 /*-----------------------------------------------------------------------------
409  * getnurbsproperty - 
410  * 
411  *-----------------------------------------------------------------------------
412  */
413
414 void
415 NurbsTessellator::getnurbsproperty( long tag, INREAL *value )
416 {
417     if( renderhints.isProperty( tag ) ) {
418         *value = renderhints.getProperty( tag );
419     } else {
420         do_nurbserror( 26 );
421     }
422 }
423
424 /*-----------------------------------------------------------------------------
425  * getnurbsproperty - 
426  * 
427  *-----------------------------------------------------------------------------
428  */
429
430 void
431 NurbsTessellator::getnurbsproperty( long type, long tag, INREAL *value )
432 {
433     Mapdesc *mapdesc = maplist.locate( type );
434
435     if( mapdesc == 0 ) 
436         do_nurbserror( 35 );
437
438     if( mapdesc->isProperty( tag  ) ) {
439         *value = mapdesc->getProperty( tag );
440     } else {
441         do_nurbserror( 26 );
442     }
443 }
444
445 /*--------------------------------------------------------------------------
446  * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
447  *--------------------------------------------------------------------------
448  */
449
450 void 
451 NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat )
452 {
453     // XXX - cannot be put in display list
454     Mapdesc *mapdesc = maplist.locate( type );
455
456     if( mapdesc == 0 ) {
457         do_nurbserror( 35 );
458         isDataValid = 0;
459     } else if( purpose == N_BBOXSIZE ) {
460         mapdesc->setBboxsize( mat );
461     } else {
462 #ifndef NDEBUG
463         _glu_dprintf( "ERRORRORRORR!!!\n");
464 #endif
465     }
466 }
467
468 /*--------------------------------------------------------------------------
469  * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
470  *--------------------------------------------------------------------------
471  */
472
473 void 
474 NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat, 
475     long rstride, long cstride )
476 {
477     // XXX - cannot be put in display list
478     Mapdesc *mapdesc = maplist.locate( type );
479
480     if( mapdesc == 0 ) {
481         do_nurbserror( 35 );
482         isDataValid = 0;
483     } else if( purpose == N_CULLINGMATRIX ) {
484         mapdesc->setCmat( mat, rstride, cstride );
485     } else if( purpose == N_SAMPLINGMATRIX ) {
486         mapdesc->setSmat( mat, rstride, cstride );
487     } else if( purpose == N_BBOXMATRIX ) {
488         mapdesc->setBmat( mat, rstride, cstride );
489     } else {
490 #ifndef NDEBUG
491         _glu_dprintf( "ERRORRORRORR!!!\n");
492 #endif
493     }
494 }
495
496 void    
497 NurbsTessellator::redefineMaps( void )
498 {
499     maplist.initialize();
500 }
501
502 void    
503 NurbsTessellator::defineMap( long type, long rational, long ncoords )
504 {
505     maplist.define( type, (int) rational, (int) ncoords );
506 }
507
508 void 
509 NurbsTessellator::discardRecording( void *_dl )
510 {
511     delete (DisplayList *) _dl;
512 }
513
514 void * 
515 NurbsTessellator::beginRecording( void )
516 {
517     dl = new DisplayList( this );
518     return (void *) dl;
519 }
520
521 void 
522 NurbsTessellator::endRecording( void )
523 {
524     dl->endList();
525     dl = 0;
526 }
527
528 void 
529 NurbsTessellator::playRecording( void *_dl )
530 {
531     playBack = 1;
532     bgnrender();
533     ((DisplayList *)_dl)->play();
534     endrender();
535     playBack = 0;
536 }
537