1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD 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
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gtk.GLArea;
26 
27 private import gdk.GLContext;
28 private import glib.ConstructionException;
29 private import glib.ErrorG;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gtk.Widget;
33 private import gtk.c.functions;
34 public  import gtk.c.types;
35 public  import gtkc.gtktypes;
36 private import std.algorithm;
37 
38 
39 /**
40  * #GtkGLArea is a widget that allows drawing with OpenGL.
41  * 
42  * #GtkGLArea sets up its own #GdkGLContext for the window it creates, and
43  * creates a custom GL framebuffer that the widget will do GL rendering onto.
44  * It also ensures that this framebuffer is the default GL rendering target
45  * when rendering.
46  * 
47  * In order to draw, you have to connect to the #GtkGLArea::render signal,
48  * or subclass #GtkGLArea and override the @GtkGLAreaClass.render() virtual
49  * function.
50  * 
51  * The #GtkGLArea widget ensures that the #GdkGLContext is associated with
52  * the widget's drawing area, and it is kept updated when the size and
53  * position of the drawing area changes.
54  * 
55  * ## Drawing with GtkGLArea ##
56  * 
57  * The simplest way to draw using OpenGL commands in a #GtkGLArea is to
58  * create a widget instance and connect to the #GtkGLArea::render signal:
59  * 
60  * |[<!-- language="C" -->
61  * // create a GtkGLArea instance
62  * GtkWidget *gl_area = gtk_gl_area_new ();
63  * 
64  * // connect to the "render" signal
65  * g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
66  * ]|
67  * 
68  * The `render()` function will be called when the #GtkGLArea is ready
69  * for you to draw its content:
70  * 
71  * |[<!-- language="C" -->
72  * static gboolean
73  * render (GtkGLArea *area, GdkGLContext *context)
74  * {
75  * // inside this function it's safe to use GL; the given
76  * // #GdkGLContext has been made current to the drawable
77  * // surface used by the #GtkGLArea and the viewport has
78  * // already been set to be the size of the allocation
79  * 
80  * // we can start by clearing the buffer
81  * glClearColor (0, 0, 0, 0);
82  * glClear (GL_COLOR_BUFFER_BIT);
83  * 
84  * // draw your object
85  * draw_an_object ();
86  * 
87  * // we completed our drawing; the draw commands will be
88  * // flushed at the end of the signal emission chain, and
89  * // the buffers will be drawn on the window
90  * return TRUE;
91  * }
92  * ]|
93  * 
94  * If you need to initialize OpenGL state, e.g. buffer objects or
95  * shaders, you should use the #GtkWidget::realize signal; you
96  * can use the #GtkWidget::unrealize signal to clean up. Since the
97  * #GdkGLContext creation and initialization may fail, you will
98  * need to check for errors, using gtk_gl_area_get_error(). An example
99  * of how to safely initialize the GL state is:
100  * 
101  * |[<!-- language="C" -->
102  * static void
103  * on_realize (GtkGLarea *area)
104  * {
105  * // We need to make the context current if we want to
106  * // call GL API
107  * gtk_gl_area_make_current (area);
108  * 
109  * // If there were errors during the initialization or
110  * // when trying to make the context current, this
111  * // function will return a #GError for you to catch
112  * if (gtk_gl_area_get_error (area) != NULL)
113  * return;
114  * 
115  * // You can also use gtk_gl_area_set_error() in order
116  * // to show eventual initialization errors on the
117  * // GtkGLArea widget itself
118  * GError *internal_error = NULL;
119  * init_buffer_objects (&error);
120  * if (error != NULL)
121  * {
122  * gtk_gl_area_set_error (area, error);
123  * g_error_free (error);
124  * return;
125  * }
126  * 
127  * init_shaders (&error);
128  * if (error != NULL)
129  * {
130  * gtk_gl_area_set_error (area, error);
131  * g_error_free (error);
132  * return;
133  * }
134  * }
135  * ]|
136  * 
137  * If you need to change the options for creating the #GdkGLContext
138  * you should use the #GtkGLArea::create-context signal.
139  *
140  * Since: 3.16
141  */
142 public class GLArea : Widget
143 {
144 	/** the main Gtk struct */
145 	protected GtkGLArea* gtkGLArea;
146 
147 	/** Get the main Gtk struct */
148 	public GtkGLArea* getGLAreaStruct(bool transferOwnership = false)
149 	{
150 		if (transferOwnership)
151 			ownedRef = false;
152 		return gtkGLArea;
153 	}
154 
155 	/** the main Gtk struct as a void* */
156 	protected override void* getStruct()
157 	{
158 		return cast(void*)gtkGLArea;
159 	}
160 
161 	/**
162 	 * Sets our main struct and passes it to the parent class.
163 	 */
164 	public this (GtkGLArea* gtkGLArea, bool ownedRef = false)
165 	{
166 		this.gtkGLArea = gtkGLArea;
167 		super(cast(GtkWidget*)gtkGLArea, ownedRef);
168 	}
169 
170 
171 	/** */
172 	public static GType getType()
173 	{
174 		return gtk_gl_area_get_type();
175 	}
176 
177 	/**
178 	 * Creates a new #GtkGLArea widget.
179 	 *
180 	 * Returns: a new #GtkGLArea
181 	 *
182 	 * Since: 3.16
183 	 *
184 	 * Throws: ConstructionException GTK+ fails to create the object.
185 	 */
186 	public this()
187 	{
188 		auto p = gtk_gl_area_new();
189 
190 		if(p is null)
191 		{
192 			throw new ConstructionException("null returned by new");
193 		}
194 
195 		this(cast(GtkGLArea*) p);
196 	}
197 
198 	/**
199 	 * Ensures that the @area framebuffer object is made the current draw
200 	 * and read target, and that all the required buffers for the @area
201 	 * are created and bound to the frambuffer.
202 	 *
203 	 * This function is automatically called before emitting the
204 	 * #GtkGLArea::render signal, and doesn't normally need to be called
205 	 * by application code.
206 	 *
207 	 * Since: 3.16
208 	 */
209 	public void attachBuffers()
210 	{
211 		gtk_gl_area_attach_buffers(gtkGLArea);
212 	}
213 
214 	/**
215 	 * Returns whether the area is in auto render mode or not.
216 	 *
217 	 * Returns: %TRUE if the @area is auto rendering, %FALSE otherwise
218 	 *
219 	 * Since: 3.16
220 	 */
221 	public bool getAutoRender()
222 	{
223 		return gtk_gl_area_get_auto_render(gtkGLArea) != 0;
224 	}
225 
226 	/**
227 	 * Retrieves the #GdkGLContext used by @area.
228 	 *
229 	 * Returns: the #GdkGLContext
230 	 *
231 	 * Since: 3.16
232 	 */
233 	public GLContext getContext()
234 	{
235 		auto p = gtk_gl_area_get_context(gtkGLArea);
236 
237 		if(p is null)
238 		{
239 			return null;
240 		}
241 
242 		return ObjectG.getDObject!(GLContext)(cast(GdkGLContext*) p);
243 	}
244 
245 	/**
246 	 * Gets the current error set on the @area.
247 	 *
248 	 * Returns: the #GError or %NULL
249 	 *
250 	 * Since: 3.16
251 	 */
252 	public ErrorG getError()
253 	{
254 		auto p = gtk_gl_area_get_error(gtkGLArea);
255 
256 		if(p is null)
257 		{
258 			return null;
259 		}
260 
261 		return new ErrorG(cast(GError*) p);
262 	}
263 
264 	/**
265 	 * Returns whether the area has an alpha component.
266 	 *
267 	 * Returns: %TRUE if the @area has an alpha component, %FALSE otherwise
268 	 *
269 	 * Since: 3.16
270 	 */
271 	public bool getHasAlpha()
272 	{
273 		return gtk_gl_area_get_has_alpha(gtkGLArea) != 0;
274 	}
275 
276 	/**
277 	 * Returns whether the area has a depth buffer.
278 	 *
279 	 * Returns: %TRUE if the @area has a depth buffer, %FALSE otherwise
280 	 *
281 	 * Since: 3.16
282 	 */
283 	public bool getHasDepthBuffer()
284 	{
285 		return gtk_gl_area_get_has_depth_buffer(gtkGLArea) != 0;
286 	}
287 
288 	/**
289 	 * Returns whether the area has a stencil buffer.
290 	 *
291 	 * Returns: %TRUE if the @area has a stencil buffer, %FALSE otherwise
292 	 *
293 	 * Since: 3.16
294 	 */
295 	public bool getHasStencilBuffer()
296 	{
297 		return gtk_gl_area_get_has_stencil_buffer(gtkGLArea) != 0;
298 	}
299 
300 	/**
301 	 * Retrieves the required version of OpenGL set
302 	 * using gtk_gl_area_set_required_version().
303 	 *
304 	 * Params:
305 	 *     major = return location for the required major version
306 	 *     minor = return location for the required minor version
307 	 *
308 	 * Since: 3.16
309 	 */
310 	public void getRequiredVersion(out int major, out int minor)
311 	{
312 		gtk_gl_area_get_required_version(gtkGLArea, &major, &minor);
313 	}
314 
315 	/**
316 	 * Retrieves the value set by gtk_gl_area_set_use_es().
317 	 *
318 	 * Returns: %TRUE if the #GtkGLArea should create an OpenGL ES context
319 	 *     and %FALSE otherwise
320 	 *
321 	 * Since: 3.22
322 	 */
323 	public bool getUseEs()
324 	{
325 		return gtk_gl_area_get_use_es(gtkGLArea) != 0;
326 	}
327 
328 	/**
329 	 * Ensures that the #GdkGLContext used by @area is associated with
330 	 * the #GtkGLArea.
331 	 *
332 	 * This function is automatically called before emitting the
333 	 * #GtkGLArea::render signal, and doesn't normally need to be called
334 	 * by application code.
335 	 *
336 	 * Since: 3.16
337 	 */
338 	public void makeCurrent()
339 	{
340 		gtk_gl_area_make_current(gtkGLArea);
341 	}
342 
343 	/**
344 	 * Marks the currently rendered data (if any) as invalid, and queues
345 	 * a redraw of the widget, ensuring that the #GtkGLArea::render signal
346 	 * is emitted during the draw.
347 	 *
348 	 * This is only needed when the gtk_gl_area_set_auto_render() has
349 	 * been called with a %FALSE value. The default behaviour is to
350 	 * emit #GtkGLArea::render on each draw.
351 	 *
352 	 * Since: 3.16
353 	 */
354 	public void queueRender()
355 	{
356 		gtk_gl_area_queue_render(gtkGLArea);
357 	}
358 
359 	/**
360 	 * If @auto_render is %TRUE the #GtkGLArea::render signal will be
361 	 * emitted every time the widget draws. This is the default and is
362 	 * useful if drawing the widget is faster.
363 	 *
364 	 * If @auto_render is %FALSE the data from previous rendering is kept
365 	 * around and will be used for drawing the widget the next time,
366 	 * unless the window is resized. In order to force a rendering
367 	 * gtk_gl_area_queue_render() must be called. This mode is useful when
368 	 * the scene changes seldomly, but takes a long time to redraw.
369 	 *
370 	 * Params:
371 	 *     autoRender = a boolean
372 	 *
373 	 * Since: 3.16
374 	 */
375 	public void setAutoRender(bool autoRender)
376 	{
377 		gtk_gl_area_set_auto_render(gtkGLArea, autoRender);
378 	}
379 
380 	/**
381 	 * Sets an error on the area which will be shown instead of the
382 	 * GL rendering. This is useful in the #GtkGLArea::create-context
383 	 * signal if GL context creation fails.
384 	 *
385 	 * Params:
386 	 *     error = a new #GError, or %NULL to unset the error
387 	 *
388 	 * Since: 3.16
389 	 */
390 	public void setError(ErrorG error)
391 	{
392 		gtk_gl_area_set_error(gtkGLArea, (error is null) ? null : error.getErrorGStruct());
393 	}
394 
395 	/**
396 	 * If @has_alpha is %TRUE the buffer allocated by the widget will have
397 	 * an alpha channel component, and when rendering to the window the
398 	 * result will be composited over whatever is below the widget.
399 	 *
400 	 * If @has_alpha is %FALSE there will be no alpha channel, and the
401 	 * buffer will fully replace anything below the widget.
402 	 *
403 	 * Params:
404 	 *     hasAlpha = %TRUE to add an alpha component
405 	 *
406 	 * Since: 3.16
407 	 */
408 	public void setHasAlpha(bool hasAlpha)
409 	{
410 		gtk_gl_area_set_has_alpha(gtkGLArea, hasAlpha);
411 	}
412 
413 	/**
414 	 * If @has_depth_buffer is %TRUE the widget will allocate and
415 	 * enable a depth buffer for the target framebuffer. Otherwise
416 	 * there will be none.
417 	 *
418 	 * Params:
419 	 *     hasDepthBuffer = %TRUE to add a depth buffer
420 	 *
421 	 * Since: 3.16
422 	 */
423 	public void setHasDepthBuffer(bool hasDepthBuffer)
424 	{
425 		gtk_gl_area_set_has_depth_buffer(gtkGLArea, hasDepthBuffer);
426 	}
427 
428 	/**
429 	 * If @has_stencil_buffer is %TRUE the widget will allocate and
430 	 * enable a stencil buffer for the target framebuffer. Otherwise
431 	 * there will be none.
432 	 *
433 	 * Params:
434 	 *     hasStencilBuffer = %TRUE to add a stencil buffer
435 	 *
436 	 * Since: 3.16
437 	 */
438 	public void setHasStencilBuffer(bool hasStencilBuffer)
439 	{
440 		gtk_gl_area_set_has_stencil_buffer(gtkGLArea, hasStencilBuffer);
441 	}
442 
443 	/**
444 	 * Sets the required version of OpenGL to be used when creating the context
445 	 * for the widget.
446 	 *
447 	 * This function must be called before the area has been realized.
448 	 *
449 	 * Params:
450 	 *     major = the major version
451 	 *     minor = the minor version
452 	 *
453 	 * Since: 3.16
454 	 */
455 	public void setRequiredVersion(int major, int minor)
456 	{
457 		gtk_gl_area_set_required_version(gtkGLArea, major, minor);
458 	}
459 
460 	/**
461 	 * Sets whether the @area should create an OpenGL or an OpenGL ES context.
462 	 *
463 	 * You should check the capabilities of the #GdkGLContext before drawing
464 	 * with either API.
465 	 *
466 	 * Params:
467 	 *     useEs = whether to use OpenGL or OpenGL ES
468 	 *
469 	 * Since: 3.22
470 	 */
471 	public void setUseEs(bool useEs)
472 	{
473 		gtk_gl_area_set_use_es(gtkGLArea, useEs);
474 	}
475 
476 	/**
477 	 * The ::create-context signal is emitted when the widget is being
478 	 * realized, and allows you to override how the GL context is
479 	 * created. This is useful when you want to reuse an existing GL
480 	 * context, or if you want to try creating different kinds of GL
481 	 * options.
482 	 *
483 	 * If context creation fails then the signal handler can use
484 	 * gtk_gl_area_set_error() to register a more detailed error
485 	 * of how the construction failed.
486 	 *
487 	 * Returns: a newly created #GdkGLContext;
488 	 *     the #GtkGLArea widget will take ownership of the returned value.
489 	 *
490 	 * Since: 3.16
491 	 */
492 	gulong addOnCreateContext(GLContext delegate(GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
493 	{
494 		return Signals.connect(this, "create-context", dlg, connectFlags ^ ConnectFlags.SWAPPED);
495 	}
496 
497 	/**
498 	 * The ::render signal is emitted every time the contents
499 	 * of the #GtkGLArea should be redrawn.
500 	 *
501 	 * The @context is bound to the @area prior to emitting this function,
502 	 * and the buffers are painted to the window once the emission terminates.
503 	 *
504 	 * Params:
505 	 *     context = the #GdkGLContext used by @area
506 	 *
507 	 * Returns: %TRUE to stop other handlers from being invoked for the event.
508 	 *     %FALSE to propagate the event further.
509 	 *
510 	 * Since: 3.16
511 	 */
512 	gulong addOnRender(bool delegate(GLContext, GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
513 	{
514 		return Signals.connect(this, "render", dlg, connectFlags ^ ConnectFlags.SWAPPED);
515 	}
516 
517 	/**
518 	 * The ::resize signal is emitted once when the widget is realized, and
519 	 * then each time the widget is changed while realized. This is useful
520 	 * in order to keep GL state up to date with the widget size, like for
521 	 * instance camera properties which may depend on the width/height ratio.
522 	 *
523 	 * The GL context for the area is guaranteed to be current when this signal
524 	 * is emitted.
525 	 *
526 	 * The default handler sets up the GL viewport.
527 	 *
528 	 * Params:
529 	 *     width = the width of the viewport
530 	 *     height = the height of the viewport
531 	 *
532 	 * Since: 3.16
533 	 */
534 	gulong addOnResize(void delegate(int, int, GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
535 	{
536 		return Signals.connect(this, "resize", dlg, connectFlags ^ ConnectFlags.SWAPPED);
537 	}
538 }