1 /*
2  * color.c:
3  * Color management example.
4  *
5  * written by Naofumi Yasufuku  <naofumi@users.sourceforge.net>
6  */
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <gtk/gtk.h>
12 
13 #include <gtk/gtkgl.h>
14 
15 #ifdef G_OS_WIN32
16 #define WIN32_LEAN_AND_MEAN 1
17 #include <windows.h>
18 #endif
19 
20 #include <GL/gl.h>
21 #include <GL/glu.h>
22 
23 /*
24  * Colors.
25  */
26 
27 #define NUM_COLORS 4
28 
29 static GdkColor colors[NUM_COLORS] = {
30   /* pixel   red     green   blue */
31   {  0,      0x0,    0x0,    0x0    }, /* black */
32   {  0,      0xffff, 0x0,    0x0    }, /* red */
33   {  0,      0x0,    0xffff, 0x0    }, /* green */
34   {  0,      0x0,    0x0,    0xffff }  /* blue */
35 };
36 
37 #define BLACK colors[0].pixel
38 #define RED   colors[1].pixel
39 #define GREEN colors[2].pixel
40 #define BLUE  colors[3].pixel
41 
42 static gboolean
configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer data)43 configure_event (GtkWidget         *widget,
44                  GdkEventConfigure *event,
45                  gpointer           data)
46 {
47   GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
48   GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
49 
50   /*** OpenGL BEGIN ***/
51   if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
52     goto NO_GL;
53 
54   glViewport (0, 0,
55               widget->allocation.width, widget->allocation.height);
56 
57   gdk_gl_drawable_gl_end (gldrawable);
58   /*** OpenGL END ***/
59 
60  NO_GL:
61 
62   return TRUE;
63 }
64 
65 static gboolean
expose_event(GtkWidget * widget,GdkEventExpose * event,gpointer data)66 expose_event (GtkWidget      *widget,
67               GdkEventExpose *event,
68               gpointer        data)
69 {
70   GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
71   GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
72 
73   /*** OpenGL BEGIN ***/
74   if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
75     goto NO_GL;
76 
77   glClear (GL_COLOR_BUFFER_BIT);
78 
79   glBegin (GL_TRIANGLES);
80     glIndexi (RED);
81     glColor3f (1.0, 0.0, 0.0);
82     glVertex2i (0, 1);
83     glIndexi (GREEN);
84     glColor3f (0.0, 1.0, 0.0);
85     glVertex2i (-1, -1);
86     glIndexi (BLUE);
87     glColor3f (0.0, 0.0, 1.0);
88     glVertex2i (1, -1);
89   glEnd ();
90 
91   if (gdk_gl_drawable_is_double_buffered (gldrawable))
92     gdk_gl_drawable_swap_buffers (gldrawable);
93   else
94     glFlush ();
95 
96   gdk_gl_drawable_gl_end (gldrawable);
97   /*** OpenGL END ***/
98 
99  NO_GL:
100 
101   return TRUE;
102 }
103 
104 static void
print_gl_config_attrib(GdkGLConfig * glconfig,const gchar * attrib_str,int attrib,gboolean is_boolean)105 print_gl_config_attrib (GdkGLConfig *glconfig,
106                         const gchar *attrib_str,
107                         int          attrib,
108                         gboolean     is_boolean)
109 {
110   int value;
111 
112   g_print ("%s = ", attrib_str);
113   if (gdk_gl_config_get_attrib (glconfig, attrib, &value))
114     {
115       if (is_boolean)
116         g_print ("%s\n", value == TRUE ? "TRUE" : "FALSE");
117       else
118         g_print ("%d\n", value);
119     }
120   else
121     g_print ("*** Cannot get %s attribute value\n", attrib_str);
122 }
123 
124 static void
examine_gl_config_attrib(GdkGLConfig * glconfig)125 examine_gl_config_attrib (GdkGLConfig *glconfig)
126 {
127   g_print ("\nOpenGL visual configurations :\n\n");
128 
129   g_print ("gdk_gl_config_is_rgba (glconfig) = %s\n",
130            gdk_gl_config_is_rgba (glconfig) ? "TRUE" : "FALSE");
131   g_print ("gdk_gl_config_is_double_buffered (glconfig) = %s\n",
132            gdk_gl_config_is_double_buffered (glconfig) ? "TRUE" : "FALSE");
133   g_print ("gdk_gl_config_is_stereo (glconfig) = %s\n",
134            gdk_gl_config_is_stereo (glconfig) ? "TRUE" : "FALSE");
135   g_print ("gdk_gl_config_has_alpha (glconfig) = %s\n",
136            gdk_gl_config_has_alpha (glconfig) ? "TRUE" : "FALSE");
137   g_print ("gdk_gl_config_has_depth_buffer (glconfig) = %s\n",
138            gdk_gl_config_has_depth_buffer (glconfig) ? "TRUE" : "FALSE");
139   g_print ("gdk_gl_config_has_stencil_buffer (glconfig) = %s\n",
140            gdk_gl_config_has_stencil_buffer (glconfig) ? "TRUE" : "FALSE");
141   g_print ("gdk_gl_config_has_accum_buffer (glconfig) = %s\n",
142            gdk_gl_config_has_accum_buffer (glconfig) ? "TRUE" : "FALSE");
143 
144   g_print ("\n");
145 
146   print_gl_config_attrib (glconfig, "GDK_GL_USE_GL",           GDK_GL_USE_GL,           TRUE);
147   print_gl_config_attrib (glconfig, "GDK_GL_BUFFER_SIZE",      GDK_GL_BUFFER_SIZE,      FALSE);
148   print_gl_config_attrib (glconfig, "GDK_GL_LEVEL",            GDK_GL_LEVEL,            FALSE);
149   print_gl_config_attrib (glconfig, "GDK_GL_RGBA",             GDK_GL_RGBA,             TRUE);
150   print_gl_config_attrib (glconfig, "GDK_GL_DOUBLEBUFFER",     GDK_GL_DOUBLEBUFFER,     TRUE);
151   print_gl_config_attrib (glconfig, "GDK_GL_STEREO",           GDK_GL_STEREO,           TRUE);
152   print_gl_config_attrib (glconfig, "GDK_GL_AUX_BUFFERS",      GDK_GL_AUX_BUFFERS,      FALSE);
153   print_gl_config_attrib (glconfig, "GDK_GL_RED_SIZE",         GDK_GL_RED_SIZE,         FALSE);
154   print_gl_config_attrib (glconfig, "GDK_GL_GREEN_SIZE",       GDK_GL_GREEN_SIZE,       FALSE);
155   print_gl_config_attrib (glconfig, "GDK_GL_BLUE_SIZE",        GDK_GL_BLUE_SIZE,        FALSE);
156   print_gl_config_attrib (glconfig, "GDK_GL_ALPHA_SIZE",       GDK_GL_ALPHA_SIZE,       FALSE);
157   print_gl_config_attrib (glconfig, "GDK_GL_DEPTH_SIZE",       GDK_GL_DEPTH_SIZE,       FALSE);
158   print_gl_config_attrib (glconfig, "GDK_GL_STENCIL_SIZE",     GDK_GL_STENCIL_SIZE,     FALSE);
159   print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_RED_SIZE",   GDK_GL_ACCUM_RED_SIZE,   FALSE);
160   print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_GREEN_SIZE", GDK_GL_ACCUM_GREEN_SIZE, FALSE);
161   print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_BLUE_SIZE",  GDK_GL_ACCUM_BLUE_SIZE,  FALSE);
162   print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_ALPHA_SIZE", GDK_GL_ACCUM_ALPHA_SIZE, FALSE);
163 
164   g_print ("\n");
165 }
166 
167 int
main(int argc,char * argv[])168 main (int argc,
169       char *argv[])
170 {
171   GdkGLConfigMode mode;
172   GdkGLConfig *glconfig;
173   gboolean is_rgba;
174   GdkColormap *colormap;
175   GdkColor color;
176   gboolean success[NUM_COLORS];
177   gint not_allocated;
178   gint major, minor;
179   int i;
180 
181   GtkWidget *window;
182   GtkWidget *vbox;
183   GtkWidget *drawing_area;
184   GtkWidget *button;
185 
186   /*
187    * Init GTK.
188    */
189 
190   gtk_init (&argc, &argv);
191 
192   /*
193    * Init GtkGLExt.
194    */
195 
196   gtk_gl_init (&argc, &argv);
197 
198   /*
199    * Display mode.
200    */
201 
202   mode = GDK_GL_MODE_INDEX;
203 
204   for (i = 0; i < argc; i++)
205     {
206       if (strcmp (argv[i], "--rgb") == 0)
207         mode = GDK_GL_MODE_RGB;
208     }
209 
210   /*
211    * Query OpenGL extension version.
212    */
213 
214   gdk_gl_query_version (&major, &minor);
215   g_print ("\nOpenGL extension version - %d.%d\n",
216            major, minor);
217 
218   /*
219    * Configure OpenGL-capable visual.
220    */
221 
222   /* Try double-buffered visual */
223   glconfig = gdk_gl_config_new_by_mode (mode | GDK_GL_MODE_DOUBLE);
224   if (glconfig == NULL)
225     {
226       g_print ("*** Cannot find the double-buffered visual.\n");
227       g_print ("*** Trying single-buffered visual.\n");
228 
229       /* Try single-buffered visual */
230       glconfig = gdk_gl_config_new_by_mode (mode);
231       if (glconfig == NULL)
232         {
233           g_print ("*** No appropriate OpenGL-capable visual found.\n");
234           exit (1);
235         }
236     }
237 
238   examine_gl_config_attrib (glconfig);
239 
240   is_rgba = gdk_gl_config_is_rgba (glconfig);
241 
242   colormap = gdk_gl_config_get_colormap (glconfig);
243 
244   /*
245    * Top-level window.
246    */
247 
248   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
249   gtk_window_set_title (GTK_WINDOW (window), "color");
250 
251   /* Get automatically redrawn if any of their children changed allocation. */
252   gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
253 
254   g_signal_connect (G_OBJECT (window), "delete_event",
255                     G_CALLBACK (gtk_main_quit), NULL);
256 
257   /*
258    * VBox.
259    */
260 
261   vbox = gtk_vbox_new (FALSE, 0);
262   gtk_container_add (GTK_CONTAINER (window), vbox);
263   gtk_widget_show (vbox);
264 
265   /*
266    * Drawing area for drawing OpenGL scene.
267    */
268 
269   drawing_area = gtk_drawing_area_new ();
270   gtk_widget_set_size_request (drawing_area, 200, 200);
271 
272   /* Set OpenGL-capability to the widget. */
273   gtk_widget_set_gl_capability (drawing_area,
274                                 glconfig,
275                                 NULL,
276                                 TRUE,
277                                 is_rgba ? GDK_GL_RGBA_TYPE : GDK_GL_COLOR_INDEX_TYPE);
278 
279   g_signal_connect (G_OBJECT (drawing_area), "configure_event",
280 		    G_CALLBACK (configure_event), NULL);
281   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
282 		    G_CALLBACK (expose_event), NULL);
283 
284   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
285 
286   gtk_widget_show (drawing_area);
287 
288   /*
289    * Simple quit button.
290    */
291 
292   button = gtk_button_new_with_label ("Quit");
293 
294   g_signal_connect (G_OBJECT (button), "clicked",
295                     G_CALLBACK (gtk_main_quit), NULL);
296 
297   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
298 
299   gtk_widget_show (button);
300 
301   /*
302    * Show window.
303    */
304 
305   gtk_widget_show (window);
306 
307   /*
308    * Allocate colors.
309    */
310 
311   if (!is_rgba)
312     {
313       g_print ("\nAllocate colors.\n");
314 
315       /* Allocate writable color cells. */
316       not_allocated = gdk_colormap_alloc_colors (colormap, colors, NUM_COLORS,
317                                                  FALSE, FALSE, success);
318       g_print ("Not allocated = %d\n", not_allocated);
319 
320       for (i = 0; i < NUM_COLORS; i++)
321         {
322           g_print ("colors[%d] = { %u, 0x%x, 0x%x, 0x%x }\n",
323                    i, colors[i].pixel,
324                    colors[i].red, colors[i].green, colors[i].blue);
325         }
326       g_print ("\n");
327 
328       g_print ("Query colors.\n");
329       for (i = 0; i < NUM_COLORS; i++)
330         {
331           color.pixel = colors[i].pixel;
332           gdk_colormap_query_color (colormap, colors[i].pixel, &color);
333           g_print ("colors[%d] = { %u, 0x%x, 0x%x, 0x%x }\n",
334                    i, colors[i].pixel,
335                    color.red, color.green, color.blue);
336         }
337       g_print ("\n");
338     }
339 
340   /*
341    * Main loop.
342    */
343 
344   gtk_main ();
345 
346   return 0;
347 }
348