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  * These functions were provided by HP with /usr/lib/starbase/demos/SBUTILS
17  *
18  * This file contains a set of example utility procedures; procedures that can
19  * help a "window-smart" Starbase or PHIGS program determine information about
20  * a device, and create image and overlay plane windows.  To use these
21  * utilities, #include "wsutils.h" and compile this file and link the results
22  * with your program.
23  *
24  ******************************************************************************/
25 /*
26  $Header: /src/master/dx/src/exec/hwrender/starbase/wsutils.c,v 1.3 1999/05/10 15:45:39 gda Exp $
27 */
28 
29 #include <X11/X.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <X11/XHPlib.h>
33 #include <stdio.h>
34 #include "hwDeclarations.h"
35 #include "wsutils.h"
36 #include "hwInteractor.h"
37 
38 #ifndef STANDALONE
39 #include "hwMemory.h"
40 #endif
41 
42 #include "hwPortLayer.h"
43 
44 #include "hwDebug.h"
45 
46 #define STATIC_GRAY	0x01
47 #define GRAY_SCALE	0x02
48 #define PSEUDO_COLOR	0x04
49 #define TRUE_COLOR	0x10
50 #define DIRECT_COLOR	0x11
51 
52 /******************************************************************************
53  *
54  * GetXVisualInfo()
55  *
56  * This routine takes an X11 Display, screen number, and returns whether the
57  * screen supports transparent overlays and three arrays:
58  *
59  *	1) All of the XVisualInfo struct's for the screen.
60  *	2) All of the OverlayInfo struct's for the screen.
61  *	3) An array of pointers to the screen's image plane XVisualInfo
62  *	   structs.
63  *
64  * The code below obtains the array of all the screen's visuals, and obtains
65  * the array of all the screen's overlay visual information.  It then processes
66  * the array of the screen's visuals, determining whether the visual is an
67  * overlay or image visual.
68  *
69  * If the routine sucessfully obtained the visual information, it returns zero.
70  * If the routine didn't obtain the visual information, it returns non-zero.
71  *
72  ******************************************************************************/
73 
GetXVisualInfo(Display * display,int screen,int * transparentOverlays,int * numVisuals,XVisualInfo ** pVisuals,int * numOverlayVisuals,OverlayInfo ** pOverlayVisuals,int * numImageVisuals,XVisualInfo *** pImageVisuals)74 int GetXVisualInfo(Display *display, int screen,
75 	int *transparentOverlays, int *numVisuals, XVisualInfo **pVisuals,
76 	int *numOverlayVisuals, OverlayInfo **pOverlayVisuals,
77 	int *numImageVisuals, XVisualInfo ***pImageVisuals)
78 
79 {
80     XVisualInfo	getVisInfo;		/* Paramters of XGetVisualInfo */
81     int		mask;
82     XVisualInfo	*pVis, **pIVis;		/* Faster, local copies */
83     OverlayInfo	*pOVis;
84     OverlayVisualPropertyRec	*pOOldVis;
85     int		nVisuals, nOVisuals, nIVisuals;
86     Atom	overlayVisualsAtom;	/* Parameters for XGetWindowProperty */
87     Atom	actualType;
88     unsigned long numLongs, bytesAfter;
89     int		actualFormat;
90     int		nImageVisualsAlloced;	/* Values to process the XVisualInfo */
91     int		imageVisual;		/* array */
92 
93 
94     ENTRY(("GetXVisualInfo(0x%x, %d, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)",
95 	   display, screen, transparentOverlays, numVisuals, pVisuals,
96 	   numOverlayVisuals, pOverlayVisuals, numImageVisuals, pImageVisuals));
97 
98     /* First, get the list of visuals for this screen. */
99     getVisInfo.screen = screen;
100     mask = VisualScreenMask;
101 
102     *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
103     if ((nVisuals = *numVisuals) <= 0)
104     {
105       /* Return that the information wasn't sucessfully obtained: */
106       EXIT(("1"));
107       return(1);
108     }
109     pVis = *pVisuals;
110 
111 
112     /* Now, get the overlay visual information for this screen.  To obtain
113      * this information, get the SERVER_OVERLAY_VISUALS property.
114      */
115     overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
116     if (overlayVisualsAtom != None)
117     {
118 	/* Since the Atom exists, we can request the property's contents.  The
119 	 * do-while loop makes sure we get the entire list from the X server.
120 	 */
121 	bytesAfter = 0;
122 	numLongs = sizeof(OverlayVisualPropertyRec) / 4;
123 	do
124 	{
125 	    numLongs += bytesAfter * 4;
126 	    XGetWindowProperty(display, RootWindow(display, screen),
127 		overlayVisualsAtom, 0, numLongs, False,
128 		overlayVisualsAtom, &actualType, &actualFormat,
129 		&numLongs, &bytesAfter, (unsigned char **)pOverlayVisuals);
130 	} while (bytesAfter > 0);
131 
132 
133 	/* Calculate the number of overlay visuals in the list. */
134 	*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4);
135     }
136     else
137     {
138 	/* This screen doesn't have overlay planes. */
139 	*numOverlayVisuals = 0;
140 	*pOverlayVisuals = NULL;
141 	*transparentOverlays = 0;
142     }
143 
144 
145     /* Process the pVisuals array. */
146     *numImageVisuals = 0;
147     nImageVisualsAlloced = 1;
148     pIVis = *pImageVisuals = (XVisualInfo **) tdmAllocateLocal(4);
149 
150     while (--nVisuals >= 0)
151     {
152 	nOVisuals = *numOverlayVisuals;
153 	pOVis = *pOverlayVisuals;
154 	imageVisual = True;
155 	while (--nOVisuals >= 0)
156 	{
157 	    pOOldVis = (OverlayVisualPropertyRec *) pOVis;
158 	    if (pVis->visualid == pOOldVis->visualID)
159 	    {
160 		imageVisual = False;
161 		pOVis->pOverlayVisualInfo = pVis;
162 		if (pOVis->transparentType == TransparentPixel)
163 		    *transparentOverlays = 1;
164 	    }
165 	    pOVis++;
166 	}
167 	if (imageVisual)
168 	{
169 	    if ((*numImageVisuals += 1) > nImageVisualsAlloced)
170 	    {
171 	      nImageVisualsAlloced++ ;
172 	      *pImageVisuals = (XVisualInfo **)
173 		tdmReAllocate(*pImageVisuals, nImageVisualsAlloced * 4) ;
174 	      pIVis = *pImageVisuals + (*numImageVisuals - 1) ;
175 	    }
176 	    *pIVis++ = pVis;
177 	}
178 	pVis++;
179     }
180 
181 
182     /* Return that the information was sucessfully obtained: */
183     EXIT(("0"));
184     return(0);
185 } /* GetXVisualInfo() */
186 
187 /******************************************************************************
188  *
189  * FindImagePlanesVisual()
190  *
191  * This routine attempts to find a visual to use to create an image planes
192  * window based upon the information passed in.
193  *
194  * The "Hint" values give guides to the routine as to what the program wants.
195  * The "depthFlexibility" value tells the routine how much the program wants
196  * the actual "depthHint" specified.  If the program can't live with the
197  * screen's image planes visuals, the routine returns non-zero, and the
198  * "depthObtained" and "pImageVisualToUse" return parameters are NOT valid.
199  * Otherwise, the "depthObtained" and "pImageVisualToUse" return parameters
200  * are valid and the routine returns zero.
201  *
202  * NOTE: This is just an example of what can be done.  It may or may not be
203  * useful for any specific application.
204  *
205  ******************************************************************************/
206 
FindImagePlanesVisual(Display * display,int screen,int numImageVisuals,XVisualInfo ** pImageVisuals,int sbCmapHint,int depthHint,int depthFlexibility,Visual ** pImageVisualToUse,int * depthObtained)207 int FindImagePlanesVisual(Display *display, int screen, int numImageVisuals,
208 	XVisualInfo **pImageVisuals, int sbCmapHint, int depthHint,
209 	int depthFlexibility, Visual **pImageVisualToUse, int *depthObtained)
210 {
211     XVisualInfo	*pVisualInfoToUse;	/* The current best visual to use. */
212     int		i;
213     int		visMask;
214     int		curDelta, newDelta;
215 
216     ENTRY(("FindImagePlanesVisual(0x%x, %d, %d, 0x%x, %d, %d, %d, 0x%x, 0x%x)",
217 	   display, screen, numImageVisuals, pImageVisuals, sbCmapHint,
218 	   depthHint, depthFlexibility, pImageVisualToUse, depthObtained));
219 
220     switch (sbCmapHint)
221     {
222 	case SB_CMAP_TYPE_NORMAL:
223 	case SB_CMAP_TYPE_NORMAL | SB_CMAP_TYPE_MONOTONIC:
224 	case SB_CMAP_TYPE_NORMAL | SB_CMAP_TYPE_MONOTONIC | SB_CMAP_TYPE_FULL:
225 	case SB_CMAP_TYPE_NORMAL | SB_CMAP_TYPE_FULL:
226 	    visMask = GRAY_SCALE | PSEUDO_COLOR;
227 	    break;
228 	case SB_CMAP_TYPE_MONOTONIC:
229 	    visMask = STATIC_GRAY | GRAY_SCALE | PSEUDO_COLOR;
230 	    break;
231 	case SB_CMAP_TYPE_MONOTONIC | SB_CMAP_TYPE_FULL:
232 	    visMask = GRAY_SCALE | PSEUDO_COLOR;
233 	    break;
234 	case SB_CMAP_TYPE_FULL:
235 	    visMask = GRAY_SCALE | PSEUDO_COLOR | TRUE_COLOR | DIRECT_COLOR;
236 	    break;
237 	default:
238 	    /* The caller didn't specify a valid combination of CMAP_ type: */
239 	    EXIT(("1"));
240 	    return(1);
241     } /* switch (sbCmapHint) */
242 
243 
244     pVisualInfoToUse = NULL;
245 
246     for (i = 0 ; i < numImageVisuals ; i++)
247     {
248 	switch (pImageVisuals[i]->class)
249 	{
250 	    case StaticGray:
251 		if (visMask & STATIC_GRAY)
252 		{
253 		    if (pVisualInfoToUse == NULL)
254 		    {
255 			if ((pImageVisuals[i]->depth == depthHint) ||
256 			    depthFlexibility)
257 			{
258 			    pVisualInfoToUse = pImageVisuals[i];
259 			}
260 		    }
261 		    else
262 		    {
263 			if (pImageVisuals[i]->depth == depthHint)
264 			    pVisualInfoToUse = pImageVisuals[i];
265 			else if (depthFlexibility)
266 			{
267 			    /* The basic hueristic used is to find the closest
268 			     * depth to "depthHint" that's also greater than
269 			     * "depthHint", or just the closest depth:
270 			     */
271 			    if ((curDelta = pVisualInfoToUse->depth -
272 				 depthHint) > 0)
273 			    {
274 				/* Only choose this new visual if it's also
275 				 * deeper than "depthHint" and closer to
276 				 * "depthHint" than the currently chosen visual:
277 				 */
278 				if (((newDelta = pImageVisuals[i]->depth -
279 				      depthHint) > 0) && (newDelta < curDelta))
280 				{
281 				    pVisualInfoToUse = pImageVisuals[i];
282 				}
283 			    }
284 			    else
285 			    {
286 				/* Choose this new visual if it's deeper than
287 				 * "depthHint" or closer to "depthHint" than
288 				 * the currently chosen visual:
289 				 */
290 				if (((newDelta = pImageVisuals[i]->depth -
291 				      depthHint) > 0) ||
292 				    (-newDelta < -curDelta))
293 				{
294 				    pVisualInfoToUse = pImageVisuals[i];
295 				}
296 			    }
297 			}
298 		    }
299 		}
300 		break;
301 	    case GrayScale:
302 		if (visMask & GRAY_SCALE)
303 		{
304 		    if (pVisualInfoToUse == NULL)
305 		    {
306 			if ((pImageVisuals[i]->depth == depthHint) ||
307 			    depthFlexibility)
308 			{
309 			    pVisualInfoToUse = pImageVisuals[i];
310 			}
311 		    }
312 		    else if (!((sbCmapHint & SB_CMAP_TYPE_FULL) &&
313 			       (pVisualInfoToUse->class == DirectColor)))
314 		    {
315 			if (pImageVisuals[i]->depth == depthHint)
316 			    pVisualInfoToUse = pImageVisuals[i];
317 			else if (depthFlexibility)
318 			{
319 			    /* The basic hueristic used is to find the closest
320 			     * depth to "depthHint" that's also greater than
321 			     * "depthHint", or just the closest depth:
322 			     */
323 			    if ((curDelta = pVisualInfoToUse->depth -
324 				 depthHint) > 0)
325 			    {
326 				/* Only choose this new visual if it's also
327 				 * deeper than "depthHint" and closer to
328 				 * "depthHint" than the currently chosen visual:
329 				 */
330 				if (((newDelta = pImageVisuals[i]->depth -
331 				      depthHint) > 0) && (newDelta < curDelta))
332 				{
333 				    pVisualInfoToUse = pImageVisuals[i];
334 				}
335 			    }
336 			    else
337 			    {
338 				/* Choose this new visual if it's deeper than
339 				 * "depthHint" or closer to "depthHint" than
340 				 * the currently chosen visual:
341 				 */
342 				if (((newDelta = pImageVisuals[i]->depth -
343 				      depthHint) > 0) ||
344 				    (-newDelta < -curDelta))
345 				{
346 				    pVisualInfoToUse = pImageVisuals[i];
347 				}
348 			    }
349 			}
350 		    }
351 		}
352 		break;
353 	    case PseudoColor:
354 		if (visMask & PSEUDO_COLOR)
355 		{
356 		    if (pVisualInfoToUse == NULL)
357 		    {
358 			if ((pImageVisuals[i]->depth == depthHint) ||
359 			    depthFlexibility)
360 			{
361 			    pVisualInfoToUse = pImageVisuals[i];
362 			}
363 		    }
364 		    else if (!((sbCmapHint & SB_CMAP_TYPE_FULL) &&
365 			       (pVisualInfoToUse->class == DirectColor)))
366 		    {
367 			if (pImageVisuals[i]->depth == depthHint)
368 			    pVisualInfoToUse = pImageVisuals[i];
369 			else if (depthFlexibility)
370 			{
371 			    /* The basic hueristic used is to find the closest
372 			     * depth to "depthHint" that's also greater than
373 			     * "depthHint", or just the closest depth:
374 			     */
375 			    if ((curDelta = pVisualInfoToUse->depth -
376 				 depthHint) > 0)
377 			    {
378 				/* Only choose this new visual if it's also
379 				 * deeper than "depthHint" and closer to
380 				 * "depthHint" than the currently chosen visual:
381 				 */
382 				if (((newDelta = pImageVisuals[i]->depth -
383 				      depthHint) > 0) && (newDelta < curDelta))
384 				{
385 				    pVisualInfoToUse = pImageVisuals[i];
386 				}
387 			    }
388 			    else
389 			    {
390 				/* Choose this new visual if it's deeper than
391 				 * "depthHint" or closer to "depthHint" than
392 				 * the currently chosen visual:
393 				 */
394 				if (((newDelta = pImageVisuals[i]->depth -
395 				      depthHint) > 0) ||
396 				    (-newDelta < -curDelta))
397 				{
398 				    pVisualInfoToUse = pImageVisuals[i];
399 				}
400 			    }
401 			}
402 		    }
403 		}
404 		break;
405 	    case StaticColor:
406 		/* Starbase doesn't work well with StaticColor visuals: */
407 		break;
408 	    case TrueColor:
409 		if (visMask & TRUE_COLOR)
410 		{
411 		    /* The only Starbase cmap type that TrueColor works with
412 		     * is SB_CMAP_TYPE_FULL, so we know that SB_CMAP_TYPE_FULL
413 		     * is what the program wants:
414 		     */
415 		    if (pVisualInfoToUse == NULL)
416 		    {
417 			if ((pImageVisuals[i]->depth == depthHint) ||
418 			    depthFlexibility)
419 			{
420 			    pVisualInfoToUse = pImageVisuals[i];
421 			}
422 		    }
423 		    /* This example code prefers DirectColor to TrueColor: */
424 		    else if (pVisualInfoToUse->class != DirectColor)
425 		    {
426 			if (pImageVisuals[i]->depth == depthHint)
427 			    pVisualInfoToUse = pImageVisuals[i];
428 			else if (depthFlexibility)
429 			{
430 			    /* The basic hueristic used is to find the closest
431 			     * depth to "depthHint" that's also greater than
432 			     * "depthHint", or just the closest depth:
433 			     */
434 			    if ((curDelta = pVisualInfoToUse->depth -
435 				 depthHint) > 0)
436 			    {
437 				/* Only choose this new visual if it's also
438 				 * deeper than "depthHint" and closer to
439 				 * "depthHint" than the currently chosen visual:
440 				 */
441 				if (((newDelta = pImageVisuals[i]->depth -
442 				      depthHint) > 0) && (newDelta < curDelta))
443 				{
444 				    pVisualInfoToUse = pImageVisuals[i];
445 				}
446 			    }
447 			    else
448 			    {
449 				/* Choose this new visual if it's deeper than
450 				 * "depthHint" or closer to "depthHint" than
451 				 * the currently chosen visual:
452 				 */
453 				if (((newDelta = pImageVisuals[i]->depth -
454 				      depthHint) > 0) ||
455 				    (-newDelta < -curDelta))
456 				{
457 				    pVisualInfoToUse = pImageVisuals[i];
458 				}
459 			    }
460 			}
461 		    }
462 		}
463 		break;
464 	    case DirectColor:
465 		if (visMask & DIRECT_COLOR)
466 		{
467 		    if (pVisualInfoToUse == NULL)
468 		    {
469 			if ((pImageVisuals[i]->depth == depthHint) ||
470 			    depthFlexibility)
471 			{
472 			    pVisualInfoToUse = pImageVisuals[i];
473 			}
474 		    }
475 		    else
476 		    {
477 			if (pImageVisuals[i]->depth == depthHint)
478 			    pVisualInfoToUse = pImageVisuals[i];
479 			else if (depthFlexibility)
480 			{
481 			    /* The basic hueristic used is to find the closest
482 			     * depth to "depthHint" that's also greater than
483 			     * "depthHint", or just the closest depth:
484 			     */
485 			    if ((curDelta = pVisualInfoToUse->depth -
486 				 depthHint) > 0)
487 			    {
488 				/* Only choose this new visual if it's also
489 				 * deeper than "depthHint" and closer to
490 				 * "depthHint" than the currently chosen visual:
491 				 */
492 				if (((newDelta = pImageVisuals[i]->depth -
493 				      depthHint) > 0) && (newDelta < curDelta))
494 				{
495 				    pVisualInfoToUse = pImageVisuals[i];
496 				}
497 			    }
498 			    else
499 			    {
500 				/* Choose this new visual if it's deeper than
501 				 * "depthHint" or closer to "depthHint" than
502 				 * the currently chosen visual:
503 				 */
504 				if (((newDelta = pImageVisuals[i]->depth -
505 				      depthHint) > 0) ||
506 				    (-newDelta < -curDelta))
507 				{
508 				    pVisualInfoToUse = pImageVisuals[i];
509 				}
510 			    }
511 			}
512 		    }
513 		}
514 		break;
515 	} /* switch (pImageVisuals[i]->class) */
516     } /* for (i = 0 ; i < numImageVisuals ; i++) */
517 
518 
519     if (pVisualInfoToUse != NULL)
520     {
521 	*pImageVisualToUse = pVisualInfoToUse->visual;
522 	*depthObtained = pVisualInfoToUse->depth;
523 	EXIT(("0"));
524 	return(0);
525     }
526     else
527     {
528 	/* Couldn't find an appropriate visual class: */
529       EXIT(("1"));
530       return(1);
531     }
532 } /* FindImagePlanesVisual() */
533 
534 /******************************************************************************
535  *
536  * CreateImagePlanesWindow()
537  *
538  * This routine creates an image planes window, potentially creates a colormap
539  * for the window to use, and sets the window's standard properties, based
540  * upon the information passed in to the routine.  While "created," the window
541  * has not been mapped.
542  *
543  * If the routine suceeds, it returns zero and the return parameters
544  * "imageWindow", "imageColormap" and "mustFreeImageColormap" are valid.
545  * Otherwise, the routine returns non-zero and the return parameters are
546  * NOT valid.
547  *
548  * NOTE: This is just an example of what can be done.  It may or may not be
549  * useful for any specific application.
550  *
551  ******************************************************************************/
552 
CreateImagePlanesWindow(Display * display,int screen,Window parentWindow,int windowX,int windowY,int windowWidth,int windowHeight,int windowDepth,Visual * pImageVisualToUse,int argc,char * argv[],char * windowName,char * iconName,Window * imageWindow,Colormap * imageColormap,int * mustFreeImageColormap)553 int CreateImagePlanesWindow(Display *display, int screen, Window parentWindow,
554 	int windowX, int windowY, int windowWidth, int windowHeight,
555 	int windowDepth, Visual *pImageVisualToUse,
556 	int argc, char *argv[], char *windowName, char *iconName,
557 	Window *imageWindow, Colormap *imageColormap,
558 	int *mustFreeImageColormap)
559 {
560     XSetWindowAttributes winAttributes;	/* Attributes for window creation */
561     XSizeHints	hints;
562 
563     ENTRY(("CreateImagePlanesWindow(0x%x, %d, 0x%x, %d, %d, %d, %d, %d,
564 0x%x, %d, 0x%x, \"%s\", \"%s\", 0x%x, 0x%x, 0x%x)",
565 	   display, screen, parentWindow,
566 	   windowX, windowY, windowWidth, windowHeight, windowDepth,
567 	   pImageVisualToUse, argc, argv, windowName, iconName,
568 	   imageWindow, imageColormap,  mustFreeImageColormap));
569 
570     if (pImageVisualToUse == DefaultVisual(display, screen))
571     {
572 	*mustFreeImageColormap = False;
573 	*imageColormap = winAttributes.colormap = DefaultColormap(display,
574 								  screen);
575 	winAttributes.background_pixel = BlackPixel(display, screen);
576 	winAttributes.border_pixel = WhitePixel(display, screen);
577     }
578     else
579     {
580 	XColor		actualColor, databaseColor;
581 
582 	*mustFreeImageColormap = True;
583 	*imageColormap = winAttributes.colormap =
584 	    XCreateColormap(display, RootWindow(display, screen),
585 			    pImageVisualToUse, AllocNone);
586 	XAllocNamedColor(display, winAttributes.colormap, "Black",
587 			 &actualColor, &databaseColor);
588 	winAttributes.background_pixel = actualColor.pixel;
589 	XAllocNamedColor(display, winAttributes.colormap, "White",
590 			 &actualColor, &databaseColor);
591 	winAttributes.border_pixel = actualColor.pixel;
592     }
593     winAttributes.event_mask = ExposureMask;
594     winAttributes.backing_store = WhenMapped ;
595 
596     *imageWindow = XCreateWindow(display, parentWindow,
597 				 0, 0, windowWidth, windowHeight, 2,
598 				 windowDepth, InputOutput, pImageVisualToUse,
599 				 (CWBackPixel | CWColormap |
600 				  CWBorderPixel | CWEventMask | CWBackingStore),
601 				 &winAttributes);
602 
603     hints.flags = (USSize | USPosition);
604     hints.x = windowX;
605     hints.y = windowY;
606     hints.width  = windowWidth;
607     hints.height = windowHeight;
608 
609     XSetStandardProperties(display, *imageWindow, (char *)windowName, iconName,
610 			   None, argv, argc, &hints);
611 
612     EXIT((""));
613     return(0);
614 } /* CreateImagePlanesWindow() */
615 
616