Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / context.c
Commit [+]AuthorDateLineData
9d2e6ef9 scottc1998-09-29 22:36:29 +00001/* context.c - X context management
6830b057 dan2004-10-12 21:28:27 +00002 *
4153e2fd dan2003-01-16 23:30:45 +00003 * Raster graphics library
6830b057 dan2004-10-12 21:28:27 +00004 *
4153e2fd dan2003-01-16 23:30:45 +00005 * Copyright (c) 1997-2003 Alfredo K. Kojima
6830b057 dan2004-10-12 21:28:27 +00006 *
9d2e6ef9 scottc1998-09-29 22:36:29 +00007 * 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.
6830b057 dan2004-10-12 21:28:27 +000011 *
9d2e6ef9 scottc1998-09-29 22:36:29 +000012 * 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.
6830b057 dan2004-10-12 21:28:27 +000016 *
9d2e6ef9 scottc1998-09-29 22:36:29 +000017 * 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>
9af1c6c4 dan1998-10-21 14:43:47 +000031#include <assert.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000032
33#include <math.h>
34
33b8c225 kojima1999-11-16 00:13:21 +000035#include "StdCmap.h"
36
9d2e6ef9 scottc1998-09-29 22:36:29 +000037#include "wraster.h"
38
e50b7e9c kojima1999-04-28 23:50:52 +000039extern void _wraster_change_filter(int type);
40
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020041static Bool bestContext(Display * dpy, int screen_number, RContext * context);
9d2e6ef9 scottc1998-09-29 22:36:29 +000042
43static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020044 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
9d2e6ef9 scottc1998-09-29 22:36:29 +000054};
55
33b8c225 kojima1999-11-16 00:13:21 +000056/*
6830b057 dan2004-10-12 21:28:27 +000057 *
33b8c225 kojima1999-11-16 00:13:21 +000058 * Colormap allocation for PseudoColor visuals:
6830b057 dan2004-10-12 21:28:27 +000059 *
60 *
33b8c225 kojima1999-11-16 00:13:21 +000061 * switch standardColormap:
62 * none:
63 * allocate colors according to colors_per_channel
6830b057 dan2004-10-12 21:28:27 +000064 *
33b8c225 kojima1999-11-16 00:13:21 +000065 * best/default:
0780ab82 kojima2000-01-19 17:47:35 +000066 * if there's a std colormap defined then use it
6830b057 dan2004-10-12 21:28:27 +000067 *
33b8c225 kojima1999-11-16 00:13:21 +000068 * else
69 * create a std colormap and set it
70 */
71
33b8c225 kojima1999-11-16 00:13:21 +000072/*
73 *----------------------------------------------------------------------
74 * allocateStandardPseudoColor
75 * Creates the internal colormap for PseudoColor, setting the
76 * color values according to the supplied standard colormap.
6830b057 dan2004-10-12 21:28:27 +000077 *
33b8c225 kojima1999-11-16 00:13:21 +000078 * Returns: -
79 *
80 * Side effects: -
81 *
82 * Notes: -
83 *----------------------------------------------------------------------
84 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020085static Bool allocateStandardPseudoColor(RContext * ctx, XStandardColormap * stdcmap)
33b8c225 kojima1999-11-16 00:13:21 +000086{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020087 int i;
33b8c225 kojima1999-11-16 00:13:21 +000088
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020089 ctx->ncolors = stdcmap->red_max * stdcmap->red_mult
90 + stdcmap->green_max * stdcmap->green_mult + stdcmap->blue_max * stdcmap->blue_mult + 1;
33b8c225 kojima1999-11-16 00:13:21 +000091
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020092 if (ctx->ncolors <= 1) {
93 RErrorCode = RERR_INTERNAL;
94 puts("wraster: bad standard colormap");
6830b057 dan2004-10-12 21:28:27 +000095
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020096 return False;
97 }
33b8c225 kojima1999-11-16 00:13:21 +000098
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020099 ctx->colors = malloc(sizeof(XColor) * ctx->ncolors);
100 if (!ctx->colors) {
101 RErrorCode = RERR_NOMEMORY;
6830b057 dan2004-10-12 21:28:27 +0000102
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200103 return False;
104 }
0780ab82 kojima2000-01-19 17:47:35 +0000105
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200106 ctx->pixels = malloc(sizeof(unsigned long) * ctx->ncolors);
107 if (!ctx->pixels) {
6830b057 dan2004-10-12 21:28:27 +0000108
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200109 free(ctx->colors);
110 ctx->colors = NULL;
6830b057 dan2004-10-12 21:28:27 +0000111
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200112 RErrorCode = RERR_NOMEMORY;
0780ab82 kojima2000-01-19 17:47:35 +0000113
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200114 return False;
115 }
6830b057 dan2004-10-12 21:28:27 +0000116
33b8c225 kojima1999-11-16 00:13:21 +0000117#define calc(max,mult) (((i / stdcmap->mult) % \
6830b057 dan2004-10-12 21:28:27 +0000118 (stdcmap->max + 1)) * 65535) / stdcmap->max
33b8c225 kojima1999-11-16 00:13:21 +0000119
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200120 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);
6830b057 dan2004-10-12 21:28:27 +0000125
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200126 ctx->pixels[i] = ctx->colors[i].pixel;
127 }
33b8c225 kojima1999-11-16 00:13:21 +0000128
129#undef calc
130
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200131 return True;
33b8c225 kojima1999-11-16 00:13:21 +0000132}
133
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200134static Bool setupStandardColormap(RContext * ctx, Atom property)
33b8c225 kojima1999-11-16 00:13:21 +0000135{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200136 if (!XmuLookupStandardColormap(ctx->dpy, ctx->screen_number,
137 ctx->visual->visualid, ctx->depth, property, True, True)) {
138 RErrorCode = RERR_STDCMAPFAIL;
33b8c225 kojima1999-11-16 00:13:21 +0000139
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200140 return False;
141 }
142 return True;
143}
33b8c225 kojima1999-11-16 00:13:21 +0000144
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200145static Bool allocatePseudoColor(RContext * ctx)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000146{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200147 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 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000267#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200268 printf("close color allocation failed. Retrying...\n");
9d2e6ef9 scottc1998-09-29 22:36:29 +0000269#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200270 }
271 }
272 }
6830b057 dan2004-10-12 21:28:27 +0000273
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200274 ctx->colors = colors;
275 ctx->ncolors = ncolors;
6830b057 dan2004-10-12 21:28:27 +0000276
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200277 /* fill the pixels shortcut array */
278 for (i = 0; i < ncolors; i++) {
279 ctx->pixels[i] = ctx->colors[i].pixel;
280 }
6830b057 dan2004-10-12 21:28:27 +0000281
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200282 return True;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000283}
284
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200285static XColor *allocateGrayScale(RContext * ctx)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000286{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200287 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++) {
9d2e6ef9 scottc1998-09-29 22:36:29 +0000327#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200328 printf("trying:%x,%x,%x\n", colors[i].red, colors[i].green, colors[i].blue);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000329#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200330 if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
331 colors[i].flags = 0; /* failed */
9d2e6ef9 scottc1998-09-29 22:36:29 +0000332#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200333 printf("failed:%x,%x,%x\n", colors[i].red, colors[i].green, colors[i].blue);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000334#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200335 } else {
336 colors[i].flags = DoRed | DoGreen | DoBlue;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000337#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200338 printf("success:%x,%x,%x\n", colors[i].red, colors[i].green, colors[i].blue);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000339#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200340 }
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 */
9d2e6ef9 scottc1998-09-29 22:36:29 +0000371#ifdef DEBUG
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200372 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);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000375#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200376 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 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000383#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200384 printf("close color allocation failed. Retrying...\n");
9d2e6ef9 scottc1998-09-29 22:36:29 +0000385#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200386 }
387 }
388 }
389 return colors;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000390}
391
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200392static Bool setupPseudoColorColormap(RContext * context)
33b8c225 kojima1999-11-16 00:13:21 +0000393{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200394 Atom property = 0;
33b8c225 kojima1999-11-16 00:13:21 +0000395
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200396 if (context->attribs->standard_colormap_mode == RCreateStdColormap) {
397 property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
33b8c225 kojima1999-11-16 00:13:21 +0000398
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200399 if (!setupStandardColormap(context, property)) {
400 return False;
401 }
402 }
33b8c225 kojima1999-11-16 00:13:21 +0000403
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200404 if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
405 XStandardColormap *maps;
406 int count, i;
33b8c225 kojima1999-11-16 00:13:21 +0000407
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200408 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 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000414
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200415 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 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000428
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200429 if (maps) {
430 int theMap = -1;
6830b057 dan2004-10-12 21:28:27 +0000431
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200432 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 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000459
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200460 context->attribs->standard_colormap_mode = RIgnoreStdColormap;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000461
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200462 /* RIgnoreStdColormap and fallback */
463 return allocatePseudoColor(context);
464}
465
466static char *mygetenv(char *var, int scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000467{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200468 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;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000477}
478
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200479static 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}
9d2e6ef9 scottc1998-09-29 22:36:29 +0000514
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200515static void getColormap(RContext * context, int screen_number)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000516{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200517 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;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000547}
548
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200549static 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}
9d2e6ef9 scottc1998-09-29 22:36:29 +0000560
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200561RContext *RCreateContext(Display * dpy, int screen_number, RContextAttributes * attribs)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000562{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200563 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);
a30475fc kojima2000-01-14 16:39:15 +0000599#ifndef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200600 _wraster_change_filter(context->attribs->scaling_filter);
a30475fc kojima2000-01-14 16:39:15 +0000601#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200602 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 */
9d2e6ef9 scottc1998-09-29 22:36:29 +0000678#ifdef XSHM
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200679 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 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000697#endif
698
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200699 return context;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000700}
701
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200702static Bool bestContext(Display * dpy, int screen_number, RContext * context)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000703{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200704 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 }
0261c326 dan1999-01-06 15:22:33 +0000722#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200723 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 }
0261c326 dan1999-01-06 15:22:33 +0000737#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200738 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;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000760}