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