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