~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to wrlib/context.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

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