00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef _WIN32
00020 #include "win32/config.h"
00021 #else
00022 #include "config.h"
00023 #endif
00024
00025 #define LOCAL_DEBUG
00026 #undef DEBUG_SL2XIMAGE
00027 #include <string.h>
00028 #ifdef HAVE_UNISTD_H
00029 #include <unistd.h>
00030 #endif
00031 #ifdef HAVE_STDLIB_H
00032 #include <stdlib.h>
00033 #endif
00034 #ifdef HAVE_STDARG_H
00035 #include <stdarg.h>
00036 #endif
00037
00038 #ifdef _WIN32
00039 # include "win32/afterbase.h"
00040 #else
00041 # include "afterbase.h"
00042 #endif
00043 #include "asvisual.h"
00044 #include "scanline.h"
00045
00046 #if defined(XSHMIMAGE) && !defined(X_DISPLAY_MISSING)
00047 # include <sys/ipc.h>
00048 # include <sys/shm.h>
00049 # include <X11/extensions/XShm.h>
00050 #else
00051 # undef XSHMIMAGE
00052 #endif
00053
00054 #if defined(HAVE_GLX) && !defined(X_DISPLAY_MISSING)
00055 # include <GL/gl.h>
00056 # include <GL/glx.h>
00057 #else
00058 # undef HAVE_GLX
00059 #endif
00060
00061
00062
00063 #ifndef X_DISPLAY_MISSING
00064 static int get_shifts (unsigned long mask);
00065 static int get_bits (unsigned long mask);
00066
00067 void _XInitImageFuncPtrs(XImage*);
00068
00069 int
00070 asvisual_empty_XErrorHandler (Display * dpy, XErrorEvent * event)
00071 {
00072 return 0;
00073 }
00074
00075 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
00076 Status
00077 debug_AllocColor( const char *file, int line, ASVisual *asv, Colormap cmap, XColor *pxcol )
00078 {
00079 Status sret ;
00080 sret = XAllocColor( asv->dpy, cmap, pxcol );
00081 show_progress( " XAllocColor in %s:%d has %s -> cmap = %lX, pixel = %lu(%8.8lX), color = 0x%4.4X, 0x%4.4X, 0x%4.4X",
00082 file, line, (sret==0)?"failed":"succeeded", (long)cmap, (unsigned long)(pxcol->pixel), (unsigned long)(pxcol->pixel), pxcol->red, pxcol->green, pxcol->blue );
00083 return sret;
00084 }
00085 #define ASV_ALLOC_COLOR(asv,cmap,pxcol) debug_AllocColor(__FILE__, __LINE__, (asv),(cmap),(pxcol))
00086 #else
00087 #define ASV_ALLOC_COLOR(asv,cmap,pxcol) XAllocColor((asv)->dpy,(cmap),(pxcol))
00088 #endif
00089
00090 #else
00091 #define ASV_ALLOC_COLOR(asv,cmap,pxcol) 0
00092 #endif
00093
00094
00095
00096 long
00097 ARGB32_manhattan_distance (long a, long b)
00098 {
00099 register int d = (int)ARGB32_RED8(a) - (int)ARGB32_RED8(b);
00100 register int t = (d < 0 )? -d : d ;
00101
00102 d = (int)ARGB32_GREEN8(a) - (int)ARGB32_GREEN8(b);
00103 t += (d < 0)? -d : d ;
00104 d = (int)ARGB32_BLUE8(a) - (int)ARGB32_BLUE8(b);
00105 return (t+((d < 0)? -d : d)) ;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114 int get_bits_per_pixel(Display *dpy, int depth)
00115 {
00116 #if 0
00117 #ifndef X_DISPLAY_MISSING
00118 register ScreenFormat *fmt = dpy->pixmap_format;
00119 register int i;
00120
00121 for (i = dpy->nformats + 1; --i; ++fmt)
00122 if (fmt->depth == depth)
00123 return(fmt->bits_per_pixel);
00124 #endif
00125 #endif
00126 if (depth <= 4)
00127 return 4;
00128 if (depth <= 8)
00129 return 8;
00130 if (depth <= 16)
00131 return 16;
00132 return 32;
00133 }
00134
00135
00136 ASVisual *_set_default_asvisual( ASVisual *new_v );
00137
00138 #ifndef X_DISPLAY_MISSING
00139 static XColor black_xcol = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue };
00140 static XColor white_xcol = { 0, 0xFFFF, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue };
00141
00142 static void find_useable_visual( ASVisual *asv, Display *dpy, int screen,
00143 Window root, XVisualInfo *list, int nitems,
00144 XSetWindowAttributes *attr )
00145 {
00146 int k ;
00147 int (*oldXErrorHandler) (Display *, XErrorEvent *) =
00148 XSetErrorHandler (asvisual_empty_XErrorHandler);
00149 Colormap orig_cmap = attr->colormap ;
00150
00151 for( k = 0 ; k < nitems ; k++ )
00152 {
00153 Window w = None, wjunk;
00154 unsigned int width, height, ujunk ;
00155 int junk;
00156
00157 if( orig_cmap == None )
00158 {
00159 if( list[k].visual == DefaultVisual( dpy, (screen) ) )
00160 {
00161 attr->colormap = DefaultColormap( dpy, screen );
00162 LOCAL_DEBUG_OUT( "Using Default colormap %lX", attr->colormap );
00163 }else
00164 {
00165 attr->colormap = XCreateColormap( dpy, root, list[k].visual, AllocNone);
00166 LOCAL_DEBUG_OUT( "DefaultVisual is %p, while ours is %p, so Created new colormap %lX", DefaultVisual( dpy, (screen) ), list[k].visual, attr->colormap );
00167 }
00168 }
00169 ASV_ALLOC_COLOR( asv, attr->colormap, &black_xcol );
00170 ASV_ALLOC_COLOR( asv, attr->colormap, &white_xcol );
00171 attr->border_pixel = black_xcol.pixel ;
00172
00173
00174 w = XCreateWindow (dpy, root, -10, -10, 10, 10, 0, list[k].depth, CopyFromParent, list[k].visual, CWColormap|CWBorderPixel, attr );
00175 if( w != None && XGetGeometry (dpy, w, &wjunk, &junk, &junk, &width, &height, &ujunk, &ujunk))
00176 {
00177
00178 asv->visual_info = list[k] ;
00179 XDestroyWindow( dpy, w );
00180 asv->colormap = attr->colormap ;
00181 asv->own_colormap = (attr->colormap != DefaultColormap( dpy, screen ));
00182 asv->white_pixel = white_xcol.pixel ;
00183 asv->black_pixel = black_xcol.pixel ;
00184 break;
00185 }
00186 if( orig_cmap == None )
00187 {
00188 if( attr->colormap != DefaultColormap( dpy, screen ))
00189 XFreeColormap( dpy, attr->colormap );
00190 attr->colormap = None ;
00191 }
00192 }
00193 XSetErrorHandler(oldXErrorHandler);
00194 }
00195 #endif
00196
00197
00198 Bool
00199 query_screen_visual_id( ASVisual *asv, Display *dpy, int screen, Window root, int default_depth, VisualID visual_id, Colormap cmap )
00200 {
00201 #ifndef X_DISPLAY_MISSING
00202 int nitems = 0 ;
00203
00204
00205
00206
00207
00208 int i ;
00209
00210 XVisualInfo *list = NULL;
00211 XSetWindowAttributes attr ;
00212 static XVisualInfo templates[] =
00213
00214 {{ NULL , 0 , 0 , 24 , TrueColor , 0xFF0000, 0x00FF00 , 0x0000FF , 0 , 0 },
00215 { NULL , 0 , 0 , 24 , TrueColor , 0x0000FF, 0x00FF00 , 0xFF0000 , 0 , 0 },
00216 { NULL , 0 , 0 , 24 , TrueColor , 0x0 , 0x0 , 0x0 , 0 , 0 },
00217 { NULL , 0 , 0 , 32 , TrueColor , 0xFF0000, 0x00FF00 , 0x0000FF , 0 , 0 },
00218 { NULL , 0 , 0 , 32 , TrueColor , 0x0000FF, 0x00FF00 , 0xFF0000 , 0 , 0 },
00219 { NULL , 0 , 0 , 32 , TrueColor , 0x0 , 0x0 , 0x0 , 0 , 0 },
00220 { NULL , 0 , 0 , 16 , TrueColor , 0xF800 , 0x07E0 , 0x001F , 0 , 0 },
00221 { NULL , 0 , 0 , 16 , TrueColor , 0x001F , 0x07E0 , 0xF800 , 0 , 0 },
00222
00223 { NULL , 0 , 0 , 16 , TrueColor , 0x0 , 0xE007 , 0x0 , 0 , 0 },
00224
00225 { NULL , 0 , 0 , 16 , TrueColor , 0x7C00 , 0x03E0 , 0x001F , 0 , 0 },
00226 { NULL , 0 , 0 , 16 , TrueColor , 0x001F , 0x03E0 , 0x7C00 , 0 , 0 },
00227 { NULL , 0 , 0 , 16 , TrueColor , 0x0 , 0xE003 , 0x0 , 0 , 0 },
00228 { NULL , 0 , 0 , 15 , TrueColor , 0x7C00 , 0x03E0 , 0x001F , 0 , 0 },
00229 { NULL , 0 , 0 , 15 , TrueColor , 0x001F , 0x03E0 , 0x7C00 , 0 , 0 },
00230 { NULL , 0 , 0 , 15 , TrueColor , 0x0 , 0xE003 , 0x0 , 0 , 0 },
00231
00232 { NULL , 0 , 0 , 24 , DirectColor, 0xFF0000, 0x00FF00 , 0x0000FF , 0 , 0 },
00233 { NULL , 0 , 0 , 24 , DirectColor, 0x0000FF, 0x00FF00 , 0xFF0000 , 0 , 0 },
00234 { NULL , 0 , 0 , 24 , DirectColor, 0x0 , 0x0 , 0x0 , 0 , 0 },
00235 { NULL , 0 , 0 , 32 , DirectColor, 0xFF0000, 0x00FF00 , 0x0000FF , 0 , 0 },
00236 { NULL , 0 , 0 , 32 , DirectColor, 0x0000FF, 0x00FF00 , 0xFF0000 , 0 , 0 },
00237 { NULL , 0 , 0 , 32 , DirectColor, 0x0 , 0x0 , 0x0 , 0 , 0 },
00238 { NULL , 0 , 0 , 16 , DirectColor, 0xF800 , 0x07E0 , 0x001F , 0 , 0 },
00239 { NULL , 0 , 0 , 16 , DirectColor, 0x001F , 0x07E0 , 0xF800 , 0 , 0 },
00240 { NULL , 0 , 0 , 16 , DirectColor, 0x0 , 0xE007 , 0x0 , 0 , 0 },
00241 { NULL , 0 , 0 , 16 , DirectColor, 0x7C00 , 0x03E0 , 0x001F , 0 , 0 },
00242 { NULL , 0 , 0 , 16 , DirectColor, 0x001F , 0x03E0 , 0x7C00 , 0 , 0 },
00243 { NULL , 0 , 0 , 16 , DirectColor, 0x0 , 0xE003 , 0x0 , 0 , 0 },
00244 { NULL , 0 , 0 , 15 , DirectColor, 0x7C00 , 0x03E0 , 0x001F , 0 , 0 },
00245 { NULL , 0 , 0 , 15 , DirectColor, 0x001F , 0x03E0 , 0x7C00 , 0 , 0 },
00246 { NULL , 0 , 0 , 15 , DirectColor, 0x0 , 0xE003 , 0x0 , 0 , 0 },
00247 { NULL , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
00248 } ;
00249 #endif
00250 if( asv == NULL )
00251 return False ;
00252 memset( asv, 0x00, sizeof(ASVisual));
00253
00254 asv->dpy = dpy ;
00255
00256 #ifndef X_DISPLAY_MISSING
00257 memset( &attr, 0x00, sizeof( attr ));
00258 attr.colormap = cmap ;
00259
00260 if( visual_id == 0 )
00261 {
00262 for( i = 0 ; templates[i].depth != 0 ; i++ )
00263 {
00264 int mask = VisualScreenMask|VisualDepthMask|VisualClassMask ;
00265
00266 templates[i].screen = screen ;
00267 if( templates[i].red_mask != 0 )
00268 mask |= VisualRedMaskMask;
00269 if( templates[i].green_mask != 0 )
00270 mask |= VisualGreenMaskMask ;
00271 if( templates[i].blue_mask != 0 )
00272 mask |= VisualBlueMaskMask ;
00273
00274 if( (list = XGetVisualInfo( dpy, mask, &(templates[i]), &nitems ))!= NULL )
00275 {
00276 find_useable_visual( asv, dpy, screen, root, list, nitems, &attr );
00277 XFree( list );
00278 list = NULL ;
00279 if( asv->visual_info.visual != NULL )
00280 break;
00281 }
00282 }
00283 }else
00284 {
00285 templates[0].visualid = visual_id ;
00286 if( (list = XGetVisualInfo( dpy, VisualIDMask, &(templates[0]), &nitems )) != NULL )
00287 {
00288 find_useable_visual( asv, dpy, screen, root, list, nitems, &attr );
00289 XFree( list );
00290 list = NULL ;
00291 }
00292 if( asv->visual_info.visual == NULL )
00293 show_error( "Visual with requested ID of 0x%X is unusable - will try default instead.", visual_id );
00294 }
00295
00296 if( asv->visual_info.visual == NULL )
00297 {
00298 register int vclass = 6 ;
00299 while( --vclass >= 0 )
00300 if( XMatchVisualInfo( dpy, screen, default_depth, vclass, &(asv->visual_info) ) )
00301 break;
00302 if( vclass < 0 )
00303 return False;
00304
00305 if( asv->visual_info.visual == DefaultVisual( dpy, screen ) )
00306 attr.colormap = DefaultColormap( dpy, screen );
00307 else
00308 attr.colormap = XCreateColormap( dpy, root, asv->visual_info.visual, AllocNone);
00309 ASV_ALLOC_COLOR( asv, attr.colormap, &black_xcol );
00310 ASV_ALLOC_COLOR( asv, attr.colormap, &white_xcol );
00311 asv->colormap = attr.colormap ;
00312 asv->own_colormap = (attr.colormap != DefaultColormap( dpy, screen ));
00313 asv->white_pixel = white_xcol.pixel ;
00314 asv->black_pixel = black_xcol.pixel ;
00315 }
00316 if( get_output_threshold() >= OUTPUT_VERBOSE_THRESHOLD )
00317 {
00318 fprintf( stderr, "Selected visual 0x%lx: depth %d, class %d\n RGB masks: 0x%lX, 0x%lX, 0x%lX, Byte Ordering: %s\n",
00319 (unsigned long)asv->visual_info.visualid,
00320 asv->visual_info.depth,
00321 asv->visual_info.class,
00322 (unsigned long)asv->visual_info.red_mask,
00323 (unsigned long)asv->visual_info.green_mask,
00324 (unsigned long)asv->visual_info.blue_mask,
00325 (ImageByteOrder(asv->dpy)==MSBFirst)?"MSBFirst":"LSBFirst" );
00326 }
00327 #else
00328 asv->white_pixel = ARGB32_White ;
00329 asv->black_pixel = ARGB32_Black ;
00330 #endif
00331 return True;
00332 }
00333
00334 ASVisual *
00335 create_asvisual_for_id( Display *dpy, int screen, int default_depth, VisualID visual_id, Colormap cmap, ASVisual *reusable_memory )
00336 {
00337 ASVisual *asv = reusable_memory ;
00338 #ifndef X_DISPLAY_MISSING
00339 Window root = dpy?RootWindow(dpy,screen):None;
00340 #endif
00341
00342 if( asv == NULL )
00343 asv = safecalloc( 1, sizeof(ASVisual) );
00344 #ifndef X_DISPLAY_MISSING
00345 if( dpy )
00346 {
00347 if( query_screen_visual_id( asv, dpy, screen, root, default_depth, visual_id, cmap ) )
00348 {
00349 if( !setup_truecolor_visual( asv ) )
00350 {
00351
00352 setup_pseudo_visual( asv );
00353 if( asv->as_colormap == NULL )
00354 setup_as_colormap( asv );
00355 }
00356 }else
00357 {
00358 if( reusable_memory != asv )
00359 free( asv );
00360 asv = NULL ;
00361 }
00362 }
00363 #endif
00364 _set_default_asvisual( asv );
00365 return asv;
00366 }
00367
00368 ASVisual *
00369 create_asvisual( Display *dpy, int screen, int default_depth, ASVisual *reusable_memory )
00370 {
00371 VisualID visual_id = 0;
00372 char *id_env_var ;
00373
00374 if( (id_env_var = getenv( ASVISUAL_ID_ENVVAR )) != NULL )
00375 visual_id = strtol(id_env_var,NULL,16);
00376
00377 return create_asvisual_for_id( dpy, screen, default_depth, visual_id, None, reusable_memory );
00378 }
00379
00380
00381 void
00382 destroy_asvisual( ASVisual *asv, Bool reusable )
00383 {
00384 if( asv )
00385 {
00386 if( get_default_asvisual() == asv )
00387 _set_default_asvisual( NULL );
00388 #ifndef X_DISPLAY_MISSING
00389 if( asv->own_colormap )
00390 {
00391 if( asv->colormap )
00392 XFreeColormap( asv->dpy, asv->colormap );
00393 }
00394 if( asv->as_colormap )
00395 {
00396 free( asv->as_colormap );
00397 if( asv->as_colormap_reverse.xref != NULL )
00398 {
00399 if( asv->as_colormap_type == ACM_12BPP )
00400 destroy_ashash( &(asv->as_colormap_reverse.hash) );
00401 else
00402 free( asv->as_colormap_reverse.xref );
00403 }
00404 }
00405 #ifdef HAVE_GLX
00406 if( asv->glx_scratch_gc_direct )
00407 glXDestroyContext(asv->dpy, asv->glx_scratch_gc_direct );
00408 if( asv->glx_scratch_gc_indirect )
00409 glXDestroyContext(asv->dpy, asv->glx_scratch_gc_indirect );
00410 #endif
00411 if( asv->scratch_window )
00412 XDestroyWindow( asv->dpy, asv->scratch_window );
00413
00414 #endif
00415 if( !reusable )
00416 free( asv );
00417 }
00418 }
00419
00420 int as_colormap_type2size( int type )
00421 {
00422 switch( type )
00423 {
00424 case ACM_3BPP :
00425 return 8 ;
00426 case ACM_6BPP :
00427 return 64 ;
00428 case ACM_12BPP :
00429 return 4096 ;
00430 default:
00431 return 0 ;
00432 }
00433 }
00434
00435 Bool
00436 visual2visual_prop( ASVisual *asv, size_t *size_ret,
00437 unsigned long *version_ret,
00438 unsigned long **data_ret )
00439 {
00440 int cmap_size = 0 ;
00441 unsigned long *prop ;
00442 size_t size;
00443
00444 if( asv == NULL || data_ret == NULL)
00445 return False;
00446
00447 cmap_size = as_colormap_type2size( asv->as_colormap_type );
00448
00449 if( cmap_size > 0 && asv->as_colormap == NULL )
00450 return False ;
00451 size = (1+1+2+1+cmap_size)*sizeof(unsigned long);
00452 prop = safemalloc( size ) ;
00453 #ifndef X_DISPLAY_MISSING
00454 prop[0] = asv->visual_info.visualid ;
00455 prop[1] = asv->colormap ;
00456 prop[2] = asv->black_pixel ;
00457 prop[3] = asv->white_pixel ;
00458 prop[4] = asv->as_colormap_type ;
00459 if( cmap_size > 0 )
00460 {
00461 register int i;
00462 for( i = 0 ; i < cmap_size ; i++ )
00463 prop[i+5] = asv->as_colormap[i] ;
00464 }
00465 if( size_ret )
00466 *size_ret = size;
00467 #endif
00468 if( version_ret )
00469 *version_ret = (1<<16)+0;
00470 *data_ret = prop ;
00471 return True;
00472 }
00473
00474 Bool
00475 visual_prop2visual( ASVisual *asv, Display *dpy, int screen,
00476 size_t size,
00477 unsigned long version,
00478 unsigned long *data )
00479 {
00480 #ifndef X_DISPLAY_MISSING
00481 XVisualInfo templ, *list ;
00482 int nitems = 0 ;
00483 int cmap_size = 0 ;
00484 #endif
00485
00486 if( asv == NULL )
00487 return False;
00488
00489 asv->dpy = dpy ;
00490
00491 if( size < (1+1+2+1)*sizeof(unsigned long) ||
00492 (version&0x00FFFF) != 0 || (version>>16) != 1 || data == NULL )
00493 return False;
00494
00495 if( data[0] == None || data[1] == None )
00496 return False;
00497
00498 #ifndef X_DISPLAY_MISSING
00499 templ.screen = screen ;
00500 templ.visualid = data[0] ;
00501
00502 list = XGetVisualInfo( dpy, VisualScreenMask|VisualIDMask, &templ, &nitems );
00503 if( list == NULL || nitems == 0 )
00504 return False;
00505
00506 asv->visual_info = *list ;
00507 XFree( list );
00508
00509 if( asv->own_colormap && asv->colormap )
00510 XFreeColormap( dpy, asv->colormap );
00511
00512 asv->colormap = data[1] ;
00513 asv->own_colormap = False ;
00514 asv->black_pixel = data[2] ;
00515 asv->white_pixel = data[3] ;
00516 asv->as_colormap_type = data[4];
00517
00518 cmap_size = as_colormap_type2size( asv->as_colormap_type );
00519
00520 if( cmap_size > 0 )
00521 {
00522 register int i ;
00523 if( asv->as_colormap )
00524 free( asv->as_colormap );
00525 asv->as_colormap = safemalloc( cmap_size );
00526 for( i = 0 ; i < cmap_size ; i++ )
00527 asv->as_colormap[i] = data[i+5];
00528 }else
00529 asv->as_colormap_type = ACM_None ;
00530 #else
00531
00532 #endif
00533 return True;
00534 }
00535
00536 Bool
00537 setup_truecolor_visual( ASVisual *asv )
00538 {
00539 #ifndef X_DISPLAY_MISSING
00540 XVisualInfo *vi = &(asv->visual_info) ;
00541
00542 if( vi->class != TrueColor )
00543 return False;
00544
00545 #ifdef HAVE_GLX
00546 if( glXQueryExtension (asv->dpy, NULL, NULL))
00547 {
00548 int val = False;
00549 glXGetConfig(asv->dpy, vi, GLX_USE_GL, &val);
00550 if( val )
00551 {
00552 asv->glx_scratch_gc_indirect = glXCreateContext (asv->dpy, &(asv->visual_info), NULL, False);
00553 if( asv->glx_scratch_gc_indirect )
00554 {
00555 set_flags( asv->glx_support, ASGLX_Available );
00556 if( glXGetConfig(asv->dpy, vi, GLX_RGBA, &val) == 0 )
00557 if( val ) set_flags( asv->glx_support, ASGLX_RGBA );
00558 if( glXGetConfig(asv->dpy, vi, GLX_DOUBLEBUFFER, &val) == 0 )
00559 if( val ) set_flags( asv->glx_support, ASGLX_DoubleBuffer );
00560 if( glXGetConfig(asv->dpy, vi, GLX_DOUBLEBUFFER, &val) == 0 )
00561 if( val ) set_flags( asv->glx_support, ASGLX_DoubleBuffer );
00562
00563 if( (asv->glx_scratch_gc_direct = glXCreateContext (asv->dpy, &(asv->visual_info), NULL, True)) != NULL )
00564 if( !glXIsDirect( asv->dpy, asv->glx_scratch_gc_direct ) )
00565 {
00566 glXDestroyContext(asv->dpy, asv->glx_scratch_gc_direct );
00567 asv->glx_scratch_gc_direct = NULL ;
00568 }
00569 #if 0
00570
00571 set_flags( asv->glx_support, ASGLX_UseForImageTx );
00572 #endif
00573 }
00574 }
00575 }
00576 #endif
00577
00578 asv->BGR_mode = ((vi->red_mask&0x0010)!=0) ;
00579 asv->rshift = get_shifts (vi->red_mask);
00580 asv->gshift = get_shifts (vi->green_mask);
00581 asv->bshift = get_shifts (vi->blue_mask);
00582 asv->rbits = get_bits (vi->red_mask);
00583 asv->gbits = get_bits (vi->green_mask);
00584 asv->bbits = get_bits (vi->blue_mask);
00585 asv->true_depth = vi->depth ;
00586 asv->msb_first = (ImageByteOrder(asv->dpy)==MSBFirst);
00587
00588 if( asv->true_depth == 16 && ((vi->red_mask|vi->blue_mask)&0x8000) == 0 )
00589 asv->true_depth = 15;
00590
00591 switch( asv->true_depth )
00592 {
00593 case 24 :
00594 case 32 :
00595 asv->color2pixel_func = (asv->BGR_mode)?color2pixel32bgr:color2pixel32rgb ;
00596 asv->pixel2color_func = (asv->BGR_mode)?pixel2color32bgr:pixel2color32rgb ;
00597 asv->ximage2scanline_func = ximage2scanline32 ;
00598 asv->scanline2ximage_func = scanline2ximage32 ;
00599 break ;
00600
00601
00602
00603
00604
00605
00606 case 16 :
00607 asv->color2pixel_func = (asv->BGR_mode)?color2pixel16bgr:color2pixel16rgb ;
00608 asv->pixel2color_func = (asv->BGR_mode)?pixel2color16bgr:pixel2color16rgb ;
00609 asv->ximage2scanline_func = ximage2scanline16 ;
00610 asv->scanline2ximage_func = scanline2ximage16 ;
00611 break ;
00612 case 15 :
00613 asv->color2pixel_func = (asv->BGR_mode)?color2pixel15bgr:color2pixel15rgb ;
00614 asv->pixel2color_func = (asv->BGR_mode)?pixel2color15bgr:pixel2color15rgb ;
00615 asv->ximage2scanline_func = ximage2scanline15 ;
00616 asv->scanline2ximage_func = scanline2ximage15 ;
00617 break ;
00618 }
00619 #endif
00620 return (asv->ximage2scanline_func != NULL) ;
00621 }
00622
00623 ARGB32 *
00624 make_reverse_colormap( unsigned long *cmap, size_t size, int depth, unsigned short mask, unsigned short shift )
00625 {
00626 unsigned int max_pixel = 0x01<<depth ;
00627 ARGB32 *rcmap = safecalloc( max_pixel, sizeof( ARGB32 ) );
00628 register int i ;
00629
00630 for( i = 0 ; i < (int)size ; i++ )
00631 if( cmap[i] < max_pixel )
00632 rcmap[cmap[i]] = MAKE_ARGB32( 0xFF, (i>>(shift<<1))& mask, (i>>(shift))&mask, i&mask);
00633 return rcmap;
00634 }
00635
00636 ASHashTable *
00637 make_reverse_colorhash( unsigned long *cmap, size_t size, int depth, unsigned short mask, unsigned short shift )
00638 {
00639 ASHashTable *hash = create_ashash( 0, NULL, NULL, NULL );
00640 register unsigned int i ;
00641
00642 if( hash )
00643 {
00644 for( i = 0 ; i < size ; i++ )
00645 add_hash_item( hash, (ASHashableValue)cmap[i], (void*)((long)MAKE_ARGB32( 0xFF, (i>>(shift<<1))& mask, (i>>(shift))&mask, i&mask)) );
00646 }
00647 return hash;
00648 }
00649
00650 void
00651 setup_pseudo_visual( ASVisual *asv )
00652 {
00653 #ifndef X_DISPLAY_MISSING
00654 XVisualInfo *vi = &(asv->visual_info) ;
00655
00656
00657 asv->true_depth = vi->depth ;
00658 if( asv->as_colormap == NULL )
00659 {
00660 if( asv->true_depth < 8 )
00661 asv->as_colormap_type = ACM_3BPP ;
00662 else if( asv->true_depth < 12 )
00663 asv->as_colormap_type = ACM_6BPP ;
00664 else
00665 asv->as_colormap_type = ACM_12BPP ;
00666 }
00667
00668 switch( asv->as_colormap_type )
00669 {
00670 case ACM_3BPP:
00671 asv->ximage2scanline_func = ximage2scanline_pseudo3bpp ;
00672 asv->scanline2ximage_func = scanline2ximage_pseudo3bpp ;
00673 asv->color2pixel_func = color2pixel_pseudo3bpp ;
00674 break ;
00675 case ACM_6BPP:
00676 asv->ximage2scanline_func = ximage2scanline_pseudo6bpp ;
00677 asv->scanline2ximage_func = scanline2ximage_pseudo6bpp ;
00678 asv->color2pixel_func = color2pixel_pseudo6bpp ;
00679 break ;
00680 default:
00681 asv->as_colormap_type = ACM_12BPP ;
00682 case ACM_12BPP:
00683 asv->ximage2scanline_func = ximage2scanline_pseudo12bpp ;
00684 asv->scanline2ximage_func = scanline2ximage_pseudo12bpp ;
00685 asv->color2pixel_func = color2pixel_pseudo12bpp ;
00686 break ;
00687 }
00688 if( asv->as_colormap != NULL )
00689 {
00690 if( asv->as_colormap_type == ACM_3BPP || asv->as_colormap_type == ACM_6BPP )
00691 {
00692 unsigned short mask = 0x0003, shift = 2 ;
00693 if( asv->as_colormap_type==ACM_3BPP )
00694 {
00695 mask = 0x0001 ;
00696 shift = 1 ;
00697 }
00698 asv->as_colormap_reverse.xref = make_reverse_colormap( asv->as_colormap,
00699 as_colormap_type2size( asv->as_colormap_type ),
00700 asv->true_depth, mask, shift );
00701 }else if( asv->as_colormap_type == ACM_12BPP )
00702 {
00703 asv->as_colormap_reverse.hash = make_reverse_colorhash( asv->as_colormap,
00704 as_colormap_type2size( asv->as_colormap_type ),
00705 asv->true_depth, 0x000F, 4 );
00706 }
00707 }
00708 #endif
00709 }
00710
00711 #ifndef X_DISPLAY_MISSING
00712 static unsigned long*
00713 make_3bpp_colormap( ASVisual *asv )
00714 {
00715 XColor colors_3bpp[8] =
00716
00717 { { 0, 0, 0xFFFF, 0, DoRed|DoGreen|DoBlue, 0},
00718 { 0, 0xFFFF, 0, 0, DoRed|DoGreen|DoBlue, 0},
00719 { 0, 0, 0, 0xFFFF, DoRed|DoGreen|DoBlue, 0},
00720 { 0, 0xFFFF, 0xFFFF, 0, DoRed|DoGreen|DoBlue, 0},
00721 { 0, 0, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue, 0},
00722 { 0, 0xFFFF, 0, 0xFFFF, DoRed|DoGreen|DoBlue, 0}} ;
00723 unsigned long *cmap ;
00724
00725 cmap = safemalloc( 8 * sizeof(unsigned long) );
00726
00727
00728 cmap[0] = cmap[1] = cmap[2] = cmap[3] = asv->black_pixel ;
00729 cmap[7] = cmap[6] = cmap[5] = cmap[4] = asv->white_pixel ;
00730 if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[0] ))
00731 cmap[0x02] = cmap[0x03] = cmap[0x06] = colors_3bpp[0].pixel ;
00732 if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[1] ))
00733 cmap[0x04] = cmap[0x05] = colors_3bpp[1].pixel ;
00734 if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[2] ))
00735 cmap[0x01] = colors_3bpp[2].pixel ;
00736 if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[3] ))
00737 cmap[0x06] = colors_3bpp[3].pixel ;
00738 if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[4] ))
00739 cmap[0x03] = colors_3bpp[4].pixel ;
00740 if( ASV_ALLOC_COLOR( asv, asv->colormap, &colors_3bpp[5] ))
00741 cmap[0x05] = colors_3bpp[5].pixel ;
00742 return cmap;
00743 }
00744
00745 static unsigned long*
00746 make_6bpp_colormap( ASVisual *asv, unsigned long *cmap_3bpp )
00747 {
00748 unsigned short red, green, blue ;
00749 unsigned long *cmap = safemalloc( 0x0040*sizeof( unsigned long) );
00750 XColor xcol ;
00751
00752 cmap[0] = asv->black_pixel ;
00753
00754 xcol.flags = DoRed|DoGreen|DoBlue ;
00755 for( blue = 0 ; blue <= 0x0003 ; blue++ )
00756 {
00757 xcol.blue = (0xFFFF*blue)/3 ;
00758 for( red = 0 ; red <= 0x0003 ; red++ )
00759 {
00760 xcol.red = (0xFFFF*red)/3 ;
00761
00762 for( green = 0 ; green <= 0x0003 ; green++ )
00763 {
00764 unsigned short index_3bpp = ((red&0x0002)<<1)|(green&0x0002)|((blue&0x0002)>>1);
00765 unsigned short index_6bpp = (red<<4)|(green<<2)|blue;
00766 xcol.green = (0xFFFF*green)/3 ;
00767
00768 if( (red&0x0001) == ((red&0x0002)>>1) &&
00769 (green&0x0001) == ((green&0x0002)>>1) &&
00770 (blue&0x0001) == ((blue&0x0002)>>1) )
00771 cmap[index_6bpp] = cmap_3bpp[index_3bpp];
00772 else
00773 {
00774 if( ASV_ALLOC_COLOR( asv, asv->colormap, &xcol) != 0 )
00775 cmap[index_6bpp] = xcol.pixel ;
00776 else
00777 cmap[index_6bpp] = cmap_3bpp[index_3bpp] ;
00778 }
00779 }
00780 }
00781 }
00782 return cmap;
00783 }
00784
00785 static unsigned long*
00786 make_9bpp_colormap( ASVisual *asv, unsigned long *cmap_6bpp )
00787 {
00788 unsigned long *cmap = safemalloc( 512*sizeof( unsigned long) );
00789 unsigned short red, green, blue ;
00790 XColor xcol ;
00791
00792 cmap[0] = asv->black_pixel ;
00793
00794 xcol.flags = DoRed|DoGreen|DoBlue ;
00795 for( blue = 0 ; blue <= 0x0007 ; blue++ )
00796 {
00797 xcol.blue = (0xFFFF*blue)/7 ;
00798 for( red = 0 ; red <= 0x0007 ; red++ )
00799 {
00800 xcol.red = (0xFFFF*red)/7 ;
00801 for( green = 0 ; green <= 0x0007 ; green++ )
00802 {
00803 unsigned short index_6bpp = ((red&0x0006)<<3)|((green&0x0006)<<1)|((blue&0x0006)>>1);
00804 unsigned short index_9bpp = (red<<6)|(green<<3)|blue;
00805 xcol.green = (0xFFFF*green)/7 ;
00806
00807 if( (red&0x0001) == ((red&0x0002)>>1) &&
00808 (green&0x0001) == ((green&0x0002)>>1) &&
00809 (blue&0x0001) == ((blue&0x0002)>>1) )
00810 cmap[index_9bpp] = cmap_6bpp[index_6bpp];
00811 else
00812 {
00813 if( ASV_ALLOC_COLOR( asv, asv->colormap, &xcol) != 0 )
00814 cmap[index_9bpp] = xcol.pixel ;
00815 else
00816 cmap[index_9bpp] = cmap_6bpp[index_6bpp] ;
00817 }
00818 }
00819 }
00820 }
00821 return cmap;
00822 }
00823
00824 static unsigned long*
00825 make_12bpp_colormap( ASVisual *asv, unsigned long *cmap_9bpp )
00826 {
00827 unsigned long *cmap = safemalloc( 4096*sizeof( unsigned long) );
00828 unsigned short red, green, blue ;
00829 XColor xcol ;
00830
00831 cmap[0] = asv->black_pixel ;
00832
00833 xcol.flags = DoRed|DoGreen|DoBlue ;
00834 for( blue = 0 ; blue <= 0x000F ; blue++ )
00835 {
00836 xcol.blue = (0xFFFF*blue)/15 ;
00837 for( red = 0 ; red <= 0x000F ; red++ )
00838 {
00839 xcol.red = (0xFFFF*red)/15 ;
00840 for( green = 0 ; green <= 0x000F ; green++ )
00841 {
00842 unsigned short index_9bpp = ((red&0x000E)<<5)|((green&0x000E)<<2)|((blue&0x000E)>>1);
00843 unsigned short index_12bpp = (red<<8)|(green<<4)|blue;
00844 xcol.green = (0xFFFF*green)/15 ;
00845
00846 if( (red&0x0001) == ((red&0x0002)>>1) &&
00847 (green&0x0001) == ((green&0x0002)>>1) &&
00848 (blue&0x0001) == ((blue&0x0002)>>1) )
00849 cmap[index_12bpp] = cmap_9bpp[index_9bpp];
00850 else
00851 {
00852 if( ASV_ALLOC_COLOR( asv, asv->colormap, &xcol) != 0 )
00853 cmap[index_12bpp] = xcol.pixel ;
00854 else
00855 cmap[index_12bpp] = cmap_9bpp[index_9bpp] ;
00856 }
00857 }
00858 }
00859 }
00860 return cmap;
00861 }
00862 #endif
00863
00864 void
00865 setup_as_colormap( ASVisual *asv )
00866 {
00867 #ifndef X_DISPLAY_MISSING
00868 unsigned long *cmap_lower, *cmap ;
00869
00870 if( asv == NULL || asv->as_colormap != NULL )
00871 return ;
00872
00873 cmap = make_3bpp_colormap( asv );
00874 if( asv->as_colormap_type == ACM_3BPP )
00875 {
00876 asv->as_colormap = cmap ;
00877 asv->as_colormap_reverse.xref = make_reverse_colormap( cmap, 8, asv->true_depth, 0x0001, 1 );
00878 return ;
00879 }
00880 cmap_lower = cmap ;
00881 cmap = make_6bpp_colormap( asv, cmap_lower );
00882 free( cmap_lower );
00883 if( asv->as_colormap_type == ACM_6BPP )
00884 {
00885 asv->as_colormap = cmap ;
00886 asv->as_colormap_reverse.xref = make_reverse_colormap( cmap, 64, asv->true_depth, 0x0003, 2 );
00887 }else
00888 {
00889 cmap_lower = cmap ;
00890 cmap = make_9bpp_colormap( asv, cmap_lower );
00891 free( cmap_lower );
00892 cmap_lower = cmap ;
00893 cmap = make_12bpp_colormap( asv, cmap_lower );
00894 free( cmap_lower );
00895
00896 asv->as_colormap = cmap ;
00897 asv->as_colormap_reverse.hash = make_reverse_colorhash( cmap, 4096, asv->true_depth, 0x000F, 4 );
00898 }
00899 #endif
00900 }
00901
00902
00903
00904
00905 Window
00906 create_visual_window( ASVisual *asv, Window parent,
00907 int x, int y, unsigned int width, unsigned int height,
00908 unsigned int border_width, unsigned int wclass,
00909 unsigned long mask, XSetWindowAttributes *attributes )
00910 {
00911 #ifndef X_DISPLAY_MISSING
00912 XSetWindowAttributes my_attr ;
00913 int depth = 0;
00914
00915 if( asv == NULL || parent == None )
00916 return None ;
00917 LOCAL_DEBUG_OUT( "Colormap %lX, parent %lX, %ux%u%+d%+d, bw = %d, class %d",
00918 asv->colormap, parent, width, height, x, y, border_width,
00919 wclass );
00920 if( attributes == NULL )
00921 {
00922 attributes = &my_attr ;
00923 memset( attributes, 0x00, sizeof(XSetWindowAttributes));
00924 mask = 0;
00925 }
00926
00927 if( width < 1 )
00928 width = 1 ;
00929 if( height < 1 )
00930 height = 1 ;
00931
00932 if( wclass == InputOnly )
00933 {
00934 border_width = 0 ;
00935 if( (mask&INPUTONLY_LEGAL_MASK) != mask )
00936 show_warning( " software BUG detected : illegal InputOnly window's mask 0x%lX - overriding", mask );
00937 mask &= INPUTONLY_LEGAL_MASK ;
00938 }else
00939 {
00940 depth = asv->visual_info.depth ;
00941 if( !get_flags(mask, CWColormap ) )
00942 {
00943 attributes->colormap = asv->colormap ;
00944 set_flags(mask, CWColormap );
00945 }
00946 if( !get_flags(mask, CWBorderPixmap ) )
00947 {
00948 attributes->border_pixmap = None ;
00949 set_flags(mask, CWBorderPixmap );
00950 }
00951
00952 clear_flags(mask, CWBorderPixmap );
00953 if( !get_flags(mask, CWBorderPixel ) )
00954 {
00955 attributes->border_pixel = asv->black_pixel ;
00956 set_flags(mask, CWBorderPixel );
00957 }
00958
00959
00960
00961 if ( get_flags(mask, CWBackPixmap) && attributes->background_pixmap == ParentRelative &&
00962 asv->visual_info.visual != DefaultVisual( asv->dpy, DefaultScreen(asv->dpy) ))
00963 {
00964 clear_flags(mask, CWBackPixmap);
00965 }
00966 }
00967 LOCAL_DEBUG_OUT( "parent = %lX, mask = 0x%lX, VisualID = 0x%lX, Border Pixel = %ld, colormap = %lX",
00968 parent, mask, asv->visual_info.visual->visualid, attributes->border_pixel, attributes->colormap );
00969 return XCreateWindow (asv->dpy, parent, x, y, width, height, border_width, depth,
00970 wclass, asv->visual_info.visual,
00971 mask, attributes);
00972 #else
00973 return None ;
00974 #endif
00975
00976 }
00977
00978
00979 GC
00980 create_visual_gc( ASVisual *asv, Window root, unsigned long mask, XGCValues *gcvalues )
00981 {
00982 GC gc = NULL ;
00983
00984 #ifndef X_DISPLAY_MISSING
00985 if( asv )
00986 {
00987 XGCValues scratch_gcv ;
00988 if( asv->scratch_window == None )
00989 asv->scratch_window = create_visual_window( asv, root, -20, -20, 10, 10, 0, InputOutput, 0, NULL );
00990 if( asv->scratch_window != None )
00991 gc = XCreateGC( asv->dpy, asv->scratch_window, gcvalues?mask:0, gcvalues?gcvalues:&scratch_gcv );
00992 }
00993 #endif
00994 return gc;
00995 }
00996
00997 Pixmap
00998 create_visual_pixmap( ASVisual *asv, Window root, unsigned int width, unsigned int height, unsigned int depth )
00999 {
01000 #ifndef X_DISPLAY_MISSING
01001 Pixmap p = None ;
01002 if( asv != NULL )
01003 {
01004 if( root == None )
01005 root = RootWindow(asv->dpy,DefaultScreen(asv->dpy));
01006 if( depth==0 )
01007 depth = asv->true_depth ;
01008 p = XCreatePixmap( asv->dpy, root, MAX(width,(unsigned)1), MAX(height,(unsigned)1), depth );
01009 }
01010 return p;
01011 #else
01012 return None ;
01013 #endif
01014 }
01015
01016 void
01017 destroy_visual_pixmap( ASVisual *asv, Pixmap *ppmap )
01018 {
01019 if( asv && ppmap )
01020 if( *ppmap )
01021 {
01022 #ifndef X_DISPLAY_MISSING
01023 XFreePixmap( asv->dpy, *ppmap );
01024 *ppmap = None ;
01025 #endif
01026 }
01027 }
01028
01029 #ifndef X_DISPLAY_MISSING
01030 static int
01031 quiet_xerror_handler (Display * dpy, XErrorEvent * error)
01032 {
01033 return 0;
01034 }
01035
01036 #endif
01037
01038 int
01039 get_dpy_drawable_size (Display *drawable_dpy, Drawable d, unsigned int *ret_w, unsigned int *ret_h)
01040 {
01041 int result = 0 ;
01042 #ifndef X_DISPLAY_MISSING
01043 if( d != None && drawable_dpy != NULL )
01044 {
01045 Window root;
01046 unsigned int ujunk;
01047 int junk;
01048 int (*oldXErrorHandler) (Display *, XErrorEvent *) = XSetErrorHandler (quiet_xerror_handler);
01049 result = XGetGeometry (drawable_dpy, d, &root, &junk, &junk, ret_w, ret_h, &ujunk, &ujunk);
01050 XSetErrorHandler (oldXErrorHandler);
01051 }
01052 #endif
01053 if ( result == 0)
01054 {
01055 *ret_w = 0;
01056 *ret_h = 0;
01057 return 0;
01058 }
01059 return 1;
01060 }
01061
01062 Bool
01063 get_dpy_window_position (Display *window_dpy, Window root, Window w, int *px, int *py, int *transparency_x, int *transparency_y)
01064 {
01065 Bool result = False ;
01066 int x = 0, y = 0, transp_x = 0, transp_y = 0 ;
01067 #ifndef X_DISPLAY_MISSING
01068 if( window_dpy != NULL && w != None )
01069 {
01070 Window wdumm;
01071 int rootHeight = XDisplayHeight(window_dpy, DefaultScreen(window_dpy) );
01072 int rootWidth = XDisplayWidth(window_dpy, DefaultScreen(window_dpy) );
01073
01074 if( root == None )
01075 root = RootWindow(window_dpy,DefaultScreen(window_dpy));
01076
01077 result = XTranslateCoordinates (window_dpy, w, root, 0, 0, &x, &y, &wdumm);
01078 if( result )
01079 {
01080
01081 result = (x < rootWidth && y < rootHeight );
01082 if( result )
01083 {
01084 unsigned int width = 0, height = 0;
01085 get_dpy_drawable_size (window_dpy, w, &width, &height);
01086 result = (x + width > 0 && y+height > 0) ;
01087 }
01088
01089 for( transp_x = x ; transp_x < 0 ; transp_x += rootWidth );
01090 for( transp_y = y ; transp_y < 0 ; transp_y += rootHeight );
01091 while( transp_x > rootWidth ) transp_x -= rootWidth ;
01092 while( transp_y > rootHeight ) transp_y -= rootHeight ;
01093 }
01094 }
01095 #endif
01096 if( px )
01097 *px = x;
01098 if( py )
01099 *py = y;
01100 if( transparency_x )
01101 *transparency_x = transp_x ;
01102 if( transparency_y )
01103 *transparency_y = transp_y ;
01104 return result;
01105 }
01106
01107
01108 #ifndef X_DISPLAY_MISSING
01109 static unsigned char *scratch_ximage_data = NULL ;
01110 static int scratch_use_count = 0 ;
01111 static size_t scratch_ximage_allocated_size = 0;
01112 #endif
01113 static size_t scratch_ximage_max_size = ASSHM_SAVED_MAX*2;
01114 static size_t scratch_ximage_normal_size = ASSHM_SAVED_MAX;
01115
01116 int
01117 set_scratch_ximage_max_size( int new_max_size )
01118 {
01119 int tmp = scratch_ximage_max_size ;
01120 scratch_ximage_max_size = new_max_size ;
01121 return tmp;
01122 }
01123
01124 int
01125 set_scratch_ximage_normal_size( int new_normal_size )
01126 {
01127 int tmp = scratch_ximage_normal_size ;
01128 scratch_ximage_normal_size = new_normal_size ;
01129 return tmp;
01130 }
01131
01132 #ifndef X_DISPLAY_MISSING
01133 static void*
01134 get_scratch_data(size_t size)
01135 {
01136 if( scratch_ximage_max_size < size || scratch_use_count > 0)
01137 return NULL;
01138 if( scratch_ximage_allocated_size < size )
01139 {
01140 scratch_ximage_allocated_size = size ;
01141 scratch_ximage_data = realloc( scratch_ximage_data, size );
01142 }
01143
01144 ++scratch_use_count;
01145 return scratch_ximage_data ;
01146 }
01147
01148 static Bool
01149 release_scratch_data( void *data )
01150 {
01151 if( scratch_use_count == 0 || data != scratch_ximage_data )
01152 return False;
01153 --scratch_use_count ;
01154 if( scratch_use_count == 0 )
01155 {
01156
01157
01158 }
01159 return True;
01160 }
01161 #endif
01162
01163 #ifdef XSHMIMAGE
01164
01165 int (*orig_XShmImage_destroy_image)(XImage *ximage) = NULL ;
01166
01167 typedef struct ASXShmImage
01168 {
01169 XImage *ximage ;
01170 XShmSegmentInfo *segment ;
01171 int ref_count ;
01172 Bool wait_completion_event ;
01173 unsigned int size ;
01174 ASVisual *asv ;
01175 }ASXShmImage;
01176
01177 typedef struct ASShmArea
01178 {
01179 unsigned int size ;
01180 char *shmaddr ;
01181 int shmid ;
01182 struct ASShmArea *next, *prev ;
01183 }ASShmArea;
01184
01185 static ASHashTable *xshmimage_segments = NULL ;
01186 static ASHashTable *xshmimage_images = NULL ;
01187
01188
01189 static ASShmArea *shm_available_mem_head = NULL ;
01190 static int shm_available_mem_used = 0 ;
01191
01192 static Bool _as_use_shm_images = False ;
01193
01194 void really_destroy_shm_area( char *shmaddr, int shmid )
01195 {
01196 shmdt (shmaddr);
01197 shmctl (shmid, IPC_RMID, 0);
01198 LOCAL_DEBUG_OUT("XSHMIMAGE> DESTROY_SHM : freeing shmid = %d, remaining in cache = %d bytes ", shmid, shm_available_mem_used );
01199 }
01200
01201 void remove_shm_area( ASShmArea *area, Bool free_resources )
01202 {
01203 if( area )
01204 {
01205 if( area == shm_available_mem_head )
01206 shm_available_mem_head = area->next ;
01207 if( area->next )
01208 area->next->prev = area->prev ;
01209 if( area->prev )
01210 area->prev->next = area->next ;
01211 shm_available_mem_used -= area->size ;
01212 if( free_resources )
01213 really_destroy_shm_area( area->shmaddr, area->shmid );
01214 else
01215 {
01216 LOCAL_DEBUG_OUT("XSHMIMAGE> REMOVE_SHM : reusing shmid = %d, size %d, remaining in cache = %d bytes ", area->shmid, area->size, shm_available_mem_used );
01217 }
01218 free( area );
01219 }
01220
01221 }
01222
01223 void flush_shm_cache( )
01224 {
01225 if( xshmimage_images )
01226 destroy_ashash( &xshmimage_images );
01227 if( xshmimage_segments )
01228 destroy_ashash( &xshmimage_segments );
01229 while( shm_available_mem_head != NULL )
01230 remove_shm_area( shm_available_mem_head, True );
01231 }
01232
01233 void save_shm_area( char *shmaddr, int shmid, int size )
01234 {
01235 ASShmArea *area;
01236
01237 if( shm_available_mem_used+size >= ASSHM_SAVED_MAX )
01238 {
01239 really_destroy_shm_area( shmaddr, shmid );
01240 return ;
01241 }
01242
01243 shm_available_mem_used+=size ;
01244 area = safecalloc( 1, sizeof(ASShmArea) );
01245
01246 area->shmaddr = shmaddr ;
01247 area->shmid = shmid ;
01248 area->size = size ;
01249 LOCAL_DEBUG_OUT("XSHMIMAGE> SAVE_SHM : saving shmid = %d, size %d, remaining in cache = %d bytes ", area->shmid, area->size, shm_available_mem_used );
01250
01251 area->next = shm_available_mem_head ;
01252 if( shm_available_mem_head )
01253 shm_available_mem_head->prev = area ;
01254 shm_available_mem_head = area ;
01255 }
01256
01257 char *get_shm_area( int size, int *shmid )
01258 {
01259 ASShmArea *selected = NULL, *curr = shm_available_mem_head;
01260
01261 while( curr != NULL )
01262 {
01263 if( curr->size >= size && curr->size < (size * 4)/3 )
01264 {
01265 if( selected == NULL )
01266 selected = curr ;
01267 else if( selected->size > curr->size )
01268 selected = curr ;
01269 }
01270 curr = curr->next ;
01271 }
01272 if( selected != NULL )
01273 {
01274 char *tmp = selected->shmaddr ;
01275 *shmid = selected->shmid ;
01276 remove_shm_area( selected, False );
01277 return tmp ;
01278 }
01279
01280 *shmid = shmget (IPC_PRIVATE, size, IPC_CREAT|0666);
01281 return shmat (*shmid, 0, 0);
01282 }
01283
01284 void
01285 destroy_xshmimage_segment(ASHashableValue value, void *data)
01286 {
01287 ASXShmImage *img_data = (ASXShmImage*)data ;
01288 if( img_data->segment != NULL )
01289 {
01290 LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_SEG : img_data = %p : segent to be freed: shminfo = %p ", img_data, img_data->segment );
01291 XShmDetach (img_data->asv->dpy, img_data->segment);
01292 save_shm_area( img_data->segment->shmaddr, img_data->segment->shmid, img_data->size );
01293 free( img_data->segment );
01294 img_data->segment = NULL ;
01295 if( img_data->ximage == NULL )
01296 free( img_data );
01297 }else
01298 {
01299 LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_SEG : img_data = %p : segment data is NULL already value = %ld!!", img_data, value );
01300 }
01301 }
01302
01303 Bool destroy_xshm_segment( ShmSeg shmseg )
01304 {
01305 if( xshmimage_segments )
01306 {
01307 if(remove_hash_item( xshmimage_segments, AS_HASHABLE(shmseg), NULL, True ) == ASH_Success)
01308 {
01309 LOCAL_DEBUG_OUT( "XSHMIMAGE> REMOVE_SEG : segment %ld removed from the hash successfully!", shmseg );
01310 return True ;
01311 }
01312 LOCAL_DEBUG_OUT( "XSHMIMAGE> ERROR : could not find segment %ld(0x%lX) in the hash!", shmseg, shmseg );
01313 }else
01314 {
01315 LOCAL_DEBUG_OUT( "XSHMIMAGE> ERROR : segments hash is %p!!", xshmimage_segments );
01316 }
01317
01318 return False ;
01319 }
01320
01321
01322 void
01323 destroy_xshmimage_image(ASHashableValue value, void *data)
01324 {
01325 ASXShmImage *img_data = (ASXShmImage*)data ;
01326 if( img_data->ximage != NULL )
01327 {
01328 if( orig_XShmImage_destroy_image )
01329 orig_XShmImage_destroy_image( img_data->ximage );
01330 else
01331 XFree ((char *)img_data->ximage);
01332 LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_XIM : ximage freed: img_data = %p, xim = %p", img_data, img_data->ximage);
01333 img_data->ximage = NULL ;
01334 if( img_data->segment != NULL && !img_data->wait_completion_event )
01335 {
01336 if( destroy_xshm_segment( img_data->segment->shmseg ) )
01337 return ;
01338 img_data->segment = NULL ;
01339 }
01340 if( img_data->segment == NULL )
01341 free( img_data );
01342 }
01343 }
01344
01345 Bool enable_shmem_images_for_visual (ASVisual *asv)
01346 {
01347 #ifndef DEBUG_ALLOCS
01348 if( asv && asv->dpy && XShmQueryExtension (asv->dpy) )
01349 {
01350 _as_use_shm_images = True ;
01351 if( xshmimage_segments == NULL )
01352 xshmimage_segments = create_ashash( 0, NULL, NULL, destroy_xshmimage_segment );
01353 if( xshmimage_images == NULL )
01354 xshmimage_images = create_ashash( 0, pointer_hash_value, NULL, destroy_xshmimage_image );
01355 }else
01356 #endif
01357 _as_use_shm_images = False ;
01358 return _as_use_shm_images;
01359 }
01360
01361 Bool enable_shmem_images ()
01362 {
01363 return enable_shmem_images_for_visual (get_default_asvisual());
01364 }
01365
01366
01367 void disable_shmem_images()
01368 {
01369 _as_use_shm_images = False ;
01370 }
01371
01372 Bool
01373 check_shmem_images_enabled()
01374 {
01375 return _as_use_shm_images ;
01376 }
01377
01378
01379 int destroy_xshm_image( XImage *ximage )
01380 {
01381 if( xshmimage_images )
01382 {
01383 if( remove_hash_item( xshmimage_images, AS_HASHABLE(ximage), NULL, True ) != ASH_Success )
01384 {
01385 if (ximage->data != NULL)
01386 free ((char *)ximage->data);
01387 if (ximage->obdata != NULL)
01388 free ((char *)ximage->obdata);
01389 XFree ((char *)ximage);
01390 LOCAL_DEBUG_OUT( "XSHMIMAGE> FREE_XIM : ximage freed: xim = %p", ximage);
01391 }
01392 }
01393 return 1;
01394 }
01395
01396 unsigned long
01397 ximage2shmseg( XImage *xim )
01398 {
01399 void *vptr = NULL ;
01400 if( get_hash_item( xshmimage_images, AS_HASHABLE(xim), &vptr ) == ASH_Success )
01401 {
01402 ASXShmImage *data = (ASXShmImage *)vptr ;
01403 if( data->segment )
01404 return data->segment->shmseg;
01405 }
01406 return 0;
01407 }
01408
01409 void registerXShmImage( ASVisual *asv, XImage *ximage, XShmSegmentInfo* shminfo )
01410 {
01411 ASXShmImage *data = safecalloc( 1, sizeof(ASXShmImage));
01412 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 );
01413 data->asv = asv ;
01414 data->ximage = ximage ;
01415 data->segment = shminfo ;
01416 data->size = ximage->bytes_per_line * ximage->height ;
01417
01418 orig_XShmImage_destroy_image = ximage->f.destroy_image ;
01419 ximage->f.destroy_image = destroy_xshm_image ;
01420
01421 add_hash_item( xshmimage_images, AS_HASHABLE(ximage), data );
01422 add_hash_item( xshmimage_segments, AS_HASHABLE(shminfo->shmseg), data );
01423 }
01424
01425 void *
01426 check_XImage_shared( XImage *xim )
01427 {
01428 ASXShmImage *img_data = NULL ;
01429 if( _as_use_shm_images )
01430 {
01431 ASHashData hdata ;
01432 if(get_hash_item( xshmimage_images, AS_HASHABLE(xim), &hdata.vptr ) != ASH_Success)
01433 img_data = NULL ;
01434 else
01435 img_data = hdata.vptr ;
01436 }
01437 return img_data ;
01438 }
01439
01440 Bool ASPutXImage( ASVisual *asv, Drawable d, GC gc, XImage *xim,
01441 int src_x, int src_y, int dest_x, int dest_y,
01442 unsigned int width, unsigned int height )
01443 {
01444 ASXShmImage *img_data = NULL ;
01445 if( xim == NULL || asv == NULL )
01446 return False ;
01447
01448 if( ( img_data = check_XImage_shared( xim )) != NULL )
01449 {
01450
01451 if( XShmPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height, True ) )
01452 {
01453 img_data->wait_completion_event = True ;
01454 return True ;
01455 }
01456 }
01457
01458 return XPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height );
01459 }
01460
01461 XImage *ASGetXImage( ASVisual *asv, Drawable d,
01462 int x, int y, unsigned int width, unsigned int height,
01463 unsigned long plane_mask )
01464 {
01465 XImage *xim = NULL ;
01466
01467 if( asv == NULL || d == None )
01468 return NULL ;
01469 if( _as_use_shm_images && width*height > 4000)
01470 {
01471 unsigned int depth ;
01472 Window root;
01473 unsigned int ujunk;
01474 int junk;
01475 if(XGetGeometry (asv->dpy, d, &root, &junk, &junk, &ujunk, &ujunk, &ujunk, &depth) == 0)
01476 return NULL ;
01477
01478 xim = create_visual_ximage(asv,width,height,depth);
01479 XShmGetImage( asv->dpy, d, xim, x, y, plane_mask );
01480
01481 }else
01482 xim = XGetImage( asv->dpy, d, x, y, width, height, plane_mask, ZPixmap );
01483 return xim ;
01484 }
01485 #else
01486
01487 Bool enable_shmem_images (){return False; }
01488 void disable_shmem_images(){}
01489 void *check_XImage_shared( XImage *xim ) {return NULL ; }
01490
01491 Bool ASPutXImage( ASVisual *asv, Drawable d, GC gc, XImage *xim,
01492 int src_x, int src_y, int dest_x, int dest_y,
01493 unsigned int width, unsigned int height )
01494 {
01495 #ifndef X_DISPLAY_MISSING
01496 if( xim == NULL || asv == NULL )
01497 return False ;
01498 return XPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height );
01499 #else
01500 return False;
01501 #endif
01502 }
01503
01504 XImage * ASGetXImage( ASVisual *asv, Drawable d,
01505 int x, int y, unsigned int width, unsigned int height,
01506 unsigned long plane_mask )
01507 {
01508 #ifndef X_DISPLAY_MISSING
01509 if( asv == NULL || d == None )
01510 return NULL ;
01511 return XGetImage( asv->dpy, d, x, y, width, height, plane_mask, ZPixmap );
01512 #else
01513 return NULL ;
01514 #endif
01515 }
01516
01517 #endif
01518
01519 #ifndef X_DISPLAY_MISSING
01520 int
01521 My_XDestroyImage (XImage *ximage)
01522 {
01523 if( !release_scratch_data(ximage->data) )
01524 if (ximage->data != NULL)
01525 free (ximage->data);
01526 if (ximage->obdata != NULL)
01527 free (ximage->obdata);
01528 XFree (ximage);
01529 return 1;
01530 }
01531 #endif
01532
01533
01534 XImage*
01535 create_visual_ximage( ASVisual *asv, unsigned int width, unsigned int height, unsigned int depth )
01536 {
01537 #ifndef X_DISPLAY_MISSING
01538 register XImage *ximage = NULL;
01539 unsigned long dsize;
01540 char *data;
01541 int unit ;
01542
01543 if( asv == NULL )
01544 return NULL;
01545
01546 #if 0
01547 unit = asv->dpy->bitmap_unit;
01548 #else
01549 if( depth == 0 )
01550 unit = (asv->true_depth+7)&0x0038;
01551 else
01552 unit = (depth+7)&0x0038;
01553 if( unit == 24 )
01554 unit = 32 ;
01555 #endif
01556 #ifdef XSHMIMAGE
01557 if( _as_use_shm_images && width*height > 4000 )
01558 {
01559 XShmSegmentInfo *shminfo = safecalloc( 1, sizeof(XShmSegmentInfo));
01560
01561 ximage = XShmCreateImage (asv->dpy, asv->visual_info.visual,
01562 (depth==0)?asv->visual_info.depth:depth,
01563 ZPixmap, NULL, shminfo,
01564 MAX(width,(unsigned int)1), MAX(height,(unsigned int)1));
01565 if( ximage == NULL )
01566 free( shminfo );
01567 else
01568 {
01569 shminfo->shmaddr = ximage->data = get_shm_area( ximage->bytes_per_line * ximage->height, &(shminfo->shmid) );
01570 if( shminfo->shmid == -1 )
01571 {
01572 static int shmem_failure_count = 0 ;
01573 show_warning( "unable to allocate %d bytes of shared image memory", ximage->bytes_per_line * ximage->height ) ;
01574 if( ximage->bytes_per_line * ximage->height < 100000 || ++shmem_failure_count > 10 )
01575 {
01576 show_error( "too many shared memory failures - disabling" ) ;
01577 _as_use_shm_images = False ;
01578 }
01579 free( shminfo );
01580 shminfo = NULL ;
01581 XFree( ximage );
01582 ximage = NULL ;
01583 }else
01584 {
01585 shminfo->readOnly = False;
01586 XShmAttach (asv->dpy, shminfo);
01587 registerXShmImage( asv, ximage, shminfo );
01588 }
01589 }
01590 }
01591 #endif
01592 if( ximage == NULL )
01593 {
01594 ximage = XCreateImage (asv->dpy, asv->visual_info.visual, (depth==0)?asv->visual_info.depth:depth, ZPixmap, 0, NULL, MAX(width,(unsigned int)1), MAX(height,(unsigned int)1),
01595 unit, 0);
01596 if (ximage != NULL)
01597 {
01598 _XInitImageFuncPtrs (ximage);
01599 ximage->obdata = NULL;
01600 ximage->f.destroy_image = My_XDestroyImage;
01601 dsize = ximage->bytes_per_line*ximage->height;
01602 if (((data = (char *)safemalloc (dsize)) == NULL) && (dsize > 0))
01603 {
01604 XFree ((char *)ximage);
01605 return (XImage *) NULL;
01606 }
01607 ximage->data = data;
01608 }
01609 }
01610 return ximage;
01611 #else
01612 return NULL ;
01613 #endif
01614 }
01615
01616
01617 XImage*
01618 create_visual_scratch_ximage( ASVisual *asv, unsigned int width, unsigned int height, unsigned int depth )
01619 {
01620 #ifndef X_DISPLAY_MISSING
01621 register XImage *ximage = NULL;
01622 char *data;
01623 int unit ;
01624
01625 if( asv == NULL )
01626 return NULL;
01627
01628 #if 0
01629 unit = asv->dpy->bitmap_unit;
01630 #else
01631 if( depth == 0 )
01632 unit = (asv->true_depth+7)&0x0038;
01633 else
01634 unit = (depth+7)&0x0038;
01635 if( unit == 24 )
01636 unit = 32 ;
01637 #endif
01638
01639
01640 #ifdef XSHMIMAGE
01641 if( _as_use_shm_images )
01642 return create_visual_ximage( asv, width, height, depth );
01643 #endif
01644
01645 if( ximage == NULL )
01646 {
01647 ximage = XCreateImage (asv->dpy, asv->visual_info.visual,
01648 (depth==0)?asv->visual_info.depth:depth, ZPixmap,
01649 0, NULL, MAX(width,(unsigned int)1), MAX(height,(unsigned int)1),
01650 unit, 0);
01651 if (ximage != NULL)
01652 {
01653 data = get_scratch_data(ximage->bytes_per_line * ximage->height);
01654 if( data == NULL )
01655 {
01656 XFree ((char *)ximage);
01657 return create_visual_ximage( asv, width, height, depth );
01658 }
01659 _XInitImageFuncPtrs (ximage);
01660 ximage->obdata = NULL;
01661 ximage->f.destroy_image = My_XDestroyImage;
01662 ximage->data = data;
01663 }
01664 }
01665 return ximage;
01666 #else
01667 return NULL ;
01668 #endif
01669 }
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 #ifndef X_DISPLAY_MISSING
01680 static int
01681 get_shifts (unsigned long mask)
01682 {
01683 register int i = 1;
01684
01685 while (mask >> i)
01686 i++;
01687
01688 return i - 1;
01689 }
01690
01691 static int
01692 get_bits (unsigned long mask)
01693 {
01694 register int i;
01695
01696 for (i = 0; mask; mask >>= 1)
01697 if (mask & 1)
01698 i++;
01699
01700 return i;
01701 }
01702 #endif
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 #ifndef X_DISPLAY_MISSING
01716 static inline void
01717 query_pixel_color( ASVisual *asv, unsigned long pixel, CARD32 *r, CARD32 *g, CARD32 *b )
01718 {
01719 XColor xcol ;
01720 xcol.flags = DoRed|DoGreen|DoBlue ;
01721 xcol.pixel = pixel ;
01722 if( XQueryColor( asv->dpy, asv->colormap, &xcol ) != 0 )
01723 {
01724 *r = xcol.red>>8 ;
01725 *g = xcol.green>>8 ;
01726 *b = xcol.blue>>8 ;
01727 }
01728 }
01729 #endif
01730
01731
01732 CARD32 color2pixel32bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01733 {
01734 *pixel = ARGB32_RED8(encoded_color)|(ARGB32_GREEN8(encoded_color)<<8)|(ARGB32_BLUE8(encoded_color)<<16);
01735 return 0;
01736 }
01737 CARD32 color2pixel32rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01738 {
01739 *pixel = encoded_color&0x00FFFFFF;
01740 return 0;
01741 }
01742 CARD32 color2pixel24bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01743 {
01744 *pixel = encoded_color&0x00FFFFFF;
01745 return 0;
01746 }
01747 CARD32 color2pixel24rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01748 {
01749 *pixel = encoded_color&0x00FFFFFF;
01750 return 0;
01751 }
01752 CARD32 color2pixel16bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01753 {
01754 register CARD32 c = encoded_color ;
01755 *pixel = ((c&0x000000F8)<<8)|((c&0x0000FC00)>>5)|((c&0x00F80000)>>19);
01756 return (c>>1)&0x00030103;
01757 }
01758 CARD32 color2pixel16rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01759 {
01760 register CARD32 c = encoded_color ;
01761 *pixel = ((c&0x00F80000)>>8)|((c&0x0000FC00)>>5)|((c&0x000000F8)>>3);
01762 return (c>>1)&0x00030103;
01763 }
01764 CARD32 color2pixel15bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01765 {
01766 register CARD32 c = encoded_color ;
01767 *pixel = ((c&0x000000F8)<<7)|((c&0x0000F800)>>6)|((c&0x00F80000)>>19);
01768 return (c>>1)&0x00030303;
01769 }
01770 CARD32 color2pixel15rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel)
01771 {
01772 register CARD32 c = encoded_color ;
01773 *pixel = ((c&0x00F80000)>>9)|((c&0x0000F800)>>6)|((c&0x000000F8)>>3);
01774 return (c>>1)&0x00030303;
01775 }
01776
01777 CARD32 color2pixel_pseudo3bpp( ASVisual *asv, CARD32 encoded_color, unsigned long *pixel )
01778 {
01779 register CARD32 c = encoded_color ;
01780 *pixel = asv->as_colormap[((c>>25)&0x0008)|((c>>16)&0x0002)|((c>>7)&0x0001)];
01781 return (c>>1)&0x003F3F3F;
01782 }
01783
01784 CARD32 color2pixel_pseudo6bpp( ASVisual *asv, CARD32 encoded_color, unsigned long *pixel )
01785 {
01786 register CARD32 c = encoded_color ;
01787 *pixel = asv->as_colormap[((c>>22)&0x0030)|((c>>14)&0x000C)|((c>>6)&0x0003)];
01788 return (c>>1)&0x001F1F1F;
01789 }
01790
01791 CARD32 color2pixel_pseudo12bpp( ASVisual *asv, CARD32 encoded_color, unsigned long *pixel )
01792 {
01793 register CARD32 c = encoded_color ;
01794 *pixel = asv->as_colormap[((c>>16)&0x0F00)|((c>>10)&0x00F0)|((c>>4)&0x000F)];
01795 return (c>>1)&0x00070707;
01796 }
01797
01798 void pixel2color32rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01799 {}
01800 void pixel2color32bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01801 {}
01802 void pixel2color24rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01803 {}
01804 void pixel2color24bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01805 {}
01806 void pixel2color16rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01807 {}
01808 void pixel2color16bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01809 {}
01810 void pixel2color15rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01811 {}
01812 void pixel2color15bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue)
01813 {}
01814
01815 void ximage2scanline32(ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
01816 {
01817 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
01818 register CARD32 *a = sl->alpha+sl->offset_x;
01819 int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
01820 register CARD32 *src = (CARD32*)xim_data ;
01821
01822
01823
01824 #ifdef WORDS_BIGENDIAN
01825 if( !asv->msb_first )
01826 #else
01827 if( asv->msb_first )
01828 #endif
01829 {
01830 while (--i >= 0)
01831 {
01832 b[i] = (src[i]>>24)&0x0ff;
01833 g[i] = (src[i]>>16)&0x0ff;
01834 r[i] = (src[i]>>8)&0x0ff;
01835 a[i] = src[i]&0x0ff;
01836
01837 }
01838 }else
01839 {
01840 while (--i >= 0)
01841 {
01842 a[i] = (src[i]>>24)&0x0ff;
01843 r[i] = (src[i]>>16)&0x0ff;
01844 g[i] = (src[i]>>8)&0x0ff;
01845 b[i] = src[i]&0x0ff;
01846 }
01847 }
01848
01849 }
01850
01851 void ximage2scanline16( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
01852 {
01853 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
01854 register CARD16 *src = (CARD16*)xim_data ;
01855 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
01856 #ifdef WORDS_BIGENDIAN
01857 if( !asv->msb_first )
01858 #else
01859 if( asv->msb_first )
01860 #endif
01861 do
01862 {
01863 #define ENCODE_MSBF_565(r,gh3,gl3,b) (((gh3)&0x0007)|((gl3)&0xE000)|((r)&0x00F8)|((b)&0x1F00))
01864 r[i] = (src[i]&0x00F8);
01865 g[i] = ((src[i]&0x0007)<<5)|((src[i]&0xE000)>>11);
01866 b[i] = (src[i]&0x1F00)>>5;
01867 }while( --i >= 0);
01868 else
01869 do
01870 {
01871 #define ENCODE_LSBF_565(r,g,b) (((g)&0x07E0)|((r)&0xF800)|((b)&0x001F))
01872 r[i] = (src[i]&0xF800)>>8;
01873 g[i] = (src[i]&0x07E0)>>3;
01874 b[i] = (src[i]&0x001F)<<3;
01875 }while( --i >= 0);
01876
01877 }
01878 void ximage2scanline15( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
01879 {
01880 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
01881 register CARD16 *src = (CARD16*)xim_data ;
01882 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
01883 #ifdef WORDS_BIGENDIAN
01884 if( !asv->msb_first )
01885 #else
01886 if( asv->msb_first )
01887 #endif
01888 do
01889 {
01890 #define ENCODE_MSBF_555(r,gh2,gl3,b) (((gh2)&0x0003)|((gl3)&0xE000)|((r)&0x007C)|((b)&0x1F00))
01891 r[i] = (src[i]&0x007C)<<1;
01892 g[i] = ((src[i]&0x0003)<<6)|((src[i]&0xE000)>>10);
01893 b[i] = (src[i]&0x1F00)>>5;
01894 }while( --i >= 0);
01895 else
01896 do
01897 {
01898 #define ENCODE_LSBF_555(r,g,b) (((g)&0x03E0)|((r)&0x7C00)|((b)&0x001F))
01899 r[i] = (src[i]&0x7C00)>>7;
01900 g[i] = (src[i]&0x03E0)>>2;
01901 b[i] = (src[i]&0x001F)<<3;
01902 }while( --i >= 0);
01903 }
01904
01905 #ifndef X_DISPLAY_MISSING
01906
01907 void
01908 ximage2scanline_pseudo3bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
01909 {
01910 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
01911 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
01912
01913 do
01914 {
01915 unsigned long pixel = XGetPixel( xim, i, y );
01916 ARGB32 c = asv->as_colormap_reverse.xref[pixel] ;
01917 if( c == 0 )
01918 query_pixel_color( asv, pixel, r+i, g+i, b+i );
01919 else
01920 {
01921 r[i] = ARGB32_RED8(c);
01922 g[i] = ARGB32_GREEN8(c);
01923 b[i] = ARGB32_BLUE8(c);
01924 }
01925 }while( --i >= 0);
01926
01927 }
01928
01929 void
01930 ximage2scanline_pseudo6bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
01931 {
01932 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
01933 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
01934
01935 if( xim->bits_per_pixel == 8 )
01936 {
01937 register CARD8 *src = (CARD8*)xim_data ;
01938 do
01939 {
01940 ARGB32 c = asv->as_colormap_reverse.xref[src[i]] ;
01941 if( c == 0 )
01942 query_pixel_color( asv, src[i], r+i, g+i, b+i );
01943 else
01944 {
01945 r[i] = ARGB32_RED8(c);
01946 g[i] = ARGB32_GREEN8(c);
01947 b[i] = ARGB32_BLUE8(c);
01948 }
01949 }while( --i >= 0);
01950
01951 }else
01952 do
01953 {
01954 unsigned long pixel = XGetPixel( xim, i, y );
01955 ARGB32 c = asv->as_colormap_reverse.xref[pixel] ;
01956 if( c == 0 )
01957 query_pixel_color( asv, pixel, r+i, g+i, b+i );
01958 else
01959 {
01960 r[i] = ARGB32_RED8(c);
01961 g[i] = ARGB32_GREEN8(c);
01962 b[i] = ARGB32_BLUE8(c);
01963 }
01964 }while( --i >= 0);
01965 }
01966
01967 void
01968 ximage2scanline_pseudo12bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
01969 {
01970 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
01971 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
01972
01973 if( xim->bits_per_pixel == 16 )
01974 {
01975 register CARD16 *src = (CARD16*)xim_data ;
01976 do
01977 {
01978 ASHashData hdata ;
01979 ARGB32 c ;
01980 if( get_hash_item( asv->as_colormap_reverse.hash, AS_HASHABLE((unsigned long)src[i]), &hdata.vptr ) != ASH_Success )
01981 query_pixel_color( asv, src[i], r+i, g+i, b+i );
01982 else
01983 {
01984 c = hdata.c32;
01985 r[i] = ARGB32_RED8(c);
01986 g[i] = ARGB32_GREEN8(c);
01987 b[i] = ARGB32_BLUE8(c);
01988 }
01989 }while( --i >= 0);
01990
01991 }else
01992 do
01993 {
01994 unsigned long pixel = XGetPixel( xim, i, y );
01995 ASHashData hdata ;
01996 ARGB32 c ;
01997 if( get_hash_item( asv->as_colormap_reverse.hash, (ASHashableValue)pixel, &hdata.vptr ) != ASH_Success )
01998 query_pixel_color( asv, pixel, r+i, g+i, b+i );
01999 else
02000 {
02001 c = hdata.c32;
02002 r[i] = ARGB32_RED8(c);
02003 g[i] = ARGB32_GREEN8(c);
02004 b[i] = ARGB32_BLUE8(c);
02005 }
02006 }while( --i >= 0);
02007 }
02008 #endif
02009
02010 void scanline2ximage32( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
02011 {
02012 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
02013 register CARD32 *a = sl->alpha+sl->offset_x;
02014 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
02015 register CARD32 *src = (CARD32*)xim_data;
02016
02017
02018 #ifdef WORDS_BIGENDIAN
02019 if( !asv->msb_first )
02020 #else
02021 if( asv->msb_first )
02022 #endif
02023 while( --i >= 0)
02024 {
02025 src[i] = (b[i]<<24)|(g[i]<<16)|(r[i]<<8)|a[i];
02026
02027 }
02028 else
02029 while( --i >= 0) src[i] = (a[i]<<24)|(r[i]<<16)|(g[i]<<8)|b[i];
02030
02031 #ifdef DEBUG_SL2XIMAGE
02032 i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x);
02033 src = (CARD32*)xim_data;
02034 src += sl->offset_x;
02035 printf( "%d: xim->width = %d, sl->width = %d, sl->offset = %d: ", y, xim->width, sl->width, sl->offset_x );
02036 while(--i>=0 ) printf( "%8.8lX ", src[i] );
02037 printf( "\n" );
02038 #endif
02039 }
02040
02041 void scanline2ximage16( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
02042 {
02043 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
02044 register CARD16 *src = (CARD16*)xim_data ;
02045 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
02046 register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
02047 #ifdef WORDS_BIGENDIAN
02048 if( !asv->msb_first )
02049 #else
02050 if( asv->msb_first )
02051 #endif
02052 do
02053 {
02054 src[i] = ENCODE_MSBF_565((c>>20),(c>>15),(c<<1),(c<<5));
02055 if( --i < 0 )
02056 break;
02057
02058 c = ((c>>1)&0x00300403)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02059 {
02060 register CARD32 d = c&0x300C0300 ;
02061 if( d )
02062 {
02063 if( c&0x30000000 )
02064 d |= 0x0FF00000;
02065 if( c&0x000C0000 )
02066 d |= 0x0003FC00 ;
02067 if( c&0x00000300 )
02068 d |= 0x000000FF ;
02069 c ^= d;
02070 }
02071
02072 }
02073 }while(1);
02074 else
02075 do
02076 {
02077 src[i] = ENCODE_LSBF_565((c>>12),(c>>7),(c>>3));
02078 if( --i < 0 )
02079 break;
02080
02081 c = ((c>>1)&0x00300403)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02082 {
02083 register CARD32 d = c&0x300C0300 ;
02084 if( d )
02085 {
02086 if( c&0x30000000 )
02087 d |= 0x0FF00000;
02088 if( c&0x000C0000 )
02089 d |= 0x0003FC00 ;
02090 if( c&0x00000300 )
02091 d |= 0x000000FF ;
02092 c ^= d;
02093 }
02094
02095 }
02096 }while(1);
02097 }
02098
02099 void scanline2ximage15( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
02100 {
02101 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
02102 register CARD16 *src = (CARD16*)xim_data ;
02103 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
02104 register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
02105 #ifdef WORDS_BIGENDIAN
02106 if( !asv->msb_first )
02107 #else
02108 if( asv->msb_first )
02109 #endif
02110 do
02111 {
02112 src[i] = ENCODE_MSBF_555((c>>21),(c>>16),c,(c<<5));
02113 if( --i < 0 )
02114 break;
02115
02116 c = ((c>>1)&0x00300C03)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02117
02118 {
02119 register CARD32 d = c&0x300C0300 ;
02120 if( d )
02121 {
02122 if( c&0x30000000 )
02123 d |= 0x0FF00000;
02124 if( c&0x000C0000 )
02125 d |= 0x0003FC00 ;
02126 if( c&0x00000300 )
02127 d |= 0x000000FF ;
02128 c ^= d;
02129 }
02130
02131 }
02132 }while(1);
02133 else
02134 {
02135 do
02136 {
02137 src[i] = ENCODE_LSBF_555((c>>13),(c>>8),(c>>3));
02138 if( --i < 0 )
02139 break;
02140
02141 c = ((c>>1)&0x00300C03)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02142 {
02143 register CARD32 d = c&0x300C0300 ;
02144 if( d )
02145 {
02146 if( c&0x30000000 )
02147 d |= 0x0FF00000;
02148 if( c&0x000C0000 )
02149 d |= 0x0003FC00 ;
02150 if( c&0x00000300 )
02151 d |= 0x000000FF ;
02152 c ^= d;
02153 }
02154 }
02155 }while(1);
02156 }
02157 }
02158
02159 #ifndef X_DISPLAY_MISSING
02160 void
02161 scanline2ximage_pseudo3bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
02162 {
02163 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
02164 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
02165 register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
02166
02167 do
02168 {
02169 XPutPixel( xim, i, y, asv->as_colormap[((c>>25)&0x0008)|((c>>16)&0x0002)|((c>>7)&0x0001)] );
02170 if( --i < 0 )
02171 break;
02172 c = ((c>>1)&0x03F0FC3F)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02173 {
02174 register CARD32 d = c&0x300C0300 ;
02175 if( d )
02176 {
02177 if( c&0x30000000 )
02178 d |= 0x0FF00000;
02179 if( c&0x000C0000 )
02180 d |= 0x0003FC00 ;
02181 if( c&0x00000300 )
02182 d |= 0x000000FF ;
02183 c ^= d;
02184 }
02185 }
02186 }while(i);
02187 }
02188
02189 void
02190 scanline2ximage_pseudo6bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
02191 {
02192 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
02193 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
02194 register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
02195
02196 if( xim->bits_per_pixel == 8 )
02197 {
02198 register CARD8 *dst = (CARD8*)xim_data ;
02199 do
02200 {
02201 dst[i] = asv->as_colormap[((c>>22)&0x0030)|((c>>14)&0x000C)|((c>>6)&0x0003)];
02202 if( --i < 0 )
02203 break;
02204 c = ((c>>1)&0x01F07C1F)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02205 {
02206 register CARD32 d = c&0x300C0300 ;
02207 if( d )
02208 {
02209 if( c&0x30000000 )
02210 d |= 0x0FF00000;
02211 if( c&0x000C0000 )
02212 d |= 0x0003FC00 ;
02213 if( c&0x00000300 )
02214 d |= 0x000000FF ;
02215 c ^= d;
02216 }
02217 }
02218 }while(i);
02219 }else
02220 {
02221 do
02222 {
02223 XPutPixel( xim, i, y, asv->as_colormap[((c>>22)&0x0030)|((c>>14)&0x000C)|((c>>6)&0x0003)] );
02224 if( --i < 0 )
02225 break;
02226 c = ((c>>1)&0x01F07C1F)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02227 {
02228 register CARD32 d = c&0x300C0300 ;
02229 if( d )
02230 {
02231 if( c&0x30000000 )
02232 d |= 0x0FF00000;
02233 if( c&0x000C0000 )
02234 d |= 0x0003FC00 ;
02235 if( c&0x00000300 )
02236 d |= 0x000000FF ;
02237 c ^= d;
02238 }
02239 }
02240 }while(i);
02241 }
02242 }
02243
02244 void
02245 scanline2ximage_pseudo12bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data )
02246 {
02247 register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x;
02248 register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1;
02249 register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]);
02250
02251 if( xim->bits_per_pixel == 16 )
02252 {
02253 register CARD16 *dst = (CARD16*)xim_data ;
02254 do
02255 {
02256 dst[i] = asv->as_colormap[((c>>16)&0x0F00)|((c>>10)&0x00F0)|((c>>4)&0x000F)];
02257 if( --i < 0 )
02258 break;
02259 c = ((c>>1)&0x00701C07)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02260 {
02261 register CARD32 d = c&0x300C0300 ;
02262 if( d )
02263 {
02264 if( c&0x30000000 )
02265 d |= 0x0FF00000;
02266 if( c&0x000C0000 )
02267 d |= 0x0003FC00 ;
02268 if( c&0x00000300 )
02269 d |= 0x000000FF ;
02270 c ^= d;
02271 }
02272 }
02273 }while(i);
02274 }else
02275 {
02276 do
02277 {
02278 XPutPixel( xim, i, y, asv->as_colormap[((c>>16)&0x0F00)|((c>>10)&0x00F0)|((c>>4)&0x000F)] );
02279 if( --i < 0 )
02280 break;
02281 c = ((c>>1)&0x00701C07)+((r[i]<<20) | (g[i]<<10) | (b[i]));
02282 {
02283 register CARD32 d = c&0x300C0300 ;
02284 if( d )
02285 {
02286 if( c&0x30000000 )
02287 d |= 0x0FF00000;
02288 if( c&0x000C0000 )
02289 d |= 0x0003FC00 ;
02290 if( c&0x00000300 )
02291 d |= 0x000000FF ;
02292 c ^= d;
02293 }
02294 }
02295 }while(i);
02296 }
02297 }
02298
02299 #endif
02300