Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / context.c
1 /* context.c - X context management
2  *
3  * Raster graphics library
4  *
5  * Copyright (c) 1997-2003 Alfredo K. Kojima
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <config.h>
23
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <X11/Xatom.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32
33 #include <math.h>
34
35 #include "StdCmap.h"
36
37 #include "wraster.h"
38
39 extern void _wraster_change_filter(int type);
40
41 static Bool bestContext(Display * dpy, int screen_number, RContext * context);
42
43 static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
44         RC_UseSharedMemory | RC_RenderMode | RC_ColorsPerChannel,       /* flags */
45         RDitheredRendering,     /* render_mode */
46         4,                      /* colors_per_channel */
47         0,
48         0,
49         0,
50         0,
51         True,                   /* use_shared_memory */
52         RMitchellFilter,
53         RUseStdColormap
54 };
55
56 /*
57  *
58  * Colormap allocation for PseudoColor visuals:
59  *
60  *
61  * switch standardColormap:
62  *      none:
63  *              allocate colors according to colors_per_channel
64  *
65  *      best/default:
66  *              if there's a std colormap defined then use it
67  *
68  *              else
69  *                      create a std colormap and set it
70  */
71
72 /*
73  *----------------------------------------------------------------------
74  * allocateStandardPseudoColor
75  *      Creates the internal colormap for PseudoColor, setting the
76  * color values according to the supplied standard colormap.
77  *
78  * Returns: -
79  *
80  * Side effects: -
81  *
82  * Notes: -
83  *----------------------------------------------------------------------
84  */
85 static Bool allocateStandardPseudoColor(RContext * ctx, XStandardColormap * stdcmap)
86 {
87         int i;
88
89         ctx->ncolors = stdcmap->red_max * stdcmap->red_mult
90             + stdcmap->green_max * stdcmap->green_mult + stdcmap->blue_max * stdcmap->blue_mult + 1;
91
92         if (ctx->ncolors <= 1) {
93                 RErrorCode = RERR_INTERNAL;
94                 puts("wraster: bad standard colormap");
95
96                 return False;
97         }
98
99         ctx->colors = malloc(sizeof(XColor) * ctx->ncolors);
100         if (!ctx->colors) {
101                 RErrorCode = RERR_NOMEMORY;
102
103                 return False;
104         }
105
106         ctx->pixels = malloc(sizeof(unsigned long) * ctx->ncolors);
107         if (!ctx->pixels) {
108
109                 free(ctx->colors);
110                 ctx->colors = NULL;
111
112                 RErrorCode = RERR_NOMEMORY;
113
114                 return False;
115         }
116
117 #define calc(max,mult) (((i / stdcmap->mult) % \
118     (stdcmap->max + 1)) * 65535) / stdcmap->max
119
120         for (i = 0; i < ctx->ncolors; i++) {
121                 ctx->colors[i].pixel = i + stdcmap->base_pixel;
122                 ctx->colors[i].red = calc(red_max, red_mult);
123                 ctx->colors[i].green = calc(green_max, green_mult);
124                 ctx->colors[i].blue = calc(blue_max, blue_mult);
125
126                 ctx->pixels[i] = ctx->colors[i].pixel;
127         }
128
129 #undef calc
130
131         return True;
132 }
133
134 static Bool setupStandardColormap(RContext * ctx, Atom property)
135 {
136         if (!XmuLookupStandardColormap(ctx->dpy, ctx->screen_number,
137                                        ctx->visual->visualid, ctx->depth, property, True, True)) {
138                 RErrorCode = RERR_STDCMAPFAIL;
139
140                 return False;
141         }
142         return True;
143 }
144
145 static Bool allocatePseudoColor(RContext * ctx)
146 {
147         XColor *colors;
148         XColor avcolors[256];
149         int avncolors;
150         int i, ncolors, r, g, b;
151         int retries;
152         int cpc = ctx->attribs->colors_per_channel;
153
154         ncolors = cpc * cpc * cpc;
155
156         if (ncolors > (1 << ctx->depth)) {
157                 /* reduce colormap size */
158                 cpc = ctx->attribs->colors_per_channel = 1 << ((int)ctx->depth / 3);
159                 ncolors = cpc * cpc * cpc;
160         }
161
162         assert(cpc >= 2 && ncolors <= (1 << ctx->depth));
163
164         colors = malloc(sizeof(XColor) * ncolors);
165         if (!colors) {
166                 RErrorCode = RERR_NOMEMORY;
167                 return False;
168         }
169
170         ctx->pixels = malloc(sizeof(unsigned long) * ncolors);
171         if (!ctx->pixels) {
172                 free(colors);
173                 RErrorCode = RERR_NOMEMORY;
174                 return False;
175         }
176
177         i = 0;
178
179         if ((ctx->attribs->flags & RC_GammaCorrection) && ctx->attribs->rgamma > 0
180             && ctx->attribs->ggamma > 0 && ctx->attribs->bgamma > 0) {
181                 double rg, gg, bg;
182                 double tmp;
183
184                 /* do gamma correction */
185                 rg = 1.0 / ctx->attribs->rgamma;
186                 gg = 1.0 / ctx->attribs->ggamma;
187                 bg = 1.0 / ctx->attribs->bgamma;
188                 for (r = 0; r < cpc; r++) {
189                         for (g = 0; g < cpc; g++) {
190                                 for (b = 0; b < cpc; b++) {
191                                         colors[i].red = (r * 0xffff) / (cpc - 1);
192                                         colors[i].green = (g * 0xffff) / (cpc - 1);
193                                         colors[i].blue = (b * 0xffff) / (cpc - 1);
194                                         colors[i].flags = DoRed | DoGreen | DoBlue;
195
196                                         tmp = (double)colors[i].red / 65536.0;
197                                         colors[i].red = (unsigned short)(65536.0 * pow(tmp, rg));
198
199                                         tmp = (double)colors[i].green / 65536.0;
200                                         colors[i].green = (unsigned short)(65536.0 * pow(tmp, gg));
201
202                                         tmp = (double)colors[i].blue / 65536.0;
203                                         colors[i].blue = (unsigned short)(65536.0 * pow(tmp, bg));
204
205                                         i++;
206                                 }
207                         }
208                 }
209
210         } else {
211                 for (r = 0; r < cpc; r++) {
212                         for (g = 0; g < cpc; g++) {
213                                 for (b = 0; b < cpc; b++) {
214                                         colors[i].red = (r * 0xffff) / (cpc - 1);
215                                         colors[i].green = (g * 0xffff) / (cpc - 1);
216                                         colors[i].blue = (b * 0xffff) / (cpc - 1);
217                                         colors[i].flags = DoRed | DoGreen | DoBlue;
218                                         i++;
219                                 }
220                         }
221                 }
222         }
223         /* try to allocate the colors */
224         for (i = 0; i < ncolors; i++) {
225                 if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
226                         colors[i].flags = 0;    /* failed */
227                 } else {
228                         colors[i].flags = DoRed | DoGreen | DoBlue;
229                 }
230         }
231         /* try to allocate close values for the colors that couldn't
232          * be allocated before */
233         avncolors = (1 << ctx->depth > 256 ? 256 : 1 << ctx->depth);
234         for (i = 0; i < avncolors; i++)
235                 avcolors[i].pixel = i;
236
237         XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
238
239         for (i = 0; i < ncolors; i++) {
240                 if (colors[i].flags == 0) {
241                         int j;
242                         unsigned long cdiff = 0xffffffff, diff;
243                         unsigned long closest = 0;
244
245                         retries = 2;
246
247                         while (retries--) {
248                                 /* find closest color */
249                                 for (j = 0; j < avncolors; j++) {
250                                         r = (colors[i].red - avcolors[i].red) >> 8;
251                                         g = (colors[i].green - avcolors[i].green) >> 8;
252                                         b = (colors[i].blue - avcolors[i].blue) >> 8;
253                                         diff = r * r + g * g + b * b;
254                                         if (diff < cdiff) {
255                                                 cdiff = diff;
256                                                 closest = j;
257                                         }
258                                 }
259                                 /* allocate closest color found */
260                                 colors[i].red = avcolors[closest].red;
261                                 colors[i].green = avcolors[closest].green;
262                                 colors[i].blue = avcolors[closest].blue;
263                                 if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
264                                         colors[i].flags = DoRed | DoGreen | DoBlue;
265                                         break;  /* succeeded, don't need to retry */
266                                 }
267 #ifdef DEBUG
268                                 printf("close color allocation failed. Retrying...\n");
269 #endif
270                         }
271                 }
272         }
273
274         ctx->colors = colors;
275         ctx->ncolors = ncolors;
276
277         /* fill the pixels shortcut array */
278         for (i = 0; i < ncolors; i++) {
279                 ctx->pixels[i] = ctx->colors[i].pixel;
280         }
281
282         return True;
283 }
284
285 static XColor *allocateGrayScale(RContext * ctx)
286 {
287         XColor *colors;
288         XColor avcolors[256];
289         int avncolors;
290         int i, ncolors, r, g, b;
291         int retries;
292         int cpc = ctx->attribs->colors_per_channel;
293
294         ncolors = cpc * cpc * cpc;
295
296         if (ctx->vclass == StaticGray) {
297                 /* we might as well use all grays */
298                 ncolors = 1 << ctx->depth;
299         } else {
300                 if (ncolors > (1 << ctx->depth)) {
301                         /* reduce colormap size */
302                         cpc = ctx->attribs->colors_per_channel = 1 << ((int)ctx->depth / 3);
303                         ncolors = cpc * cpc * cpc;
304                 }
305
306                 assert(cpc >= 2 && ncolors <= (1 << ctx->depth));
307         }
308
309         if (ncolors >= 256 && ctx->vclass == StaticGray) {
310                 /* don't need dithering for 256 levels of gray in StaticGray visual */
311                 ctx->attribs->render_mode = RBestMatchRendering;
312         }
313
314         colors = malloc(sizeof(XColor) * ncolors);
315         if (!colors) {
316                 RErrorCode = RERR_NOMEMORY;
317                 return False;
318         }
319         for (i = 0; i < ncolors; i++) {
320                 colors[i].red = (i * 0xffff) / (ncolors - 1);
321                 colors[i].green = (i * 0xffff) / (ncolors - 1);
322                 colors[i].blue = (i * 0xffff) / (ncolors - 1);
323                 colors[i].flags = DoRed | DoGreen | DoBlue;
324         }
325         /* try to allocate the colors */
326         for (i = 0; i < ncolors; i++) {
327 #ifdef DEBUG
328                 printf("trying:%x,%x,%x\n", colors[i].red, colors[i].green, colors[i].blue);
329 #endif
330                 if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
331                         colors[i].flags = 0;    /* failed */
332 #ifdef DEBUG
333                         printf("failed:%x,%x,%x\n", colors[i].red, colors[i].green, colors[i].blue);
334 #endif
335                 } else {
336                         colors[i].flags = DoRed | DoGreen | DoBlue;
337 #ifdef DEBUG
338                         printf("success:%x,%x,%x\n", colors[i].red, colors[i].green, colors[i].blue);
339 #endif
340                 }
341         }
342         /* try to allocate close values for the colors that couldn't
343          * be allocated before */
344         avncolors = (1 << ctx->depth > 256 ? 256 : 1 << ctx->depth);
345         for (i = 0; i < avncolors; i++)
346                 avcolors[i].pixel = i;
347
348         XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
349
350         for (i = 0; i < ncolors; i++) {
351                 if (colors[i].flags == 0) {
352                         int j;
353                         unsigned long cdiff = 0xffffffff, diff;
354                         unsigned long closest = 0;
355
356                         retries = 2;
357
358                         while (retries--) {
359                                 /* find closest color */
360                                 for (j = 0; j < avncolors; j++) {
361                                         r = (colors[i].red - avcolors[i].red) >> 8;
362                                         g = (colors[i].green - avcolors[i].green) >> 8;
363                                         b = (colors[i].blue - avcolors[i].blue) >> 8;
364                                         diff = r * r + g * g + b * b;
365                                         if (diff < cdiff) {
366                                                 cdiff = diff;
367                                                 closest = j;
368                                         }
369                                 }
370                                 /* allocate closest color found */
371 #ifdef DEBUG
372                                 printf("best match:%x,%x,%x => %x,%x,%x\n", colors[i].red, colors[i].green,
373                                        colors[i].blue, avcolors[closest].red, avcolors[closest].green,
374                                        avcolors[closest].blue);
375 #endif
376                                 colors[i].red = avcolors[closest].red;
377                                 colors[i].green = avcolors[closest].green;
378                                 colors[i].blue = avcolors[closest].blue;
379                                 if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
380                                         colors[i].flags = DoRed | DoGreen | DoBlue;
381                                         break;  /* succeeded, don't need to retry */
382                                 }
383 #ifdef DEBUG
384                                 printf("close color allocation failed. Retrying...\n");
385 #endif
386                         }
387                 }
388         }
389         return colors;
390 }
391
392 static Bool setupPseudoColorColormap(RContext * context)
393 {
394         Atom property = 0;
395
396         if (context->attribs->standard_colormap_mode == RCreateStdColormap) {
397                 property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
398
399                 if (!setupStandardColormap(context, property)) {
400                         return False;
401                 }
402         }
403
404         if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
405                 XStandardColormap *maps;
406                 int count, i;
407
408                 if (!property) {
409                         property = XInternAtom(context->dpy, "RGB_BEST_MAP", False);
410                         if (!XGetRGBColormaps(context->dpy,
411                                               DefaultRootWindow(context->dpy), &maps, &count, property)) {
412                                 maps = NULL;
413                         }
414
415                         if (!maps) {
416                                 property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
417                                 if (!XGetRGBColormaps(context->dpy,
418                                                       DefaultRootWindow(context->dpy), &maps, &count, property)) {
419                                         maps = NULL;
420                                 }
421                         }
422                 } else {
423                         if (!XGetRGBColormaps(context->dpy,
424                                               DefaultRootWindow(context->dpy), &maps, &count, property)) {
425                                 maps = NULL;
426                         }
427                 }
428
429                 if (maps) {
430                         int theMap = -1;
431
432                         for (i = 0; i < count; i++) {
433                                 if (maps[i].visualid == context->visual->visualid) {
434                                         theMap = i;
435                                         break;
436                                 }
437                         }
438
439                         if (theMap < 0) {
440                                 puts("wrlib: no std cmap found");
441                         }
442
443                         if (theMap >= 0 && allocateStandardPseudoColor(context, &maps[theMap])) {
444
445                                 context->std_rgb_map = XAllocStandardColormap();
446
447                                 *context->std_rgb_map = maps[theMap];
448
449                                 context->cmap = context->std_rgb_map->colormap;
450
451                                 XFree(maps);
452
453                                 return True;
454                         }
455
456                         XFree(maps);
457                 }
458         }
459
460         context->attribs->standard_colormap_mode = RIgnoreStdColormap;
461
462         /* RIgnoreStdColormap and fallback */
463         return allocatePseudoColor(context);
464 }
465
466 static char *mygetenv(char *var, int scr)
467 {
468         char *p;
469         char varname[64];
470
471         sprintf(varname, "%s%i", var, scr);
472         p = getenv(varname);
473         if (!p) {
474                 p = getenv(var);
475         }
476         return p;
477 }
478
479 static void gatherconfig(RContext * context, int screen_n)
480 {
481         char *ptr;
482
483         ptr = mygetenv("WRASTER_GAMMA", screen_n);
484         if (ptr) {
485                 float g1, g2, g3;
486                 if (sscanf(ptr, "%f/%f/%f", &g1, &g2, &g3) != 3 || g1 <= 0.0 || g2 <= 0.0 || g3 <= 0.0) {
487                         printf("wrlib: invalid value(s) for gamma correction \"%s\"\n", ptr);
488                 } else {
489                         context->attribs->flags |= RC_GammaCorrection;
490                         context->attribs->rgamma = g1;
491                         context->attribs->ggamma = g2;
492                         context->attribs->bgamma = g3;
493                 }
494         }
495         ptr = mygetenv("WRASTER_COLOR_RESOLUTION", screen_n);
496         if (ptr) {
497                 int i;
498                 if (sscanf(ptr, "%d", &i) != 1 || i < 2 || i > 6) {
499                         printf("wrlib: invalid value for color resolution \"%s\"\n", ptr);
500                 } else {
501                         context->attribs->flags |= RC_ColorsPerChannel;
502                         context->attribs->colors_per_channel = i;
503                 }
504         }
505
506         ptr = mygetenv("WRASTER_OPTIMIZE_FOR_SPEED", screen_n);
507         if (ptr) {
508                 context->flags.optimize_for_speed = 1;
509         } else {
510                 context->flags.optimize_for_speed = 0;
511         }
512
513 }
514
515 static void getColormap(RContext * context, int screen_number)
516 {
517         Colormap cmap = None;
518         XStandardColormap *cmaps;
519         int ncmaps, i;
520
521         if (XGetRGBColormaps(context->dpy,
522                              RootWindow(context->dpy, screen_number), &cmaps, &ncmaps, XA_RGB_DEFAULT_MAP)) {
523                 for (i = 0; i < ncmaps; ++i) {
524                         if (cmaps[i].visualid == context->visual->visualid) {
525                                 cmap = cmaps[i].colormap;
526                                 break;
527                         }
528                 }
529                 XFree(cmaps);
530         }
531         if (cmap == None) {
532                 XColor color;
533
534                 cmap = XCreateColormap(context->dpy,
535                                        RootWindow(context->dpy, screen_number), context->visual, AllocNone);
536
537                 color.red = color.green = color.blue = 0;
538                 XAllocColor(context->dpy, cmap, &color);
539                 context->black = color.pixel;
540
541                 color.red = color.green = color.blue = 0xffff;
542                 XAllocColor(context->dpy, cmap, &color);
543                 context->white = color.pixel;
544
545         }
546         context->cmap = cmap;
547 }
548
549 static int count_offset(unsigned long mask)
550 {
551         int i;
552
553         i = 0;
554         while ((mask & 1) == 0) {
555                 i++;
556                 mask = mask >> 1;
557         }
558         return i;
559 }
560
561 RContext *RCreateContext(Display * dpy, int screen_number, RContextAttributes * attribs)
562 {
563         RContext *context;
564         XGCValues gcv;
565
566         context = malloc(sizeof(RContext));
567         if (!context) {
568                 RErrorCode = RERR_NOMEMORY;
569                 return NULL;
570         }
571         memset(context, 0, sizeof(RContext));
572
573         context->dpy = dpy;
574
575         context->screen_number = screen_number;
576
577         context->attribs = malloc(sizeof(RContextAttributes));
578         if (!context->attribs) {
579                 free(context);
580                 RErrorCode = RERR_NOMEMORY;
581                 return NULL;
582         }
583         if (!attribs)
584                 *context->attribs = DEFAULT_CONTEXT_ATTRIBS;
585         else
586                 *context->attribs = *attribs;
587
588         if (!(context->attribs->flags & RC_StandardColormap)) {
589                 context->attribs->standard_colormap_mode = RUseStdColormap;
590         }
591
592         if (!(context->attribs->flags & RC_ScalingFilter)) {
593                 context->attribs->flags |= RC_ScalingFilter;
594                 context->attribs->scaling_filter = RMitchellFilter;
595         }
596
597         /* get configuration from environment variables */
598         gatherconfig(context, screen_number);
599 #ifndef BENCH
600         _wraster_change_filter(context->attribs->scaling_filter);
601 #endif
602         if ((context->attribs->flags & RC_VisualID)) {
603                 XVisualInfo *vinfo, templ;
604                 int nret;
605
606                 templ.screen = screen_number;
607                 templ.visualid = context->attribs->visualid;
608                 vinfo = XGetVisualInfo(context->dpy, VisualIDMask | VisualScreenMask, &templ, &nret);
609                 if (!vinfo || nret == 0) {
610                         free(context);
611                         RErrorCode = RERR_BADVISUALID;
612                         return NULL;
613                 }
614
615                 if (vinfo[0].visual == DefaultVisual(dpy, screen_number)) {
616                         context->attribs->flags |= RC_DefaultVisual;
617                 } else {
618                         XSetWindowAttributes attr;
619                         unsigned long mask;
620
621                         context->visual = vinfo[0].visual;
622                         context->depth = vinfo[0].depth;
623                         context->vclass = vinfo[0].class;
624                         getColormap(context, screen_number);
625                         attr.colormap = context->cmap;
626                         attr.override_redirect = True;
627                         attr.border_pixel = 0;
628                         attr.background_pixel = 0;
629                         mask = CWBorderPixel | CWColormap | CWOverrideRedirect | CWBackPixel;
630                         context->drawable =
631                             XCreateWindow(dpy, RootWindow(dpy, screen_number), 1, 1,
632                                           1, 1, 0, context->depth, CopyFromParent, context->visual, mask, &attr);
633                         /*          XSetWindowColormap(dpy, context->drawable, attr.colormap); */
634                 }
635                 XFree(vinfo);
636         }
637
638         /* use default */
639         if (!context->visual) {
640                 if ((context->attribs->flags & RC_DefaultVisual)
641                     || !bestContext(dpy, screen_number, context)) {
642                         context->visual = DefaultVisual(dpy, screen_number);
643                         context->depth = DefaultDepth(dpy, screen_number);
644                         context->cmap = DefaultColormap(dpy, screen_number);
645                         context->drawable = RootWindow(dpy, screen_number);
646                         context->black = BlackPixel(dpy, screen_number);
647                         context->white = WhitePixel(dpy, screen_number);
648                         context->vclass = context->visual->class;
649                 }
650         }
651
652         gcv.function = GXcopy;
653         gcv.graphics_exposures = False;
654         context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction | GCGraphicsExposures, &gcv);
655
656         if (context->vclass == PseudoColor || context->vclass == StaticColor) {
657                 if (!setupPseudoColorColormap(context)) {
658                         free(context);
659                         return NULL;
660                 }
661         } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
662                 context->colors = allocateGrayScale(context);
663                 if (!context->colors) {
664                         free(context);
665                         return NULL;
666                 }
667         } else if (context->vclass == TrueColor) {
668                 /* calc offsets to create a TrueColor pixel */
669                 context->red_offset = count_offset(context->visual->red_mask);
670                 context->green_offset = count_offset(context->visual->green_mask);
671                 context->blue_offset = count_offset(context->visual->blue_mask);
672                 /* disable dithering on 24 bits visuals */
673                 if (context->depth >= 24)
674                         context->attribs->render_mode = RBestMatchRendering;
675         }
676
677         /* check avaiability of MIT-SHM */
678 #ifdef XSHM
679         if (!(context->attribs->flags & RC_UseSharedMemory)) {
680                 context->attribs->flags |= RC_UseSharedMemory;
681                 context->attribs->use_shared_memory = True;
682         }
683
684         if (context->attribs->use_shared_memory) {
685                 int major, minor;
686                 Bool sharedPixmaps;
687
688                 context->flags.use_shared_pixmap = 0;
689
690                 if (!XShmQueryVersion(context->dpy, &major, &minor, &sharedPixmaps)) {
691                         context->attribs->use_shared_memory = False;
692                 } else {
693                         if (XShmPixmapFormat(context->dpy) == ZPixmap)
694                                 context->flags.use_shared_pixmap = sharedPixmaps;
695                 }
696         }
697 #endif
698
699         return context;
700 }
701
702 static Bool bestContext(Display * dpy, int screen_number, RContext * context)
703 {
704         XVisualInfo *vinfo = NULL, rvinfo;
705         int best = -1, numvis, i;
706         long flags;
707         XSetWindowAttributes attr;
708
709         rvinfo.class = TrueColor;
710         rvinfo.screen = screen_number;
711         flags = VisualClassMask | VisualScreenMask;
712
713         vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
714         if (vinfo) {            /* look for a TrueColor, 24-bit or more (pref 24) */
715                 for (i = numvis - 1, best = -1; i >= 0; i--) {
716                         if (vinfo[i].depth == 24)
717                                 best = i;
718                         else if (vinfo[i].depth > 24 && best < 0)
719                                 best = i;
720                 }
721         }
722 #if 0
723         if (best == -1) {       /* look for a DirectColor, 24-bit or more (pref 24) */
724                 rvinfo.class = DirectColor;
725                 if (vinfo)
726                         XFree((char *)vinfo);
727                 vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
728                 if (vinfo) {
729                         for (i = 0, best = -1; i < numvis; i++) {
730                                 if (vinfo[i].depth == 24)
731                                         best = i;
732                                 else if (vinfo[i].depth > 24 && best < 0)
733                                         best = i;
734                         }
735                 }
736         }
737 #endif
738         if (best > -1) {
739                 context->visual = vinfo[best].visual;
740                 context->depth = vinfo[best].depth;
741                 context->vclass = vinfo[best].class;
742                 getColormap(context, screen_number);
743                 attr.colormap = context->cmap;
744                 attr.override_redirect = True;
745                 attr.border_pixel = 0;
746                 context->drawable =
747                     XCreateWindow(dpy, RootWindow(dpy, screen_number),
748                                   1, 1, 1, 1, 0, context->depth,
749                                   CopyFromParent, context->visual,
750                                   CWBorderPixel | CWColormap | CWOverrideRedirect, &attr);
751                 /*      XSetWindowColormap(dpy, context->drawable, context->cmap); */
752         }
753         if (vinfo)
754                 XFree((char *)vinfo);
755
756         if (best < 0)
757                 return False;
758         else
759                 return True;
760 }