move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / software_xcb / evas_xcb_color.c
1 #include "evas_common.h"
2 #include "evas_engine.h"
3
4 #include <xcb/xcb.h>
5
6 typedef struct _Convert_Pal_Priv Convert_Pal_Priv;
7
8 struct _Convert_Pal_Priv
9 {
10    xcb_connection_t *conn;
11    xcb_colormap_t    cmap;
12    xcb_visualtype_t *vis;
13 };
14
15 typedef DATA8 * (*Xcb_Func_Alloc_Colors) (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
16
17 static Xcb_Func_Alloc_Colors x_color_alloc[PAL_MODE_LAST + 1];
18 static int                   x_color_count[PAL_MODE_LAST + 1];
19 static Evas_List            *palettes = NULL;
20
21 static DATA8 * x_color_alloc_rgb(int nr, int ng, int nb, xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
22 static DATA8 * x_color_alloc_gray(int ng, xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
23
24 static DATA8 * x_color_alloc_rgb_332  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
25 static DATA8 * x_color_alloc_rgb_666  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
26 static DATA8 * x_color_alloc_rgb_232  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
27 static DATA8 * x_color_alloc_rgb_222  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
28 static DATA8 * x_color_alloc_rgb_221  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
29 static DATA8 * x_color_alloc_rgb_121  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
30 static DATA8 * x_color_alloc_rgb_111  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
31 static DATA8 * x_color_alloc_gray_256 (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
32 static DATA8 * x_color_alloc_gray_64  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
33 static DATA8 * x_color_alloc_gray_16  (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
34 static DATA8 * x_color_alloc_gray_4   (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
35 static DATA8 * x_color_alloc_mono     (xcb_connection_t *conn, xcb_colormap_t cmap, xcb_visualtype_t *v);
36
37 static DATA8 *
38 x_color_alloc_rgb(int               nr,
39                   int               ng,
40                   int               nb,
41                   xcb_connection_t *conn,
42                   xcb_colormap_t    cmap,
43                   xcb_visualtype_t *v)
44 {
45    int    r, g, b, i;
46    DATA8 *color_lut;
47    int    sig_mask = 0;
48    int    delt = 0;
49
50    for (i = 0; i < v->bits_per_rgb_value; i++) sig_mask |= (0x1 << i);
51    sig_mask <<= (16 - v->bits_per_rgb_value);
52    i = 0;
53    color_lut = malloc((nr) * (ng) * (nb));
54    if (!color_lut) return NULL;
55    delt = 0x0101 * 3;
56    /* FIXME: remove the round-trip ? */
57    for (r = 0; r < (nr); r++)
58      {
59         for (g = 0; g < (ng); g++)
60           {
61              for (b = 0; b < (nb); b++)
62                {
63                   xcb_coloritem_t          xcl;
64                   xcb_coloritem_t          xcl_in;
65                   xcb_alloc_color_reply_t *rep;
66                   int                      val;
67                   int                      dr, dg, db;
68
69                   val = (int)((((double)r) / ((nr) - 1)) * 255);
70                   val = (val << 8) | val;
71                   xcl.red = (uint16_t)(val);
72                   val = (int)((((double)g) / ((ng) - 1)) * 255);
73                   val = (val << 8) | val;
74                   xcl.green = (uint16_t)(val);
75                   val = (int)((((double)b) / ((nb) - 1)) * 255);
76                   val = (val << 8) | val;
77                   xcl.blue = (uint16_t)(val);
78                   xcl_in = xcl;
79                   rep = xcb_alloc_color_reply(conn,
80                                               xcb_alloc_color_unchecked(conn,
81                                                                         cmap,
82                                                                         xcl.red,
83                                                                         xcl.green,
84                                                                         xcl.blue),
85                                               0);
86                   dr = (int)xcl_in.red - (int)xcl.red;
87                   if (dr < 0) dr = -dr;
88                   dg = (int)xcl_in.green - (int)xcl.green;
89                   if (dg < 0) dg = -dg;
90                   db = (int)xcl_in.blue - (int)xcl.blue;
91                   if (db < 0) db = -db;
92 /*
93                  printf("ASK [%i]: %04x %04x %04x = %04x %04x %04x | dif = %04x / %04x\n",
94                         ret,
95                         xcl_in.red, xcl_in.green, xcl_in.blue,
96                         xcl.red, xcl.green, xcl.blue,
97                         (dr + dg +db), delt);
98  */
99
100                   /* TODO: XAllocColor tries to approach the color */
101                   /* in case the allocation fails */
102                   /* XCB does not that (i think). It should be done */
103                   /* So if rep == NULL, the other following tests */
104                   /* should be always satisfied */
105                   if ((!rep) ||
106                       ((dr + dg + db) > delt)
107                       /*
108                       ((xcl_in.red   & sig_mask) != (xcl.red   & sig_mask)) ||
109                       ((xcl_in.green & sig_mask) != (xcl.green & sig_mask)) ||
110                       ((xcl_in.blue  & sig_mask) != (xcl.blue  & sig_mask))
111                       */
112                       )
113                     {
114                        uint32_t pixels[256];
115                        int      j;
116
117                        if (i > 0)
118                          {
119                             for (j = 0; j < i; j++)
120                               pixels[j] = (uint32_t)color_lut[j];
121                             xcb_free_colors(conn, cmap, 0, i, pixels);
122                          }
123                        free(color_lut);
124                        return NULL;
125                     }
126                   color_lut[i] = rep->pixel;
127                   i++;
128                   free(rep);
129                }
130           }
131      }
132    return color_lut;
133 }
134
135 static DATA8 *
136 x_color_alloc_gray(int               ng,
137                    xcb_connection_t *conn,
138                    xcb_colormap_t    cmap,
139                    xcb_visualtype_t *v)
140 {
141    int g, i;
142    DATA8 *color_lut;
143    int sig_mask = 0;
144
145    for (i = 0; i < v->bits_per_rgb_value; i++) sig_mask |= (0x1 << i);
146    sig_mask <<= (16 - v->bits_per_rgb_value);
147    i = 0;
148    color_lut = malloc(ng);
149    if (!color_lut) return NULL;
150    /* FIXME: remove the round-trip ? */
151    for (g = 0; g < (ng); g++)
152      {
153         xcb_coloritem_t          xcl;
154         xcb_coloritem_t          xcl_in;
155         int                      val;
156         xcb_alloc_color_reply_t *rep;
157
158         val = (int)((((double)g) / ((ng) - 1)) * 255);
159         val = (val << 8) | val;
160         xcl.red = (uint16_t)(val);
161         xcl.green = (uint16_t)(val);
162         xcl.blue = (uint16_t)(val);
163         xcl_in = xcl;
164         rep = xcb_alloc_color_reply(conn,
165                                     xcb_alloc_color_unchecked(conn,
166                                                               cmap,
167                                                               xcl.red,
168                                                               xcl.green,
169                                                               xcl.blue),
170                                     0);
171         /* FIXME: XAllocColor tries to approach the color */
172         /* in case the allocation fails */
173         /* XCB does not that (i think). It should be done */
174         /* So if rep == NULL, the other following tests */
175         /* should be always satisfied */
176         if ((!rep) ||
177             ((xcl_in.red   & sig_mask) != (xcl.red   & sig_mask)) ||
178             ((xcl_in.green & sig_mask) != (xcl.green & sig_mask)) ||
179             ((xcl_in.blue  & sig_mask) != (xcl.blue  & sig_mask)))
180           {
181              uint32_t pixels[256];
182              int      j;
183
184              if (i > 0)
185                {
186                   for (j = 0; j < i; j++)
187                     pixels[j] = (uint32_t) color_lut[j];
188                   xcb_free_colors(conn, cmap, 0, i, pixels);
189                }
190              free(color_lut);
191              return NULL;
192           }
193         color_lut[i] = rep->pixel;
194         i++;
195         free(rep);
196      }
197    return color_lut;
198 }
199
200 static DATA8 *
201 x_color_alloc_rgb_332(xcb_connection_t *conn,
202                       xcb_colormap_t    cmap,
203                       xcb_visualtype_t *v)
204 {
205    return x_color_alloc_rgb(8, 8, 4, conn, cmap, v);
206 }
207
208 static DATA8 *
209 x_color_alloc_rgb_666(xcb_connection_t *conn,
210                       xcb_colormap_t    cmap,
211                       xcb_visualtype_t *v)
212 {
213    return x_color_alloc_rgb(6, 6, 6, conn, cmap, v);
214 }
215
216 static DATA8 *
217 x_color_alloc_rgb_232(xcb_connection_t *conn,
218                       xcb_colormap_t    cmap,
219                       xcb_visualtype_t *v)
220 {
221    return x_color_alloc_rgb(4, 8, 4, conn, cmap, v);
222 }
223
224 static DATA8 *
225 x_color_alloc_rgb_222(xcb_connection_t *conn,
226                       xcb_colormap_t    cmap,
227                       xcb_visualtype_t *v)
228 {
229    return x_color_alloc_rgb(4, 4, 4, conn, cmap, v);
230 }
231
232 static DATA8 *
233 x_color_alloc_rgb_221(xcb_connection_t *conn,
234                       xcb_colormap_t    cmap,
235                       xcb_visualtype_t *v)
236 {
237    return x_color_alloc_rgb(4, 4, 2, conn, cmap, v);
238 }
239
240 static DATA8 *
241 x_color_alloc_rgb_121(xcb_connection_t *conn,
242                       xcb_colormap_t    cmap,
243                       xcb_visualtype_t *v)
244 {
245    return x_color_alloc_rgb(2, 4, 2, conn, cmap, v);
246 }
247
248 static DATA8 *
249 x_color_alloc_rgb_111(xcb_connection_t *conn,
250                       xcb_colormap_t    cmap,
251                       xcb_visualtype_t *v)
252 {
253    return x_color_alloc_rgb(2, 2, 2, conn, cmap, v);
254 }
255
256 static DATA8 *
257 x_color_alloc_gray_256(xcb_connection_t *conn,
258                        xcb_colormap_t    cmap,
259                        xcb_visualtype_t *v)
260 {
261    return x_color_alloc_gray(256, conn, cmap, v);
262 }
263
264 static DATA8 *
265 x_color_alloc_gray_64(xcb_connection_t *conn,
266                       xcb_colormap_t    cmap,
267                       xcb_visualtype_t *v)
268 {
269    return x_color_alloc_gray(64, conn, cmap, v);
270 }
271
272 static DATA8 *
273 x_color_alloc_gray_16(xcb_connection_t *conn,
274                       xcb_colormap_t    cmap,
275                       xcb_visualtype_t *v)
276 {
277    return x_color_alloc_gray(32, conn, cmap, v);
278 }
279
280 static DATA8 *
281 x_color_alloc_gray_4(xcb_connection_t *conn,
282                      xcb_colormap_t    cmap,
283                      xcb_visualtype_t *v)
284 {
285    return x_color_alloc_gray(16, conn, cmap, v);
286 }
287
288 static DATA8 *
289 x_color_alloc_mono(xcb_connection_t *conn,
290                    xcb_colormap_t    cmap,
291                    xcb_visualtype_t *v)
292 {
293    return x_color_alloc_gray(2, conn, cmap, v);
294 }
295
296 void
297 evas_software_xcb_x_color_init(void)
298 {
299    static int initialised = 0;
300
301    if (initialised) return;
302    x_color_alloc[PAL_MODE_NONE]    = NULL;
303    x_color_count[PAL_MODE_NONE]    = 0;
304
305    x_color_alloc[PAL_MODE_MONO]    = x_color_alloc_mono;
306    x_color_count[PAL_MODE_MONO]    = 2;
307
308    x_color_alloc[PAL_MODE_GRAY4]   = x_color_alloc_gray_4;
309    x_color_count[PAL_MODE_GRAY4]   = 4;
310
311    x_color_alloc[PAL_MODE_GRAY16]  = x_color_alloc_gray_16;
312    x_color_count[PAL_MODE_GRAY16]  = 16;
313
314    x_color_alloc[PAL_MODE_GRAY64]  = x_color_alloc_gray_64;
315    x_color_count[PAL_MODE_GRAY64]  = 64;
316
317    x_color_alloc[PAL_MODE_GRAY256] = x_color_alloc_gray_256;
318    x_color_count[PAL_MODE_GRAY256] = 256;
319
320    x_color_alloc[PAL_MODE_RGB111]  = x_color_alloc_rgb_111;
321    x_color_count[PAL_MODE_RGB111]  = 2 * 2 * 2;
322
323    x_color_alloc[PAL_MODE_RGB121]  = x_color_alloc_rgb_121;
324    x_color_count[PAL_MODE_RGB121]  = 2 * 4 * 2;
325
326    x_color_alloc[PAL_MODE_RGB221]  = x_color_alloc_rgb_221;
327    x_color_count[PAL_MODE_RGB221]  = 4 * 4 * 2;
328
329    x_color_alloc[PAL_MODE_RGB222]  = x_color_alloc_rgb_222;
330    x_color_count[PAL_MODE_RGB222]  = 4 * 4 * 4;
331
332    x_color_alloc[PAL_MODE_RGB232]  = x_color_alloc_rgb_232;
333    x_color_count[PAL_MODE_RGB232]  = 4 * 8 * 4;
334
335    x_color_alloc[PAL_MODE_RGB666]  = x_color_alloc_rgb_666;
336    x_color_count[PAL_MODE_RGB666]  = 6 * 6 * 6;
337
338    x_color_alloc[PAL_MODE_RGB332]  = x_color_alloc_rgb_332;
339    x_color_count[PAL_MODE_RGB332]  = 8 * 8 * 4;
340
341    x_color_alloc[PAL_MODE_LAST]    = NULL;
342    x_color_count[PAL_MODE_LAST]    = 0;
343    initialised = 1;
344 }
345
346 Convert_Pal *
347 evas_software_xcb_x_color_allocate(xcb_connection_t   *conn,
348                                    xcb_colormap_t      cmap,
349                                    xcb_visualtype_t   *vis,
350                                    Convert_Pal_Mode    colors)
351 {
352    Convert_Pal_Priv *palpriv;
353    Convert_Pal      *pal;
354    Convert_Pal_Mode  c;
355    Evas_List        *l;
356
357 /*   printf("ALLOC cmap=%i vis=%p\n", cmap, vis);*/
358    for (l = palettes; l; l = l->next)
359      {
360         pal = l->data;
361         palpriv = pal->data;
362         if ((conn == palpriv->conn) &&
363             (vis  == palpriv->vis)  &&
364             (cmap == palpriv->cmap))
365           {
366              pal->references++;
367              return pal;
368           }
369      }
370    pal = calloc(1, sizeof(struct _Convert_Pal));
371    if (!pal) return NULL;
372    for (c = colors; c > PAL_MODE_NONE; c--)
373      {
374         if (x_color_alloc[c])
375           {
376 /*          printf("TRY PAL %i\n", c);*/
377              pal->lookup = (x_color_alloc[c])(conn, cmap, vis);
378              if (pal->lookup) break;
379           }
380      }
381    pal->references = 1;
382    pal->colors = c;
383    pal->count = x_color_count[c];
384    palpriv = calloc(1, sizeof(Convert_Pal_Priv));
385    pal->data = palpriv;
386    if (!palpriv)
387      {
388         if (pal->lookup) free(pal->lookup);
389         free(pal);
390         return NULL;
391      }
392    palpriv->conn = conn;
393    palpriv->vis = vis;
394    palpriv->cmap = cmap;
395    if (pal->colors == PAL_MODE_NONE)
396      {
397         if (pal->lookup) free(pal->lookup);
398         free(pal);
399         return NULL;
400      }
401    palettes = evas_list_append(palettes, pal);
402    return pal;
403 }
404
405 void
406 evas_software_xcb_x_color_deallocate(xcb_connection_t *conn,
407                                      xcb_colormap_t    cmap,
408                                      xcb_visualtype_t *vis,
409                                      Convert_Pal      *pal)
410 {
411    uint32_t pixels[256];
412    int      j;
413
414    pal->references--;
415    if (pal->references > 0) return;
416    if (pal->lookup)
417      {
418         for(j = 0; j < pal->count; j++)
419           pixels[j] = (uint32_t) pal->lookup[j];
420         xcb_free_colors(conn, cmap, 0, pal->count, pixels);
421         free(pal->lookup);
422      }
423    free(pal->data);
424    palettes = evas_list_remove(palettes, pal);
425    free(pal);
426 }