1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.
23  */
24 
25 /*
26  * GTK+ DirectFB backend
27  * Copyright (C) 2001-2002  convergence integrated media GmbH
28  * Copyright (C) 2002-2004  convergence GmbH
29  * Written by Denis Oliver Kropp <dok@convergence.de> and
30  *            Sven Neumann <sven@convergence.de>
31  */
32 
33 #include "config.h"
34 
35 #include "gdkdirectfb.h"
36 #include "gdkprivate-directfb.h"
37 
38 #include "gdkscreen.h"
39 #include "gdkvisual.h"
40 #include "gdkalias.h"
41 
42 
43 struct _GdkVisualClass
44 {
45   GObjectClass parent_class;
46 };
47 
48 
49 static void                gdk_visual_decompose_mask  (gulong   mask,
50                                                        gint    *shift,
51                                                        gint    *prec);
52 static GdkVisualDirectFB * gdk_directfb_visual_create (DFBSurfacePixelFormat  pixelformat);
53 
54 
55 static DFBSurfacePixelFormat formats[] =
56   {
57     DSPF_ARGB,
58     DSPF_LUT8,
59     DSPF_RGB32,
60     DSPF_RGB24,
61     DSPF_RGB16,
62     DSPF_ARGB1555,
63     DSPF_RGB332
64   };
65 
66 GdkVisual                * system_visual                                = NULL;
67 static GdkVisualDirectFB * visuals[G_N_ELEMENTS (formats) + 1]          = { NULL };
68 static gint                available_depths[G_N_ELEMENTS (formats) + 1] = {0};
69 static GdkVisualType       available_types[G_N_ELEMENTS (formats) + 1]  = {0};
70 
71 
72 static void
gdk_visual_finalize(GObject * object)73 gdk_visual_finalize (GObject *object)
74 {
75   g_error ("A GdkVisual object was finalized. This should not happen");
76 }
77 
78 static void
gdk_visual_class_init(GObjectClass * class)79 gdk_visual_class_init (GObjectClass *class)
80 {
81   class->finalize = gdk_visual_finalize;
82 }
83 
84 GType
gdk_visual_get_type(void)85 gdk_visual_get_type (void)
86 {
87   static GType object_type = 0;
88 
89   if (!object_type)
90     {
91       const GTypeInfo object_info =
92         {
93           sizeof (GdkVisualClass),
94           (GBaseInitFunc) NULL,
95           (GBaseFinalizeFunc) NULL,
96           (GClassInitFunc) gdk_visual_class_init,
97           NULL,           /* class_finalize */
98           NULL,           /* class_data */
99           sizeof (GdkVisualDirectFB),
100           0,              /* n_preallocs */
101           (GInstanceInitFunc) NULL,
102         };
103 
104       object_type = g_type_register_static (G_TYPE_OBJECT,
105                                             "GdkVisual",
106                                             &object_info, 0);
107     }
108 
109   return object_type;
110 }
111 
112 void
_gdk_visual_init(void)113 _gdk_visual_init (void)
114 {
115   DFBDisplayLayerConfig  dlc;
116   DFBSurfaceDescription  desc;
117   IDirectFBSurface      *dest;
118   gint                   i, c;
119 
120 
121   _gdk_display->layer->GetConfiguration (_gdk_display->layer, &dlc);
122   g_assert (dlc.pixelformat != DSPF_UNKNOWN);
123 
124   dest = gdk_display_dfb_create_surface (_gdk_display, dlc.pixelformat, 8, 8);
125   g_assert (dest != NULL);
126 
127   /* We could provide all visuals since DirectFB allows us to mix
128      surface formats. Blitting with format conversion can however
129      be incredibly slow, so we've choosen to register only those
130      visuals that can be blitted to the display layer in hardware.
131 
132      If you want to use a special pixelformat that is not registered
133      here, you can create it using the DirectFB-specific function
134      gdk_directfb_visual_by_format().
135      Note:
136      changed to do all formats but we should redo this code
137      to ensure the base format ARGB LUT8 RGB etc then add ones supported
138      by the hardware
139   */
140   for (i = 0; i < G_N_ELEMENTS (formats); i++)
141     {
142       IDirectFBSurface    *src;
143       DFBAccelerationMask  acc;
144 
145       desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
146       desc.width       = 8;
147       desc.height      = 8;
148       desc.pixelformat = formats[i];
149       //call direct so fail silently  is ok
150       if (_gdk_display->directfb->CreateSurface (_gdk_display->directfb,
151                                                  &desc, &src) != DFB_OK)
152         continue;
153 
154       visuals[i] = gdk_directfb_visual_create (formats[i]);
155 
156       dest->GetAccelerationMask (dest, src, &acc);
157 
158       if (acc & DFXL_BLIT || formats[i] == dlc.pixelformat)
159         {
160           system_visual = GDK_VISUAL (visuals[i]);
161         }
162 
163       src->Release (src);
164     }
165 
166   dest->Release (dest);
167 
168   //fallback to ARGB must be supported
169   if (!system_visual)
170     {
171       g_assert (visuals[DSPF_ARGB] != NULL);
172       system_visual = GDK_VISUAL(visuals[DSPF_ARGB]);
173     }
174 
175   g_assert (system_visual != NULL);
176 }
177 
178 gint
gdk_visual_get_best_depth(void)179 gdk_visual_get_best_depth (void)
180 {
181   return system_visual->depth;
182 }
183 
184 GdkVisualType
gdk_visual_get_best_type(void)185 gdk_visual_get_best_type (void)
186 {
187   return system_visual->type;
188 }
189 
190 GdkVisual *
gdk_screen_get_system_visual(GdkScreen * screen)191 gdk_screen_get_system_visual (GdkScreen *screen)
192 {
193   g_assert (system_visual);
194   return system_visual;
195 }
196 
197 GdkVisual *
gdk_visual_get_best(void)198 gdk_visual_get_best (void)
199 {
200   return system_visual;
201 }
202 
203 GdkVisual *
gdk_visual_get_best_with_depth(gint depth)204 gdk_visual_get_best_with_depth (gint depth)
205 {
206   gint i;
207 
208   for (i = 0; visuals[i]; i++)
209     {
210       if (visuals[i]) {
211         GdkVisual *visual = GDK_VISUAL (visuals[i]);
212 
213         if (depth == visual->depth)
214           return visual;
215       }
216     }
217 
218   return NULL;
219 }
220 
221 GdkVisual *
gdk_visual_get_best_with_type(GdkVisualType visual_type)222 gdk_visual_get_best_with_type (GdkVisualType visual_type)
223 {
224   gint i;
225 
226   for (i = 0; visuals[i]; i++)
227     {
228       if (visuals[i]) {
229         GdkVisual *visual = GDK_VISUAL (visuals[i]);
230 
231         if (visual_type == visual->type)
232           return visual;
233       }
234     }
235 
236   return NULL;
237 }
238 
239 GdkVisual*
gdk_visual_get_best_with_both(gint depth,GdkVisualType visual_type)240 gdk_visual_get_best_with_both (gint          depth,
241                                GdkVisualType visual_type)
242 {
243   gint i;
244 
245   for (i = 0; visuals[i]; i++)
246     {
247       if (visuals[i]) {
248         GdkVisual *visual = GDK_VISUAL (visuals[i]);
249 
250         if (depth == visual->depth && visual_type == visual->type)
251           return visual;
252       }
253     }
254 
255   return system_visual;
256 }
257 
258 void
gdk_query_depths(gint ** depths,gint * count)259 gdk_query_depths (gint **depths,
260                   gint  *count)
261 {
262   gint i;
263 
264   for (i = 0; available_depths[i]; i++)
265     ;
266 
267   *count = i;
268   *depths = available_depths;
269 }
270 
271 void
gdk_query_visual_types(GdkVisualType ** visual_types,gint * count)272 gdk_query_visual_types (GdkVisualType **visual_types,
273                         gint           *count)
274 {
275   gint i;
276 
277   for (i = 0; available_types[i]; i++)
278     ;
279 
280   *count = i;
281   *visual_types = available_types;
282 }
283 
284 GList *
gdk_screen_list_visuals(GdkScreen * screen)285 gdk_screen_list_visuals (GdkScreen *screen)
286 {
287   GList *list = NULL;
288   gint   i;
289 
290   for (i = 0; visuals[i]; i++)
291     if (visuals[i]) {
292       GdkVisual * vis = GDK_VISUAL (visuals[i]);
293       list = g_list_append (list,vis);
294     }
295 
296   return list;
297 }
298 
299 /**
300  * gdk_directfb_visual_by_format:
301  * @pixel_format: the pixel_format of the requested visual
302  *
303  * This function is specific to the DirectFB backend. It allows
304  * to specify a GdkVisual by @pixel_format.
305  *
306  * At startup, only those visuals that can be blitted
307  * hardware-accelerated are registered.  By using
308  * gdk_directfb_visual_by_format() you can retrieve visuals that
309  * don't match this criteria since this function will try to create
310  * a new visual for the desired @pixel_format for you.
311  *
312  * Return value: a pointer to the GdkVisual or %NULL if the
313  * pixel_format is unsupported.
314  **/
315 GdkVisual *
gdk_directfb_visual_by_format(DFBSurfacePixelFormat pixel_format)316 gdk_directfb_visual_by_format (DFBSurfacePixelFormat pixel_format)
317 {
318   gint i;
319 
320   /* first check if one the registered visuals matches */
321   for (i = 0; visuals[i]; i++)
322     if (visuals[i] && visuals[i]->format == pixel_format)
323       return GDK_VISUAL (visuals[i]);
324 
325   /* none matched, try to create a new one for this pixel_format */
326   {
327     DFBSurfaceDescription  desc;
328     IDirectFBSurface      *test;
329 
330     desc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
331     desc.width       = 8;
332     desc.height      = 8;
333     desc.pixelformat = pixel_format;
334 
335     if (_gdk_display->directfb->CreateSurface (_gdk_display->directfb,
336                                                &desc, &test) != DFB_OK)
337       return NULL;
338 
339     test->Release (test);
340   }
341 
342   return GDK_VISUAL (gdk_directfb_visual_create (pixel_format));
343 }
344 
345 GdkScreen *
gdk_visual_get_screen(GdkVisual * visual)346 gdk_visual_get_screen (GdkVisual *visual)
347 {
348   g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
349 
350   return gdk_screen_get_default ();
351 }
352 
353 static void
gdk_visual_decompose_mask(gulong mask,gint * shift,gint * prec)354 gdk_visual_decompose_mask (gulong  mask,
355                            gint   *shift,
356                            gint   *prec)
357 {
358   *shift = 0;
359   *prec  = 0;
360 
361   while (!(mask & 0x1))
362     {
363       (*shift)++;
364       mask >>= 1;
365     }
366 
367   while (mask & 0x1)
368     {
369       (*prec)++;
370       mask >>= 1;
371     }
372 }
373 
374 static GdkVisualDirectFB *
gdk_directfb_visual_create(DFBSurfacePixelFormat pixelformat)375 gdk_directfb_visual_create (DFBSurfacePixelFormat  pixelformat)
376 {
377   GdkVisual *visual;
378   gint       i;
379 
380   for (i = 0; i < G_N_ELEMENTS (formats); i++)
381     if (formats[i] == pixelformat)
382       break;
383 
384   if (i ==  G_N_ELEMENTS (formats))
385     {
386       g_warning ("unsupported pixelformat");
387       return NULL;
388     }
389 
390   visual = g_object_new (GDK_TYPE_VISUAL, NULL);
391 
392   switch (pixelformat)
393     {
394     case DSPF_LUT8:
395       visual->type         = GDK_VISUAL_PSEUDO_COLOR;
396       visual->bits_per_rgb = 8;
397       break;
398 
399     case DSPF_RGB332:
400       visual->type         = GDK_VISUAL_STATIC_COLOR;
401       visual->bits_per_rgb = 3;
402       break;
403 
404     case DSPF_ARGB1555:
405       visual->type         = GDK_VISUAL_TRUE_COLOR;
406       visual->red_mask     = 0x00007C00;
407       visual->green_mask   = 0x000003E0;
408       visual->blue_mask    = 0x0000001F;
409       visual->bits_per_rgb = 5;
410       break;
411 
412     case DSPF_RGB16:
413       visual->type         = GDK_VISUAL_TRUE_COLOR;
414       visual->red_mask     = 0x0000F800;
415       visual->green_mask   = 0x000007E0;
416       visual->blue_mask    = 0x0000001F;
417       visual->bits_per_rgb = 6;
418       break;
419 
420     case DSPF_RGB24:
421     case DSPF_RGB32:
422     case DSPF_ARGB:
423       visual->type         = GDK_VISUAL_TRUE_COLOR;
424       visual->red_mask     = 0x00FF0000;
425       visual->green_mask   = 0x0000FF00;
426       visual->blue_mask    = 0x000000FF;
427       visual->bits_per_rgb = 8;
428       break;
429 
430     default:
431       g_assert_not_reached ();
432     }
433 
434 #if G_BYTE_ORDER == G_BIG_ENDIAN
435   visual->byte_order = GDK_MSB_FIRST;
436 #else
437   visual->byte_order = GDK_LSB_FIRST;
438 #endif
439 
440   visual->depth      = DFB_BITS_PER_PIXEL (pixelformat);
441 
442   switch (visual->type)
443     {
444     case GDK_VISUAL_TRUE_COLOR:
445       gdk_visual_decompose_mask (visual->red_mask,
446                                  &visual->red_shift, &visual->red_prec);
447       gdk_visual_decompose_mask (visual->green_mask,
448                                  &visual->green_shift, &visual->green_prec);
449       gdk_visual_decompose_mask (visual->blue_mask,
450                                  &visual->blue_shift, &visual->blue_prec);
451 
452       /* the number of possible levels per color component */
453       visual->colormap_size = 1 << MAX (visual->red_prec,
454                                         MAX (visual->green_prec,
455                                              visual->blue_prec));
456       break;
457 
458     case GDK_VISUAL_STATIC_COLOR:
459     case GDK_VISUAL_PSEUDO_COLOR:
460       visual->colormap_size = 1 << visual->depth;
461 
462       visual->red_mask    = 0;
463       visual->red_shift   = 0;
464       visual->red_prec    = 0;
465 
466       visual->green_mask  = 0;
467       visual->green_shift = 0;
468       visual->green_prec  = 0;
469 
470       visual->blue_mask   = 0;
471       visual->blue_shift  = 0;
472       visual->blue_prec   = 0;
473 
474       break;
475 
476     default:
477       g_assert_not_reached ();
478     }
479 
480   ((GdkVisualDirectFB *)visual)->format = pixelformat;
481 
482   for (i = 0; available_depths[i]; i++)
483     if (available_depths[i] == visual->depth)
484       break;
485   if (!available_depths[i])
486     available_depths[i] = visual->depth;
487 
488   for (i = 0; available_types[i]; i++)
489     if (available_types[i] == visual->type)
490       break;
491   if (!available_types[i])
492     available_types[i] = visual->type;
493 
494   return (GdkVisualDirectFB *) visual;
495 }
496 
497 #define __GDK_VISUAL_X11_C__
498 #include "gdkaliasdef.c"
499