1 /*
2  * Copyright (c) 2001,2000,1999 Sasha Vasko <sasha at aftercode.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 #ifdef _WIN32
20 #include "win32/config.h"
21 #else
22 #include "config.h"
23 #endif
24 
25 #undef LOCAL_DEBUG
26 #undef DEBUG_SL2XIMAGE
27 #include <string.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 #ifdef HAVE_STDARG_H
35 #include <stdarg.h>
36 #endif
37 
38 #ifdef _WIN32
39 # include "win32/afterbase.h"
40 #else
41 # include "afterbase.h"
42 #endif
43 #include "asvisual.h"
44 #include "scanline.h"
45 
46 #if defined(XSHMIMAGE) && !defined(X_DISPLAY_MISSING)
47 # include <sys/ipc.h>
48 # include <sys/shm.h>
49 # include <X11/extensions/XShm.h>
50 #else
51 # undef XSHMIMAGE
52 #endif
53 
54 #if defined(HAVE_GLX) && !defined(X_DISPLAY_MISSING)
55 # include <GL/gl.h>
56 # include <GL/glx.h>
57 #else
58 # undef HAVE_GLX
59 #endif
60 
61 
62 
63 #ifndef X_DISPLAY_MISSING
64 static int  get_shifts (unsigned long mask);
65 static int  get_bits (unsigned long mask);
66 
67 void _XInitImageFuncPtrs(XImage*);
68 
69 int
asvisual_empty_XErrorHandler(Display * dpy,XErrorEvent * event)70 asvisual_empty_XErrorHandler (Display * dpy, XErrorEvent * event)
71 {
72     return 0;
73 }
74 /***************************************************************************/
75 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
76 Status
debug_AllocColor(const char * file,int line,ASVisual * asv,Colormap cmap,XColor * pxcol)77 debug_AllocColor( const char *file, int line, ASVisual *asv, Colormap cmap, XColor *pxcol )
78 {
79 	Status sret ;
80 	sret = XAllocColor( asv->dpy, cmap, pxcol );
81 	show_progress( " XAllocColor in %s:%d has %s -> cmap = %lX, pixel = %lu(%8.8lX), color = 0x%4.4X, 0x%4.4X, 0x%4.4X",
82 				   file, line, (sret==0)?"failed":"succeeded", (long)cmap, (unsigned long)(pxcol->pixel), (unsigned long)(pxcol->pixel), pxcol->red, pxcol->green, pxcol->blue );
83 	return sret;
84 }
85 #define ASV_ALLOC_COLOR(asv,cmap,pxcol)  debug_AllocColor(__FILE__, __LINE__, (asv),(cmap),(pxcol))
86 #else
87 #define ASV_ALLOC_COLOR(asv,cmap,pxcol)  XAllocColor((asv)->dpy,(cmap),(pxcol))
88 #endif
89 
90 #else
91 #define ASV_ALLOC_COLOR(asv,cmap,pxcol)   0
92 #endif   /* ndef X_DISPLAY_MISSING */
93 
94 /**********************************************************************/
95 /* returns the maximum number of true colors between a and b          */
96 long
ARGB32_manhattan_distance(long a,long b)97 ARGB32_manhattan_distance (long a, long b)
98 {
99 	register int d = (int)ARGB32_RED8(a)   - (int)ARGB32_RED8(b);
100 	register int t = (d < 0 )? -d : d ;
101 
102 	d = (int)ARGB32_GREEN8(a) - (int)ARGB32_GREEN8(b);
103 	t += (d < 0)? -d : d ;
104 	d = (int)ARGB32_BLUE8(a)  - (int)ARGB32_BLUE8(b);
105 	return (t+((d < 0)? -d : d)) ;
106 }
107 
108 
109 
110 /***************************************************************************
111  * ASVisual :
112  * encoding/decoding/querying/setup
113  ***************************************************************************/
get_bits_per_pixel(Display * dpy,int depth)114 int get_bits_per_pixel(Display *dpy, int depth)
115 {
116 #if 0
117 #ifndef X_DISPLAY_MISSING
118  	register ScreenFormat *fmt = dpy->pixmap_format;
119  	register int i;
120 
121  	for (i = dpy->nformats + 1; --i; ++fmt)
122  		if (fmt->depth == depth)
123  			return(fmt->bits_per_pixel);
124 #endif
125 #endif
126 	if (depth <= 4)
127 	    return 4;
128 	if (depth <= 8)
129 	    return 8;
130 	if (depth <= 16)
131 	    return 16;
132 	return 32;
133  }
134 
135 /* ********************* ASVisual ************************************/
136 ASVisual *_set_default_asvisual( ASVisual *new_v );
137 
138 #ifndef X_DISPLAY_MISSING
139 static XColor black_xcol = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue };
140 static XColor white_xcol = { 0, 0xFFFF, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue };
141 
find_useable_visual(ASVisual * asv,Display * dpy,int screen,Window root,XVisualInfo * list,int nitems,XSetWindowAttributes * attr)142 static void find_useable_visual( ASVisual *asv, Display *dpy, int screen,
143 	                             Window root, XVisualInfo *list, int nitems,
144 								 XSetWindowAttributes *attr )
145 {
146 	int k ;
147 	int (*oldXErrorHandler) (Display *, XErrorEvent *) =
148 						XSetErrorHandler (asvisual_empty_XErrorHandler);
149 	Colormap orig_cmap = attr->colormap ;
150 
151 	for( k = 0  ; k < nitems ; k++ )
152 	{
153 		Window       w = None, wjunk;
154 		unsigned int width, height, ujunk ;
155 		int          junk;
156 		/* try and use default colormap when possible : */
157 		if( orig_cmap == None )
158 		{
159   			if( list[k].visual == DefaultVisual( dpy, (screen) ) )
160 			{
161 				attr->colormap = DefaultColormap( dpy, screen );
162 				LOCAL_DEBUG_OUT( "Using Default colormap %lX", attr->colormap );
163 			}else
164 			{
165 				attr->colormap = XCreateColormap( dpy, root, list[k].visual, AllocNone);
166 				LOCAL_DEBUG_OUT( "DefaultVisual is %p, while ours is %p, so Created new colormap %lX", DefaultVisual( dpy, (screen) ), list[k].visual, attr->colormap );
167 			}
168 		}
169 		ASV_ALLOC_COLOR( asv, attr->colormap, &black_xcol );
170 		ASV_ALLOC_COLOR( asv, attr->colormap, &white_xcol );
171 		attr->border_pixel = black_xcol.pixel ;
172 
173 /*fprintf( stderr, "checking out visual ID %d, class %d, depth = %d mask = %X,%X,%X\n", list[k].visualid, list[k].class, list[k].depth, list[k].red_mask, list[k].green_mask, list[k].blue_mask 	);*/
174 		w = XCreateWindow (dpy, root, -10, -10, 10, 10, 0, list[k].depth, CopyFromParent, list[k].visual, CWColormap|CWBorderPixel, attr );
175 		if( w != None && XGetGeometry (dpy, w, &wjunk, &junk, &junk, &width, &height, &ujunk, &ujunk))
176 		{
177 			/* don't really care what's in it since we do not use it anyways : */
178 			asv->visual_info = list[k] ;
179 			XDestroyWindow( dpy, w );
180 			asv->colormap = attr->colormap ;
181 			asv->own_colormap = (attr->colormap != DefaultColormap( dpy, screen ));
182 			asv->white_pixel = white_xcol.pixel ;
183 			asv->black_pixel = black_xcol.pixel ;
184 			break;
185 		}
186 		if( orig_cmap == None )
187 		{
188 			if( attr->colormap != DefaultColormap( dpy, screen ))
189 				XFreeColormap( dpy, attr->colormap );
190 			attr->colormap = None ;
191 		}
192 	}
193 	XSetErrorHandler(oldXErrorHandler);
194 }
195 #endif
196 
197 /* Main procedure finding and querying the best visual */
198 Bool
query_screen_visual_id(ASVisual * asv,Display * dpy,int screen,Window root,int default_depth,VisualID visual_id,Colormap cmap)199 query_screen_visual_id( ASVisual *asv, Display *dpy, int screen, Window root, int default_depth, VisualID visual_id, Colormap cmap )
200 {
201 #ifndef X_DISPLAY_MISSING
202 	int nitems = 0 ;
203 	/* first  - attempt locating 24bpp TrueColor or DirectColor RGB or BGR visuals as the best cases : */
204 	/* second - attempt locating 32bpp TrueColor or DirectColor RGB or BGR visuals as the next best cases : */
205 	/* third  - lesser but still capable 16bpp 565 RGB or BGR modes : */
206 	/* forth  - even more lesser 15bpp 555 RGB or BGR modes : */
207 	/* nothing nice has been found - use whatever X has to offer us as a default :( */
208 	int i ;
209 
210 	XVisualInfo *list = NULL;
211 	XSetWindowAttributes attr ;
212 	static XVisualInfo templates[] =
213 		/* Visual, visualid, screen, depth, class      , red_mask, green_mask, blue_mask, colormap_size, bits_per_rgb */
214 		{{ NULL  , 0       , 0     , 24   , TrueColor  , 0xFF0000, 0x00FF00  , 0x0000FF , 0            , 0 },
215 		 { NULL  , 0       , 0     , 24   , TrueColor  , 0x0000FF, 0x00FF00  , 0xFF0000 , 0            , 0 },
216 		 { NULL  , 0       , 0     , 24   , TrueColor  , 0x0     , 0x0       , 0x0      , 0            , 0 },
217 		 { NULL  , 0       , 0     , 32   , TrueColor  , 0xFF0000, 0x00FF00  , 0x0000FF , 0            , 0 },
218 		 { NULL  , 0       , 0     , 32   , TrueColor  , 0x0000FF, 0x00FF00  , 0xFF0000 , 0            , 0 },
219 		 { NULL  , 0       , 0     , 32   , TrueColor  , 0x0     , 0x0       , 0x0      , 0            , 0 },
220 		 { NULL  , 0       , 0     , 16   , TrueColor  , 0xF800  , 0x07E0    , 0x001F   , 0            , 0 },
221 		 { NULL  , 0       , 0     , 16   , TrueColor  , 0x001F  , 0x07E0    , 0xF800   , 0            , 0 },
222 		 /* big endian or MBR_First modes : */
223 		 { NULL  , 0       , 0     , 16   , TrueColor  , 0x0     , 0xE007    , 0x0      , 0            , 0 },
224 		 /* some misrepresented modes that really are 15bpp : */
225 		 { NULL  , 0       , 0     , 16   , TrueColor  , 0x7C00  , 0x03E0    , 0x001F   , 0            , 0 },
226 		 { NULL  , 0       , 0     , 16   , TrueColor  , 0x001F  , 0x03E0    , 0x7C00   , 0            , 0 },
227 		 { NULL  , 0       , 0     , 16   , TrueColor  , 0x0     , 0xE003    , 0x0      , 0            , 0 },
228 		 { NULL  , 0       , 0     , 15   , TrueColor  , 0x7C00  , 0x03E0    , 0x001F   , 0            , 0 },
229 		 { NULL  , 0       , 0     , 15   , TrueColor  , 0x001F  , 0x03E0    , 0x7C00   , 0            , 0 },
230 		 { NULL  , 0       , 0     , 15   , TrueColor  , 0x0     , 0xE003    , 0x0      , 0            , 0 },
231 /* no suitable TrueColorMode found - now do the same thing to DirectColor :*/
232 		 { NULL  , 0       , 0     , 24   , DirectColor, 0xFF0000, 0x00FF00  , 0x0000FF , 0            , 0 },
233 		 { NULL  , 0       , 0     , 24   , DirectColor, 0x0000FF, 0x00FF00  , 0xFF0000 , 0            , 0 },
234 		 { NULL  , 0       , 0     , 24   , DirectColor, 0x0     , 0x0       , 0x0      , 0            , 0 },
235 		 { NULL  , 0       , 0     , 32   , DirectColor, 0xFF0000, 0x00FF00  , 0x0000FF , 0            , 0 },
236 		 { NULL  , 0       , 0     , 32   , DirectColor, 0x0000FF, 0x00FF00  , 0xFF0000 , 0            , 0 },
237 		 { NULL  , 0       , 0     , 32   , DirectColor, 0x0     , 0x0       , 0x0      , 0            , 0 },
238 		 { NULL  , 0       , 0     , 16   , DirectColor, 0xF800  , 0x07E0    , 0x001F   , 0            , 0 },
239 		 { NULL  , 0       , 0     , 16   , DirectColor, 0x001F  , 0x07E0    , 0xF800   , 0            , 0 },
240 		 { NULL  , 0       , 0     , 16   , DirectColor, 0x0     , 0xE007    , 0x0      , 0            , 0 },
241 		 { NULL  , 0       , 0     , 16   , DirectColor, 0x7C00  , 0x03E0    , 0x001F   , 0            , 0 },
242 		 { NULL  , 0       , 0     , 16   , DirectColor, 0x001F  , 0x03E0    , 0x7C00   , 0            , 0 },
243 		 { NULL  , 0       , 0     , 16   , DirectColor, 0x0     , 0xE003    , 0x0      , 0            , 0 },
244 		 { NULL  , 0       , 0     , 15   , DirectColor, 0x7C00  , 0x03E0    , 0x001F   , 0            , 0 },
245 		 { NULL  , 0       , 0     , 15   , DirectColor, 0x001F  , 0x03E0    , 0x7C00   , 0            , 0 },
246 		 { NULL  , 0       , 0     , 15   , DirectColor, 0x0     , 0xE003    , 0x0      , 0            , 0 },
247 		 { NULL  , 0       , 0     , 0    , 0          , 0       , 0         , 0        , 0            , 0 },
248 		} ;
249 #endif /*ifndef X_DISPLAY_MISSING */
250 	if( asv == NULL )
251 		return False ;
252 	memset( asv, 0x00, sizeof(ASVisual));
253 
254 	asv->dpy = dpy ;
255 
256 #ifndef X_DISPLAY_MISSING
257 	memset( &attr, 0x00, sizeof( attr ));
258 	attr.colormap = cmap ;
259 
260 	if( visual_id == 0 )
261 	{
262 		for( i = 0 ; templates[i].depth != 0 ; i++ )
263 		{
264 			int mask = VisualScreenMask|VisualDepthMask|VisualClassMask ;
265 
266 			templates[i].screen = screen ;
267 			if( templates[i].red_mask != 0 )
268 				mask |= VisualRedMaskMask;
269 			if( templates[i].green_mask != 0 )
270 				mask |= VisualGreenMaskMask ;
271 			if( templates[i].blue_mask != 0 )
272 				mask |= VisualBlueMaskMask ;
273 
274 			if( (list = XGetVisualInfo( dpy, mask, &(templates[i]), &nitems ))!= NULL )
275 			{
276 				find_useable_visual( asv, dpy, screen, root, list, nitems, &attr );
277 				XFree( list );
278 				list = NULL ;
279 				if( asv->visual_info.visual != NULL )
280 					break;
281 			}
282 		}
283 	}else
284 	{
285 		templates[0].visualid = visual_id ;
286 		if( (list = XGetVisualInfo( dpy, VisualIDMask, &(templates[0]), &nitems )) != NULL )
287 		{
288 			find_useable_visual( asv, dpy, screen, root, list, nitems, &attr );
289 		 	XFree( list );
290 			list = NULL ;
291 		}
292 		if( asv->visual_info.visual == NULL )
293 			show_error( "Visual with requested ID of 0x%X is unusable - will try default instead.", visual_id );
294 	}
295 
296 	if( asv->visual_info.visual == NULL )
297 	{  /* we ain't found any decent Visuals - that's some crappy screen you have! */
298 		register int vclass = 6 ;
299 		while( --vclass >= 0 )
300 			if( XMatchVisualInfo( dpy, screen, default_depth, vclass, &(asv->visual_info) ) )
301 				break;
302 		if( vclass < 0 )
303 			return False;
304 		/* try and use default colormap when possible : */
305 		if( asv->visual_info.visual == DefaultVisual( dpy, screen ) )
306 			attr.colormap = DefaultColormap( dpy, screen );
307 		else
308 			attr.colormap = XCreateColormap( dpy, root, asv->visual_info.visual, AllocNone);
309 		ASV_ALLOC_COLOR( asv, attr.colormap, &black_xcol );
310 		ASV_ALLOC_COLOR( asv, attr.colormap, &white_xcol );
311 		asv->colormap = attr.colormap ;
312 		asv->own_colormap = (attr.colormap != DefaultColormap( dpy, screen ));
313 		asv->white_pixel = white_xcol.pixel ;
314 		asv->black_pixel = black_xcol.pixel ;
315 	}
316 	if( get_output_threshold() >= OUTPUT_VERBOSE_THRESHOLD )
317 	{
318 		fprintf( stderr, "Selected visual 0x%lx: depth %d, class %d\n RGB masks: 0x%lX, 0x%lX, 0x%lX, Byte Ordering: %s\n",
319 				 (unsigned long)asv->visual_info.visualid,
320 				 asv->visual_info.depth,
321 				 asv->visual_info.class,
322 				 (unsigned long)asv->visual_info.red_mask,
323 				 (unsigned long)asv->visual_info.green_mask,
324 				 (unsigned long)asv->visual_info.blue_mask,
325 				 (ImageByteOrder(asv->dpy)==MSBFirst)?"MSBFirst":"LSBFirst" );
326 	}
327 #else
328 	asv->white_pixel = ARGB32_White ;
329 	asv->black_pixel = ARGB32_Black ;
330 #endif /*ifndef X_DISPLAY_MISSING */
331 	return True;
332 }
333 
334 ASVisual *
create_asvisual_for_id(Display * dpy,int screen,int default_depth,VisualID visual_id,Colormap cmap,ASVisual * reusable_memory)335 create_asvisual_for_id( Display *dpy, int screen, int default_depth, VisualID visual_id, Colormap cmap, ASVisual *reusable_memory )
336 {
337 	ASVisual *asv = reusable_memory ;
338 #ifndef X_DISPLAY_MISSING
339     Window root = dpy?RootWindow(dpy,screen):None;
340 #endif /*ifndef X_DISPLAY_MISSING */
341 
342 	if( asv == NULL )
343         asv = safecalloc( 1, sizeof(ASVisual) );
344 #ifndef X_DISPLAY_MISSING
345     if( dpy )
346     {
347         if( query_screen_visual_id( asv, dpy, screen, root, default_depth, visual_id, cmap ) )
348         {   /* found visual - now off to decide about color handling on it : */
349             if( !setup_truecolor_visual( asv ) )
350             {  /* well, we don't - lets try and preallocate as many colors as we can but up to
351                 * 1/4 of the colorspace or 12bpp colors, whichever is smaller */
352                 setup_pseudo_visual( asv );
353                 if( asv->as_colormap == NULL )
354                     setup_as_colormap( asv );
355             }
356         }else
357         {
358             if( reusable_memory != asv )
359                 free( asv );
360             asv = NULL ;
361         }
362     }
363 #endif /*ifndef X_DISPLAY_MISSING */
364 	_set_default_asvisual( asv );
365 	return asv;
366 }
367 
368 ASVisual *
create_asvisual(Display * dpy,int screen,int default_depth,ASVisual * reusable_memory)369 create_asvisual( Display *dpy, int screen, int default_depth, ASVisual *reusable_memory )
370 {
371 	VisualID visual_id = 0;
372 	char *id_env_var ;
373 
374 	if( (id_env_var = getenv( ASVISUAL_ID_ENVVAR )) != NULL )
375 		visual_id = strtol(id_env_var,NULL,16);
376 
377 	return create_asvisual_for_id( dpy, screen, default_depth, visual_id, None, reusable_memory );
378 }
379 
380 
381 void
destroy_asvisual(ASVisual * asv,Bool reusable)382 destroy_asvisual( ASVisual *asv, Bool reusable )
383 {
384 	if( asv )
385 	{
386 		if( get_default_asvisual() == asv )
387 			_set_default_asvisual( NULL );
388 #ifndef X_DISPLAY_MISSING
389 	 	if( asv->own_colormap )
390 	 	{
391 	 		if( asv->colormap )
392 	 			XFreeColormap( asv->dpy, asv->colormap );
393 	 	}
394 	 	if( asv->as_colormap )
395 		{
396 	 		free( asv->as_colormap );
397 			if( asv->as_colormap_reverse.xref != NULL )
398 			{
399 				if( asv->as_colormap_type == ACM_12BPP )
400 					destroy_ashash( &(asv->as_colormap_reverse.hash) );
401 				else
402 					free( asv->as_colormap_reverse.xref );
403 			}
404 		}
405 #ifdef HAVE_GLX
406 		if( asv->glx_scratch_gc_direct )
407 			glXDestroyContext(asv->dpy, asv->glx_scratch_gc_direct );
408 		if( asv->glx_scratch_gc_indirect )
409 			glXDestroyContext(asv->dpy, asv->glx_scratch_gc_indirect );
410 #endif
411 		if( asv->scratch_window )
412 			XDestroyWindow( asv->dpy, asv->scratch_window );
413 
414 #endif /*ifndef X_DISPLAY_MISSING */
415 		if( !reusable )
416 			free( asv );
417 	}
418 }
419 
as_colormap_type2size(int type)420 int as_colormap_type2size( int type )
421 {
422 	switch( type )
423 	{
424 		case ACM_3BPP :
425 			return 8 ;
426 		case ACM_6BPP :
427 			return 64 ;
428 		case ACM_12BPP :
429 			return 4096 ;
430 		default:
431 			return 0 ;
432 	}
433 }
434 
435 Bool
visual2visual_prop(ASVisual * asv,size_t * size_ret,unsigned long * version_ret,unsigned long ** data_ret)436 visual2visual_prop( ASVisual *asv, size_t *size_ret,
437 								   unsigned long *version_ret,
438 								   unsigned long **data_ret )
439 {
440 	int cmap_size = 0 ;
441 	unsigned long *prop ;
442 	size_t size;
443 
444 	if( asv == NULL || data_ret == NULL)
445 		return False;
446 
447 	cmap_size = as_colormap_type2size( asv->as_colormap_type );
448 
449 	if( cmap_size > 0 && asv->as_colormap == NULL )
450 		return False ;
451 	size = (1+1+2+1+cmap_size)*sizeof(unsigned long);
452 	prop = safemalloc( size ) ;
453 #ifndef X_DISPLAY_MISSING
454 	prop[0] = asv->visual_info.visualid ;
455 	prop[1] = asv->colormap ;
456 	prop[2] = asv->black_pixel ;
457 	prop[3] = asv->white_pixel ;
458 	prop[4] = asv->as_colormap_type ;
459 	if( cmap_size > 0 )
460 	{
461 		register int i;
462 		for( i = 0 ; i < cmap_size ; i++ )
463 			prop[i+5] = asv->as_colormap[i] ;
464 	}
465 	if( size_ret )
466 		*size_ret = size;
467 #endif /*ifndef X_DISPLAY_MISSING */
468 	if( version_ret )
469 		*version_ret = (1<<16)+0;                        /* version is 1.0 */
470 	*data_ret = prop ;
471 	return True;
472 }
473 
474 Bool
visual_prop2visual(ASVisual * asv,Display * dpy,int screen,size_t size,unsigned long version,unsigned long * data)475 visual_prop2visual( ASVisual *asv, Display *dpy, int screen,
476 								   size_t size,
477 								   unsigned long version,
478 								   unsigned long *data )
479 {
480 #ifndef X_DISPLAY_MISSING
481 	XVisualInfo templ, *list ;
482 	int nitems = 0 ;
483 	int cmap_size = 0 ;
484 #endif /*ifndef X_DISPLAY_MISSING */
485 
486 	if( asv == NULL )
487 		return False;
488 
489 	asv->dpy = dpy ;
490 
491 	if( size < (1+1+2+1)*sizeof(unsigned long) ||
492 		(version&0x00FFFF) != 0 || (version>>16) != 1 || data == NULL )
493 		return False;
494 
495 	if( data[0] == None || data[1] == None ) /* we MUST have valid colormap and visualID !!!*/
496 		return False;
497 
498 #ifndef X_DISPLAY_MISSING
499 	templ.screen = screen ;
500 	templ.visualid = data[0] ;
501 
502 	list = XGetVisualInfo( dpy, VisualScreenMask|VisualIDMask, &templ, &nitems );
503 	if( list == NULL || nitems == 0 )
504 		return False;   /* some very bad visual ID has been requested :( */
505 
506 	asv->visual_info = *list ;
507 	XFree( list );
508 
509 	if( asv->own_colormap && asv->colormap )
510 		XFreeColormap( dpy, asv->colormap );
511 
512 	asv->colormap = data[1] ;
513 	asv->own_colormap = False ;
514 	asv->black_pixel = data[2] ;
515 	asv->white_pixel = data[3] ;
516 	asv->as_colormap_type = data[4];
517 
518 	cmap_size = as_colormap_type2size( asv->as_colormap_type );
519 
520 	if( cmap_size > 0 )
521 	{
522 		register int i ;
523 		if( asv->as_colormap )
524 			free( asv->as_colormap );
525 		asv->as_colormap = safemalloc( cmap_size );
526 		for( i = 0 ; i < cmap_size ; i++ )
527 			asv->as_colormap[i] = data[i+5];
528 	}else
529 		asv->as_colormap_type = ACM_None ;     /* just in case */
530 #else
531 
532 #endif /*ifndef X_DISPLAY_MISSING */
533 	return True;
534 }
535 
536 Bool
setup_truecolor_visual(ASVisual * asv)537 setup_truecolor_visual( ASVisual *asv )
538 {
539 #ifndef X_DISPLAY_MISSING
540 	XVisualInfo *vi = &(asv->visual_info) ;
541 
542 	if( vi->class != TrueColor )
543 		return False;
544 
545 #ifdef HAVE_GLX
546 	if( glXQueryExtension (asv->dpy, NULL, NULL))
547 	{
548 		int val = False;
549 		glXGetConfig(asv->dpy, vi, GLX_USE_GL, &val);
550 		if( val )
551 		{
552 			asv->glx_scratch_gc_indirect = glXCreateContext (asv->dpy, &(asv->visual_info), NULL, False);
553 			if( asv->glx_scratch_gc_indirect )
554 			{
555 				set_flags( asv->glx_support, ASGLX_Available );
556 				if( glXGetConfig(asv->dpy, vi, GLX_RGBA, &val) == 0 )
557 					if( val ) set_flags( asv->glx_support, ASGLX_RGBA );
558 				if( glXGetConfig(asv->dpy, vi, GLX_DOUBLEBUFFER, &val) == 0 )
559 					if( val ) set_flags( asv->glx_support, ASGLX_DoubleBuffer );
560 				if( glXGetConfig(asv->dpy, vi, GLX_DOUBLEBUFFER, &val) == 0 )
561 					if( val ) set_flags( asv->glx_support, ASGLX_DoubleBuffer );
562 
563 				if( (asv->glx_scratch_gc_direct = glXCreateContext (asv->dpy, &(asv->visual_info), NULL, True)) != NULL )
564 					if( !glXIsDirect( asv->dpy, asv->glx_scratch_gc_direct ) )
565 					{
566 						glXDestroyContext(asv->dpy, asv->glx_scratch_gc_direct );
567 						asv->glx_scratch_gc_direct = NULL ;
568 					}
569 #if 0                          /* that needs some more research :  */
570 				/* under Cygwin that seems to be 40% faster then regular XImage for some reason */
571 				set_flags( asv->glx_support, ASGLX_UseForImageTx );
572 #endif
573 			}
574 		}
575 	}
576 #endif
577 
578 	asv->BGR_mode = ((vi->red_mask&0x0010)!=0) ;
579 	asv->rshift = get_shifts (vi->red_mask);
580 	asv->gshift = get_shifts (vi->green_mask);
581 	asv->bshift = get_shifts (vi->blue_mask);
582 	asv->rbits = get_bits (vi->red_mask);
583 	asv->gbits = get_bits (vi->green_mask);
584 	asv->bbits = get_bits (vi->blue_mask);
585 	asv->true_depth = vi->depth ;
586 	asv->msb_first = (ImageByteOrder(asv->dpy)==MSBFirst);
587 
588 	if( asv->true_depth == 16 && ((vi->red_mask|vi->blue_mask)&0x8000) == 0 )
589 		asv->true_depth = 15;
590 	/* setting up conversion handlers : */
591 	switch( asv->true_depth )
592 	{
593 		case 24 :
594 		case 32 :
595 			asv->color2pixel_func     = (asv->BGR_mode)?color2pixel32bgr:color2pixel32rgb ;
596 			asv->pixel2color_func     = (asv->BGR_mode)?pixel2color32bgr:pixel2color32rgb ;
597 			asv->ximage2scanline_func = ximage2scanline32 ;
598 			asv->scanline2ximage_func = scanline2ximage32 ;
599 		    break ;
600 /*		case 24 :
601 			scr->color2pixel_func     = (bgr_mode)?color2pixel24bgr:color2pixel24rgb ;
602 			scr->pixel2color_func     = (bgr_mode)?pixel2color24bgr:pixel2color24rgb ;
603 			scr->ximage2scanline_func = ximage2scanline24 ;
604 			scr->scanline2ximage_func = scanline2ximage24 ;
605 		    break ;
606   */	case 16 :
607 			asv->color2pixel_func     = (asv->BGR_mode)?color2pixel16bgr:color2pixel16rgb ;
608 			asv->pixel2color_func     = (asv->BGR_mode)?pixel2color16bgr:pixel2color16rgb ;
609 			asv->ximage2scanline_func = ximage2scanline16 ;
610 			asv->scanline2ximage_func = scanline2ximage16 ;
611 		    break ;
612 		case 15 :
613 			asv->color2pixel_func     = (asv->BGR_mode)?color2pixel15bgr:color2pixel15rgb ;
614 			asv->pixel2color_func     = (asv->BGR_mode)?pixel2color15bgr:pixel2color15rgb ;
615 			asv->ximage2scanline_func = ximage2scanline15 ;
616 			asv->scanline2ximage_func = scanline2ximage15 ;
617 		    break ;
618 	}
619 #endif /*ifndef X_DISPLAY_MISSING */
620 	return (asv->ximage2scanline_func != NULL) ;
621 }
622 
623 ARGB32 *
make_reverse_colormap(unsigned long * cmap,size_t size,int depth,unsigned short mask,unsigned short shift)624 make_reverse_colormap( unsigned long *cmap, size_t size, int depth, unsigned short mask, unsigned short shift )
625 {
626 	unsigned int max_pixel = 0x01<<depth ;
627 	ARGB32 *rcmap = safecalloc( max_pixel, sizeof( ARGB32 ) );
628 	register int i ;
629 
630 	for( i = 0 ; i < (int)size ; i++ )
631 		if( cmap[i] < max_pixel )
632 			rcmap[cmap[i]] = MAKE_ARGB32( 0xFF, (i>>(shift<<1))& mask, (i>>(shift))&mask, i&mask);
633 	return rcmap;
634 }
635 
636 ASHashTable *
make_reverse_colorhash(unsigned long * cmap,size_t size,int depth,unsigned short mask,unsigned short shift)637 make_reverse_colorhash( unsigned long *cmap, size_t size, int depth, unsigned short mask, unsigned short shift )
638 {
639 	ASHashTable *hash = create_ashash( 0, NULL, NULL, NULL );
640 	register unsigned int i ;
641 
642 	if( hash )
643 	{
644 		for( i = 0 ; i < size ; i++ )
645 			add_hash_item( hash, (ASHashableValue)cmap[i], (void*)((long)MAKE_ARGB32( 0xFF, (i>>(shift<<1))& mask, (i>>(shift))&mask, i&mask)) );
646 	}
647 	return hash;
648 }
649 
650 void
setup_pseudo_visual(ASVisual * asv)651 setup_pseudo_visual( ASVisual *asv  )
652 {
653 #ifndef X_DISPLAY_MISSING
654 	XVisualInfo *vi = &(asv->visual_info) ;
655 
656 	/* we need to allocate new usable list of colors based on available bpp */
657 	asv->true_depth = vi->depth ;
658 	if( asv->as_colormap == NULL )
659 	{
660 		if( asv->true_depth < 8 )
661 			asv->as_colormap_type = ACM_3BPP ;
662 		else if( asv->true_depth < 12 )
663 			asv->as_colormap_type = ACM_6BPP ;
664 		else
665 			asv->as_colormap_type = ACM_12BPP ;
666 	}
667 	/* then we need to set up hooks : */
668 	switch( asv->as_colormap_type )
669 	{
670 		case ACM_3BPP:
671 			asv->ximage2scanline_func = ximage2scanline_pseudo3bpp ;
672 			asv->scanline2ximage_func = scanline2ximage_pseudo3bpp ;
673 			asv->color2pixel_func = color2pixel_pseudo3bpp ;
674 		    break ;
675 		case ACM_6BPP:
676 			asv->ximage2scanline_func = ximage2scanline_pseudo6bpp ;
677 			asv->scanline2ximage_func = scanline2ximage_pseudo6bpp ;
678 			asv->color2pixel_func = color2pixel_pseudo6bpp ;
679 		    break ;
680 		default:
681 			asv->as_colormap_type = ACM_12BPP ;
682 		case ACM_12BPP:
683 			asv->ximage2scanline_func = ximage2scanline_pseudo12bpp ;
684 			asv->scanline2ximage_func = scanline2ximage_pseudo12bpp ;
685 			asv->color2pixel_func = color2pixel_pseudo12bpp ;
686 		    break ;
687 	}
688 	if( asv->as_colormap != NULL )
689 	{
690 		if( asv->as_colormap_type == ACM_3BPP || asv->as_colormap_type == ACM_6BPP )
691 		{
692 			unsigned short mask = 0x0003, shift = 2 ;
693 			if( asv->as_colormap_type==ACM_3BPP )
694 			{
695 				mask = 0x0001 ;
696 				shift = 1 ;
697 			}
698 			asv->as_colormap_reverse.xref = make_reverse_colormap( asv->as_colormap,
699 															  as_colormap_type2size( asv->as_colormap_type ),
700 															  asv->true_depth, mask, shift );
701 		}else if( asv->as_colormap_type == ACM_12BPP )
702 		{
703 			asv->as_colormap_reverse.hash = make_reverse_colorhash( asv->as_colormap,
704 															  as_colormap_type2size( asv->as_colormap_type ),
705 															  asv->true_depth, 0x000F, 4 );
706 		}
707 	}
708 #endif /*ifndef X_DISPLAY_MISSING */
709 }
710 
711 #ifndef X_DISPLAY_MISSING
712 static unsigned long*
make_3bpp_colormap(ASVisual * asv)713 make_3bpp_colormap( ASVisual *asv )
714 {
715 	XColor colors_3bpp[8] =
716 	/* list of non-white, non-black colors in order of decreasing importance: */
717 	{   { 0, 0, 0xFFFF, 0, DoRed|DoGreen|DoBlue, 0},
718 		{ 0, 0xFFFF, 0, 0, DoRed|DoGreen|DoBlue, 0},
719 		{ 0, 0, 0, 0xFFFF, DoRed|DoGreen|DoBlue, 0},
720 	 	{ 0, 0xFFFF, 0xFFFF, 0, DoRed|DoGreen|DoBlue, 0},
721 	    { 0, 0, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue, 0},
722 	    { 0, 0xFFFF, 0, 0xFFFF, DoRed|DoGreen|DoBlue, 0}} ;
723 	unsigned long *cmap ;
724 
725 	cmap = safemalloc( 8 * sizeof(unsigned long) );
726 	/* fail safe code - if any of the alloc fails - colormap entry will still have
727 	 * most suitable valid value ( black or white in 1bpp mode for example ) : */
728 	cmap[0] = cmap[1] = cmap[2] = cmap[3] = asv->black_pixel ;
729 	cmap[7] = cmap[6] = cmap[5] = cmap[4] = asv->white_pixel ;
730 	if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[0] ))  /* pure green */
731 		cmap[0x02] = cmap[0x03] = cmap[0x06] = colors_3bpp[0].pixel ;
732 	if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[1] ))  /* pure red */
733 		cmap[0x04] = cmap[0x05] = colors_3bpp[1].pixel ;
734 	if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[2] ))  /* pure blue */
735 		cmap[0x01] = colors_3bpp[2].pixel ;
736 	if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[3] ))  /* yellow */
737 		cmap[0x06] = colors_3bpp[3].pixel ;
738 	if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[4] ))  /* cyan */
739 		cmap[0x03] = colors_3bpp[4].pixel ;
740 	if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[5] ))  /* magenta */
741 		cmap[0x05] = colors_3bpp[5].pixel ;
742 	return cmap;
743 }
744 
745 static unsigned long*
make_6bpp_colormap(ASVisual * asv,unsigned long * cmap_3bpp)746 make_6bpp_colormap( ASVisual *asv, unsigned long *cmap_3bpp )
747 {
748 	unsigned short red, green, blue ;
749 	unsigned long *cmap = safemalloc( 0x0040*sizeof( unsigned long) );
750 	XColor xcol ;
751 
752 	cmap[0] = asv->black_pixel ;
753 
754 	xcol.flags = DoRed|DoGreen|DoBlue ;
755 	for( blue = 0 ; blue <= 0x0003 ; blue++ )
756 	{
757 		xcol.blue = (0xFFFF*blue)/3 ;
758 		for( red = 0 ; red <= 0x0003 ; red++ )
759 		{	                                /* red has highier priority then blue */
760 			xcol.red = (0xFFFF*red)/3 ;
761 /*			green = ( blue == 0 && red == 0 )?1:0 ; */
762 			for( green = 0 ; green <= 0x0003 ; green++ )
763 			{                                  /* green has highier priority then red */
764 				unsigned short index_3bpp = ((red&0x0002)<<1)|(green&0x0002)|((blue&0x0002)>>1);
765 				unsigned short index_6bpp = (red<<4)|(green<<2)|blue;
766 				xcol.green = (0xFFFF*green)/3 ;
767 
768 				if( (red&0x0001) == ((red&0x0002)>>1) &&
769 					(green&0x0001) == ((green&0x0002)>>1) &&
770 					(blue&0x0001) == ((blue&0x0002)>>1) )
771 					cmap[index_6bpp] = cmap_3bpp[index_3bpp];
772 				else
773 				{
774 					if( ASV_ALLOC_COLOR( asv, asv->colormap, &xcol) != 0 )
775 						cmap[index_6bpp] = xcol.pixel ;
776 					else
777 						cmap[index_6bpp] = cmap_3bpp[index_3bpp] ;
778 				}
779 			}
780 		}
781 	}
782 	return cmap;
783 }
784 
785 static unsigned long*
make_9bpp_colormap(ASVisual * asv,unsigned long * cmap_6bpp)786 make_9bpp_colormap( ASVisual *asv, unsigned long *cmap_6bpp )
787 {
788 	unsigned long *cmap = safemalloc( 512*sizeof( unsigned long) );
789 	unsigned short red, green, blue ;
790 	XColor xcol ;
791 
792 	cmap[0] = asv->black_pixel ;               /* just in case  */
793 
794 	xcol.flags = DoRed|DoGreen|DoBlue ;
795 	for( blue = 0 ; blue <= 0x0007 ; blue++ )
796 	{
797 		xcol.blue = (0xFFFF*blue)/7 ;
798 		for( red = 0 ; red <= 0x0007 ; red++ )
799 		{	                                /* red has highier priority then blue */
800 			xcol.red = (0xFFFF*red)/7 ;
801 			for( green = 0 ; green <= 0x0007 ; green++ )
802 			{                                  /* green has highier priority then red */
803 				unsigned short index_6bpp = ((red&0x0006)<<3)|((green&0x0006)<<1)|((blue&0x0006)>>1);
804 				unsigned short index_9bpp = (red<<6)|(green<<3)|blue;
805 				xcol.green = (0xFFFF*green)/7 ;
806 
807 				if( (red&0x0001) == ((red&0x0002)>>1) &&
808 					(green&0x0001) == ((green&0x0002)>>1) &&
809 					(blue&0x0001) == ((blue&0x0002)>>1) )
810 					cmap[index_9bpp] = cmap_6bpp[index_6bpp];
811 				else
812 				{
813 					if( ASV_ALLOC_COLOR( asv, asv->colormap, &xcol) != 0 )
814 						cmap[index_9bpp] = xcol.pixel ;
815 					else
816 						cmap[index_9bpp] = cmap_6bpp[index_6bpp] ;
817 				}
818 			}
819 		}
820 	}
821 	return cmap;
822 }
823 
824 static unsigned long*
make_12bpp_colormap(ASVisual * asv,unsigned long * cmap_9bpp)825 make_12bpp_colormap( ASVisual *asv, unsigned long *cmap_9bpp )
826 {
827 	unsigned long *cmap = safemalloc( 4096*sizeof( unsigned long) );
828 	unsigned short red, green, blue ;
829 	XColor xcol ;
830 
831 	cmap[0] = asv->black_pixel ;               /* just in case  */
832 
833 	xcol.flags = DoRed|DoGreen|DoBlue ;
834 	for( blue = 0 ; blue <= 0x000F ; blue++ )
835 	{
836 		xcol.blue = (0xFFFF*blue)/15 ;
837 		for( red = 0 ; red <= 0x000F ; red++ )
838 		{	                                /* red has highier priority then blue */
839 			xcol.red = (0xFFFF*red)/15 ;
840 			for( green = 0 ; green <= 0x000F ; green++ )
841 			{                                  /* green has highier priority then red */
842 				unsigned short index_9bpp = ((red&0x000E)<<5)|((green&0x000E)<<2)|((blue&0x000E)>>1);
843 				unsigned short index_12bpp = (red<<8)|(green<<4)|blue;
844 				xcol.green = (0xFFFF*green)/15 ;
845 
846 				if( (red&0x0001) == ((red&0x0002)>>1) &&
847 					(green&0x0001) == ((green&0x0002)>>1) &&
848 					(blue&0x0001) == ((blue&0x0002)>>1) )
849 					cmap[index_12bpp] = cmap_9bpp[index_9bpp];
850 				else
851 				{
852 					if( ASV_ALLOC_COLOR( asv, asv->colormap, &xcol) != 0 )
853 						cmap[index_12bpp] = xcol.pixel ;
854 					else
855 						cmap[index_12bpp] = cmap_9bpp[index_9bpp] ;
856 				}
857 			}
858 		}
859 	}
860 	return cmap;
861 }
862 #endif /*ifndef X_DISPLAY_MISSING */
863 
864 void
setup_as_colormap(ASVisual * asv)865 setup_as_colormap( ASVisual *asv )
866 {
867 #ifndef X_DISPLAY_MISSING
868 	unsigned long *cmap_lower, *cmap ;
869 
870 	if( asv == NULL || asv->as_colormap != NULL )
871 		return ;
872 
873 	cmap = make_3bpp_colormap( asv );
874 	if( asv->as_colormap_type == ACM_3BPP )
875 	{
876 		asv->as_colormap = cmap ;
877 		asv->as_colormap_reverse.xref = make_reverse_colormap( cmap, 8, asv->true_depth, 0x0001, 1 );
878 		return ;
879 	}
880 	cmap_lower = cmap ;
881 	cmap = make_6bpp_colormap( asv, cmap_lower );
882 	free( cmap_lower );
883 	if( asv->as_colormap_type == ACM_6BPP )
884 	{
885 		asv->as_colormap = cmap ;
886 		asv->as_colormap_reverse.xref = make_reverse_colormap( cmap, 64, asv->true_depth, 0x0003, 2 );
887 	}else
888 	{
889 		cmap_lower = cmap ;
890 		cmap = make_9bpp_colormap( asv, cmap_lower );
891 		free( cmap_lower );
892 		cmap_lower = cmap ;
893 		cmap = make_12bpp_colormap( asv, cmap_lower );
894 		free( cmap_lower );
895 
896 		asv->as_colormap = cmap ;
897 		asv->as_colormap_reverse.hash = make_reverse_colorhash( cmap, 4096, asv->true_depth, 0x000F, 4 );
898 	}
899 #endif /*ifndef X_DISPLAY_MISSING */
900 }
901 
902 /*********************************************************************/
903 /* handy utility functions for creation of windows/pixmaps/XImages : */
904 /*********************************************************************/
905 Window
create_visual_window(ASVisual * asv,Window parent,int x,int y,unsigned int width,unsigned int height,unsigned int border_width,unsigned int wclass,unsigned long mask,XSetWindowAttributes * attributes)906 create_visual_window( ASVisual *asv, Window parent,
907 					  int x, int y, unsigned int width, unsigned int height,
908 					  unsigned int border_width, unsigned int wclass,
909  					  unsigned long mask, XSetWindowAttributes *attributes )
910 {
911 #ifndef X_DISPLAY_MISSING
912 	XSetWindowAttributes my_attr ;
913 	int depth = 0;
914 
915 	if( asv == NULL || parent == None )
916 		return None ;
917 LOCAL_DEBUG_OUT( "Colormap %lX, parent %lX, %ux%u%+d%+d, bw = %d, class %d",
918 				  asv->colormap, parent, width, height, x, y, border_width,
919 				  wclass );
920 	if( attributes == NULL )
921 	{
922 		attributes = &my_attr ;
923 		memset( attributes, 0x00, sizeof(XSetWindowAttributes));
924 		mask = 0;
925 	}
926 
927 	if( width < 1 )
928 		width = 1 ;
929 	if( height < 1 )
930 		height = 1 ;
931 
932 	if( wclass == InputOnly )
933 	{
934 		border_width = 0 ;
935 		if( (mask&INPUTONLY_LEGAL_MASK) != mask )
936 			show_warning( " software BUG detected : illegal InputOnly window's mask 0x%lX - overriding", mask );
937 		mask &= INPUTONLY_LEGAL_MASK ;
938 	}else
939 	{
940 		depth = asv->visual_info.depth ;
941 		if( !get_flags(mask, CWColormap ) )
942 		{
943 			attributes->colormap = asv->colormap ;
944 			set_flags(mask, CWColormap );
945 		}
946 		if( !get_flags(mask, CWBorderPixmap ) )
947 		{
948 			attributes->border_pixmap = None ;
949 			set_flags(mask, CWBorderPixmap );
950 		}
951 
952 		clear_flags(mask, CWBorderPixmap );
953 		if( !get_flags(mask, CWBorderPixel ) )
954 		{
955 			attributes->border_pixel = asv->black_pixel ;
956 			set_flags(mask, CWBorderPixel );
957 		}
958 		/* If the parent window and the new window have different bit
959 		** depths (such as on a Solaris box with 8bpp root window and
960 		** 24bpp child windows), ParentRelative will not work. */
961 		if ( get_flags(mask, CWBackPixmap) && attributes->background_pixmap == ParentRelative &&
962 			 asv->visual_info.visual != DefaultVisual( asv->dpy, DefaultScreen(asv->dpy) ))
963 		{
964 			clear_flags(mask, CWBackPixmap);
965 		}
966 	}
967 	LOCAL_DEBUG_OUT( "parent = %lX, mask = 0x%lX, VisualID = 0x%lX, Border Pixel = %ld, colormap = %lX",
968 					  parent, mask, asv->visual_info.visual->visualid, attributes->border_pixel, attributes->colormap );
969 	return XCreateWindow (asv->dpy, parent, x, y, width, height, border_width, depth,
970 						  wclass, asv->visual_info.visual,
971 	                      mask, attributes);
972 #else
973 	return None ;
974 #endif /*ifndef X_DISPLAY_MISSING */
975 
976 }
977 
978 
979 GC
create_visual_gc(ASVisual * asv,Window root,unsigned long mask,XGCValues * gcvalues)980 create_visual_gc( ASVisual *asv, Window root, unsigned long mask, XGCValues *gcvalues )
981 {
982    	GC gc = NULL ;
983 
984 #ifndef X_DISPLAY_MISSING
985 	if( asv )
986 	{
987 		XGCValues scratch_gcv ;
988 		if( asv->scratch_window == None )
989 			asv->scratch_window = create_visual_window( asv, root, -20, -20, 10, 10, 0, InputOutput, 0, NULL );
990 		if( asv->scratch_window != None )
991 			gc = XCreateGC( asv->dpy, asv->scratch_window, gcvalues?mask:0, gcvalues?gcvalues:&scratch_gcv );
992 	}
993 #endif
994 	return gc;
995 }
996 
997 Pixmap
create_visual_pixmap(ASVisual * asv,Window root,unsigned int width,unsigned int height,unsigned int depth)998 create_visual_pixmap( ASVisual *asv, Window root, unsigned int width, unsigned int height, unsigned int depth )
999 {
1000 #ifndef X_DISPLAY_MISSING
1001 	Pixmap p = None ;
1002 	if( asv != NULL )
1003 	{
1004 		if( root == None )
1005 			root = RootWindow(asv->dpy,DefaultScreen(asv->dpy));
1006 		if( depth==0 )
1007 			depth = asv->true_depth ;
1008 		p = XCreatePixmap( asv->dpy, root, MAX(width,(unsigned)1), MAX(height,(unsigned)1), depth );
1009 	}
1010 	return p;
1011 #else
1012 	return None ;
1013 #endif /*ifndef X_DISPLAY_MISSING */
1014 }
1015 
1016 void
destroy_visual_pixmap(ASVisual * asv,Pixmap * ppmap)1017 destroy_visual_pixmap( ASVisual *asv, Pixmap *ppmap )
1018 {
1019 	if( asv && ppmap )
1020 		if( *ppmap )
1021 		{
1022 #ifndef X_DISPLAY_MISSING
1023 			XFreePixmap( asv->dpy, *ppmap );
1024 			*ppmap = None ;
1025 #endif
1026 		}
1027 }
1028 
1029 #ifndef X_DISPLAY_MISSING
1030 static int
quiet_xerror_handler(Display * dpy,XErrorEvent * error)1031 quiet_xerror_handler (Display * dpy, XErrorEvent * error)
1032 {
1033     return 0;
1034 }
1035 
1036 #endif
1037 
1038 int
get_dpy_drawable_size(Display * drawable_dpy,Drawable d,unsigned int * ret_w,unsigned int * ret_h)1039 get_dpy_drawable_size (Display *drawable_dpy, Drawable d, unsigned int *ret_w, unsigned int *ret_h)
1040 {
1041 	int result = 0 ;
1042 #ifndef X_DISPLAY_MISSING
1043 	if( d != None && drawable_dpy != NULL )
1044 	{
1045 		Window        root;
1046 		unsigned int  ujunk;
1047 		int           junk;
1048 		int           (*oldXErrorHandler) (Display *, XErrorEvent *) = XSetErrorHandler (quiet_xerror_handler);
1049 		result = XGetGeometry (drawable_dpy, d, &root, &junk, &junk, ret_w, ret_h, &ujunk, &ujunk);
1050 		XSetErrorHandler (oldXErrorHandler);
1051 	}
1052 #endif
1053 	if ( result == 0)
1054 	{
1055 		*ret_w = 0;
1056 		*ret_h = 0;
1057 		return 0;
1058 	}
1059 	return 1;
1060 }
1061 
1062 Bool
get_dpy_window_position(Display * window_dpy,Window root,Window w,int * px,int * py,int * transparency_x,int * transparency_y)1063 get_dpy_window_position (Display *window_dpy, Window root, Window w, int *px, int *py, int *transparency_x, int *transparency_y)
1064 {
1065 	Bool result = False ;
1066 	int x = 0, y = 0, transp_x = 0, transp_y = 0 ;
1067 #ifndef X_DISPLAY_MISSING
1068 	if( window_dpy != NULL && w != None )
1069 	{
1070 		Window wdumm;
1071 		int rootHeight = XDisplayHeight(window_dpy, DefaultScreen(window_dpy) );
1072 		int rootWidth = XDisplayWidth(window_dpy, DefaultScreen(window_dpy) );
1073 
1074 		if( root == None )
1075 			root = RootWindow(window_dpy,DefaultScreen(window_dpy));
1076 
1077 		result = XTranslateCoordinates (window_dpy, w, root, 0, 0, &x, &y, &wdumm);
1078 		if( result )
1079 		{
1080 			/* taking in to consideration virtual desktopping */
1081 			result = (x < rootWidth && y < rootHeight );
1082 			if( result )
1083 			{
1084 				unsigned int width = 0, height = 0;
1085 				get_dpy_drawable_size (window_dpy, w, &width, &height);
1086 				result = (x + width > 0 && y+height > 0) ;
1087 			}
1088 
1089 			for( transp_x = x ; transp_x < 0 ; transp_x += rootWidth );
1090 			for( transp_y = y ; transp_y < 0 ; transp_y += rootHeight );
1091 			while( transp_x > rootWidth ) transp_x -= rootWidth ;
1092 			while( transp_y > rootHeight ) transp_y -= rootHeight ;
1093 		}
1094 	}
1095 #endif
1096 	if( px )
1097 		*px = x;
1098 	if( py )
1099 		*py = y;
1100 	if( transparency_x )
1101 		*transparency_x = transp_x ;
1102 	if( transparency_y )
1103 		*transparency_y = transp_y ;
1104 	return result;
1105 }
1106 
1107 
1108 #ifndef X_DISPLAY_MISSING
1109 static unsigned char *scratch_ximage_data = NULL ;
1110 static int scratch_use_count = 0 ;
1111 static size_t scratch_ximage_allocated_size = 0;
1112 #endif
1113 static size_t scratch_ximage_max_size = ASSHM_SAVED_MAX*2;  /* maximum of 512 KBytes is default  */
1114 static size_t scratch_ximage_normal_size = ASSHM_SAVED_MAX;  /* normal usage of scratch pool is 256 KBytes is default  */
1115 
1116 int
set_scratch_ximage_max_size(int new_max_size)1117 set_scratch_ximage_max_size( int new_max_size )
1118 {
1119 	int tmp = scratch_ximage_max_size ;
1120 	scratch_ximage_max_size = new_max_size ;
1121 	return tmp;
1122 }
1123 
1124 int
set_scratch_ximage_normal_size(int new_normal_size)1125 set_scratch_ximage_normal_size( int new_normal_size )
1126 {
1127 	int tmp = scratch_ximage_normal_size ;
1128 	scratch_ximage_normal_size = new_normal_size ;
1129 	return tmp;
1130 }
1131 
1132 #ifndef X_DISPLAY_MISSING
1133 static void*
get_scratch_data(size_t size)1134 get_scratch_data(size_t size)
1135 {
1136 	if( scratch_ximage_max_size < size || scratch_use_count > 0)
1137 		return NULL;
1138 	if( scratch_ximage_allocated_size < size )
1139 	{
1140 		scratch_ximage_allocated_size = size ;
1141 		scratch_ximage_data = realloc( scratch_ximage_data, size );
1142 	}
1143 
1144 	++scratch_use_count;
1145 	return scratch_ximage_data ;
1146 }
1147 
1148 static Bool
release_scratch_data(void * data)1149 release_scratch_data( void *data )
1150 {
1151 	if( scratch_use_count == 0 || data != scratch_ximage_data )
1152 		return False;
1153 	--scratch_use_count ;
1154 	if( scratch_use_count == 0 )
1155 	{
1156 		/* want to deallocate if too much is allocated ? */
1157 
1158 	}
1159 	return True;
1160 }
1161 #endif
1162 
1163 #ifdef XSHMIMAGE
1164 
1165 int	(*orig_XShmImage_destroy_image)(XImage *ximage) = NULL ;
1166 
1167 typedef struct ASXShmImage
1168 {
1169 	XImage 			*ximage ;
1170 	XShmSegmentInfo *segment ;
1171 	int 			 ref_count ;
1172 	Bool			 wait_completion_event ;
1173 	unsigned int 	 size ;
1174   ASVisual *asv ;
1175 }ASXShmImage;
1176 
1177 typedef struct ASShmArea
1178 {
1179 	unsigned int 	 size ;
1180 	char *shmaddr ;
1181 	int shmid ;
1182 	struct ASShmArea *next, *prev ;
1183 }ASShmArea;
1184 
1185 static ASHashTable	*xshmimage_segments = NULL ;
1186 static ASHashTable	*xshmimage_images = NULL ;
1187 /* attempt to reuse 256 Kb of shmem - no reason to reuse more than that,
1188  * since most XImages will be in range of 20K-100K */
1189 static ASShmArea  *shm_available_mem_head = NULL ;
1190 static int shm_available_mem_used = 0 ;
1191 
1192 static Bool _as_use_shm_images = False ;
1193 
really_destroy_shm_area(char * shmaddr,int shmid)1194 void really_destroy_shm_area( char *shmaddr, int shmid )
1195 {
1196 	shmdt (shmaddr);
1197 	shmctl (shmid, IPC_RMID, 0);
1198 	LOCAL_DEBUG_OUT("XSHMIMAGE> DESTROY_SHM : freeing shmid = %d, remaining in cache = %d bytes ", shmid, shm_available_mem_used );
1199 }
1200 
remove_shm_area(ASShmArea * area,Bool free_resources)1201 void remove_shm_area( ASShmArea *area, Bool free_resources )
1202 {
1203 	if( area )
1204 	{
1205 		if( area == shm_available_mem_head )
1206 			shm_available_mem_head = area->next ;
1207 		if( area->next )
1208 			area->next->prev = area->prev ;
1209 		if( area->prev )
1210 			area->prev->next = area->next ;
1211 		shm_available_mem_used -= area->size ;
1212 		if( free_resources )
1213 			really_destroy_shm_area( area->shmaddr, area->shmid );
1214 		else
1215 		{
1216 			LOCAL_DEBUG_OUT("XSHMIMAGE> REMOVE_SHM : reusing shmid = %d, size %d, remaining in cache = %d bytes ", area->shmid, area->size, shm_available_mem_used );
1217 		}
1218 		free( area );
1219 	}
1220 
1221 }
1222 
flush_shm_cache()1223 void flush_shm_cache( )
1224 {
1225 	if( xshmimage_images )
1226 		destroy_ashash( &xshmimage_images );
1227 	if( xshmimage_segments )
1228 		destroy_ashash( &xshmimage_segments );
1229 	while( shm_available_mem_head != NULL )
1230 		remove_shm_area( shm_available_mem_head, True );
1231 }
1232 
save_shm_area(char * shmaddr,int shmid,int size)1233 void save_shm_area( char *shmaddr, int shmid, int size )
1234 {
1235 	ASShmArea *area;
1236 
1237 	if( shm_available_mem_used+size >= ASSHM_SAVED_MAX )
1238 	{
1239 	  	really_destroy_shm_area( shmaddr, shmid );
1240 		return ;
1241 	}
1242 
1243 	shm_available_mem_used+=size ;
1244 	area = safecalloc( 1, sizeof(ASShmArea) );
1245 
1246 	area->shmaddr = shmaddr ;
1247 	area->shmid = shmid ;
1248 	area->size = size ;
1249 	LOCAL_DEBUG_OUT("XSHMIMAGE> SAVE_SHM : saving shmid = %d, size %d, remaining in cache = %d bytes ", area->shmid, area->size, shm_available_mem_used );
1250 
1251 	area->next = shm_available_mem_head ;
1252 	if( shm_available_mem_head )
1253 		shm_available_mem_head->prev = area ;
1254 	shm_available_mem_head = area ;
1255 }
1256 
get_shm_area(int size,int * shmid)1257 char *get_shm_area( int size, int *shmid )
1258 {
1259 	ASShmArea *selected = NULL, *curr = shm_available_mem_head;
1260 
1261 	while( curr != NULL )
1262 	{
1263 		if( curr->size >= size && curr->size < (size * 4)/3 )
1264 		{
1265 			if( selected == NULL )
1266 				selected = curr ;
1267 			else if( selected->size > curr->size )
1268 				selected = curr ;
1269 		}
1270 		curr = curr->next ;
1271 	}
1272 	if( selected != NULL )
1273 	{
1274 		char *tmp = selected->shmaddr ;
1275 		*shmid = selected->shmid ;
1276 		remove_shm_area( selected, False );
1277 		return tmp ;
1278 	}
1279 
1280 	*shmid = shmget (IPC_PRIVATE, size, IPC_CREAT|0666);
1281 	return shmat (*shmid, 0, 0);
1282 }
1283 
1284 void
destroy_xshmimage_segment(ASHashableValue value,void * data)1285 destroy_xshmimage_segment(ASHashableValue value, void *data)
1286 {
1287 	ASXShmImage *img_data = (ASXShmImage*)data ;
1288 	if( img_data->segment != NULL )
1289 	{
1290 		LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_SEG : img_data = %p : segent to be freed: shminfo = %p ", img_data, img_data->segment );
1291 		XShmDetach (img_data->asv->dpy, img_data->segment);
1292 		save_shm_area( img_data->segment->shmaddr, img_data->segment->shmid, img_data->size );
1293 		free( img_data->segment );
1294 		img_data->segment = NULL ;
1295 		if( img_data->ximage == NULL )
1296 			free( img_data );
1297 	}else
1298 	{
1299 		LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_SEG : img_data = %p : segment data is NULL already value = %ld!!", img_data, value );
1300 	}
1301 }
1302 
destroy_xshm_segment(ShmSeg shmseg)1303 Bool destroy_xshm_segment( ShmSeg shmseg )
1304 {
1305 	if( xshmimage_segments )
1306 	{
1307 		if(remove_hash_item( xshmimage_segments, AS_HASHABLE(shmseg), NULL, True ) == ASH_Success)
1308 		{
1309 			LOCAL_DEBUG_OUT( "XSHMIMAGE> REMOVE_SEG : segment %ld removed from the hash successfully!", shmseg );
1310 			return True ;
1311 		}
1312 		LOCAL_DEBUG_OUT( "XSHMIMAGE> ERROR : could not find segment %ld(0x%lX) in the hash!", shmseg, shmseg );
1313 	}else
1314 	{
1315 		LOCAL_DEBUG_OUT( "XSHMIMAGE> ERROR : segments hash is %p!!", xshmimage_segments );
1316 	}
1317 
1318 	return False ;
1319 }
1320 
1321 
1322 void
destroy_xshmimage_image(ASHashableValue value,void * data)1323 destroy_xshmimage_image(ASHashableValue value, void *data)
1324 {
1325 	ASXShmImage *img_data = (ASXShmImage*)data ;
1326 	if( img_data->ximage != NULL )
1327 	{
1328 		if( orig_XShmImage_destroy_image )
1329 			orig_XShmImage_destroy_image( img_data->ximage );
1330 		else
1331 			XFree ((char *)img_data->ximage);
1332 		LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_XIM : ximage freed: img_data = %p, xim = %p", img_data, img_data->ximage);
1333 		img_data->ximage = NULL ;
1334 		if( img_data->segment != NULL && !img_data->wait_completion_event )
1335 		{
1336 			if( destroy_xshm_segment( img_data->segment->shmseg ) )
1337 				return ;
1338 			img_data->segment = NULL ;
1339 		}
1340 		if( img_data->segment == NULL )
1341 			free( img_data );
1342 	}
1343 }
1344 
enable_shmem_images_for_visual(ASVisual * asv)1345 Bool enable_shmem_images_for_visual (ASVisual *asv)
1346 {
1347 #ifndef DEBUG_ALLOCS
1348 	if( asv && asv->dpy && XShmQueryExtension (asv->dpy) )
1349 	{
1350 		_as_use_shm_images = True ;
1351 		if( xshmimage_segments == NULL )
1352 			xshmimage_segments = create_ashash( 0, NULL, NULL, destroy_xshmimage_segment );
1353 		if( xshmimage_images == NULL )
1354 			xshmimage_images = create_ashash( 0, pointer_hash_value, NULL, destroy_xshmimage_image );
1355 	}else
1356 #endif
1357 		_as_use_shm_images = False ;
1358 	return _as_use_shm_images;
1359 }
1360 
enable_shmem_images()1361 Bool enable_shmem_images ()
1362 {
1363 	return enable_shmem_images_for_visual (get_default_asvisual());
1364 }
1365 
1366 
disable_shmem_images()1367 void disable_shmem_images()
1368 {
1369 	_as_use_shm_images = False ;
1370 }
1371 
1372 Bool
check_shmem_images_enabled()1373 check_shmem_images_enabled()
1374 {
1375 	return _as_use_shm_images ;
1376 }
1377 
1378 
destroy_xshm_image(XImage * ximage)1379 int destroy_xshm_image( XImage *ximage )
1380 {
1381 	if( xshmimage_images )
1382 	{
1383 		if( remove_hash_item( xshmimage_images, AS_HASHABLE(ximage), NULL, True ) != ASH_Success )
1384 		{
1385 			if (ximage->data != NULL)
1386 				free ((char *)ximage->data);
1387 			if (ximage->obdata != NULL)
1388 				free ((char *)ximage->obdata);
1389 			XFree ((char *)ximage);
1390 			LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_XIM : ximage freed: xim = %p", ximage);
1391 		}
1392 	}
1393 	return 1;
1394 }
1395 
1396 unsigned long
ximage2shmseg(XImage * xim)1397 ximage2shmseg( XImage *xim )
1398 {
1399 	void *vptr = NULL ;
1400 	if( get_hash_item( xshmimage_images, AS_HASHABLE(xim), &vptr ) == ASH_Success )
1401 	{
1402 		ASXShmImage *data = (ASXShmImage *)vptr ;
1403 		if( data->segment )
1404 			return data->segment->shmseg;
1405 	}
1406 	return 0;
1407 }
1408 
registerXShmImage(ASVisual * asv,XImage * ximage,XShmSegmentInfo * shminfo)1409 void registerXShmImage( ASVisual *asv, XImage *ximage, XShmSegmentInfo* shminfo )
1410 {
1411 	ASXShmImage *data = safecalloc( 1, sizeof(ASXShmImage));
1412 	LOCAL_DEBUG_OUT( "XSHMIMAGE> CREATE_XIM : img_data = %p : image created: xiom = %p, shminfo = %p, segment = %d, data = %p", data, ximage, shminfo, shminfo->shmid, ximage->data );
1413   data->asv = asv ;
1414 	data->ximage = ximage ;
1415 	data->segment = shminfo ;
1416 	data->size = ximage->bytes_per_line * ximage->height ;
1417 
1418 	orig_XShmImage_destroy_image = ximage->f.destroy_image ;
1419 	ximage->f.destroy_image = destroy_xshm_image ;
1420 
1421 	add_hash_item( xshmimage_images, AS_HASHABLE(ximage), data );
1422 	add_hash_item( xshmimage_segments, AS_HASHABLE(shminfo->shmseg), data );
1423 }
1424 
1425 void *
check_XImage_shared(XImage * xim)1426 check_XImage_shared( XImage *xim )
1427 {
1428 	ASXShmImage *img_data = NULL ;
1429 	if( _as_use_shm_images )
1430 	{
1431 		ASHashData hdata ;
1432 		if(get_hash_item( xshmimage_images, AS_HASHABLE(xim), &hdata.vptr ) != ASH_Success)
1433 			img_data = NULL ;
1434 		else
1435 			img_data = hdata.vptr ;
1436 	}
1437 	return img_data ;
1438 }
1439 
ASPutXImage(ASVisual * asv,Drawable d,GC gc,XImage * xim,int src_x,int src_y,int dest_x,int dest_y,unsigned int width,unsigned int height)1440 Bool ASPutXImage( ASVisual *asv, Drawable d, GC gc, XImage *xim,
1441                   int src_x, int src_y, int dest_x, int dest_y,
1442 				  unsigned int width, unsigned int height )
1443 {
1444 	ASXShmImage *img_data = NULL ;
1445 	if( xim == NULL || asv == NULL )
1446 		return False ;
1447 
1448 	if( ( img_data = check_XImage_shared( xim )) != NULL )
1449 	{
1450 /*		LOCAL_DEBUG_OUT( "XSHMIMAGE> PUT_XIM : using shared memory Put = %p", xim ); */
1451 		if( XShmPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height, True ) )
1452 		{
1453 			img_data->wait_completion_event = True ;
1454 			return True ;
1455 		}
1456 	}
1457 /*	LOCAL_DEBUG_OUT( "XSHMIMAGE> PUT_XIM : using normal Put = %p", xim ); */
1458 	return XPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height );
1459 }
1460 
ASGetXImage(ASVisual * asv,Drawable d,int x,int y,unsigned int width,unsigned int height,unsigned long plane_mask)1461 XImage *ASGetXImage( ASVisual *asv, Drawable d,
1462                   int x, int y, unsigned int width, unsigned int height,
1463 				  unsigned long plane_mask )
1464 {
1465 	XImage *xim = NULL ;
1466 
1467 	if( asv == NULL || d == None )
1468 		return NULL ;
1469 	if( _as_use_shm_images && width*height > 4000)
1470 	{
1471 		unsigned int depth ;
1472 		Window        root;
1473 		unsigned int  ujunk;
1474 		int           junk;
1475 		if(XGetGeometry (asv->dpy, d, &root, &junk, &junk, &ujunk, &ujunk, &ujunk, &depth) == 0)
1476 			return NULL ;
1477 
1478 		xim = create_visual_ximage(asv,width,height,depth);
1479 		XShmGetImage( asv->dpy, d, xim, x, y, plane_mask );
1480 
1481 	}else
1482 		xim = XGetImage( asv->dpy, d, x, y, width, height, plane_mask, ZPixmap );
1483 	return xim ;
1484 }
1485 #else
1486 
enable_shmem_images()1487 Bool enable_shmem_images (){return False; }
disable_shmem_images()1488 void disable_shmem_images(){}
check_XImage_shared(XImage * xim)1489 void *check_XImage_shared( XImage *xim ) {return NULL ; }
1490 
ASPutXImage(ASVisual * asv,Drawable d,GC gc,XImage * xim,int src_x,int src_y,int dest_x,int dest_y,unsigned int width,unsigned int height)1491 Bool ASPutXImage( ASVisual *asv, Drawable d, GC gc, XImage *xim,
1492                   int src_x, int src_y, int dest_x, int dest_y,
1493 				  unsigned int width, unsigned int height )
1494 {
1495 #ifndef X_DISPLAY_MISSING
1496 	if( xim == NULL || asv == NULL )
1497 		return False ;
1498 	return XPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height );
1499 #else
1500 	return False;
1501 #endif
1502 }
1503 
ASGetXImage(ASVisual * asv,Drawable d,int x,int y,unsigned int width,unsigned int height,unsigned long plane_mask)1504 XImage * ASGetXImage( ASVisual *asv, Drawable d,
1505                   int x, int y, unsigned int width, unsigned int height,
1506 				  unsigned long plane_mask )
1507 {
1508 #ifndef X_DISPLAY_MISSING
1509 	if( asv == NULL || d == None )
1510 		return NULL ;
1511 	return XGetImage( asv->dpy, d, x, y, width, height, plane_mask, ZPixmap );
1512 #else
1513 	return NULL ;
1514 #endif
1515 }
1516 
1517 #endif                                         /* XSHMIMAGE */
1518 
1519 #ifndef X_DISPLAY_MISSING
1520 int
My_XDestroyImage(XImage * ximage)1521 My_XDestroyImage (XImage *ximage)
1522 {
1523 	if( !release_scratch_data(ximage->data) )
1524 		if (ximage->data != NULL)
1525 			free (ximage->data);
1526 	if (ximage->obdata != NULL)
1527 		free (ximage->obdata);
1528 	XFree (ximage);
1529 	return 1;
1530 }
1531 #endif /*ifndef X_DISPLAY_MISSING */
1532 
1533 
1534 XImage*
create_visual_ximage(ASVisual * asv,unsigned int width,unsigned int height,unsigned int depth)1535 create_visual_ximage( ASVisual *asv, unsigned int width, unsigned int height, unsigned int depth )
1536 {
1537 #ifndef X_DISPLAY_MISSING
1538 	register XImage *ximage = NULL;
1539 	unsigned long dsize;
1540 	char         *data;
1541 	int unit ;
1542 
1543 	if( asv == NULL )
1544 		return NULL;
1545 
1546 #if 0
1547 	unit = asv->dpy->bitmap_unit;
1548 #else
1549 	if( depth == 0 )
1550 		unit = (asv->true_depth+7)&0x0038;
1551 	else
1552 		unit = (depth+7)&0x0038;
1553 	if( unit == 24 )
1554 		unit = 32 ;
1555 #endif
1556 #ifdef XSHMIMAGE
1557 	if( _as_use_shm_images && width*height > 4000 )
1558 	{
1559 		XShmSegmentInfo *shminfo = safecalloc( 1, sizeof(XShmSegmentInfo));
1560 
1561 		ximage = XShmCreateImage (asv->dpy, asv->visual_info.visual,
1562 			                      (depth==0)?asv->visual_info.depth/*true_depth*/:depth,
1563 								  ZPixmap, NULL, shminfo,
1564 								  MAX(width,(unsigned int)1), MAX(height,(unsigned int)1));
1565 		if( ximage == NULL )
1566 			free( shminfo );
1567 		else
1568 		{
1569 			shminfo->shmaddr = ximage->data = get_shm_area( ximage->bytes_per_line * ximage->height, &(shminfo->shmid) );
1570 			if( shminfo->shmid == -1 )
1571 			{
1572 				static int shmem_failure_count = 0 ;
1573 			    show_warning( "unable to allocate %d bytes of shared image memory", ximage->bytes_per_line * ximage->height ) ;
1574 				if( ximage->bytes_per_line * ximage->height < 100000 || ++shmem_failure_count > 10 )
1575 				{
1576 					show_error( "too many shared memory failures - disabling" ) ;
1577 					_as_use_shm_images = False ;
1578 				}
1579 				free( shminfo );
1580 				shminfo = NULL ;
1581 				XFree( ximage );
1582 				ximage = NULL ;
1583 			}else
1584 			{
1585 				shminfo->readOnly = False;
1586 				XShmAttach (asv->dpy, shminfo);
1587 				registerXShmImage( asv, ximage, shminfo );
1588 			}
1589 		}
1590 	}
1591 #endif
1592 	if( ximage == NULL )
1593 	{
1594 		ximage = XCreateImage (asv->dpy, asv->visual_info.visual, (depth==0)?asv->visual_info.depth/*true_depth*/:depth, ZPixmap, 0, NULL, MAX(width,(unsigned int)1), MAX(height,(unsigned int)1),
1595 						   	unit, 0);
1596 		if (ximage != NULL)
1597 		{
1598 			_XInitImageFuncPtrs (ximage);
1599 			ximage->obdata = NULL;
1600 			ximage->f.destroy_image = My_XDestroyImage;
1601 			dsize = ximage->bytes_per_line*ximage->height;
1602 	    	if (((data = (char *)safemalloc (dsize)) == NULL) && (dsize > 0))
1603 			{
1604 				XFree ((char *)ximage);
1605 				return (XImage *) NULL;
1606 			}
1607 			ximage->data = data;
1608 		}
1609 	}
1610 	return ximage;
1611 #else
1612 	return NULL ;
1613 #endif /*ifndef X_DISPLAY_MISSING */
1614 }
1615 /* this is the vehicle to use static allocated buffer for temporary XImages
1616  * in order to reduce XImage meory allocation overhead */
1617 XImage*
create_visual_scratch_ximage(ASVisual * asv,unsigned int width,unsigned int height,unsigned int depth)1618 create_visual_scratch_ximage( ASVisual *asv, unsigned int width, unsigned int height, unsigned int depth )
1619 {
1620 #ifndef X_DISPLAY_MISSING
1621 	register XImage *ximage = NULL;
1622 	char         *data;
1623 	int unit ;
1624 
1625 	if( asv == NULL )
1626 		return NULL;
1627 
1628 #if 0
1629 	unit = asv->dpy->bitmap_unit;
1630 #else
1631 	if( depth == 0 )
1632 		unit = (asv->true_depth+7)&0x0038;
1633 	else
1634 		unit = (depth+7)&0x0038;
1635 	if( unit == 24 )
1636 		unit = 32 ;
1637 #endif
1638 
1639 	/* for shared memory XImage we already do caching - no need for scratch ximage */
1640 #ifdef XSHMIMAGE
1641 	if( _as_use_shm_images )
1642 		return create_visual_ximage( asv, width, height, depth );
1643 #endif
1644 
1645 	if( ximage == NULL )
1646 	{
1647 		ximage = XCreateImage (asv->dpy, asv->visual_info.visual,
1648 			                   (depth==0)?asv->visual_info.depth/*true_depth*/:depth, ZPixmap,
1649 							   0, NULL, MAX(width,(unsigned int)1), MAX(height,(unsigned int)1),
1650 						   	   unit, 0);
1651 		if (ximage != NULL)
1652 		{
1653 			data = get_scratch_data(ximage->bytes_per_line * ximage->height);
1654 			if( data == NULL )
1655 			{
1656 				XFree ((char *)ximage);
1657 				return create_visual_ximage( asv, width, height, depth );/* fall back */
1658 			}
1659 			_XInitImageFuncPtrs (ximage);
1660 			ximage->obdata = NULL;
1661 			ximage->f.destroy_image = My_XDestroyImage;
1662 			ximage->data = data;
1663 		}
1664 	}
1665 	return ximage;
1666 #else
1667 	return NULL ;
1668 #endif /*ifndef X_DISPLAY_MISSING */
1669 }
1670 
1671 
1672 
1673 /****************************************************************************/
1674 /* Color manipulation functions :                                           */
1675 /****************************************************************************/
1676 
1677 
1678 /* misc function to calculate number of bits/shifts */
1679 #ifndef X_DISPLAY_MISSING
1680 static int
get_shifts(unsigned long mask)1681 get_shifts (unsigned long mask)
1682 {
1683 	register int  i = 1;
1684 
1685 	while (mask >> i)
1686 		i++;
1687 
1688 	return i - 1;							   /* can't be negative */
1689 }
1690 
1691 static int
get_bits(unsigned long mask)1692 get_bits (unsigned long mask)
1693 {
1694 	register int  i;
1695 
1696 	for (i = 0; mask; mask >>= 1)
1697 		if (mask & 1)
1698 			i++;
1699 
1700 	return i;								   /* can't be negative */
1701 }
1702 #endif
1703 /***************************************************************************/
1704 /* Screen color format -> AS color format conversion ; 					   */
1705 /***************************************************************************/
1706 /***************************************************************************/
1707 /* Screen color format -> AS color format conversion ; 					   */
1708 /***************************************************************************/
1709 /* this functions convert encoded color values into real pixel values, and
1710  * return half of the quantization error so we can do error diffusion : */
1711 /* encoding scheme : 0RRRrrrr rrrrGGgg ggggggBB bbbbbbbb
1712  * where RRR, GG and BB are overflow bits so we can do all kinds of funky
1713  * combined adding, note that we don't use 32'd bit as it is a sign bit */
1714 
1715 #ifndef X_DISPLAY_MISSING
1716 static inline void
query_pixel_color(ASVisual * asv,unsigned long pixel,CARD32 * r,CARD32 * g,CARD32 * b)1717 query_pixel_color( ASVisual *asv, unsigned long pixel, CARD32 *r, CARD32 *g, CARD32 *b )
1718 {
1719 	XColor xcol ;
1720 	xcol.flags = DoRed|DoGreen|DoBlue ;
1721 	xcol.pixel = pixel ;
1722 	if( XQueryColor( asv->dpy, asv->colormap, &xcol ) != 0 )
1723 	{
1724 		*r = xcol.red>>8 ;
1725 		*g = xcol.green>>8 ;
1726 		*b = xcol.blue>>8 ;
1727 	}
1728 }
1729 #endif /*ifndef X_DISPLAY_MISSING */
1730 
1731 
color2pixel32bgr(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1732 CARD32 color2pixel32bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1733 {
1734 	*pixel = ARGB32_RED8(encoded_color)|(ARGB32_GREEN8(encoded_color)<<8)|(ARGB32_BLUE8(encoded_color)<<16);
1735 	return 0;
1736 }
color2pixel32rgb(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1737 CARD32 color2pixel32rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1738 {
1739 	*pixel = encoded_color&0x00FFFFFF;
1740 	return 0;
1741 }
color2pixel24bgr(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1742 CARD32 color2pixel24bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1743 {
1744 	*pixel = encoded_color&0x00FFFFFF;
1745 	return 0;
1746 }
color2pixel24rgb(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1747 CARD32 color2pixel24rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1748 {
1749 	*pixel = encoded_color&0x00FFFFFF;
1750 	return 0;
1751 }
color2pixel16bgr(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1752 CARD32 color2pixel16bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1753 {
1754 	register CARD32 c = encoded_color ;
1755     *pixel = ((c&0x000000F8)<<8)|((c&0x0000FC00)>>5)|((c&0x00F80000)>>19);
1756 	return (c>>1)&0x00030103;
1757 }
color2pixel16rgb(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1758 CARD32 color2pixel16rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1759 {
1760 	register CARD32 c = encoded_color ;
1761     *pixel = ((c&0x00F80000)>>8)|((c&0x0000FC00)>>5)|((c&0x000000F8)>>3);
1762 	return (c>>1)&0x00030103;
1763 }
color2pixel15bgr(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1764 CARD32 color2pixel15bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1765 {
1766 	register CARD32 c = encoded_color ;
1767     *pixel = ((c&0x000000F8)<<7)|((c&0x0000F800)>>6)|((c&0x00F80000)>>19);
1768 	return (c>>1)&0x00030303;
1769 }
color2pixel15rgb(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1770 CARD32 color2pixel15rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
1771 {
1772 	register CARD32 c = encoded_color ;
1773     *pixel = ((c&0x00F80000)>>9)|((c&0x0000F800)>>6)|((c&0x000000F8)>>3);
1774 	return (c>>1)&0x00030303;
1775 }
1776 
color2pixel_pseudo3bpp(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1777 CARD32 color2pixel_pseudo3bpp( ASVisual *asv, CARD32 encoded_color, unsigned long *pixel )
1778 {
1779 	register CARD32 c = encoded_color ;
1780 	*pixel = asv->as_colormap[((c>>25)&0x0008)|((c>>16)&0x0002)|((c>>7)&0x0001)];
1781 	return (c>>1)&0x003F3F3F;
1782 }
1783 
color2pixel_pseudo6bpp(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1784 CARD32 color2pixel_pseudo6bpp( ASVisual *asv, CARD32 encoded_color, unsigned long *pixel )
1785 {
1786 	register CARD32 c = encoded_color ;
1787 	*pixel = asv->as_colormap[((c>>22)&0x0030)|((c>>14)&0x000C)|((c>>6)&0x0003)];
1788 	return (c>>1)&0x001F1F1F;
1789 }
1790 
color2pixel_pseudo12bpp(ASVisual * asv,CARD32 encoded_color,unsigned long * pixel)1791 CARD32 color2pixel_pseudo12bpp( ASVisual *asv, CARD32 encoded_color, unsigned long *pixel )
1792 {
1793 	register CARD32 c = encoded_color ;
1794 	*pixel = asv->as_colormap[((c>>16)&0x0F00)|((c>>10)&0x00F0)|((c>>4)&0x000F)];
1795 	return (c>>1)&0x00070707;
1796 }
1797 
pixel2color32rgb(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1798 void pixel2color32rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1799 {}
pixel2color32bgr(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1800 void pixel2color32bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1801 {}
pixel2color24rgb(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1802 void pixel2color24rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1803 {}
pixel2color24bgr(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1804 void pixel2color24bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1805 {}
pixel2color16rgb(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1806 void pixel2color16rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1807 {}
pixel2color16bgr(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1808 void pixel2color16bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1809 {}
pixel2color15rgb(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1810 void pixel2color15rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1811 {}
pixel2color15bgr(ASVisual * asv,unsigned long pixel,CARD32 * red,CARD32 * green,CARD32 * blue)1812 void pixel2color15bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
1813 {}
1814 
ximage2scanline32(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)1815 void ximage2scanline32(ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
1816 {
1817 	register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
1818 	register CARD32 *a = sl->alpha+sl->offset_x;
1819 	int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
1820 	register CARD32 *src = (CARD32*)xim_data ;
1821 /*	src += sl->offset_x; */
1822 /*fprintf( stderr, "%d: ", y);*/
1823 
1824 #ifdef WORDS_BIGENDIAN
1825 	if( !asv->msb_first )
1826 #else
1827 	if( asv->msb_first )
1828 #endif
1829 	{
1830 		while (--i >= 0)
1831 		{
1832 			b[i] = (src[i]>>24)&0x0ff;
1833 			g[i] = (src[i]>>16)&0x0ff;
1834 			r[i] = (src[i]>>8)&0x0ff;
1835 			a[i] = src[i]&0x0ff;
1836 /*			fprintf( stderr, "[%d->%8.8X %8.8X %8.8X %8.8X = %8.8X]", i, r[i], g[i], b[i], a[i], src[i]);*/
1837 		}
1838 	}else
1839 	{
1840 		while (--i >= 0)
1841 		{
1842 			a[i] = (src[i]>>24)&0x0ff;
1843 			r[i] = (src[i]>>16)&0x0ff;
1844 			g[i] = (src[i]>>8)&0x0ff;
1845 			b[i] =  src[i]&0x0ff;
1846 		}
1847 	}
1848 /*fprintf( stderr, "\n");*/
1849 }
1850 
ximage2scanline16(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)1851 void ximage2scanline16( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
1852 {
1853 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
1854 	register CARD16 *src = (CARD16*)xim_data ;
1855     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
1856 #ifdef WORDS_BIGENDIAN
1857 	if( !asv->msb_first )
1858 #else
1859 	if( asv->msb_first )
1860 #endif
1861 		do
1862 		{
1863 #define ENCODE_MSBF_565(r,gh3,gl3,b)	(((gh3)&0x0007)|((gl3)&0xE000)|((r)&0x00F8)|((b)&0x1F00))
1864 			r[i] =  (src[i]&0x00F8);
1865 			g[i] = ((src[i]&0x0007)<<5)|((src[i]&0xE000)>>11);
1866 			b[i] =  (src[i]&0x1F00)>>5;
1867 		}while( --i >= 0);
1868 	else
1869 		do
1870 		{
1871 #define ENCODE_LSBF_565(r,g,b) (((g)&0x07E0)|((r)&0xF800)|((b)&0x001F))
1872 			r[i] =  (src[i]&0xF800)>>8;
1873 			g[i] =  (src[i]&0x07E0)>>3;
1874 			b[i] =  (src[i]&0x001F)<<3;
1875 		}while( --i >= 0);
1876 
1877 }
ximage2scanline15(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)1878 void ximage2scanline15( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
1879 {
1880 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
1881 	register CARD16 *src = (CARD16*)xim_data ;
1882     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
1883 #ifdef WORDS_BIGENDIAN
1884 	if( !asv->msb_first )
1885 #else
1886 	if( asv->msb_first )
1887 #endif
1888 		do
1889 		{
1890 #define ENCODE_MSBF_555(r,gh2,gl3,b)	(((gh2)&0x0003)|((gl3)&0xE000)|((r)&0x007C)|((b)&0x1F00))
1891 			r[i] =  (src[i]&0x007C)<<1;
1892 			g[i] = ((src[i]&0x0003)<<6)|((src[i]&0xE000)>>10);
1893 			b[i] =  (src[i]&0x1F00)>>5;
1894 		}while( --i >= 0);
1895 	else
1896 		do
1897 		{
1898 #define ENCODE_LSBF_555(r,g,b) (((g)&0x03E0)|((r)&0x7C00)|((b)&0x001F))
1899 			r[i] =  (src[i]&0x7C00)>>7;
1900 			g[i] =  (src[i]&0x03E0)>>2;
1901 			b[i] =  (src[i]&0x001F)<<3;
1902 		}while( --i >= 0);
1903 }
1904 
1905 #ifndef X_DISPLAY_MISSING
1906 
1907 void
ximage2scanline_pseudo3bpp(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)1908 ximage2scanline_pseudo3bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
1909 {
1910 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
1911     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
1912 
1913 	do
1914 	{
1915 		unsigned long pixel = XGetPixel( xim, i, y );
1916 		ARGB32 c = asv->as_colormap_reverse.xref[pixel] ;
1917 		if( c == 0 )
1918 			query_pixel_color( asv, pixel, r+i, g+i, b+i );
1919 		else
1920 		{
1921 			r[i] =  ARGB32_RED8(c);
1922 			g[i] =  ARGB32_GREEN8(c);
1923 			b[i] =  ARGB32_BLUE8(c);
1924 		}
1925 	}while( --i >= 0);
1926 
1927 }
1928 
1929 void
ximage2scanline_pseudo6bpp(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)1930 ximage2scanline_pseudo6bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
1931 {
1932 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
1933     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
1934 
1935 	if( xim->bits_per_pixel == 8 )
1936 	{
1937 		register CARD8 *src = (CARD8*)xim_data ;
1938 		do
1939 		{
1940 			ARGB32 c = asv->as_colormap_reverse.xref[src[i]] ;
1941 			if( c == 0 )
1942 				query_pixel_color( asv, src[i], r+i, g+i, b+i );
1943 			else
1944 			{
1945 				r[i] =  ARGB32_RED8(c);
1946 				g[i] =  ARGB32_GREEN8(c);
1947 				b[i] =  ARGB32_BLUE8(c);
1948 			}
1949 		}while( --i >= 0);
1950 
1951 	}else
1952 		do
1953 		{
1954 			unsigned long pixel = XGetPixel( xim, i, y );
1955 			ARGB32 c = asv->as_colormap_reverse.xref[pixel] ;
1956 			if( c == 0 )
1957 				query_pixel_color( asv, pixel, r+i, g+i, b+i );
1958 			else
1959 			{
1960 				r[i] =  ARGB32_RED8(c);
1961 				g[i] =  ARGB32_GREEN8(c);
1962 				b[i] =  ARGB32_BLUE8(c);
1963 			}
1964 		}while( --i >= 0);
1965 }
1966 
1967 void
ximage2scanline_pseudo12bpp(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)1968 ximage2scanline_pseudo12bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
1969 {
1970 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
1971     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
1972 
1973 	if( xim->bits_per_pixel == 16 )
1974 	{
1975 		register CARD16 *src = (CARD16*)xim_data ;
1976 		do
1977 		{
1978             ASHashData hdata ;
1979             ARGB32 c ;
1980             if( get_hash_item( asv->as_colormap_reverse.hash, AS_HASHABLE((unsigned long)src[i]), &hdata.vptr ) != ASH_Success )
1981 				query_pixel_color( asv, src[i], r+i, g+i, b+i );
1982 			else
1983 			{
1984                 c = hdata.c32;
1985 				r[i] =  ARGB32_RED8(c);
1986 				g[i] =  ARGB32_GREEN8(c);
1987 				b[i] =  ARGB32_BLUE8(c);
1988 			}
1989 		}while( --i >= 0);
1990 
1991 	}else
1992 		do
1993 		{
1994 			unsigned long pixel = XGetPixel( xim, i, y );
1995             ASHashData hdata ;
1996 			ARGB32 c ;
1997             if( get_hash_item( asv->as_colormap_reverse.hash, (ASHashableValue)pixel, &hdata.vptr ) != ASH_Success )
1998 				query_pixel_color( asv, pixel, r+i, g+i, b+i );
1999 			else
2000 			{
2001                 c = hdata.c32;
2002 				r[i] =  ARGB32_RED8(c);
2003 				g[i] =  ARGB32_GREEN8(c);
2004 				b[i] =  ARGB32_BLUE8(c);
2005 			}
2006 		}while( --i >= 0);
2007 }
2008 #endif
2009 
scanline2ximage32(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2010 void scanline2ximage32( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2011 {
2012 	register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2013 	register CARD32 *a = sl->alpha+sl->offset_x;
2014 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
2015 	register CARD32 *src = (CARD32*)xim_data;
2016 /*	src += sl->offset_x ; */
2017 /*fprintf( stderr, "%d: ", y);*/
2018 #ifdef WORDS_BIGENDIAN
2019 	if( !asv->msb_first )
2020 #else
2021 	if( asv->msb_first )
2022 #endif
2023 		while( --i >= 0)
2024 		{
2025 			src[i] = (b[i]<<24)|(g[i]<<16)|(r[i]<<8)|a[i];
2026 /*			fprintf( stderr, "[%d->%8.8X %8.8X %8.8X %8.8X = %8.8X]", i, r[i], g[i], b[i], a[i], src[i]);  */
2027 		}
2028 	else
2029 		while( --i >= 0) src[i] = (a[i]<<24)|(r[i]<<16)|(g[i]<<8)|b[i];
2030 /*fprintf( stderr, "\n");*/
2031 #ifdef DEBUG_SL2XIMAGE
2032 	i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
2033 	src = (CARD32*)xim_data;
2034 	src += sl->offset_x;
2035 	printf( "%d: xim->width = %d, sl->width = %d, sl->offset = %d: ", y, xim->width, sl->width, sl->offset_x );
2036 	while(--i>=0 )	printf( "%8.8lX ", src[i] );
2037 	printf( "\n" );
2038 #endif
2039 }
2040 
2041 /* most LCD can only show 18bpp despite driver's claim to the opposite, hence this artificial mode:
2042  */
scanline2ximage18(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2043 void scanline2ximage18( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2044 {
2045 	register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2046 	register CARD32 *a = sl->alpha+sl->offset_x;
2047 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
2048 	register CARD32 *src = (CARD32*)xim_data;
2049 	register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
2050 
2051 #ifdef WORDS_BIGENDIAN
2052 	if( !asv->msb_first )
2053 #else
2054 	if( asv->msb_first )
2055 #endif
2056 		do
2057 		{
2058 			src[i] = (b[i]<<24)|(g[i]<<16)|(r[i]<<8)|a[i];
2059 			if( --i < 0 )
2060 				break;
2061 			/* carry over quantization error allow for error diffusion:*/
2062 			c = ((c>>1)&0x00400404)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2063 			{
2064 				register CARD32 d = c&0x300C0300 ;
2065 				if( d )
2066 				{
2067 					if( c&0x30000000 )
2068 						d |= 0x0FF00000;
2069 					if( c&0x000C0000 )
2070 						d |= 0x0003FC00 ;
2071 					if( c&0x00000300 )
2072 						d |= 0x000000FF ;
2073 					c ^= d;
2074 				}
2075 /*fprintf( stderr, "c = 0x%X, d = 0x%X, c^d = 0x%X\n", c, d, c^d );*/
2076 			}
2077 		}while(1);
2078 	else
2079 		while( --i >= 0) src[i] = (a[i]<<24)|(r[i]<<16)|(g[i]<<8)|b[i];
2080 }
2081 
scanline2ximage16(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2082 void scanline2ximage16( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2083 {
2084 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
2085 	register CARD16 *src = (CARD16*)xim_data ;
2086     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2087 	register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
2088 #ifdef WORDS_BIGENDIAN
2089 	if( !asv->msb_first )
2090 #else
2091 	if( asv->msb_first )
2092 #endif
2093 		do
2094 		{
2095 			src[i] = ENCODE_MSBF_565((c>>20),(c>>15),(c<<1),(c<<5));
2096 			if( --i < 0 )
2097 				break;
2098 			/* carry over quantization error allow for error diffusion:*/
2099 			c = ((c>>1)&0x00300403)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2100 			{
2101 				register CARD32 d = c&0x300C0300 ;
2102 				if( d )
2103 				{
2104 					if( c&0x30000000 )
2105 						d |= 0x0FF00000;
2106 					if( c&0x000C0000 )
2107 						d |= 0x0003FC00 ;
2108 					if( c&0x00000300 )
2109 						d |= 0x000000FF ;
2110 					c ^= d;
2111 				}
2112 /*fprintf( stderr, "c = 0x%X, d = 0x%X, c^d = 0x%X\n", c, d, c^d );*/
2113 			}
2114 		}while(1);
2115 	else
2116 		do
2117 		{
2118 			src[i] = ENCODE_LSBF_565((c>>12),(c>>7),(c>>3));
2119 			if( --i < 0 )
2120 				break;
2121 			/* carry over quantization error allow for error diffusion:*/
2122 			c = ((c>>1)&0x00300403)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2123 			{
2124 				register CARD32 d = c&0x300C0300 ;
2125 				if( d )
2126 				{
2127 					if( c&0x30000000 )
2128 						d |= 0x0FF00000;
2129 					if( c&0x000C0000 )
2130 						d |= 0x0003FC00 ;
2131 					if( c&0x00000300 )
2132 						d |= 0x000000FF ;
2133 					c ^= d;
2134 				}
2135 /*fprintf( stderr, "c = 0x%X, d = 0x%X, c^d = 0x%X\n", c, d, c^d );*/
2136 			}
2137 		}while(1);
2138 }
2139 
scanline2ximage15(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2140 void scanline2ximage15( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2141 {
2142 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
2143 	register CARD16 *src = (CARD16*)xim_data ;
2144     register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2145 	register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
2146 #ifdef WORDS_BIGENDIAN
2147 	if( !asv->msb_first )
2148 #else
2149 	if( asv->msb_first )
2150 #endif
2151 		do
2152 		{
2153 			src[i] = ENCODE_MSBF_555((c>>21),(c>>16),c/*(c>>2)*/,(c<<5));
2154 			if( --i < 0 )
2155 				break;
2156 			/* carry over quantization error allow for error diffusion:*/
2157 			c = ((c>>1)&0x00300C03)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2158 /*fprintf( stderr, "%s:%d src[%d] = 0x%4.4X, c = 0x%X, color[%d] = #%2.2X%2.2X%2.2X\n", __FUNCTION__, __LINE__, i+1, src[i+1], c, i, r[i], g[i], b[i]);*/
2159 			{
2160 				register CARD32 d = c&0x300C0300 ;
2161 				if( d )
2162 				{
2163 					if( c&0x30000000 )
2164 						d |= 0x0FF00000;
2165 					if( c&0x000C0000 )
2166 						d |= 0x0003FC00 ;
2167 					if( c&0x00000300 )
2168 						d |= 0x000000FF ;
2169 					c ^= d;
2170 				}
2171 /*fprintf( stderr, "%s:%d c = 0x%X, d = 0x%X, c^d = 0x%X\n", __FUNCTION__, __LINE__, c, d, c^d );*/
2172 			}
2173 		}while(1);
2174 	else
2175 	{
2176 		do
2177 		{
2178 			src[i] = ENCODE_LSBF_555((c>>13),(c>>8),(c>>3));
2179 			if( --i < 0 )
2180 				break;
2181 			/* carry over quantization error allow for error diffusion:*/
2182 			c = ((c>>1)&0x00300C03)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2183 			{
2184 				register CARD32 d = c&0x300C0300 ;
2185 				if( d )
2186 				{
2187 					if( c&0x30000000 )
2188 						d |= 0x0FF00000;
2189 					if( c&0x000C0000 )
2190 						d |= 0x0003FC00 ;
2191 					if( c&0x00000300 )
2192 						d |= 0x000000FF ;
2193 					c ^= d;
2194 				}
2195 			}
2196 		}while(1);
2197 	}
2198 }
2199 
2200 #ifndef X_DISPLAY_MISSING
2201 void
scanline2ximage_pseudo3bpp(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2202 scanline2ximage_pseudo3bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2203 {
2204 	register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2205 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
2206 	register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
2207 
2208 	do
2209 	{
2210 		XPutPixel( xim, i, y, asv->as_colormap[((c>>25)&0x0008)|((c>>16)&0x0002)|((c>>7)&0x0001)] );
2211 		if( --i < 0 )
2212 			break;
2213 		c = ((c>>1)&0x03F0FC3F)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2214 		{/* handling possible overflow : */
2215 			register CARD32 d = c&0x300C0300 ;
2216 			if( d )
2217 			{
2218 				if( c&0x30000000 )
2219 					d |= 0x0FF00000;
2220 				if( c&0x000C0000 )
2221 					d |= 0x0003FC00 ;
2222 				if( c&0x00000300 )
2223 					d |= 0x000000FF ;
2224 				c ^= d;
2225 			}
2226 		}
2227 	}while(i);
2228 }
2229 
2230 void
scanline2ximage_pseudo6bpp(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2231 scanline2ximage_pseudo6bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2232 {
2233 	register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2234 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
2235 	register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
2236 
2237 	if( xim->bits_per_pixel == 8 )
2238 	{
2239 		register CARD8 *dst = (CARD8*)xim_data ;
2240 		do
2241 		{
2242 			dst[i] = asv->as_colormap[((c>>22)&0x0030)|((c>>14)&0x000C)|((c>>6)&0x0003)];
2243 			if( --i < 0 )
2244 				break;
2245 			c = ((c>>1)&0x01F07C1F)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2246 			{/* handling possible overflow : */
2247 				register CARD32 d = c&0x300C0300 ;
2248 				if( d )
2249 				{
2250 					if( c&0x30000000 )
2251 						d |= 0x0FF00000;
2252 					if( c&0x000C0000 )
2253 						d |= 0x0003FC00 ;
2254 					if( c&0x00000300 )
2255 						d |= 0x000000FF ;
2256 					c ^= d;
2257 				}
2258 			}
2259 		}while(i);
2260 	}else
2261 	{
2262 		do
2263 		{
2264 			XPutPixel( xim, i, y, asv->as_colormap[((c>>22)&0x0030)|((c>>14)&0x000C)|((c>>6)&0x0003)] );
2265 			if( --i < 0 )
2266 				break;
2267 			c = ((c>>1)&0x01F07C1F)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2268 			{/* handling possible overflow : */
2269 				register CARD32 d = c&0x300C0300 ;
2270 				if( d )
2271 				{
2272 					if( c&0x30000000 )
2273 						d |= 0x0FF00000;
2274 					if( c&0x000C0000 )
2275 						d |= 0x0003FC00 ;
2276 					if( c&0x00000300 )
2277 						d |= 0x000000FF ;
2278 					c ^= d;
2279 				}
2280 			}
2281 		}while(i);
2282 	}
2283 }
2284 
2285 void
scanline2ximage_pseudo12bpp(ASVisual * asv,XImage * xim,ASScanline * sl,int y,register unsigned char * xim_data)2286 scanline2ximage_pseudo12bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y,  register unsigned char *xim_data )
2287 {
2288 	register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
2289 	register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
2290 	register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
2291 
2292 	if( xim->bits_per_pixel == 16 )
2293 	{
2294 		register CARD16 *dst = (CARD16*)xim_data ;
2295 		do
2296 		{
2297 			dst[i] = asv->as_colormap[((c>>16)&0x0F00)|((c>>10)&0x00F0)|((c>>4)&0x000F)];
2298 			if( --i < 0 )
2299 				break;
2300 			c = ((c>>1)&0x00701C07)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2301 			{/* handling possible overflow : */
2302 				register CARD32 d = c&0x300C0300 ;
2303 				if( d )
2304 				{
2305 					if( c&0x30000000 )
2306 						d |= 0x0FF00000;
2307 					if( c&0x000C0000 )
2308 						d |= 0x0003FC00 ;
2309 					if( c&0x00000300 )
2310 						d |= 0x000000FF ;
2311 					c ^= d;
2312 				}
2313 			}
2314 		}while(i);
2315 	}else
2316 	{
2317 		do
2318 		{
2319 			XPutPixel( xim, i, y, asv->as_colormap[((c>>16)&0x0F00)|((c>>10)&0x00F0)|((c>>4)&0x000F)] );
2320 			if( --i < 0 )
2321 				break;
2322 			c = ((c>>1)&0x00701C07)+((r[i]<<20) | (g[i]<<10) | (b[i]));
2323 			{/* handling possible overflow : */
2324 				register CARD32 d = c&0x300C0300 ;
2325 				if( d )
2326 				{
2327 					if( c&0x30000000 )
2328 						d |= 0x0FF00000;
2329 					if( c&0x000C0000 )
2330 						d |= 0x0003FC00 ;
2331 					if( c&0x00000300 )
2332 						d |= 0x000000FF ;
2333 					c ^= d;
2334 				}
2335 			}
2336 		}while(i);
2337 	}
2338 }
2339 
2340 #endif /* ifndef X_DISPLAY_MISSING */
2341 
2342