1 /*
2  * Copyright (C) 2001-2015, AdaCore
3  * Copyright (C) 1997-1998 Janne L�f <jlof@mail.student.oulu.fi>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 #include <stdarg.h>
21 
22 #include "gdkgl.h"
23 #include "gtkglarea.h"
24 
25 static void gtk_gl_area_class_init    (GtkGLAreaClass *klass);
26 static void gtk_gl_area_init          (GtkGLArea      *glarea);
27 static void gtk_gl_area_destroy       (GObject      *object); /* change to finalize? */
28 
29 static GtkDrawingAreaClass *parent_class = NULL;
30 
31 
32 GType
gtk_gl_area_get_type(void)33 gtk_gl_area_get_type (void)
34 {
35   static GType object_type = 0;
36 
37   if (!object_type)
38     {
39       static const GTypeInfo object_info =
40       {
41         sizeof (GtkGLAreaClass),
42         (GBaseInitFunc) NULL,
43         (GBaseFinalizeFunc) NULL,
44         (GClassInitFunc) gtk_gl_area_class_init,
45         NULL,           /* class_finalize */
46         NULL,           /* class_data */
47         sizeof (GtkGLArea),
48         0,              /* n_preallocs */
49         (GInstanceInitFunc) gtk_gl_area_init,
50       };
51 
52       object_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
53                                             "GtkGLArea",
54                                             &object_info, 0);
55     }
56   return object_type;
57 }
58 
59 static void
gtk_gl_area_class_init(GtkGLAreaClass * klass)60 gtk_gl_area_class_init (GtkGLAreaClass *klass)
61 {
62   GObjectClass *object_class;
63 
64   parent_class = g_type_class_peek_parent(klass);
65   object_class = (GObjectClass*) klass;
66 
67   object_class->finalize = gtk_gl_area_destroy;
68 }
69 
70 
71 static void
gtk_gl_area_init(GtkGLArea * gl_area)72 gtk_gl_area_init (GtkGLArea *gl_area)
73 {
74   gl_area->glcontext = NULL;
75   gtk_widget_set_double_buffered(GTK_WIDGET(gl_area), FALSE);
76 }
77 
78 
79 
80 GtkWidget*
gtk_gl_area_new_vargs(GtkGLArea * share,...)81 gtk_gl_area_new_vargs(GtkGLArea *share, ...)
82 {
83   GtkWidget *glarea;
84   va_list ap;
85   int i;
86   gint *attrlist;
87 
88   va_start(ap, share);
89   i=1;
90   while (va_arg(ap, int) != GDK_GL_NONE) /* get number of arguments */
91     i++;
92   va_end(ap);
93 
94   attrlist = g_new(int,i);
95 
96   va_start(ap,share);
97   i=0;
98   while ( (attrlist[i] = va_arg(ap, int)) != GDK_GL_NONE) /* copy args to list */
99     i++;
100   va_end(ap);
101 
102   glarea = gtk_gl_area_share_new(attrlist, share);
103 
104   g_free(attrlist);
105 
106   return glarea;
107 }
108 
109 GtkWidget*
gtk_gl_area_new(int * attrlist)110 gtk_gl_area_new (int *attrlist)
111 {
112   return gtk_gl_area_share_new(attrlist, NULL);
113 }
114 
115 GtkWidget*
gtk_gl_area_share_new(int * attrlist,GtkGLArea * share)116 gtk_gl_area_share_new (int *attrlist, GtkGLArea *share)
117 {
118   GdkGLContext *glcontext;
119   GtkGLArea *gl_area;
120 #if defined GDK_WINDOWING_X11
121   GdkVisual *visual;
122 #endif
123 
124   g_return_val_if_fail(share == NULL || GTK_IS_GL_AREA(share), NULL);
125 
126 #if defined GDK_WINDOWING_X11
127   visual = gdk_gl_choose_visual(attrlist);
128   if (visual == NULL)
129     return NULL;
130 
131   glcontext = gdk_gl_context_share_new(visual, share ? share->glcontext : NULL, TRUE);
132 #else
133   glcontext = gdk_gl_context_attrlist_share_new(attrlist, share ? share->glcontext : NULL, TRUE);
134 #endif
135   if (glcontext == NULL)
136     return NULL;
137 
138 #if defined GDK_WINDOWING_X11
139   /* use colormap and visual suitable for OpenGL rendering */
140   // gtk_widget_push_colormap(gdk_colormap_new(visual,TRUE));
141   // gtk_widget_push_visual(visual);
142 #endif
143 
144   gl_area = g_object_new(GTK_TYPE_GL_AREA, NULL);
145   gl_area->glcontext = glcontext;
146 
147 #if defined GDK_WINDOWING_X11
148   /* pop back defaults */
149   // gtk_widget_pop_visual();
150   // gtk_widget_pop_colormap();
151 #endif
152 
153   return GTK_WIDGET(gl_area);
154 }
155 
156 
157 static void
gtk_gl_area_destroy(GObject * object)158 gtk_gl_area_destroy(GObject *object)
159 {
160   GtkGLArea *gl_area;
161 
162   g_return_if_fail (object != NULL);
163   g_return_if_fail (GTK_IS_GL_AREA(object));
164 
165   gl_area = GTK_GL_AREA(object);
166 
167   if (gl_area->glcontext)
168     g_object_unref(gl_area->glcontext);
169   gl_area->glcontext = NULL;
170 
171   if (G_OBJECT_GET_CLASS (parent_class)->finalize)
172     (* G_OBJECT_GET_CLASS (parent_class)->finalize) (object);
173 }
174 
175 
gtk_gl_area_make_current(GtkGLArea * gl_area)176 gint gtk_gl_area_make_current(GtkGLArea *gl_area)
177 {
178   g_return_val_if_fail(gl_area != NULL, FALSE);
179   g_return_val_if_fail(GTK_IS_GL_AREA (gl_area), FALSE);
180   // g_return_val_if_fail(GTK_WIDGET_REALIZED(gl_area), FALSE);
181 
182   return gdk_gl_make_current(gtk_widget_get_window(GTK_WIDGET(gl_area)), gl_area->glcontext);
183 }
184 
gtk_gl_area_swap_buffers(GtkGLArea * gl_area)185 void gtk_gl_area_swap_buffers(GtkGLArea *gl_area)
186 {
187   g_return_if_fail(gl_area != NULL);
188   g_return_if_fail(GTK_IS_GL_AREA(gl_area));
189   // g_return_if_fail(GTK_WIDGET_REALIZED(gl_area));
190 
191   gdk_gl_swap_buffers(gtk_widget_get_window (GTK_WIDGET (gl_area)));
192 }
193