1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 /*********************************************************************/
9 /*                     I.B.M. CONFIENTIAL                           */
10 /*********************************************************************/
11 
12 #include <dxconfig.h>
13 
14 
15 /*---------------------------------------------------------------------------*\
16  $Source: /src/master/dx/src/exec/hwrender/xgl/hwInteractorEchoXGL.c,v $
17 
18   These are the XGL implementations of the TDM direct interactor echos,
19   along with miscellaneous utility routines.  Each function needs to be
20   ported to the native graphics API of the target system in order to provide
21   support for direct interactors.
22 
23   Applications such as DX can be ported as a first step without direct
24   interactor facilities by stubbing out everything here.
25 
26   TDM's idea of the origin of DC space is the lower-left corner of the
27   graphics window, while XGL uses the upper-left convention.  The only
28   primitives in XGL which use device coordinates are the pixel level
29   read/write primitives.  Therefore, in order to draw in pixel space we set
30   up model and world coordinates to map to TDM's notion of DC; XGL then
31   flips the Y coordinate implicitly.  However, when we use the XGL pixel
32   read/write primitives we have to flip the Y coordinate ourselves.
33 
34  $Log: hwInteractorEchoXGL.c,v $
35  Revision 1.3  1999/05/10 15:45:39  gda
36  Copyright message
37 
38  Revision 1.3  1999/05/10 15:45:39  gda
39  Copyright message
40 
41  Revision 1.2  1999/05/03 14:06:42  gda
42  moved to using dxconfig.h rather than command-line defines
43 
44  Revision 1.1.1.1  1999/03/24 15:18:36  gda
45  Initial CVS Version
46 
47  Revision 1.1.1.1  1999/03/19 20:59:49  gda
48  Initial CVS
49 
50  Revision 10.1  1999/02/23 21:01:47  gda
51  OpenDX Baseline
52 
53  Revision 9.1  1997/05/22 22:33:11  svs
54  Copy of release 3.1.4 code
55 
56  * Revision 8.1  1996/05/03  17:54:54  gda
57  * fix(?) zoom box when NO_BACKING_STORE set
58  *
59  * Revision 8.0  1995/10/03  22:14:56  nsc
60  * Copy of release 3.1 code
61  *
62  * Revision 7.8  1995/08/30  21:09:53  c1orrang
63  * Re-doublebuffered solaris build w/ DX_SINGLE_BUFFER_SUN flag
64  *
65  * Revision 7.4  1994/06/08  20:07:53  jrush
66  * Change made in common layer to interface to SET_LINE_ATTRIBUTES
67  * from long to int32.  This has no effect other than to generate
68  * a compile time warning, thus this change.
69  * ,.
70  *
71  * Revision 7.3  1994/05/06  14:26:42  mjh
72  * Cursor interactor maintenance:  add SetLineAttributes to support dashed
73  * lines.
74  *
75  * Revision 7.2  94/03/31  15:55:11  tjm
76  * added versioning
77  *
78  * Revision 7.1  94/01/18  18:59:57  svs
79  * changes since release 2.0.1
80  *
81  * Revision 6.1  93/11/16  10:26:03  svs
82  * ship level code, release 2.0
83  *
84  * Revision 1.4  93/10/05  18:11:43  ellen
85  * Fixed Zoombox...it wasn't redrawing correctly, and
86  * was leaving the white zoom box trail.
87  *
88  * Revision 1.3  93/09/28  08:39:00  tjm
89  * fixed <DMCZAP54> garbage on screen when moving roam point
90  *
91  * Revision 1.2  93/07/14  13:28:51  tjm
92  * added solaris ifdefs
93  *
94  * Revision 1.1  93/06/29  10:01:25  tjm
95  * Initial revision
96  *
97  * Revision 5.3  93/05/11  18:04:30  mjh
98  * Implement screen door transparency for the GT.
99  *
100  * Revision 5.2  93/04/09  18:34:39  mjh
101  * replace calls to TDM_DRAW_ARROWHEAD_XGL with _dxf_DRAW_ARROWHEAD_XGL
102  *
103  * Revision 5.1  93/03/30  14:40:57  ellen
104  * Moved these files from the 5.0.2 Branch
105  *
106  * Revision 5.0.2.9  93/03/29  15:37:30  ellen
107  * Cleaned up _dxf_CREATE_CURSOR_PIXMAPS.
108  *
109  * Revision 5.0.2.8  93/03/22  18:41:56  ellen
110  * Set error in _dxf_CREATE_CURSOR_PIXMAPS if there isn't enough memory.
111  *
112  * Revision 5.0.2.7  93/02/11  20:39:55  mjh
113  * In _dxf_DRAW_GNOMON() and _dxf_DRAW_GLOBE(), use PDATA(buffermode)
114  * instead of PDATA(redrawmode) restoring the frame buffer configuration
115  * after blitting the echo from the draw buffer to the display buffer.
116  *
117  * Revision 5.0.2.6  93/02/04  19:25:36  mjh
118  * Implement cursor interactor echo.
119  *
120  * Revision 5.0.2.5  93/02/02  18:39:19  mjh
121  * Implement globe echo.  DXRemove shadow rendering code since this is
122  * very slow on the Sun GS.
123  *
124  * Revision 5.0.2.4  93/02/01  22:22:11  mjh
125  * Implement pixel read/write, gnomon and zoom box echos.
126  *
127  * The gnomon echo is no longer double-buffered as this incurs the expense
128  * of copying the display buffer to the draw buffer as part of the
129  * interactor setup, and this is quite slow with the Sun GS card.  The echo
130  * is now rendered into the draw buffer and then blitted into the display
131  * buffer.
132  *
133  * Revision 5.0.2.3  93/01/06  17:00:55  mjh
134  * window creation and destruction
135  *
136  * Revision 5.0.2.2  93/01/06  04:42:00  mjh
137  * initial revision
138  *
139 \*---------------------------------------------------------------------------*/
140 
141 #include <stdio.h>
142 #define STRUCTURES_ONLY
143 #include "hwDeclarations.h"
144 #include "hwPortXGL.h"
145 #include "hwMatrix.h"
146 #include "hwInteractor.h"
147 #include "hwInteractorEcho.h"
148 #include "hwCursorInteractor.h"
149 #include "hwRotateInteractor.h"
150 #include "hwZoomInteractor.h"
151 #include "hwGlobeEchoDef.h"
152 
153 #ifndef STANDALONE
154 #include "hwMemory.h"
155 #endif
156 
157 #include "hwPortLayer.h"
158 
159 void *
160 _dxf_ALLOCATE_PIXEL_ARRAY (void *ctx, int width, int height) ;
161 
162 void
_dxf_BUFFER_CONFIG(void * ctx,void * image,int llx,int lly,int urx,int ury,int * CurrentDisplayMode,int * CurrentBufferMode,tdmInteractorRedrawMode redrawMode)163 _dxf_BUFFER_CONFIG (void *ctx, void *image, int llx, int lly, int urx, int ury,
164 		   int *CurrentDisplayMode, int *CurrentBufferMode,
165 		   tdmInteractorRedrawMode redrawMode)
166 {
167   /*
168    *  Direct interactor echos use this and following routine to manage
169    *  double buffering.
170    */
171 
172   DEFCONTEXT(ctx) ;
173   DPRINT("\n(_dxf_BUFFER_CONFIG") ;
174 
175   if(!DOUBLE_BUFFER_MODE)
176      return;
177 
178   *CurrentBufferMode = BUFFER_CONFIG_MODE ;
179 
180   if (redrawMode == tdmBothBufferDraw ||
181       redrawMode == tdmFrontBufferDraw)
182     {
183       DPRINT1 ("\n%s", redrawMode == tdmBothBufferDraw ?
184 	       "tdmBothBufferDraw" : "tdmFrontBufferDraw") ;
185       /*
186        *  Enable the front buffer for writing.  This translates into
187        *  setting the XGL draw and display buffers to the same buffer so
188        *  that draw updates are immediately visible.
189        *
190        *  We won't be double buffering the globe and gnomon echos for the
191        *  XGL port, so we needn't be concerned with keeping the back
192        *  buffer contents identical to the front.
193        */
194 
195       if (DISPLAY_BUFFER != DRAW_BUFFER)
196 	  if (DISPLAY_BUFFER == 1)
197 	    {
198 	      xgl_object_set (XGLRAS,
199 			      XGL_WIN_RAS_BUF_DRAW, 1,
200 			      XGL_WIN_RAS_BUF_DISPLAY, 1,
201 			      NULL) ;
202 	      DRAW_BUFFER = 1 ;
203 	    }
204 	  else
205 	    {
206 	      xgl_object_set (XGLRAS,
207 			      XGL_WIN_RAS_BUF_DRAW, 0,
208 			      XGL_WIN_RAS_BUF_DISPLAY, 0,
209 			      NULL) ;
210 	      DRAW_BUFFER = 0 ;
211 	    }
212 
213       BUFFER_CONFIG_MODE = FRNTBUFFER ;
214     }
215   else if (redrawMode == tdmBackBufferDraw ||
216 	   redrawMode == tdmViewEchoMode)
217     {
218       DPRINT1 ("\n%s", redrawMode == tdmViewEchoMode ?
219 	       "tdmViewEchoMode" : "tdmBackBufferDraw") ;
220       /*
221        *  Enable the back buffer for writing.  In XGL this just means
222        *  setting the draw and display buffers not equal to each other.
223        */
224 
225       if (DISPLAY_BUFFER == DRAW_BUFFER)
226 	  if (DISPLAY_BUFFER == 1)
227 	    {
228 	      xgl_object_set (XGLRAS,
229 			      XGL_WIN_RAS_BUF_DRAW, 0,
230 			      XGL_WIN_RAS_BUF_DISPLAY, 1,
231 			      NULL) ;
232 	      DRAW_BUFFER = 0 ;
233 	    }
234 	  else
235 	    {
236 	      xgl_object_set (XGLRAS,
237 			      XGL_WIN_RAS_BUF_DRAW, 1,
238 			      XGL_WIN_RAS_BUF_DISPLAY, 0,
239 			      NULL) ;
240 	      DRAW_BUFFER = 1 ;
241 	    }
242 
243       BUFFER_CONFIG_MODE = BCKBUFFER ;
244     }
245   else
246       DPRINT("\nignoring redraw mode") ;
247 
248   DPRINT(")") ;
249 }
250 
251 
252 void
_dxf_BUFFER_RESTORE_CONFIG(void * ctx,int OrigDisplayMode,int OrigBufferMode,tdmInteractorRedrawMode redrawMode)253 _dxf_BUFFER_RESTORE_CONFIG (void *ctx, int OrigDisplayMode, int OrigBufferMode,
254 			   tdmInteractorRedrawMode redrawMode)
255 {
256   /*
257    *  Restore frame buffer configuration.
258    */
259 
260   DEFCONTEXT(ctx) ;
261   DPRINT("\n(_dxf_BUFFER_RESTORE_CONFIG") ;
262 
263   if(!DOUBLE_BUFFER_MODE)
264     return;
265 
266   if (redrawMode == tdmBothBufferDraw ||
267       redrawMode == tdmFrontBufferDraw)
268     {
269       DPRINT1("\ncurrent interactor redraw mode is %s",
270 	      redrawMode == tdmFrontBufferDraw ?
271 	      "tdmFrontBufferDraw" : "tdmBothBufferDraw") ;
272 
273       if (OrigBufferMode == BCKBUFFER)
274         {
275           DPRINT("\nrestoring to original back buffer draw") ;
276 	  if (DISPLAY_BUFFER == 1)
277 	    {
278 	      xgl_object_set (XGLRAS,
279 			      XGL_WIN_RAS_BUF_DRAW, 0,
280 			      XGL_WIN_RAS_BUF_DISPLAY, 1,
281 			      NULL) ;
282 	      DRAW_BUFFER = 0 ;
283 	    }
284 	  else
285 	    {
286 	      xgl_object_set (XGLRAS,
287 			      XGL_WIN_RAS_BUF_DRAW, 1,
288 			      XGL_WIN_RAS_BUF_DISPLAY, 0,
289 			      NULL) ;
290 	      DRAW_BUFFER = 1 ;
291 	    }
292 
293 	  BUFFER_CONFIG_MODE = BCKBUFFER ;
294 	}
295       else
296 	  DPRINT("\nremaining in original front buffer draw") ;
297     }
298   else if (redrawMode == tdmBackBufferDraw ||
299 	   redrawMode == tdmViewEchoMode)
300     {
301       DPRINT1 ("\ncurrent interactor redraw mode is %s",
302 	       redrawMode == tdmViewEchoMode ?
303 	       "tdmViewEchoMode" : "tdmBackBufferDraw") ;
304 
305       if (OrigBufferMode == FRNTBUFFER)
306         {
307           DPRINT("\nrestoring to original front buffer draw") ;
308 	  if (DISPLAY_BUFFER == 1)
309 	    {
310 	      xgl_object_set (XGLRAS,
311 			      XGL_WIN_RAS_BUF_DRAW, 1,
312 			      XGL_WIN_RAS_BUF_DISPLAY, 1,
313 			      NULL) ;
314 	      DRAW_BUFFER = 1 ;
315 	    }
316 	  else
317 	    {
318 	      xgl_object_set (XGLRAS,
319 			      XGL_WIN_RAS_BUF_DRAW, 0,
320 			      XGL_WIN_RAS_BUF_DISPLAY, 0,
321 			      NULL) ;
322 	      DRAW_BUFFER = 0 ;
323 	    }
324 
325 	  BUFFER_CONFIG_MODE = FRNTBUFFER ;
326 	}
327       else
328           DPRINT("\nremaining in original back buffer draw") ;
329     }
330   else
331       DPRINT("\nignoring redraw mode") ;
332 
333   DPRINT(")") ;
334 }
335 
336 void
_dxf_READ_BUFFER(void * ctx,int llx,int lly,int urx,int ury,void * buff)337 _dxf_READ_BUFFER(void *ctx, int llx, int lly, int urx, int ury, void *buff)
338 {
339   /*
340    *  DXRead an array of pixels from display buffer into buff.
341    */
342 
343   DEFCONTEXT(ctx) ;
344   Xgl_bounds_i2d rect ;
345 
346   DPRINT("\n(_dxf_READ_BUFFER") ;
347   DPRINT1("\nllx %d", llx) ; DPRINT1("  lly %d", lly) ;
348   DPRINT1("  urx %d", urx) ; DPRINT1("  ury %d", ury) ;
349 
350   rect.xmin = llx ;         rect.xmax = urx ;
351   rect.ymin = VP_YMAX-ury ; rect.ymax = VP_YMAX-lly ;
352 
353   /* set buff as rendering surface for temporary XGL context */
354   xgl_object_set (XGLTMPCTX, XGL_CTX_DEVICE, buff, NULL) ;
355 
356   if (DISPLAY_BUFFER == DRAW_BUFFER)
357       /* doesn't matter which buffer we read from */
358 #ifdef solaris
359       xgl_context_copy_buffer (XGLTMPCTX, &rect, NULL, XGLRAS) ;
360 #else
361       xgl_context_copy_raster (XGLTMPCTX, &rect, NULL, XGLRAS) ;
362 #endif
363   else
364       if (DISPLAY_BUFFER == 1)
365 	{
366 	  /* set draw buffer to 1 so we can read it, but don't swap display */
367 	  xgl_object_set (XGLRAS,
368 			  XGL_WIN_RAS_BUF_DRAW, 1,
369 			  XGL_WIN_RAS_BUF_DISPLAY, 1,
370 			  NULL) ;
371 
372 	  /* read pixels and reset original buffer assignments */
373 #ifdef solaris
374       xgl_context_copy_buffer (XGLTMPCTX, &rect, NULL, XGLRAS) ;
375 #else
376       xgl_context_copy_raster (XGLTMPCTX, &rect, NULL, XGLRAS) ;
377 #endif
378 	  xgl_object_set (XGLRAS,
379 			  XGL_WIN_RAS_BUF_DRAW, 0,
380 			  XGL_WIN_RAS_BUF_DISPLAY, 1,
381 			  NULL) ;
382 	}
383       else
384 	{
385 	  /* set draw buffer to 0 so we can read it, but don't swap display */
386 	  xgl_object_set (XGLRAS,
387 			  XGL_WIN_RAS_BUF_DRAW, 0,
388 			  XGL_WIN_RAS_BUF_DISPLAY, 0,
389 			  NULL) ;
390 
391 	  /* read pixels and reset original buffer assignments */
392 #ifdef solaris
393       xgl_context_copy_buffer (XGLTMPCTX, &rect, NULL, XGLRAS) ;
394 #else
395       xgl_context_copy_raster (XGLTMPCTX, &rect, NULL, XGLRAS) ;
396 #endif
397 	  xgl_object_set (XGLRAS,
398 			  XGL_WIN_RAS_BUF_DRAW, 1,
399 			  XGL_WIN_RAS_BUF_DISPLAY, 0,
400 			  NULL) ;
401 	}
402 
403   DPRINT(")") ;
404 }
405 
406 void
_dxf_WRITE_BUFFER(void * ctx,int llx,int lly,int urx,int ury,void * buff)407 _dxf_WRITE_BUFFER (void *ctx, int llx, int lly, int urx, int ury, void *buff)
408 {
409   /*
410    *  DXWrite pixel array from buff.  The entire contents of buff are written.
411    */
412 
413   DEFCONTEXT(ctx) ;
414   Xgl_pt_i2d position ;
415 
416   DPRINT("\n(_dxf_WRITE_BUFFER") ;
417   DPRINT1("\nllx %d", llx) ; DPRINT1("  lly %d", lly) ;
418   DPRINT1("  urx %d", urx) ; DPRINT1("  ury %d", ury) ;
419 
420   position.x = llx ; position.y = VP_YMAX-ury ;
421 #ifdef solaris
422   xgl_context_copy_buffer (XGLCTX, NULL, &position, buff) ;
423 #else
424   xgl_context_copy_raster (XGLCTX, NULL, &position, buff) ;
425 #endif
426 
427   DPRINT(")") ;
428 }
429 
430 void
_dxf_DRAW_GLOBE(tdmInteractor I,void * udata,float rot[4][4],int draw)431 _dxf_DRAW_GLOBE (tdmInteractor I, void *udata, float rot[4][4], int draw)
432 {
433   /*
434    *  draw == 1 to draw globe, draw == 0 to undraw.  This is done with two
435    *  separate calls in order to support explicit erasure of edges for
436    *  some implementations.  A draw is always preceded by an undraw and
437    *  the pair of invocations is assumed to be atomic.
438    */
439 
440   DEFDATA(I,tdmRotateData) ;
441   DEFPORT(I_PORT_HANDLE) ;
442   Xgl_color color ;
443   Xgl_pt_list line ;
444   Xgl_pt_f3d pos[LATS+LONGS+1] ;
445   register Xgl_pt_f3d *p ;
446   int u, v, on, dummy = 0 ;
447 
448   /* globe edge visibility flags.  all globe instance share this data. */
449   static struct {
450     int latvis, longvis ;
451   } edges[LATS][LONGS] ;
452 
453   /* globe and globeface defined in tdmGlobeEchoDef.h */
454   register float (*Globe)[LONGS][3] = (float (*)[LONGS][3])globe ;
455   register struct Face (*Globeface)[LONGS] = (struct Face(*)[LONGS])globeface ;
456 
457   /* view normal */
458   register float z0, z1, z2 ;
459   z0 = rot[0][2] ; z1 = rot[1][2] ; z2 = rot[2][2] ;
460 
461 #define FACEVISIBLE(u,v,z0,z1,z2) \
462   (Globeface[u][v].norm[0] * z0 + \
463    Globeface[u][v].norm[1] * z1 + \
464    Globeface[u][v].norm[2] * z2 > 0.0)
465 
466 #define ENDLINE { \
467   if (p != pos) xgl_multipolyline (XGLCTX, NULL, 1, &line) ; \
468   p = pos ; }
469 
470 #define MOVE(vertex) { \
471   ENDLINE ; \
472   *p = *(Xgl_pt_f3d *)vertex ; \
473   line.num_pts = 1 ; }
474 
475 #define DRAW(vertex) { \
476   *++p = *(Xgl_pt_f3d *)vertex ; \
477   line.num_pts++ ; }
478 
479   DPRINT("\n(DrawGlobe") ;
480   if (draw)
481     {
482       color.rgb.r = 1.0 ;
483       color.rgb.g = 1.0 ;
484       color.rgb.b = 1.0 ;
485       xgl_object_set (XGLCTX,
486 		      XGL_CTX_LINE_COLOR, &color,
487 		      NULL) ;
488     }
489   else
490     {
491       if (PDATA(redrawmode) != tdmViewEchoMode)
492 	{
493 	  /*
494 	   *  In tdmViewEchoMode (DX's Execute On Change), we are drawing
495 	   *  the globe echo on top of a background image that is redrawn
496 	   *  with every frame of a direct interaction.
497 	   *
498 	   *  If we're not in that mode, the background image is static
499 	   *  while the globe echo rotates in front of it, so erasing the
500 	   *  globe means we have to repair damage to the background.  We
501 	   *  do this by blitting a portion of the static image to the
502 	   *  back buffer, drawing the globe over that, then blitting the
503 	   *  combined results back to the front buffer.
504 	   */
505 
506 	  /* force graphics output into back (draw) buffer */
507 	  _dxf_BUFFER_CONFIG (PORT_CTX, &dummy, dummy, dummy, dummy, dummy,
508 			     &dummy, &dummy, tdmBackBufferDraw) ;
509 
510 	  /* erase globe background */
511 	  _dxf_WRITE_BUFFER (PORT_CTX, PDATA(illx), PDATA(illy),
512 			    PDATA(iurx), PDATA(iury), PDATA(background)) ;
513 	}
514 
515       DPRINT(")") ;
516       return ;
517     }
518 
519   /* mark visible edges */
520   for (u=0 ; u<LATS-1 ; u++)
521     {
522       if (FACEVISIBLE(u, 0, z0, z1, z2))
523 	{
524 	  edges[u][LONGS-1].latvis++ ;
525 	  edges[u+1][LONGS-1].latvis++ ;
526 	  edges[u][0].longvis++ ;
527 	  edges[u][LONGS-1].longvis++ ;
528 	}
529       for (v=1 ; v<LONGS ; v++)
530 	  if (FACEVISIBLE(u, v, z0, z1, z2))
531 	    {
532 	      edges[u][v-1].latvis++ ;
533 	      edges[u+1][v-1].latvis++ ;
534 	      edges[u][v].longvis++ ;
535 	      edges[u][v-1].longvis++ ;
536 	    }
537     }
538 
539   /* north pole */
540   if (z1 > 0.0)
541       for (v=0 ; v<LONGS ; v++)
542 	  edges[LATS-1][v].latvis++ ;
543 
544   /* south pole */
545   if (z1 < 0.0)
546       for (v=0 ; v<LONGS ; v++)
547 	  edges[0][v].latvis++ ;
548 
549   /* set up XGL point list */
550   line.pt_type = XGL_PT_F3D ;
551   line.bbox = NULL ;
552   line.pts.f3d = p = pos ;
553 
554   /* draw each visible edge exactly once */
555   for (u=0 ; u<LATS ; u++)
556     {
557       /* latitude lines */
558       for (v=0, on=0 ; v<LONGS-1 ; v++)
559           if (edges[u][v].latvis)
560             {
561               if (!on)
562                 {
563                   on = 1 ;
564 		  MOVE(Globe[u][v]) ;
565                 }
566 	      DRAW(Globe[u][v+1]) ;
567               edges[u][v].latvis = 0 ;
568             }
569           else on = 0 ;
570 
571       /* close latitude line if necessary */
572       if (edges[u][LONGS-1].latvis)
573         {
574           if (!on) MOVE(Globe[u][LONGS-1]) ;
575 
576 	  DRAW(Globe[u][0]) ;
577           edges[u][LONGS-1].latvis = 0 ;
578         }
579     }
580 
581   for (v=0 ; v<LONGS ; v++)
582       /* longitude lines */
583       for (u=0, on=0 ; u<LATS-1 ; u++)
584           if (edges[u][v].longvis)
585             {
586               if (!on)
587                 {
588                   on = 1 ;
589 		  MOVE(Globe[u][v]) ;
590                 }
591 	      DRAW(Globe[u+1][v]) ;
592               edges[u][v].longvis = 0 ;
593             }
594           else on = 0 ;
595 
596   ENDLINE ;
597 
598   if (PDATA(redrawmode) != tdmViewEchoMode)
599     {
600       /* copy rendered globe from draw buffer to display buffer */
601       Xgl_bounds_i2d rect ;
602       Xgl_pt_i2d position ;
603 
604       position.x = PDATA(illx) ; position.y = VP_YMAX-PDATA(iury) ;
605       rect.xmin =  PDATA(illx) ;  rect.ymin = VP_YMAX-PDATA(iury) ;
606       rect.xmax =  PDATA(iurx) ;  rect.ymax = VP_YMAX-PDATA(illy) ;
607 
608       /* ensure that draw buffer rendering is completed */
609       xgl_context_post (XGLCTX, 0) ;
610 
611       /* copy the combined globe and background image to display buffer */
612 #ifdef solaris
613       xgl_object_set (XGLRAS,
614 		      XGL_RAS_SOURCE_BUFFER, DRAW_BUFFER,
615 		      NULL) ;
616 
617       /* Set XGLCTX output dest to XGL_RENDER_DISPLAY_BUFFER
618 	 ( == DISPLAY_BUFFER) */
619       xgl_object_set (XGLCTX,
620 		      XGL_CTX_RENDER_BUFFER, XGL_RENDER_DISPLAY_BUFFER,
621 		      NULL) ;
622       xgl_context_copy_buffer
623 	  (XGLCTX, &rect, &position, XGLRAS) ;
624 
625       /* Reset XGLCTX output dest to default */
626       xgl_object_set (XGLCTX,
627 		      XGL_CTX_RENDER_BUFFER, XGL_RENDER_DRAW_BUFFER,
628 		      NULL) ;
629 #else
630       xgl_context_copy_buffer
631 	  (XGLCTX, &rect, &position, DRAW_BUFFER, DISPLAY_BUFFER) ;
632 #endif
633 
634       _dxf_BUFFER_RESTORE_CONFIG
635 	  (PORT_CTX, dummy, PDATA(buffermode), tdmBackBufferDraw) ;
636     }
637   DPRINT(")") ;
638 }
639 
640 void
_dxf_DRAW_ARROWHEAD(void * ctx,float ax,float ay)641 _dxf_DRAW_ARROWHEAD (void *ctx, float ax, float ay)
642 {
643   DEFCONTEXT(ctx) ;
644   Xgl_pt_list line ;
645   Xgl_pt_f3d verts[3] ;
646   double angle, hyp, length ;
647   float x1, y1 ;
648 
649   /* set up XGL point list */
650   line.pt_type = XGL_PT_F3D ;
651   line.bbox = NULL ;
652   line.num_pts = 3 ;
653   line.pts.f3d = verts ;
654   verts[1].x = ax ;
655   verts[1].y = ay ;
656   verts[0].z = 0 ;
657   verts[1].z = 0 ;
658   verts[2].z = 0 ;
659 
660   hyp = sqrt(ax*ax + ay*ay) ;
661 
662   if (hyp == 0.0)
663       return ;
664 
665   if (hyp < 0.2)
666       length = 0.06 ;
667   else
668       length = 0.12 ;
669 
670   /* To avoid acos DOMAIN errors due to floating point inaccuracies */
671   if (-ax/hyp > 1.0)
672     hyp = -ax;
673   if (-ax/hyp < -1.0)
674     hyp = ax;
675 
676   angle = acos((double)(-ax/hyp)) ;
677   if (ay > 0)
678       angle = 2*M_PI - angle ;
679 
680   angle = angle + M_PI/6 ;
681   if (angle > 2*M_PI)
682       angle = angle - 2*M_PI ;
683 
684   x1 = cos(angle) * length ;
685   y1 = sin(angle) * length ;
686 
687   verts[0].x = ax + x1 ;
688   verts[0].y = ay + y1 ;
689 
690   angle = angle - M_PI/3 ;
691   if (angle < 0)
692       angle = angle + 2*M_PI ;
693 
694   x1 = cos(angle) * length ;
695   y1 = sin(angle) * length ;
696 
697   verts[2].x = ax + x1 ;
698   verts[2].y = ay + y1 ;
699 
700   xgl_multipolyline (XGLCTX, NULL, 1, &line) ;
701 }
702 
703 void
_dxf_DRAW_GNOMON(tdmInteractor I,void * udata,float rot[4][4],int draw)704 _dxf_DRAW_GNOMON (tdmInteractor I, void *udata, float rot[4][4], int draw)
705 {
706   /*
707    *  draw == 1 to draw gnomon, draw == 0 to undraw.  This is done with
708    *  two separate calls in order to support explicit erasure of edges for
709    *  some implementations.  A draw is always preceded by an undraw and
710    *  the pair of invocations is assumed to be atomic.
711    *
712    *  Computations are done in normalized screen coordinates in order to
713    *  render arrow heads correctly.
714    */
715 
716   DEFDATA(I,tdmRotateData) ;
717   DEFPORT(I_PORT_HANDLE) ;
718   Xgl_color color ;
719   Xgl_pt_list line ;
720   Xgl_pt_f3d pos[2] ;
721   int dummy = 0 ;
722 
723   float origin[2] ;
724   float xaxis[2],  yaxis[2],  zaxis[2] ;
725   float xlabel[2], ylabel[2], zlabel[2] ;
726 
727   DPRINT("\n(DrawGnomon") ;
728 
729   if (draw)
730     {
731       color.rgb.r = 1.0 ;
732       color.rgb.g = 1.0 ;
733       color.rgb.b = 1.0 ;
734       xgl_object_set (XGLCTX,
735 		      XGL_CTX_LINE_COLOR, &color,
736 #ifdef solaris
737 		      XGL_CTX_STEXT_COLOR, &color,
738 #else
739 		      XGL_CTX_SFONT_TEXT_COLOR, &color,
740 #endif
741 		      NULL) ;
742     }
743   else
744     {
745       if (PDATA(redrawmode) != tdmViewEchoMode)
746 	{
747 	  /*
748 	   *  In tdmViewEchoMode (DX's Execute On Change), we are drawing
749 	   *  the gnomon echo on top of a background image that is redrawn
750 	   *  with every frame of a direct interaction.
751 	   *
752 	   *  If we're not in that mode, the background image is static
753 	   *  while the gnomon echo rotates in front of it, so erasing the
754 	   *  gnomon means we have to repair damage to the background.  We
755 	   *  do this by blitting a portion of the static image to the
756 	   *  back buffer, drawing the gnomon over that, then blitting the
757 	   *  combined results back to the front buffer.
758 	   */
759 
760 	  /* force graphics output into back (draw) buffer */
761 	  _dxf_BUFFER_CONFIG (PORT_CTX, &dummy, dummy, dummy, dummy, dummy,
762 			     &dummy, &dummy, tdmBackBufferDraw) ;
763 
764 	  /* erase gnomon background */
765 	  _dxf_WRITE_BUFFER (PORT_CTX, PDATA(illx), PDATA(illy),
766 			    PDATA(iurx), PDATA(iury), PDATA(background)) ;
767 	}
768 
769       DPRINT(")") ;
770       return ;
771     }
772 
773   origin[0] = 0.0 ;
774   origin[1] = 0.0 ;
775 
776   xaxis[0] = 0.7 * rot[0][0] ; xaxis[1] = 0.7 * rot[0][1] ;
777   yaxis[0] = 0.7 * rot[1][0] ; yaxis[1] = 0.7 * rot[1][1] ;
778   zaxis[0] = 0.7 * rot[2][0] ; zaxis[1] = 0.7 * rot[2][1] ;
779 
780   /* set up normalized coordinates */
781   _dxf_PUSH_REPLACE_MATRIX (PORT_CTX, (float (*)[4])identity) ;
782 
783   /* set up XGL point list */
784   line.pt_type = XGL_PT_F3D ;
785   line.bbox = NULL ;
786   line.num_pts = 2 ;
787   line.pts.f3d = pos ;
788   pos[0].x = origin[0] ;
789   pos[0].y = origin[1] ;
790   pos[0].z = 0 ;
791   pos[1].z = 0 ;
792 
793   /* draw x axis */
794   pos[1].x = xaxis[0] ;
795   pos[1].y = xaxis[1] ;
796   xgl_multipolyline (XGLCTX, NULL, 1, &line) ;
797   _dxf_DRAW_ARROWHEAD (PORT_CTX, xaxis[0], xaxis[1]) ;
798 
799   /* draw y axis */
800   pos[1].x = yaxis[0] ;
801   pos[1].y = yaxis[1] ;
802   xgl_multipolyline (XGLCTX, NULL, 1, &line) ;
803   _dxf_DRAW_ARROWHEAD (PORT_CTX, yaxis[0], yaxis[1]) ;
804 
805   /* draw z axis */
806   pos[1].x = zaxis[0] ;
807   pos[1].y = zaxis[1] ;
808   xgl_multipolyline (XGLCTX, NULL, 1, &line) ;
809   _dxf_DRAW_ARROWHEAD (PORT_CTX, zaxis[0], zaxis[1]) ;
810 
811   /* compute axes label positions */
812   xlabel[0] = 0.8 * rot[0][0] ; xlabel[1] = 0.8 * rot[0][1] ;
813   ylabel[0] = 0.8 * rot[1][0] ; ylabel[1] = 0.8 * rot[1][1] ;
814   zlabel[0] = 0.8 * rot[2][0] ; zlabel[1] = 0.8 * rot[2][1] ;
815 
816   /* move labels left and/or down if they're going to hit arrowheads */
817   if (xlabel[0] <= 0) xlabel[0] -= 0.15 ;
818   if (xlabel[1] <= 0) xlabel[1] -= 0.15 ;
819 
820   if (ylabel[0] <= 0) ylabel[0] -= 0.15 ;
821   if (ylabel[1] <= 0) ylabel[1] -= 0.15 ;
822 
823   if (zlabel[0] <= 0) zlabel[0] -= 0.15 ;
824   if (zlabel[1] <= 0) zlabel[1] -= 0.15 ;
825 
826   /* render the axes labels */
827   pos[1].x = 0 ; pos[1].y = 0 ;
828 #ifdef solaris
829   xgl_object_set (XGLCTX, XGL_CTX_ATEXT_CHAR_HEIGHT, 0.15, 0) ;
830 #else
831   xgl_object_set (XGLCTX, XGL_CTX_ANNOT_CHAR_HEIGHT, 0.15, 0) ;
832 #endif
833 
834   pos[0].x = xlabel[0] ; pos[0].y = xlabel[1] ;
835   xgl_annotation_text (XGLCTX, "X", &pos[0], &pos[1]) ;
836 
837   pos[0].x = ylabel[0] ; pos[0].y = ylabel[1] ;
838   xgl_annotation_text (XGLCTX, "Y", &pos[0], &pos[1]) ;
839 
840   pos[0].x = zlabel[0] ; pos[0].y = zlabel[1] ;
841   xgl_annotation_text (XGLCTX, "Z", &pos[0], &pos[1]) ;
842 
843   /* return to pushed coordinate system */
844   _dxf_POP_MATRIX(PORT_CTX) ;
845 
846   if (PDATA(redrawmode) != tdmViewEchoMode)
847     {
848       /* copy draw buffer to display buffer */
849       Xgl_bounds_i2d rect ;
850       Xgl_pt_i2d position ;
851 
852       position.x = PDATA(illx) ; position.y = VP_YMAX-PDATA(iury) ;
853       rect.xmin =  PDATA(illx) ;  rect.ymin = VP_YMAX-PDATA(iury) ;
854       rect.xmax =  PDATA(iurx) ;  rect.ymax = VP_YMAX-PDATA(illy) ;
855 
856       /* ensure that draw buffer rendering is completed */
857       xgl_context_post (XGLCTX, 0) ;
858 
859       /* copy the combined gnomon and background image to display buffer */
860 #ifdef solaris
861       xgl_object_set (XGLRAS,
862 		      XGL_RAS_SOURCE_BUFFER, DRAW_BUFFER,
863 		      NULL) ;
864       xgl_object_set (XGLCTX,
865 		      XGL_CTX_RENDER_BUFFER, XGL_RENDER_DISPLAY_BUFFER,
866 		      NULL) ;
867       xgl_context_copy_buffer
868 	  (XGLCTX, &rect, &position, XGLRAS) ;
869       xgl_object_set (XGLCTX,
870 		      XGL_CTX_RENDER_BUFFER, XGL_RENDER_DRAW_BUFFER,
871 		      NULL) ;
872 #else
873       xgl_context_copy_buffer
874 	  (XGLCTX, &rect, &position, DRAW_BUFFER, DISPLAY_BUFFER) ;
875 #endif
876 
877       _dxf_BUFFER_RESTORE_CONFIG
878 	  (PORT_CTX, dummy, PDATA(buffermode), tdmBackBufferDraw) ;
879     }
880 
881   DPRINT(")") ;
882 }
883 
884 
885 static void
_dxf_captureZoomBox(tdmInteractor I,void * udata,float rot[4][4])886 _dxf_captureZoomBox (tdmInteractor I, void *udata, float rot[4][4])
887 {
888   DEFDATA(I,tdmZoomData) ;
889   DEFPORT(I_PORT_HANDLE) ;
890   Xgl_bounds_i2d rect ;
891   Xgl_pt_i2d position ;
892   int x1, y1, x2, y2 ;
893 
894   xgl_object_set(XGLTMPCTX, XGL_CTX_DEVICE, CDATA(image), NULL);
895 
896   /* left */
897   rect.xmin =  MAX(0,x1-1) ;       rect.xmax =  rect.xmin + 1 ;
898   rect.ymin =  MAX(0,VP_YMAX-y2) ; rect.ymax =  MAX(0,VP_YMAX-y1) ;
899   position.x = rect.xmin ;         position.y = rect.ymin ;
900 #ifdef solaris
901   xgl_context_copy_buffer (XGLTMPCTX, &rect, &position, XGLRAS);
902 #else
903   xgl_context_copy_raster (XGLTMPCTX, &rect, &position, XGLRAS);
904 #endif
905 
906       /* right */
907   rect.xmin =  MAX(0,x2-1) ;       rect.xmax =  rect.xmin + 1 ;
908   rect.ymin =  MAX(0,VP_YMAX-y2) ; rect.ymax =  MAX(0,VP_YMAX-y1) ;
909   position.x = rect.xmin ;         position.y = rect.ymin ;
910 #ifdef solaris
911   xgl_context_copy_buffer (XGLTMPCTX, &rect, &position, XGLRAS);
912 #else
913   xgl_context_copy_raster (XGLTMPCTX, &rect, &position, XGLRAS);
914 #endif
915 
916   /* bottom */
917   rect.xmin =  MAX(0,x1) ;         rect.xmax =  MAX(0,x2) ;
918   rect.ymin =  MAX(0,VP_YMAX-y1-1) ; rect.ymax =  rect.ymin + 1 ;
919   position.x = rect.xmin ;         position.y = rect.ymin ;
920 #ifdef solaris
921   xgl_context_copy_buffer (XGLTMPCTX, &rect, &position, XGLRAS);
922 #else
923   xgl_context_copy_raster (XGLTMPCTX, &rect, &position, XGLRAS);
924 #endif
925 
926   /* top */
927   rect.xmin =  MAX(0,x1) ;         rect.xmax =  MAX(0,x2) ;
928   rect.ymin =  MAX(0,VP_YMAX-y2-1) ; rect.ymax =  rect.ymin + 1 ;
929   position.x = rect.xmin ;         position.y = rect.ymin ;
930 #ifdef solaris
931   xgl_context_copy_buffer (XGLTMPCTX, &rect, &position, XGLRAS);
932 #else
933   xgl_context_copy_raster (XGLTMPCTX, &rect, &position, XGLRAS);
934 #endif
935 }
936 
937 static void
_dxf_restoreZoomBox(tdmInteractor I,void * udata,float rot[4][4])938 _dxf_restoreZoomBox (tdmInteractor I, void *udata, float rot[4][4])
939 {
940   DEFDATA(I,tdmZoomData) ;
941   DEFPORT(I_PORT_HANDLE) ;
942   Xgl_bounds_i2d rect ;
943   Xgl_pt_i2d position ;
944   int x1, y1, x2, y2 ;
945 
946   /*
947    *  Repair the image by blitting pixels from backing store.  The
948    *  blits are expressed in XGL's notion of device coordinates, so we
949    *  must flip the Y coordinates.
950    */
951 
952   /* left */
953   rect.xmin =  MAX(0,x1-1) ;       rect.xmax =  rect.xmin + 1 ;
954   rect.ymin =  MAX(0,VP_YMAX-y2) ; rect.ymax =  MAX(0,VP_YMAX-y1) ;
955   position.x = rect.xmin ;         position.y = rect.ymin ;
956 #ifdef solaris
957   xgl_context_copy_buffer (XGLCTX, &rect, &position, CDATA(image)) ;
958 #else
959   xgl_context_copy_raster (XGLCTX, &rect, &position, CDATA(image)) ;
960 #endif
961 
962       /* right */
963   rect.xmin =  MAX(0,x2-1) ;       rect.xmax =  rect.xmin + 1 ;
964   rect.ymin =  MAX(0,VP_YMAX-y2) ; rect.ymax =  MAX(0,VP_YMAX-y1) ;
965   position.x = rect.xmin ;         position.y = rect.ymin ;
966 #ifdef solaris
967   xgl_context_copy_buffer (XGLCTX, &rect, &position, CDATA(image)) ;
968 #else
969   xgl_context_copy_raster (XGLCTX, &rect, &position, CDATA(image)) ;
970 #endif
971 
972   /* bottom */
973   rect.xmin =  MAX(0,x1) ;         rect.xmax =  MAX(0,x2) ;
974   rect.ymin =  MAX(0,VP_YMAX-y1-1) ; rect.ymax =  rect.ymin + 1 ;
975   position.x = rect.xmin ;         position.y = rect.ymin ;
976 #ifdef solaris
977   xgl_context_copy_buffer (XGLCTX, &rect, &position, CDATA(image)) ;
978 #else
979   xgl_context_copy_raster (XGLCTX, &rect, &position, CDATA(image)) ;
980 #endif
981 
982   /* top */
983   rect.xmin =  MAX(0,x1) ;         rect.xmax =  MAX(0,x2) ;
984   rect.ymin =  MAX(0,VP_YMAX-y2-1) ; rect.ymax =  rect.ymin + 1 ;
985   position.x = rect.xmin ;         position.y = rect.ymin ;
986 #ifdef solaris
987   xgl_context_copy_buffer (XGLCTX, &rect, &position, CDATA(image)) ;
988 #else
989   xgl_context_copy_raster (XGLCTX, &rect, &position, CDATA(image)) ;
990 #endif
991 }
992 
993 #undef _dxf_SERVICES_FLAGS
994 extern hwFlags _dxf_SERVICES_FLAGS();
995 
996 void
_dxf_DRAW_ZOOMBOX(tdmInteractor I,void * udata,float rot[4][4],int draw)997 _dxf_DRAW_ZOOMBOX (tdmInteractor I, void *udata, float rot[4][4], int draw)
998 {
999   /*
1000    *  draw == 1 to draw zoombox, draw == 0 to undraw.  This is done with
1001    *  two separate calls in order to support explicit erasure.
1002    */
1003 
1004   DEFDATA(I,tdmZoomData) ;
1005   DEFPORT(I_PORT_HANDLE) ;
1006   int x1, y1, x2, y2 ;
1007   DPRINT("\n(DrawZoomBox") ;
1008 
1009   x1 = PDATA(x1) ; x2 = PDATA(x2) ;
1010   y1 = PDATA(y1) ; y2 = PDATA(y2) ;
1011 
1012   if (draw)
1013     {
1014       /*
1015        *  Coordinates are expressed in TDM's notion of device coordinates,
1016        *  so _dxf_SET_WORLD_SCREEN() needs to be called before this routine
1017        *  is invoked.
1018        */
1019 
1020       Xgl_color color ;
1021       Xgl_pt_list box ;
1022       Xgl_pt_f3d pos[5] ;
1023 
1024       if (_dxf_isFlagsSet(_dxf_SERVICES_FLAGS(), SF_INVALIDATE_BACKSTORE))
1025 	      _dxf_captureZoomBox(I, udata, rot);
1026 
1027       color.rgb.r = 1.0 ; color.rgb.g = 1.0 ; color.rgb.b = 1.0 ;
1028       xgl_object_set (XGLCTX,
1029 		      XGL_CTX_LINE_COLOR, &color,
1030 		      NULL) ;
1031 
1032       box.pt_type = XGL_PT_F3D ;
1033       box.bbox = NULL ;
1034       box.num_pts = 5 ;
1035       box.pts.f3d = pos ;
1036 
1037       pos[0].x = x1 ; pos[0].y = y1 ; pos[0].z = 0 ;
1038       pos[1].x = x2 ; pos[1].y = y1 ; pos[1].z = 0 ;
1039       pos[2].x = x2 ; pos[2].y = y2 ; pos[2].z = 0 ;
1040       pos[3].x = x1 ; pos[3].y = y2 ; pos[3].z = 0 ;
1041       pos[4].x = x1 ; pos[4].y = y1 ; pos[4].z = 0 ;
1042 
1043       xgl_multipolyline (XGLCTX, NULL, 1, &box) ;
1044       xgl_context_post (XGLCTX, 0) ;
1045     }
1046   else if (CDATA(image))
1047     {
1048 	_dxf_restoreZoomBox(I, udata, rot);
1049     }
1050   else
1051     {
1052       DPRINT("\nno backing store to erase zoombox") ;
1053     }
1054 
1055   DPRINT(")") ;
1056 }
1057 
1058 
1059 int
_dxf_GET_ZBUFFER_STATUS(void * ctx)1060 _dxf_GET_ZBUFFER_STATUS (void *ctx)
1061 {
1062   /*
1063    *  return whether zbuffer is active or not
1064    */
1065 
1066   DEFCONTEXT(ctx) ;
1067   Xgl_hlhsr_mode zmode ;
1068   int status ;
1069   DPRINT("\n(_dxf_GET_ZBUFFER_STATUS:") ;
1070 
1071   xgl_object_get (XGLCTX, XGL_3D_CTX_HLHSR_MODE, &zmode) ;
1072   if (zmode == XGL_HLHSR_NONE)
1073       status = 0 ;
1074   else
1075       status = 1 ;
1076 
1077   DPRINT1 ("%d)", status) ;
1078   return status ;
1079 }
1080 
1081 void
_dxf_SET_ZBUFFER_STATUS(void * ctx,int status)1082 _dxf_SET_ZBUFFER_STATUS (void *ctx, int status)
1083 {
1084   /*
1085    *  set zbuffer off or on
1086    */
1087 
1088   DEFCONTEXT(ctx) ;
1089   DPRINT1 ("\n(_dxf_SET_ZBUFFER_STATUS:%d", status) ;
1090 
1091   if (status)
1092 #ifdef solaris
1093       xgl_object_set (XGLCTX, XGL_3D_CTX_HLHSR_MODE, XGL_HLHSR_Z_BUFFER, 0) ;
1094 #else
1095       xgl_object_set (XGLCTX, XGL_3D_CTX_HLHSR_MODE, XGL_HLHSR_ZBUFFER, 0) ;
1096 #endif
1097   else
1098       xgl_object_set (XGLCTX, XGL_3D_CTX_HLHSR_MODE, XGL_HLHSR_NONE, 0) ;
1099 
1100   DPRINT(")") ;
1101 }
1102 
1103 void
_dxf_SET_SOLID_FILL_PATTERN(void * ctx)1104 _dxf_SET_SOLID_FILL_PATTERN (void *ctx)
1105 {
1106   /*
1107    *  reset screen door half transparency to solid if used
1108    */
1109 
1110   DEFCONTEXT(ctx) ;
1111   DPRINT("\n(_dxf_SET_SOLID_FILL_PATTERN") ;
1112 
1113   xgl_object_set
1114       (XGLCTX,
1115        XGL_CTX_SURF_FRONT_FILL_STYLE, XGL_SURF_FILL_SOLID,
1116        NULL) ;
1117 
1118   DPRINT(")") ;
1119 }
1120 
1121 void
_dxf_GET_WINDOW_ORIGIN(void * ctx,int * x,int * y)1122 _dxf_GET_WINDOW_ORIGIN (void *ctx, int *x, int *y)
1123 {
1124   /*
1125    *  return LL corner of window relative to LL corner of screen in pixels
1126    */
1127 
1128   DEFCONTEXT(ctx) ;
1129   Xgl_pt_i2d origin ;
1130   DPRINT("\n(_dxf_GET_WINDOW_ORIGIN") ;
1131 
1132   xgl_object_get (XGLRAS, XGL_WIN_RAS_POSITION, &origin) ;
1133 
1134   *y = SCREEN_YMAX - (origin.y + VP_YMAX) ;
1135   *x = origin.x ;
1136 
1137   DPRINT1 ("\n%d,", *x) ; DPRINT1 (" %d)", *y) ;
1138 }
1139 
1140 void
_dxf_GET_MAXSCREEN(void * ctx,int * x,int * y)1141 _dxf_GET_MAXSCREEN (void *ctx, int *x, int *y)
1142 {
1143   /*
1144    *  return maximum coordinates of entire screen in pixels
1145    */
1146 
1147   DEFCONTEXT(ctx) ;
1148   DPRINT("\n(_dxf_GET_MAXSCREEN") ;
1149 
1150   *x = SCREEN_XMAX ;
1151   *y = SCREEN_YMAX ;
1152   DPRINT1 ("\n%d,", *x) ; DPRINT1 (" %d)", *y) ;
1153 }
1154 
1155 void
_dxf_SET_WORLD_SCREEN(void * ctx,int w,int h)1156 _dxf_SET_WORLD_SCREEN (void *ctx, int w, int h)
1157 {
1158   /*
1159    *  This routine can be ignored if API can write directly to DC,
1160    *  otherwise, must set up transforms for screen mode.
1161    */
1162 
1163   DEFCONTEXT(ctx) ;
1164   float S[4][4], xs, ys ;
1165   DPRINT("\n(_dxf_SET_WORLD_SCREEN") ;
1166 
1167   xs = 2.0 / ((w-1) + 0.5) ;
1168   ys = 2.0 / ((h-1) + 0.5) ;
1169 
1170   S[0][0] = xs ; S[0][1] =  0 ; S[0][2] = 0 ; S[0][3] = 0 ;
1171   S[1][0] =  0 ; S[1][1] = ys ; S[1][2] = 0 ; S[1][3] = 0 ;
1172   S[2][0] =  0 ; S[2][1] =  0 ; S[2][2] = 1 ; S[2][3] = 0 ;
1173   S[3][0] = -1 ; S[3][1] = -1 ; S[3][2] = 0 ; S[3][3] = 1 ;
1174 
1175   _dxf_SET_VIEWPORT (ctx, 0, w-1, 0, h-1) ;
1176   xgl_transform_write (PROJECTION_TRANSFORM, S) ;
1177   xgl_transform_write (MODEL_VIEW_TRANSFORM, identity) ;
1178 
1179   DPRINT(")") ;
1180 }
1181 
1182 void
_dxf_CREATE_CURSOR_PIXMAPS(tdmInteractor I)1183 _dxf_CREATE_CURSOR_PIXMAPS (tdmInteractor I)
1184 {
1185   /*
1186    *  Cursors are pixmaps used for representing probe/roam positions.
1187    */
1188 
1189   DEFDATA(I,CursorData) ;
1190   DEFPORT(I_PORT_HANDLE) ;
1191   Xgl_pt_i2d pos ;
1192   Xgl_color black, gray, green, white ;
1193   DPRINT("\n(xglTDM_CREATE_CURSOR_PIXMAPS") ;
1194 
1195   /* set up XGL rgb colors */
1196   green.rgb.r = 0.0 ;  green.rgb.g = 1.0 ; green.rgb.b = 0.0 ;
1197   gray.rgb.r  = 0.5 ;   gray.rgb.g = 0.5 ;  gray.rgb.b = 0.5 ;
1198   black.rgb.r = 0.0 ;  black.rgb.g = 0.0 ; black.rgb.b = 0.0 ;
1199   white.rgb.r = 1.0 ;  white.rgb.g = 1.0 ; white.rgb.b = 1.0 ;
1200 
1201   /* Initialize the Interactors */
1202   PDATA(cursor_saveunder) = PDATA(ActiveSquareCursor) =
1203         PDATA(PassiveSquareCursor) = PDATA(ProjectionMark) = NULL ;
1204 
1205   /* allocate a cursor save-under for the roam/probe interactor */
1206   if ( !(PDATA(cursor_saveunder) = _dxf_ALLOCATE_PIXEL_ARRAY (PORT_CTX,
1207 		PDATA(cursor_size), PDATA(cursor_size)) ))  goto error ;
1208 
1209   /* allocate and init active cursor pixmap: green outline, black interior */
1210   if ( !(PDATA(ActiveSquareCursor) = _dxf_ALLOCATE_PIXEL_ARRAY (PORT_CTX,
1211 		PDATA(cursor_size), PDATA(cursor_size)) ))  goto error ;
1212 
1213   /* set pixel array as rendering surface for temporary XGL context */
1214   xgl_object_set (XGLTMPCTX, XGL_CTX_DEVICE, PDATA(ActiveSquareCursor), NULL) ;
1215 
1216   for (pos.x=0 ; pos.x<PDATA(cursor_size) ; pos.x++)
1217       for (pos.y=0 ; pos.y<PDATA(cursor_size) ; pos.y++)
1218 	  if (pos.x==0 || pos.x==PDATA(cursor_size)-1 ||
1219 	      pos.y==0 || pos.y==PDATA(cursor_size)-1 )
1220 
1221 	      xgl_context_set_pixel (XGLTMPCTX, &pos, &green) ;
1222 	  else
1223 	      xgl_context_set_pixel (XGLTMPCTX, &pos, &black) ;
1224 
1225   /* allocate and init passive cursor pixmap: gray outline, black interior */
1226   if ( !(PDATA(PassiveSquareCursor) = _dxf_ALLOCATE_PIXEL_ARRAY (PORT_CTX,
1227 		PDATA(cursor_size), PDATA(cursor_size)) )) goto error ;
1228 
1229   /* set pixel array as rendering surface for temporary XGL context */
1230   xgl_object_set (XGLTMPCTX,
1231 		  XGL_CTX_DEVICE, PDATA(PassiveSquareCursor),
1232 		  NULL) ;
1233 
1234   for (pos.x=0 ; pos.x<PDATA(cursor_size) ; pos.x++)
1235       for (pos.y=0 ; pos.y<PDATA(cursor_size) ; pos.y++)
1236 	  if (pos.x==0 || pos.x==PDATA(cursor_size)-1 ||
1237 	      pos.y==0 || pos.y==PDATA(cursor_size)-1 )
1238 
1239 	      xgl_context_set_pixel (XGLTMPCTX, &pos, &gray) ;
1240 	  else
1241 	      xgl_context_set_pixel (XGLTMPCTX, &pos, &black) ;
1242 
1243   /* allocate and init projection mark pixmap */
1244   if ( !(PDATA(ProjectionMark) = _dxf_ALLOCATE_PIXEL_ARRAY (PORT_CTX, 3, 3)) )
1245 	goto error ;
1246 
1247   /* set pixel array as rendering surface for temporary XGL context */
1248   xgl_object_set (XGLTMPCTX,
1249 		  XGL_CTX_DEVICE, PDATA(ProjectionMark),
1250 		  NULL) ;
1251 
1252   for (pos.x=0 ; pos.x<3 ; pos.x++)
1253       for (pos.y=0 ; pos.y<3 ; pos.y++)
1254 	  xgl_context_set_pixel (XGLTMPCTX, &pos, &white) ;
1255 
1256   DPRINT(")") ;
1257   return ;
1258 
1259 error:
1260   DPRINT("\nerror)" ) ;
1261   PDATA(cursor_saveunder) = PDATA(ActiveSquareCursor) =
1262         PDATA(PassiveSquareCursor) = PDATA(ProjectionMark) = NULL ;
1263   return ;
1264 
1265 }
1266 
1267 void
_dxf_DRAW_MARKER(tdmInteractor I)1268 _dxf_DRAW_MARKER (tdmInteractor I)
1269 {
1270   /*
1271    *  Draw projection marks for the probe/roam interactor.  Marks are the
1272    *  projections of a probe/roam interactor's position onto the bounding
1273    *  box.
1274    */
1275 
1276   DEFDATA(I,CursorData) ;
1277   DEFPORT(I_PORT_HANDLE) ;
1278   register int i, mx, my ;
1279   Xgl_rect_af3d rect ;
1280   Xgl_rect_list rect_list ;
1281   DPRINT("\n(_dxf_DRAW_MARKER") ;
1282 
1283   for (i = 0 ; i < PDATA(iMark) ; i++)
1284     {
1285       PDATA(pXmark)[i] = PDATA(Xmark)[i] ;
1286       PDATA(pYmark)[i] = PDATA(Ymark)[i] ;
1287     }
1288 
1289   PDATA(piMark) = PDATA(iMark) ;
1290 
1291   for (i = 0 ; i < PDATA(iMark) ; i++)
1292     {
1293       /* round marker to int */
1294       mx = (int)(PDATA(Xmark[i])+0.5) ;
1295       my = (int)(PDATA(Ymark[i])+0.5) ;
1296 
1297       /* blit it */
1298       if (!CLIPPED(mx,my))
1299 	  _dxf_WRITE_BUFFER (PORT_CTX, mx-1, my-1, mx+1, my+1,
1300 			    PDATA(ProjectionMark)) ;
1301     }
1302   DPRINT(")") ;
1303 }
1304 
1305 void
_dxf_ERASE_PREVIOUS_MARKS(tdmInteractor I)1306 _dxf_ERASE_PREVIOUS_MARKS (tdmInteractor I)
1307 {
1308   DEFDATA(I,CursorData) ;
1309   DEFPORT(I_PORT_HANDLE) ;
1310   Xgl_pt_i2d position ;
1311   Xgl_bounds_i2d rect ;
1312   register int i, j, mx, my ;
1313 
1314   /* do nothing if interactor is invisible or backing store not available */
1315   if (!PDATA(visible) || !CDATA(image)) return ;
1316 
1317   /* restore the image over the previous projection marks */
1318   for (i = 0 ; i < PDATA(piMark) ; i++)
1319     {
1320       /* round mark coordinates to int */
1321       mx = (long)(PDATA(pXmark[i])+0.5) ;
1322       my = (long)(PDATA(pYmark[i])+0.5) ;
1323 
1324       if (!CLIPPED(mx,my))
1325 	{
1326 	  rect.xmin = mx-1 ; rect.ymin = VP_YMAX - (my+1) ;
1327 	  rect.xmax = mx+1 ; rect.ymax = VP_YMAX - (my-1) ;
1328 	  position.x = rect.xmin ; position.y = rect.ymin ;
1329 #ifdef solaris
1330 	  xgl_context_copy_buffer (XGLCTX, &rect, &position, CDATA(image)) ;
1331 #else
1332 	  xgl_context_copy_raster (XGLCTX, &rect, &position, CDATA(image)) ;
1333 #endif
1334 	}
1335     }
1336 }
1337 
1338 void
_dxf_ERASE_CURSOR(tdmInteractor I,int x,int y)1339 _dxf_ERASE_CURSOR (tdmInteractor I, int x, int y)
1340 {
1341   /*
1342    *  Erase previous probe/roam cursor position by blitting stored image.
1343    */
1344 
1345   DEFDATA(I,CursorData) ;
1346   DEFPORT(I_PORT_HANDLE) ;
1347   Xgl_pt_i2d position ;
1348   Xgl_bounds_i2d rect ;
1349   int s2 ;
1350 
1351   /* if not visible, nor backing store available, nor within window, return */
1352   if (!PDATA(visible) || !CDATA(image) || CLIPPED(x,y)) return ;
1353 
1354   s2= PDATA(cursor_size) / 2 ;
1355   rect.xmin = x-s2 ; rect.ymin = VP_YMAX - (y+s2) ;
1356   rect.xmax = x+s2 ; rect.ymax = VP_YMAX - (y-s2) ;
1357   position.x = rect.xmin ; position.y = rect.ymin ;
1358 #ifdef solaris
1359   xgl_context_copy_buffer (XGLCTX, &rect, &position, CDATA(image)) ;
1360 #else
1361   xgl_context_copy_raster (XGLCTX, &rect, &position, CDATA(image)) ;
1362 #endif
1363 }
1364 
1365 
1366 void
_dxf_POINTER_INVISIBLE(void * ctx)1367 _dxf_POINTER_INVISIBLE (void *ctx)
1368 {
1369   /*
1370    *  Substitute an invisible mouse pointer.
1371    */
1372 
1373   DEFCONTEXT(ctx) ;
1374   int i ;
1375   Pixmap p1, p2 ;
1376   XColor fc, bc ;
1377   char tmp_bits[8] ;
1378   Cursor cursorId ;
1379   DPRINT("\n(_dxf_POINTER_INVISIBLE)") ;
1380 
1381   for (i = 0 ; i < 8 ; i++)
1382     tmp_bits[i] = 0 ;
1383 
1384   p1 = XCreatePixmapFromBitmapData
1385      (XGLDISPLAY, RootWindow(XGLDISPLAY, XGLSCREEN), tmp_bits, 4, 4, 0, 0, 1) ;
1386   p2 = XCreatePixmapFromBitmapData
1387      (XGLDISPLAY, RootWindow(XGLDISPLAY, XGLSCREEN), tmp_bits, 4, 4, 0, 0, 1) ;
1388 
1389   cursorId = XCreatePixmapCursor (XGLDISPLAY, p1, p2, &fc, &bc, 1, 1 ) ;
1390 
1391   XFreePixmap (XGLDISPLAY, p1) ;
1392   XFreePixmap (XGLDISPLAY, p2) ;
1393 
1394   XDefineCursor (XGLDISPLAY, XGLXWINID, cursorId) ;
1395 }
1396 
1397 void
_dxf_POINTER_VISIBLE(void * ctx)1398 _dxf_POINTER_VISIBLE (void *ctx)
1399 {
1400   /*
1401    *  Use the default visible mouse pointer.
1402    */
1403 
1404   DEFCONTEXT(ctx) ;
1405   DPRINT("\n(_dxf_POINTER_VISIBLE)") ;
1406 
1407   XUndefineCursor (XGLDISPLAY, XGLXWINID) ;
1408 }
1409 
1410 void
_dxf_WARP_POINTER(void * ctx,int x,int y)1411 _dxf_WARP_POINTER (void *ctx, int x, int y)
1412 {
1413   /*
1414    *  Warp mouse pointer to specified position.
1415    */
1416 
1417   DEFCONTEXT(ctx) ;
1418   DPRINT("\n(_dxf_WARP_POINTER)") ;
1419 
1420   XWarpPointer (XGLDISPLAY, None, DefaultRootWindow(XGLDISPLAY), 0, 0, 0, 0,
1421 		x, SCREEN_YMAX-y) ;
1422 }
1423 
1424 static void
_dxf_SET_LINE_ATTRIBUTES(void * ctx,int32 color,int style,float width)1425 _dxf_SET_LINE_ATTRIBUTES (void *ctx, int32 color, int style, float width)
1426 {
1427   DEFCONTEXT(ctx) ;
1428   Xgl_color xgl_color ;
1429 
1430   /*
1431    *  color is packed RGB.
1432    *  style 0 is solid.  style 1 is dashed.
1433    *  width is screen width of line, may be subpixel.  not currently used.
1434    */
1435 
1436   switch (color)
1437     {
1438     case 0x8f8f8f8f:
1439       xgl_color.rgb.r = 0.5 ; xgl_color.rgb.g = 0.5 ; xgl_color.rgb.b = 0.5 ;
1440       break ;
1441     case 0xffffffff:
1442     default:
1443       xgl_color.rgb.r = 1.0 ; xgl_color.rgb.g = 1.0 ; xgl_color.rgb.b = 1.0 ;
1444       break ;
1445     }
1446 
1447   xgl_object_set (XGLCTX, XGL_CTX_LINE_COLOR, &xgl_color, NULL) ;
1448 
1449   switch (style)
1450     {
1451     case 1:
1452       xgl_object_set (XGLCTX, XGL_CTX_LINE_STYLE, XGL_LINE_PATTERNED, 0) ;
1453       xgl_object_set (XGLCTX, XGL_CTX_LINE_PATTERN, xgl_lpat_dashed, 0);
1454       break ;
1455     case 0:
1456     default:
1457       xgl_object_set (XGLCTX, XGL_CTX_LINE_STYLE, XGL_LINE_SOLID, 0) ;
1458       break ;
1459     }
1460 }
1461 
1462 
1463 void
_dxf_SET_LINE_COLOR_WHITE(void * ctx)1464 _dxf_SET_LINE_COLOR_WHITE (void *ctx)
1465 {
1466   /* obsolete entry:  do not use in new code */
1467   DEFCONTEXT(ctx) ;
1468   Xgl_color color  ;
1469 
1470   color.rgb.r = 1.0 ; color.rgb.g = 1.0 ; color.rgb.b = 1.0 ;
1471   xgl_object_set (XGLCTX, XGL_CTX_LINE_COLOR, &color, NULL) ;
1472 }
1473 
1474 void
_dxf_SET_LINE_COLOR_GRAY(void * ctx)1475 _dxf_SET_LINE_COLOR_GRAY (void *ctx)
1476 {
1477   /* obsolete entry:  do not use in new code */
1478   DEFCONTEXT(ctx) ;
1479   Xgl_color color ;
1480 
1481   color.rgb.r = 0.5 ; color.rgb.g = 0.5 ; color.rgb.b = 0.5 ;
1482   xgl_object_set (XGLCTX, XGL_CTX_LINE_COLOR, &color, NULL) ;
1483 }
1484 
1485 void
_dxf_DRAW_LINE(void * ctx,int x1,int y1,int x2,int y2)1486 _dxf_DRAW_LINE(void *ctx, int x1, int y1, int x2, int y2)
1487 {
1488   /*
1489    *  Used for cursor box.
1490    */
1491 
1492   DEFCONTEXT(ctx) ;
1493   Xgl_pt_list line  ;
1494   static Xgl_pt_f3d verts[2] = {0, 0, 0, 0, 0, 0} ;
1495 
1496   DPRINT("\n(_dxf_DRAW_LINE") ;
1497   DPRINT1("\n%d", x1) ; DPRINT1(" %d", y1) ;
1498   DPRINT1("\n%d", x2) ; DPRINT1(" %d", y2) ;
1499 
1500   line.pt_type = XGL_PT_F3D ;
1501   line.bbox = NULL ;
1502   line.num_pts = 2 ;
1503   line.pts.f3d = verts ;
1504 
1505   verts[0].x = x1 ;
1506   verts[0].y = y1 ;
1507   verts[1].x = x2 ;
1508   verts[1].y = y2 ;
1509 
1510   xgl_multipolyline (XGLCTX, NULL, 1, &line) ;
1511   DPRINT(")") ;
1512 }
1513 
1514 void
_dxf_DRAW_CURSOR_COORDS(tdmInteractor I,char * text)1515 _dxf_DRAW_CURSOR_COORDS (tdmInteractor I, char *text)
1516 {
1517   /*
1518    *  Draw cursor coordinates at specified position.
1519    */
1520 
1521   DEFDATA(I,CursorData) ;
1522   DEFPORT(I_PORT_HANDLE) ;
1523   Xgl_pt_f3d pos, offs ;
1524   Xgl_color white, black ;
1525 
1526   white.rgb.r = 1.0 ;
1527   white.rgb.g = 1.0 ;
1528   white.rgb.b = 1.0 ;
1529 
1530   black.rgb.r = 0.0 ;
1531   black.rgb.g = 0.0 ;
1532   black.rgb.b = 0.0 ;
1533 
1534   offs.x = 0 ; offs.y = 0 ; offs.z = 0 ; pos.z = 0 ;
1535 
1536 #ifdef solaris
1537   xgl_object_set (XGLCTX,
1538 		  XGL_CTX_ATEXT_CHAR_HEIGHT, 0.036,
1539 		  XGL_CTX_STEXT_CHAR_EXPANSION_FACTOR, 0.7,
1540 		  XGL_CTX_STEXT_COLOR, &black,
1541 		  NULL) ;
1542 #else
1543   xgl_object_set (XGLCTX,
1544 		  XGL_CTX_ANNOT_CHAR_HEIGHT, 0.036,
1545 		  XGL_CTX_SFONT_CHAR_EXPANSION_FACTOR, 0.7,
1546 		  XGL_CTX_SFONT_TEXT_COLOR, &black,
1547 		  NULL) ;
1548 #endif
1549 
1550   pos.x = PDATA(coord_llx)+5 ; pos.y = PDATA(coord_lly)+3 ;
1551   xgl_annotation_text (XGLCTX, text, &pos, &offs) ;
1552 
1553   xgl_object_set (XGLCTX,
1554 #ifdef solaris
1555 		  XGL_CTX_STEXT_COLOR, &white,
1556 #else
1557 		  XGL_CTX_SFONT_TEXT_COLOR, &white,
1558 #endif
1559 		  NULL) ;
1560 
1561   pos.x = PDATA(coord_llx)+4 ; pos.y = PDATA(coord_lly)+4 ;
1562   xgl_annotation_text (XGLCTX, text, &pos, &offs) ;
1563 
1564 }
1565 
1566 tdmInteractorEchoT	_dxd_hwInteractorEchoPort =
1567 {
1568   /* BufferConfig */		_dxf_BUFFER_CONFIG,
1569   /* BufferRestoreConfig */	_dxf_BUFFER_RESTORE_CONFIG,
1570   /* CreateCurXFsorPixmaps */	_dxf_CREATE_CURSOR_PIXMAPS,
1571   /* DrawArrowhead */		_dxf_DRAW_ARROWHEAD,
1572   /* DrawCursorCoords */	_dxf_DRAW_CURSOR_COORDS,
1573   /* DrawGlobe */		_dxf_DRAW_GLOBE,
1574   /* DrawGnomon */ 		_dxf_DRAW_GNOMON,
1575   /* DrawLine */		_dxf_DRAW_LINE,
1576   /* DrawMarker */		_dxf_DRAW_MARKER,
1577   /* DrawZoombox */		_dxf_DRAW_ZOOMBOX,
1578   /* EraseCursor */		_dxf_ERASE_CURSOR,
1579   /* ErasePreviousMarks */	_dxf_ERASE_PREVIOUS_MARKS,
1580   /* GetMaxscreen */		_dxf_GET_MAXSCREEN,
1581   /* GetWindowOrigin */		_dxf_GET_WINDOW_ORIGIN,
1582   /* GetZbufferStatus */	_dxf_GET_ZBUFFER_STATUS,
1583   /* PointerInvisible */	_dxf_POINTER_INVISIBLE,
1584   /* PointerVisible */		_dxf_POINTER_VISIBLE,
1585   /* ReadBuffer */		_dxf_READ_BUFFER,
1586   /* SetLineColorGray */	_dxf_SET_LINE_COLOR_GRAY,
1587   /* SetLineColorWhite */	_dxf_SET_LINE_COLOR_WHITE,
1588   /* SetSolidFillPattern */	_dxf_SET_SOLID_FILL_PATTERN,
1589   /* SetWorldScreen */		_dxf_SET_WORLD_SCREEN,
1590   /* SetZbufferStatus */	_dxf_SET_ZBUFFER_STATUS,
1591   /* WarpPointer */		_dxf_WARP_POINTER,
1592   /* WriteBuffer */		_dxf_WRITE_BUFFER,
1593   /* SetLineAttributes */       _dxf_SET_LINE_ATTRIBUTES
1594 };
1595