1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3  * Copyright (C) 2010 Emweb bv, Herent, Belgium.
4  *
5  * See the LICENSE file for terms of use.
6  */
7 #ifndef WGLWIDGET_H_
8 #define WGLWIDGET_H_
9 
10 #include <Wt/WException.h>
11 #include <Wt/WInteractWidget.h>
12 #include <Wt/WJavaScriptSlot.h>
13 #include <Wt/WGenericMatrix.h>
14 #include <Wt/WMatrix4x4.h>
15 
16 #ifndef WT_TARGET_JAVA
17 namespace Wt {
18 typedef std::vector<float> FloatBuffer;
19 typedef std::vector<int> IntBuffer;
20 }
21 #else
22 #include <java/buffer>
23 #endif
24 
25 namespace Wt {
26 
27 // define to enable WebGL debug code
28 #define WT_WGLWIDGET_DEBUG
29 
30 #ifdef WT_TARGET_JAVA
31 #define __FUNCTION__ "(unknown)"
32 #endif
33 
34 #ifdef WT_WGLWIDGET_DEBUG
35 #define GLDEBUG do {if (debugging_) {js_ << "\n{var err = ctx.getError(); if(err != ctx.NO_ERROR && err != ctx.CONTEXT_LOST_WEBGL) {alert('error " << __FUNCTION__ << ": ' + err); debugger;}}\n";}} while(false)
36   //if (glGetError() != GL_NO_ERROR){}
37 #define SERVERGLDEBUG do {if (debugging_) {int err = glGetError(); if (err != GL_NO_ERROR){std::cerr << "gl error occured in " << __FUNCTION__ << ": " << err << std::endl;}} } while(false)
38 //#define GLDEBUG do {js_ << "\n{var err = ctx.getError(); if(err != ctx.NO_ERROR) {debugger;}}\n";} while(false)
39 #else
40 #define GLDEBUG
41 #endif
42 
43 class WAbstractGLImplementation;
44 class WPaintDevice;
45 
46 #if !defined(WT_TARGET_JAVA)
47 #define WT_WGL_TEMPLATE(...) template < __VA_ARGS__ >
48 #else
49 #define WT_WGL_TEMPLATE(...)
50 #endif
51 
52 class WHTML5Video;
53 class WImage;
54 
55 enum class JsArrayType {
56   Array,
57   Float32Array
58 };
59 
60 /*! \brief Enumeration for render options
61  *
62  * \sa setRenderOptions()
63  */
64 enum class GLRenderOption {
65   ClientSide = 0x1,   //!< Enables client-side rendering
66   ServerSide = 0x2,   //!< Enables server-side rendering
67   AntiAliasing = 0x4  //!< Enables anti-aliasing
68 };
69 
70 /*! \brief Specifies what GL function needs to be updated
71  */
72 enum class GLClientSideRenderer {
73   PAINT_GL = 0x1,  //!< refresh paintGL()
74   RESIZE_GL = 0x2, //!< refresh resizeGL()
75   UPDATE_GL = 0x4  //!< refresh updateGL()
76 };
77 
78 /*! \class WGLWidget Wt/WGLWidget.h Wt/WGLWidget.h
79  *  \brief GL support class
80  *
81  * The WGLWidget class is an interface to the HTML5 WebGL infrastructure
82  * for client-side rendering, and OpenGL for server-side rendering.
83  * Its API is based on the WebGL API. To fully understand WebGL, it is
84  * recommended to read the WebGL standard in addition to this documentation.
85  *
86  * The most recent version of the WebGL specification can be found here:
87  * http://www.khronos.org/registry/webgl/specs/latest/1.0/
88  *
89  * The goal of the WGLWidget class is to provide a method to render 3D
90  * structures in the browser, where rendering and rerendering is normally
91  * done at the client side in JavaScript without interaction from the server,
92  * in order to obtain a smooth user interaction. Unless the scene requires
93  * server-side updates, there is no communication with the server.
94  *
95  * The rendering interface resembles to OpenGL ES, the same standard as
96  * WebGL is based on. This is a stripped down version of the normal OpenGL
97  * as we usually find them on desktops. Many stateful OpenGL features are
98  * not present in OpenGL ES: no modelview and camera transformation stacks,
99  * no default lighting models, no support for other rendering methods than
100  * through VBOs, ... Therefore much existing example code for OpenGL
101  * applications and shaders will not work on WebGL without modifications.
102  * The 'learning webgl' web site at http://learningwebgl.com/ is a good
103  * starting point to get familiar with WebGL.
104  *
105  * To use a %WGLWidget, you must derive from it and reimplement
106  * the painter methods. Usually, you will always need to implement
107  * initializeGL() and paintGL(). Optionally, you may choose to implement
108  * resizeGL() (if your widget does not have a fixed size), and updateGL().
109  * If you need to modify the painting methods, a repaint is triggered by
110  * calling the repaintGL() method. The default behaviour for any of these
111  * four painting functions is to do nothing.
112  *
113  * The four painter methods (initializeGL(), resizeGL(), paintGL() and
114  * updateGL()) all record JavaScript which is sent to the
115  * browser. The JavaScript code of paintGL() is cached client-side, and
116  * may be executed many times, e.g. to repaint a scene from different
117  * viewpoints. The JavaScript code of initializeGL(), resizeGL() and
118  * updateGL() are intended for OpenGL state updates, and is therefore
119  * only executed once on the client and is then discarded.
120  *
121  * There are four painting methods that you may implement in a
122  * specialization of this class. The purpose of these functions is
123  * to register what JavaScript code has to be executed to render a
124  * scene. Through invocations of the WebGL functions documented below,
125  * %Wt records the JavaScript calls that have to be invoked in the
126  * browser.
127  * <ul>
128  * <li><b>initializeGL()</b>: this function is executed after the GL
129  *     context has been initialized. It is also executed when the
130  *     \c webglcontextrestored signal is fired. You can distinguish between
131  *     the first initialization and restoration of context using restoringContext().
132  *     This is the ideal location to compose shader programs, send VBO's to
133  *     the client, extract uniform and attribute locations, ... Due to
134  *     the presence of VBO's, this function may generate a large amount
135  *     of data to the client.
136  * <li><b>resizeGL()</b>: this function is executed whenever the canvas
137  *     dimensions change. A change in canvas size will require you to
138  *     invoke the viewport() function again, as well as recalculate the
139  *     projection matrices (especially when the aspect ratio has changed).
140  *     The resizeGL() function is therefore the ideal location to set those
141  *     properties.
142  *     The resizeGL() function is invoked automatically on every resize,
143  *     and after the first initializeGL() invocation. Additional invocations
144  *     may be triggered by calling repaint() with the RESIZE_GL flag.
145  * <li><b>paintGL()</b>: this is the main scene drawing function. Through
146  *     its execution, %Wt records what has to be done to render a scene,
147  *     and it is executed every time that the scene is to be redrawn. You
148  *     can use the VBO's and shaders prepared in the initializeGL() phase.
149  *     Usually, this function sets uniforms and attributes, links
150  *     attributes to VBO's, applies textures, and draws primitives.
151  *     You may also create local programs, buffers, ... Remember that this
152  *     function is executed a lot of times, so every buffer/program created
153  *     in this function should also be destroyed to avoid memory leaks.
154  *     This function is transmitted once to the client, and is executed
155  *     when the scene needs to be redrawn. Redraws may be triggered from
156  *     mouse events, timer triggers, events on e.g. a video element, or
157  *     whatever other event.
158  *     The paintGL() function can be updated through invoking repaintGL()
159  *     with the PAINT_GL flag.
160  * <li><b>updateGL()</b>: VBO's, programs, uniforms, GL properties,
161  *     or anything else set during intializeGL() are not necessarily
162  *     immutable. If you want to change, add, remove or reconfigure those
163  *     properties, the execution of an updateGL() function can be triggered
164  *     by invoking repaintGL() with the UPDATE_GL flag. This signals that
165  *     updateGL() needs to be evaluated - just once. It is possible that
166  *     the paintGL() function also requires updates as consequence of the
167  *     changes in the updateGL() function; in this case, you should also set
168  *     the PAINT_GL flag of repaintGL().
169  * </ul>
170  *
171  * The GL functions are intended to be used exclusively from within the
172  * invocation of the four callback functions mentioned above. In order to
173  * manually trigger the execution of these function, use the repaintGL().
174  *
175  * A WGLWidget must be given a size explicitly, or must be put inside a
176  * layout manager that manages its width and height. The behaviour of a
177  * WGLWidget that was not given a size is undefined.
178  *
179  * <h3>Binary buffer transfers</h3>
180  *
181  * In bufferDatafv(), there is an additional boolean argument where you
182  * can indicate that you want the data to be transferred to the client in
183  * binary form. A WMemoryResource is created for each of these buffers. If
184  * you know all previous resources are not required in the client anymore,
185  * you can free memory with the method clearBinaryResources() (the memory
186  * is also managed, so this is not neccesary). If you want to manage these
187  * resources entirely by yourself, the following method can be used.
188  *
189  * Using createAndLoadArrayBuffer(), you can load an array buffer in
190  * binary format from an URL. This will cause the client to fetch the
191  * given URL, and make the contents of the file available in an
192  * ArrayBuffer, which can then be used by BufferData() to bind them
193  * to an OpenGL buffer. This is ideal to load VBO buffers in a faster
194  * way, as it avoids converting floats to text strings on the server
195  * and then back to floats on the client. You can combine this with
196  * the use of WResource (e.g. WMemoryResource) to send an std::vector of
197  * vertices to the client. Note that using ArrayBuffer is not possible when
198  * you want a fall-back in the form of server-side rendering.
199  *
200  * <h3>Client side matrices and vectors.</h3>
201  *
202  * The WGLWidget provides the WGLWidget::JavaScriptMatrix4x4 class as
203  * a mechanism to use client-side modifiable matrices in the render
204  * functions. These matrices can be used identically to the
205  * 'constant', with the advantage that there is no need to have a
206  * roundtrip to the server to redraw the scene when they are changed.
207  * As such, they are ideal for mouse-based camera manipulations, timer
208  * triggered animations, or object manipulations.
209  *
210  * There's also support for client-side modifiable vectors, with
211  * WGLWidget::JavaScriptVector.
212  */
213 class WT_API WGLWidget: public WInteractWidget
214 {
215 #ifdef WT_TARGET_JAVA
216   typedef float FloatArray;
217   typedef int IntArray;
218   typedef double MatrixType;
219 #endif
220 
221 public:
222   /*! \brief Typedef for enum Wt::GLRenderOption */
223   typedef GLRenderOption RenderOption;
224   /*! \brief Typedef for enum Wt::GLClientSideRenderer */
225   typedef GLClientSideRenderer ClientSideRenderer;
226 
227 
228   //! Abstract base class for all GL objects
229   class WT_API GlObject {
230   public:
GlObject()231     GlObject(): id_(-1) {}
GlObject(int id)232     GlObject(int id) :
233       id_(id) {}
~GlObject()234     virtual ~GlObject() {}
235 
236     virtual std::string jsRef() const = 0;
237 
getId()238     int getId() const { return id_; }
239 
clear()240     void clear() { id_ = -1; }
241 
isNull()242     bool isNull() const { return id_ == -1; }
243 
244   private:
245     int id_;
246   };
247 
248   //!  Reference to a WebGLShader class
249   class WT_API Shader : public GlObject {
250   public:
Shader()251     Shader() {}
252 
Shader(int i)253     explicit Shader(int i) :
254       GlObject(i) {}
255 
jsRef()256     virtual std::string jsRef() const override
257     {
258       if (isNull())
259 	throw WException("Shader: is null");
260       return std::string("ctx.WtShader") + std::to_string(getId());
261     }
262   };
263 
264   //! Reference to a WebGLProgram class
265   class WT_API Program : public GlObject {
266   public:
Program()267     Program() {}
Program(int i)268     explicit Program(int i) :
269       GlObject(i) {}
270 
jsRef()271     virtual std::string jsRef() const override
272     {
273       if (isNull())
274 	throw WException("Program: is null");
275       return std::string("ctx.WtProgram") + std::to_string(getId());
276     }
277   };
278 
279   //! Reference to a shader attribute location
280   class WT_API AttribLocation : public GlObject {
281   public:
AttribLocation()282     AttribLocation() {}
AttribLocation(int i)283     explicit AttribLocation(int i) :
284       GlObject(i) {}
285 
jsRef()286     virtual std::string jsRef() const override
287     {
288       if (isNull())
289 	throw WException("AttribLocation: is null");
290       return std::string("ctx.WtAttrib") + std::to_string(getId());
291     }
292   };
293 
294   //! Reference to a WebGLBuffer class
295   class WT_API Buffer : public GlObject {
296   public:
Buffer()297     Buffer() {}
Buffer(int i)298     explicit Buffer(int i) :
299       GlObject(i) {}
300 
jsRef()301     virtual std::string jsRef() const override
302     {
303       if (isNull())
304 	throw WException("Buffer: is null");
305       return std::string("ctx.WtBuffer") + std::to_string(getId());
306     }
307   };
308 
309   //! Reference to a WebGLUniformLocation class
310   class WT_API UniformLocation : public GlObject {
311   public:
UniformLocation()312     UniformLocation() {}
UniformLocation(int i)313     explicit UniformLocation(int i) :
314       GlObject(i) {}
315 
jsRef()316     virtual std::string jsRef() const override
317     {
318       if (isNull())
319 	throw WException("UniformLocation: is null");
320       return std::string("ctx.WtUniform") + std::to_string(getId());
321     }
322   };
323 
324   //! Reference to a WebGLTexture class
325   class WT_API Texture: public GlObject {
326   public:
Texture()327     Texture()
328       : url_("")
329       {}
Texture(int i)330     explicit Texture(int i) :
331       GlObject(i) {}
332 
jsRef()333     virtual std::string jsRef() const override
334     {
335       if (isNull()) {
336 	// throw WException("Texture: is null");
337 	return "null";
338       }
339       return std::string("ctx.WtTexture") + std::to_string(getId());
340     }
341 
setUrl(std::string url)342     void setUrl(std::string url) {
343       url_ = url;
344     }
345 
url()346     const std::string& url() const {
347       return url_;
348     }
349 
350   private:
351     std::string url_;
352   };
353 
354   //! Reference to a WebGLFramebuffer class
355   class WT_API Framebuffer : public GlObject {
356   public:
Framebuffer()357     Framebuffer() {}
Framebuffer(int i)358     Framebuffer(int i) :
359       GlObject(i) {}
360 
jsRef()361     virtual std::string jsRef() const override
362     {
363       if (isNull()) {
364 	//throw WException("FrameBuffer: is null");
365 	return "null";
366       }
367       return "ctx.WtFramebuffer" + std::to_string(getId());
368     }
369   };
370 
371   //! Reference to a WebGLRenderbuffer class
372   class WT_API Renderbuffer : public GlObject {
373   public:
Renderbuffer()374     Renderbuffer() {}
Renderbuffer(int i)375     Renderbuffer(int i) :
376       GlObject(i) {}
377 
jsRef()378     virtual std::string jsRef() const override
379     {
380       if (isNull()) {
381 	//throw WException("RenderBuffer: is null");
382 	return "null";
383       }
384       return "ctx.WtRenderbuffer" + std::to_string(getId());
385     }
386   };
387 
388   /*!
389    * \brief Reference to a javascript %ArrayBuffer class
390    */
391   class WT_API ArrayBuffer : public GlObject {
392   public:
ArrayBuffer()393     ArrayBuffer() {}
ArrayBuffer(int i)394     ArrayBuffer(int i) :
395       GlObject(i) {}
396 
jsRef()397     virtual std::string jsRef() const override
398     {
399       if (isNull())
400 	throw WException("ArrayBuffer: is null");
401       return "ctx.WtBufferResource" + std::to_string(getId());
402     }
403   };
404 
405   /*! \brief A client-side JavaScript vector
406    *
407    * Using a JavaScriptVector, GL parameters can be modified without
408    * communication with the server. The value of the JavaScriptMatrix4x4
409    * is updated server-side whenever an event is sent to the server.
410    *
411    * The JavaScriptVector is represented in JavaScript as an array, either
412    * as a Float32Array or as a plain JavaScript array.
413    */
414   class WT_API JavaScriptVector {
415   public:
416     /** \brief Create a temporarily invalid JavaScriptVector.
417      *
418      *  Should be added to a %WGLWidget with
419      *  WGLWidget::addJavaScriptVector(), and initialized with
420      *  WGLWidget::initJavaScriptVector().
421      */
422     JavaScriptVector(unsigned length);
423 
424 #ifndef WT_TARGET_JAVA
425     JavaScriptVector(const JavaScriptVector &other);
426 
427     JavaScriptVector &operator=(const JavaScriptVector &rhs);
428 #endif
429 
id()430     int id() const { return id_; }
431 
432     /** \brief Returns whether this %JavaScriptVector has been initialized.
433      */
initialized()434     bool initialized() const { return initialized_; }
435 
436     /** \brief Returns whether this %JavaScriptVector has been assigned
437      *         to a WGLWidget.
438      */
hasContext()439     bool hasContext() const { return context_ != nullptr; }
440 
441     /** \brief Returns the length (number of items) of this JavaScriptVector.
442      */
length()443     unsigned length() const { return length_; }
444 
445     /** \brief Returns the JavaScript reference to this JavaScriptVector.
446      *
447      * In order to get a valid JavaScript reference, this vector
448      * should have been added to a WGLWidget.
449      */
jsRef()450     std::string jsRef() const
451     {
452       if (!hasContext())
453 	throw WException("JavaScriptVector: does not belong to a "
454 			 "WGLWidget yet");
455       return jsRef_;
456     }
457 
458     /** \brief Returns the current server-side value.
459      *
460      * Client-side changes to the JavaScriptVector are automatically
461      * synchronized.
462      */
463     std::vector<float> value() const;
464 
465 #ifdef WT_TARGET_JAVA
466     JavaScriptVector clone() const;
467 #endif
468   private:
469     void assignToContext(int id, const WGLWidget* context);
initialize()470     void initialize() { initialized_ = true; }
471     int id_;
472     unsigned length_;
473     std::string jsRef_;
474     const WGLWidget* context_;
475     bool initialized_;
476 
477     friend class WGLWidget;
478     friend class WServerGLWidget;
479     friend class WClientGLWidget;
480   };
481 
482   /*! \brief A client-side JavaScript matrix
483    *
484    * A JavaScriptMatrix has methods that make it possible to do client-side
485    * calculations on matrices.
486    *
487    * Using a JavaScriptMatrix4x4, GL parameters can be modified without
488    * communication with the server. The value of the JavaScriptMatrix4x4
489    * is updated server-side whenever an event is sent to the server.
490    *
491    * Important: only the jsRef() of the return value from a call to
492    * WGLWidget::createJavaScriptMatrix() is a variable name that can be used
493    * in custom JavaScript to modify a matrix from external scripts.
494    * The jsRef() of return values of operations refer to unnamed temporary
495    * objects - rvalues in C++-lingo.
496    *
497    * The JavaScriptMatrix4x4 is represented in JavaScript as an array of 16
498    * elements. This array represents the values of the matrix in column-major
499    * order. It is either a Float32Array or a plain JavaScript array.
500    */
501   class WT_API JavaScriptMatrix4x4 {
502   public:
503     /** \brief Creates a temporarily invalid JavaScriptMatrix4x4.
504      *
505      *  Should be added to a %WGLWidget with
506      *  WGLWidget::addJavaScriptMatrix4, and initialized with
507      *  WGLWidget::initJavaScriptMatrix4.
508      */
509     JavaScriptMatrix4x4();
510 
511 #ifndef WT_TARGET_JAVA
512     JavaScriptMatrix4x4(const JavaScriptMatrix4x4 &other);
513 
514     JavaScriptMatrix4x4 &operator=(const JavaScriptMatrix4x4 &rhs);
515 #endif
516 
id()517     int id() const { return id_; }
518 
519     /** \brief Returns whether this JavaScriptMatrix4x4 has been initialized.
520      */
initialized()521     bool initialized() const { return initialized_; }
522 
523     /** \brief Returns whether this JavaScriptMatrix4x4 has been assigned
524      *         to a WGLWidget.
525      */
hasContext()526     bool hasContext() const { return context_ != nullptr; }
527 
528     /** \brief Returns the JavaScript reference to this JavaScriptMatrix4x4.
529      *
530      * In order to get a valid JavaScript reference, this matrix should
531      * have been added to a WGLWidget.
532      */
jsRef()533     std::string jsRef() const
534     {
535       if (!hasContext())
536 	throw WException("JavaScriptMatrix4x4: does not belong to a WGLWidget yet");
537       return jsRef_;
538     }
539 
540     /** \brief Returns the current server-side value.
541      *
542      * Client-side changes to the JavaScriptMatrix4x4 are automatically
543      * synchronized.
544      */
545     WMatrix4x4 value() const;
546 
547     JavaScriptMatrix4x4 inverted() const;
548     JavaScriptMatrix4x4 transposed() const;
549 
550 #if !defined(WT_TARGET_JAVA)
551     JavaScriptMatrix4x4 operator*(const WGenericMatrix<double, 4, 4> &m) const;
552 #else
553     JavaScriptMatrix4x4 multiply(const WGenericMatrix<MatrixType, 4, 4> &m) const;
554 #endif
555 
556 #ifdef WT_TARGET_JAVA
557     JavaScriptMatrix4x4 clone() const;
558 #endif
559 
560   private:
561     void assignToContext(int i, const WGLWidget* context);
initialize()562     void initialize() { initialized_ = true; }
hasOperations()563     bool hasOperations() const { return operations_.size() > 0;}
564 
565     // void invert();
566     // void transpose();
567     // void mul(const WGenericMatrix<double, 4, 4> &m);
568 
569     int id_;
570     std::string jsRef_;
571     const WGLWidget* context_;
572 
573     enum class op {TRANSPOSE, INVERT, MULTIPLY};
574     std::vector<op> operations_;
575     std::vector< WGenericMatrix<double, 4, 4> > matrices_;
576 
577     bool initialized_;
578 
579     friend class WGLWidget;
580     friend class WServerGLWidget;
581     friend class WClientGLWidget;
582   };
583 
584   /*! \brief Construct a GL widget.
585    *
586    * Before the first rendering, you must apply a size to the WGLWidget.
587    */
588   WGLWidget();
589 
590   /*! \brief Destructor
591    */
592   ~WGLWidget();
593 
594   /*! \brief Sets the rendering option.
595    *
596    * Use this method to configure whether client-side and/or
597    * server-side rendering can be used, and whether anti-aliasing
598    * should be enabled. The actual choice is also based
599    * on availability (respectively client-side or server-side).
600    *
601    * The default value is to try both ClientSide or ServerSide rendering,
602    * and to enable anti-aliasing if available.
603    *
604    * \note Options must be set before the widget is being rendered.
605    */
606   void setRenderOptions(WFlags<GLRenderOption> options);
607 
608 protected:
609 
610   /*! \brief Initialize the GL state when the widget is first shown.
611    *
612    * initializeGL() is called when the widget is first rendered, and
613    * when the webglcontextrestored signal is fired. You can distinguish
614    * between the first initialization and context restoration using
615    * restoringContext().
616    * It usually creates most of the GL related state: shaders, VBOs,
617    * uniform locations, ...
618    *
619    * If this state is to be updated during the lifetime of the widget,
620    * you should specialize the updateGL() to accomodate for this.
621    */
622   virtual void initializeGL();
623 
624   /*! \brief Act on resize events
625    *
626    * Usually, this method only contains functions to set the viewport
627    * and the projection matrix (as this is aspect ration dependent).
628    *
629    * resizeGL() is rendered after initializeGL, and whenever widget is
630    * resized. After this method finishes, the widget is repainted with
631    * the cached client-side paint function.
632    */
633   virtual void resizeGL(int width, int height);
634 
635   /*! \brief Update the client-side painting function.
636    *
637    * This method is invoked client-side when a repaint is required,
638    * i.e. when the repaintSlot() (a JavaScript-side JSlot) is triggered.
639    * Typical examples are: after mouse-based camera movements, after
640    * a timed update of a camera or an object's position, after
641    * a resize event (resizeGL() will also be called then), after
642    * an animation event, ... In many cases, this function will be
643    * executed client-side many many times.
644    *
645    * Using the GL functions from this class, you construct a scene.
646    * The implementation tracks all JavaScript calls that need to be
647    * performed to draw the scenes, and will replay them verbatim on
648    * every trigger of the repaintSlot(). There are a few mechanisms
649    * that may be employed to change what is rendered without updating
650    * the paintGL() cache:
651    * <ul>
652    * <li>Client-side matrices may be used to change camera viewpoints,
653    *     manipilate separate object's model transformation matrices, ...
654    *     </li>
655    * <li>Shader sources can be updated without requiring the paint
656    *     function to be renewed</li>
657    * </ul>
658    *
659    * Updating the paintGL() cache is usually not too expensive; the VBOs,
660    * which are large in many cases, are already at the client side, while
661    * the paintGL() code only draws the VBOs. Of course, if you have to
662    * draw many separate objects, the paintGL() JS code may become large
663    * and updating is more expensive.
664    *
665    * In order to update the paintGL() cache, call repaintGL() with
666    * the PAINT_GL parameter, which will cause the invocation of this
667    * method.
668    */
669   virtual void paintGL();
670 
671   /*! \brief Update state set in initializeGL()
672    *
673    * Invoked when repaint is called with the UPDATE_GL call.
674    *
675    * This is intended to be executed when you want to change programs,
676    * 'constant' uniforms, or even VBO's, ... without resending already
677    * initialized data. It is a mechanism to make changes to what you've
678    * set in intializeGL(). For every server-side invocation of this method,
679    * the result will be rendered client-side exactly once.
680    */
681   virtual void updateGL();
682 
683 public:
684 
685   /*! \brief Request invocation of resizeGL, paintGL and/or updateGL.
686    *
687    * If invoked with PAINT_GL, the client-side cached paint function
688    * is updated. If invoked with RESIZE_GL or UPDATE_GL, the code
689    * will be executed once.
690    *
691    * If invoked with multiple flags set, the order of execution will be
692    * updateGL(), resizeGL(), paintGL().
693    */
694   void repaintGL(WFlags<GLClientSideRenderer> which);
695 
696   /*! \brief Returns whether a lost context is in the process of being restored.
697    *
698    * You can check for this in initializeGL(), to handle the first
699    * initialization and restoration of context differently.
700    */
restoringContext()701   bool restoringContext() const { return restoringContext_; }
702 
703   void resize(const WLength &width, const WLength &height) override;
704 
705   /*! \brief The enormous GLenum
706    *
707    * This enum contains all numeric constants defined by the WebGL
708    * standard, see:
709    * http://www.khronos.org/registry/webgl/specs/latest/1.0/#WEBGLRENDERINGCONTEXT
710    */
711   enum GLenum {
712     /* ClearBufferMask */
713     DEPTH_BUFFER_BIT               = 0x00000100,
714     STENCIL_BUFFER_BIT             = 0x00000400,
715     COLOR_BUFFER_BIT               = 0x00004000,
716 
717     /* BeginMode */
718     POINTS                         = 0x0000,
719     LINES                          = 0x0001,
720     LINE_LOOP                      = 0x0002,
721     LINE_STRIP                     = 0x0003,
722     TRIANGLES                      = 0x0004,
723     TRIANGLE_STRIP                 = 0x0005,
724     TRIANGLE_FAN                   = 0x0006,
725 
726     /* AlphaFunction (not supported in ES20) */
727     /*      NEVER */
728     /*      LESS */
729     /*      EQUAL */
730     /*      LEQUAL */
731     /*      GREATER */
732     /*      NOTEQUAL */
733     /*      GEQUAL */
734     /*      ALWAYS */
735 
736     /* BlendingFactorDest */
737     ZERO                           = 0x0,
738     ONE                            = 0x1,
739     SRC_COLOR                      = 0x0300,
740     ONE_MINUS_SRC_COLOR            = 0x0301,
741     SRC_ALPHA                      = 0x0302,
742     ONE_MINUS_SRC_ALPHA            = 0x0303,
743     DST_ALPHA                      = 0x0304,
744     ONE_MINUS_DST_ALPHA            = 0x0305,
745 
746     /* BlendingFactorSrc */
747     /*      ZERO */
748     /*      ONE */
749     DST_COLOR                      = 0x0306,
750     ONE_MINUS_DST_COLOR            = 0x0307,
751     SRC_ALPHA_SATURATE             = 0x0308,
752     /*      SRC_ALPHA */
753     /*      ONE_MINUS_SRC_ALPHA */
754     /*      DST_ALPHA */
755     /*      ONE_MINUS_DST_ALPHA */
756 
757     /* BlendEquationSeparate */
758     FUNC_ADD                       = 0x8006,
759     BLEND_EQUATION                 = 0x8009,
760     BLEND_EQUATION_RGB             = 0x8009,   /* same as BLEND_EQUATION */
761     BLEND_EQUATION_ALPHA           = 0x883D,
762 
763     /* BlendSubtract */
764     FUNC_SUBTRACT                  = 0x800A,
765     FUNC_REVERSE_SUBTRACT          = 0x800B,
766 
767     /* Separate Blend Functions */
768     BLEND_DST_RGB                  = 0x80C8,
769     BLEND_SRC_RGB                  = 0x80C9,
770     BLEND_DST_ALPHA                = 0x80CA,
771     BLEND_SRC_ALPHA                = 0x80CB,
772     CONSTANT_COLOR                 = 0x8001,
773     ONE_MINUS_CONSTANT_COLOR       = 0x8002,
774     CONSTANT_ALPHA                 = 0x8003,
775     ONE_MINUS_CONSTANT_ALPHA       = 0x8004,
776     BLEND_COLOR                    = 0x8005,
777 
778     /* Buffer Objects */
779     ARRAY_BUFFER                   = 0x8892,
780     ELEMENT_ARRAY_BUFFER           = 0x8893,
781     ARRAY_BUFFER_BINDING           = 0x8894,
782     ELEMENT_ARRAY_BUFFER_BINDING   = 0x8895,
783 
784     STREAM_DRAW                    = 0x88E0,
785     STATIC_DRAW                    = 0x88E4,
786     DYNAMIC_DRAW                   = 0x88E8,
787 
788     BUFFER_SIZE                    = 0x8764,
789     BUFFER_USAGE                   = 0x8765,
790 
791     CURRENT_VERTEX_ATTRIB          = 0x8626,
792 
793     /* CullFaceMode */
794     FRONT                          = 0x0404,
795     BACK                           = 0x0405,
796     FRONT_AND_BACK                 = 0x0408,
797 
798     /* DepthFunction */
799     /*      NEVER */
800     /*      LESS */
801     /*      EQUAL */
802     /*      LEQUAL */
803     /*      GREATER */
804     /*      NOTEQUAL */
805     /*      GEQUAL */
806     /*      ALWAYS */
807 
808     /* EnableCap */
809     /* TEXTURE_2D */
810     CULL_FACE                      = 0x0B44,
811     BLEND                          = 0x0BE2,
812     DITHER                         = 0x0BD0,
813     STENCIL_TEST                   = 0x0B90,
814     DEPTH_TEST                     = 0x0B71,
815     SCISSOR_TEST                   = 0x0C11,
816     POLYGON_OFFSET_FILL            = 0x8037,
817     SAMPLE_ALPHA_TO_COVERAGE       = 0x809E,
818     SAMPLE_COVERAGE                = 0x80A0,
819 
820     /* ErrorCode */
821     NO_ERROR                       = 0x0,
822     INVALID_ENUM                   = 0x0500,
823     INVALID_VALUE                  = 0x0501,
824     INVALID_OPERATION              = 0x0502,
825     OUT_OF_MEMORY                  = 0x0505,
826 
827     /* FrontFaceDirection */
828     CW                             = 0x0900,
829     CCW                            = 0x0901,
830 
831     /* GetPName */
832     LINE_WIDTH                     = 0x0B21,
833     ALIASED_POINT_SIZE_RANGE       = 0x846D,
834     ALIASED_LINE_WIDTH_RANGE       = 0x846E,
835     CULL_FACE_MODE                 = 0x0B45,
836     FRONT_FACE                     = 0x0B46,
837     DEPTH_RANGE                    = 0x0B70,
838     DEPTH_WRITEMASK                = 0x0B72,
839     DEPTH_CLEAR_VALUE              = 0x0B73,
840     DEPTH_FUNC                     = 0x0B74,
841     STENCIL_CLEAR_VALUE            = 0x0B91,
842     STENCIL_FUNC                   = 0x0B92,
843     STENCIL_FAIL                   = 0x0B94,
844     STENCIL_PASS_DEPTH_FAIL        = 0x0B95,
845     STENCIL_PASS_DEPTH_PASS        = 0x0B96,
846     STENCIL_REF                    = 0x0B97,
847     STENCIL_VALUE_MASK             = 0x0B93,
848     STENCIL_WRITEMASK              = 0x0B98,
849     STENCIL_BACK_FUNC              = 0x8800,
850     STENCIL_BACK_FAIL              = 0x8801,
851     STENCIL_BACK_PASS_DEPTH_FAIL   = 0x8802,
852     STENCIL_BACK_PASS_DEPTH_PASS   = 0x8803,
853     STENCIL_BACK_REF               = 0x8CA3,
854     STENCIL_BACK_VALUE_MASK        = 0x8CA4,
855     STENCIL_BACK_WRITEMASK         = 0x8CA5,
856     VIEWPORT                       = 0x0BA2,
857     SCISSOR_BOX                    = 0x0C10,
858     /*      SCISSOR_TEST */
859     COLOR_CLEAR_VALUE              = 0x0C22,
860     COLOR_WRITEMASK                = 0x0C23,
861     UNPACK_ALIGNMENT               = 0x0CF5,
862     PACK_ALIGNMENT                 = 0x0D05,
863     MAX_TEXTURE_SIZE               = 0x0D33,
864     MAX_VIEWPORT_DIMS              = 0x0D3A,
865     SUBPIXEL_BITS                  = 0x0D50,
866     RED_BITS                       = 0x0D52,
867     GREEN_BITS                     = 0x0D53,
868     BLUE_BITS                      = 0x0D54,
869     ALPHA_BITS                     = 0x0D55,
870     DEPTH_BITS                     = 0x0D56,
871     STENCIL_BITS                   = 0x0D57,
872     POLYGON_OFFSET_UNITS           = 0x2A00,
873     /*      POLYGON_OFFSET_FILL */
874     POLYGON_OFFSET_FACTOR          = 0x8038,
875     TEXTURE_BINDING_2D             = 0x8069,
876     SAMPLE_BUFFERS                 = 0x80A8,
877     SAMPLES                        = 0x80A9,
878     SAMPLE_COVERAGE_VALUE          = 0x80AA,
879     SAMPLE_COVERAGE_INVERT         = 0x80AB,
880 
881     /* GetTextureParameter */
882     /*      TEXTURE_MAG_FILTER */
883     /*      TEXTURE_MIN_FILTER */
884     /*      TEXTURE_WRAP_S */
885     /*      TEXTURE_WRAP_T */
886 
887     NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2,
888     COMPRESSED_TEXTURE_FORMATS     = 0x86A3,
889 
890     /* HintMode */
891     DONT_CARE                      = 0x1100,
892     FASTEST                        = 0x1101,
893     NICEST                         = 0x1102,
894 
895     /* HintTarget */
896     GENERATE_MIPMAP_HINT            = 0x8192,
897 
898     /* DataType */
899     BYTE                           = 0x1400,
900     UNSIGNED_BYTE                  = 0x1401,
901     SHORT                          = 0x1402,
902     UNSIGNED_SHORT                 = 0x1403,
903     INT                            = 0x1404,
904     UNSIGNED_INT                   = 0x1405,
905     FLOAT                          = 0x1406,
906 
907     /* PixelFormat */
908     DEPTH_COMPONENT                = 0x1902,
909     ALPHA                          = 0x1906,
910     RGB                            = 0x1907,
911     RGBA                           = 0x1908,
912     LUMINANCE                      = 0x1909,
913     LUMINANCE_ALPHA                = 0x190A,
914 
915     /* PixelType */
916     /*      UNSIGNED_BYTE */
917     UNSIGNED_SHORT_4_4_4_4         = 0x8033,
918     UNSIGNED_SHORT_5_5_5_1         = 0x8034,
919     UNSIGNED_SHORT_5_6_5           = 0x8363,
920 
921     /* Shaders */
922     FRAGMENT_SHADER                  = 0x8B30,
923     VERTEX_SHADER                    = 0x8B31,
924     MAX_VERTEX_ATTRIBS               = 0x8869,
925     MAX_VERTEX_UNIFORM_VECTORS       = 0x8DFB,
926     MAX_VARYING_VECTORS              = 0x8DFC,
927     MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D,
928     MAX_VERTEX_TEXTURE_IMAGE_UNITS   = 0x8B4C,
929     MAX_TEXTURE_IMAGE_UNITS          = 0x8872,
930     MAX_FRAGMENT_UNIFORM_VECTORS     = 0x8DFD,
931     SHADER_TYPE                      = 0x8B4F,
932     DELETE_STATUS                    = 0x8B80,
933     LINK_STATUS                      = 0x8B82,
934     VALIDATE_STATUS                  = 0x8B83,
935     ATTACHED_SHADERS                 = 0x8B85,
936     ACTIVE_UNIFORMS                  = 0x8B86,
937     ACTIVE_UNIFORM_MAX_LENGTH        = 0x8B87,
938     ACTIVE_ATTRIBUTES                = 0x8B89,
939     ACTIVE_ATTRIBUTE_MAX_LENGTH      = 0x8B8A,
940     SHADING_LANGUAGE_VERSION         = 0x8B8C,
941     CURRENT_PROGRAM                  = 0x8B8D,
942 
943     /* StencilFunction */
944     NEVER                          = 0x0200,
945     LESS                           = 0x0201,
946     EQUAL                          = 0x0202,
947     LEQUAL                         = 0x0203,
948     GREATER                        = 0x0204,
949     NOTEQUAL                       = 0x0205,
950     GEQUAL                         = 0x0206,
951     ALWAYS                         = 0x0207,
952 
953     /* StencilOp */
954     /*      ZERO */
955     KEEP                           = 0x1E00,
956     REPLACE                        = 0x1E01,
957     INCR                           = 0x1E02,
958     DECR                           = 0x1E03,
959     INVERT                         = 0x150A,
960     INCR_WRAP                      = 0x8507,
961     DECR_WRAP                      = 0x8508,
962 
963     /* StringName */
964     VENDOR                         = 0x1F00,
965     RENDERER                       = 0x1F01,
966     VERSION                        = 0x1F02,
967 
968     /* TextureMagFilter */
969     NEAREST                        = 0x2600,
970     LINEAR                         = 0x2601,
971 
972     /* TextureMinFilter */
973     /*      NEAREST */
974     /*      LINEAR */
975     NEAREST_MIPMAP_NEAREST         = 0x2700,
976     LINEAR_MIPMAP_NEAREST          = 0x2701,
977     NEAREST_MIPMAP_LINEAR          = 0x2702,
978     LINEAR_MIPMAP_LINEAR           = 0x2703,
979 
980     /* TextureParameterName */
981     TEXTURE_MAG_FILTER             = 0x2800,
982     TEXTURE_MIN_FILTER             = 0x2801,
983     TEXTURE_WRAP_S                 = 0x2802,
984     TEXTURE_WRAP_T                 = 0x2803,
985 
986     /* TextureTarget */
987     TEXTURE_2D                     = 0x0DE1,
988     TEXTURE                        = 0x1702,
989 
990     TEXTURE_CUBE_MAP               = 0x8513,
991     TEXTURE_BINDING_CUBE_MAP       = 0x8514,
992     TEXTURE_CUBE_MAP_POSITIVE_X    = 0x8515,
993     TEXTURE_CUBE_MAP_NEGATIVE_X    = 0x8516,
994     TEXTURE_CUBE_MAP_POSITIVE_Y    = 0x8517,
995     TEXTURE_CUBE_MAP_NEGATIVE_Y    = 0x8518,
996     TEXTURE_CUBE_MAP_POSITIVE_Z    = 0x8519,
997     TEXTURE_CUBE_MAP_NEGATIVE_Z    = 0x851A,
998     MAX_CUBE_MAP_TEXTURE_SIZE      = 0x851C,
999 
1000     /* TextureUnit */
1001     TEXTURE0                       = 0x84C0,
1002     TEXTURE1                       = 0x84C1,
1003     TEXTURE2                       = 0x84C2,
1004     TEXTURE3                       = 0x84C3,
1005     TEXTURE4                       = 0x84C4,
1006     TEXTURE5                       = 0x84C5,
1007     TEXTURE6                       = 0x84C6,
1008     TEXTURE7                       = 0x84C7,
1009     TEXTURE8                       = 0x84C8,
1010     TEXTURE9                       = 0x84C9,
1011     TEXTURE10                      = 0x84CA,
1012     TEXTURE11                      = 0x84CB,
1013     TEXTURE12                      = 0x84CC,
1014     TEXTURE13                      = 0x84CD,
1015     TEXTURE14                      = 0x84CE,
1016     TEXTURE15                      = 0x84CF,
1017     TEXTURE16                      = 0x84D0,
1018     TEXTURE17                      = 0x84D1,
1019     TEXTURE18                      = 0x84D2,
1020     TEXTURE19                      = 0x84D3,
1021     TEXTURE20                      = 0x84D4,
1022     TEXTURE21                      = 0x84D5,
1023     TEXTURE22                      = 0x84D6,
1024     TEXTURE23                      = 0x84D7,
1025     TEXTURE24                      = 0x84D8,
1026     TEXTURE25                      = 0x84D9,
1027     TEXTURE26                      = 0x84DA,
1028     TEXTURE27                      = 0x84DB,
1029     TEXTURE28                      = 0x84DC,
1030     TEXTURE29                      = 0x84DD,
1031     TEXTURE30                      = 0x84DE,
1032     TEXTURE31                      = 0x84DF,
1033     ACTIVE_TEXTURE                 = 0x84E0,
1034 
1035     /* TextureWrapMode */
1036     REPEAT                         = 0x2901,
1037     CLAMP_TO_EDGE                  = 0x812F,
1038     MIRRORED_REPEAT                = 0x8370,
1039 
1040     /* Uniform Types */
1041     FLOAT_VEC2                     = 0x8B50,
1042     FLOAT_VEC3                     = 0x8B51,
1043     FLOAT_VEC4                     = 0x8B52,
1044     INT_VEC2                       = 0x8B53,
1045     INT_VEC3                       = 0x8B54,
1046     INT_VEC4                       = 0x8B55,
1047     BOOL                           = 0x8B56,
1048     BOOL_VEC2                      = 0x8B57,
1049     BOOL_VEC3                      = 0x8B58,
1050     BOOL_VEC4                      = 0x8B59,
1051     FLOAT_MAT2                     = 0x8B5A,
1052     FLOAT_MAT3                     = 0x8B5B,
1053     FLOAT_MAT4                     = 0x8B5C,
1054     SAMPLER_2D                     = 0x8B5E,
1055     SAMPLER_CUBE                   = 0x8B60,
1056 
1057     /* Vertex Arrays */
1058     VERTEX_ATTRIB_ARRAY_ENABLED        = 0x8622,
1059     VERTEX_ATTRIB_ARRAY_SIZE           = 0x8623,
1060     VERTEX_ATTRIB_ARRAY_STRIDE         = 0x8624,
1061     VERTEX_ATTRIB_ARRAY_TYPE           = 0x8625,
1062     VERTEX_ATTRIB_ARRAY_NORMALIZED     = 0x886A,
1063     VERTEX_ATTRIB_ARRAY_POINTER        = 0x8645,
1064     VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F,
1065 
1066     /* Shader Source */
1067     COMPILE_STATUS                 = 0x8B81,
1068     INFO_LOG_LENGTH                = 0x8B84,
1069     SHADER_SOURCE_LENGTH           = 0x8B88,
1070 
1071     /* Shader Precision-Specified Types */
1072     LOW_FLOAT                      = 0x8DF0,
1073     MEDIUM_FLOAT                   = 0x8DF1,
1074     HIGH_FLOAT                     = 0x8DF2,
1075     LOW_INT                        = 0x8DF3,
1076     MEDIUM_INT                     = 0x8DF4,
1077     HIGH_INT                       = 0x8DF5,
1078 
1079     /* Framebuffer Object. */
1080     FRAMEBUFFER                    = 0x8D40,
1081     RENDERBUFFER                   = 0x8D41,
1082 
1083     RGBA4                          = 0x8056,
1084     RGB5_A1                        = 0x8057,
1085     RGB565                         = 0x8D62,
1086     DEPTH_COMPONENT16              = 0x81A5,
1087     STENCIL_INDEX                  = 0x1901,
1088     STENCIL_INDEX8                 = 0x8D48,
1089     DEPTH_STENCIL                  = 0x84F9,
1090 
1091     RENDERBUFFER_WIDTH             = 0x8D42,
1092     RENDERBUFFER_HEIGHT            = 0x8D43,
1093     RENDERBUFFER_INTERNAL_FORMAT   = 0x8D44,
1094     RENDERBUFFER_RED_SIZE          = 0x8D50,
1095     RENDERBUFFER_GREEN_SIZE        = 0x8D51,
1096     RENDERBUFFER_BLUE_SIZE         = 0x8D52,
1097     RENDERBUFFER_ALPHA_SIZE        = 0x8D53,
1098     RENDERBUFFER_DEPTH_SIZE        = 0x8D54,
1099     RENDERBUFFER_STENCIL_SIZE      = 0x8D55,
1100 
1101     FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           = 0x8CD0,
1102     FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           = 0x8CD1,
1103     FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         = 0x8CD2,
1104     FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3,
1105 
1106     COLOR_ATTACHMENT0              = 0x8CE0,
1107     DEPTH_ATTACHMENT               = 0x8D00,
1108     STENCIL_ATTACHMENT             = 0x8D20,
1109     DEPTH_STENCIL_ATTACHMENT       = 0x821A,
1110 
1111     NONE                           = 0x0,
1112 
1113     FRAMEBUFFER_COMPLETE                      = 0x8CD5,
1114     FRAMEBUFFER_INCOMPLETE_ATTACHMENT         = 0x8CD6,
1115     FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7,
1116     FRAMEBUFFER_INCOMPLETE_DIMENSIONS         = 0x8CD9,
1117     FRAMEBUFFER_UNSUPPORTED                   = 0x8CDD,
1118 
1119     FRAMEBUFFER_BINDING            = 0x8CA6,
1120     RENDERBUFFER_BINDING           = 0x8CA7,
1121     MAX_RENDERBUFFER_SIZE          = 0x84E8,
1122 
1123     INVALID_FRAMEBUFFER_OPERATION  = 0x0506,
1124 
1125     /* WebGL-specific enums */
1126     UNPACK_FLIP_Y_WEBGL            = 0x9240,
1127     UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241,
1128     CONTEXT_LOST_WEBGL             = 0x9242,
1129     UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243,
1130     BROWSER_DEFAULT_WEBGL          = 0x9244,
1131   };
1132 
1133   void debugger();
1134 
1135   /*! @name GL methods
1136    * The GL methods are mostly 1-on-1 translated to the identical
1137    * JavaScript call in WebGL. You can use the GL methods in your resizeGL(),
1138    * paintGL() and updateGL() specializations. Wt takes care that data,
1139    * arguments, ... are transfered to the client side and that the equivalent
1140    * JavaScript WebGL funtion is executed when using client-side rendering.
1141    * When using server-side rendering, the appropriate OpenGL functions
1142    * are called.
1143    * @{
1144    */
1145 
1146 
1147   /*! \brief GL function to activate an existing texture
1148    *
1149    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glActiveTexture.xml">
1150    * glActiveTexture() OpenGL ES manpage</a>
1151    */
1152   void activeTexture(GLenum texture);
1153 
1154   /*! \brief GL function to attach a shader to a program
1155    *
1156    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glAttachShader.xml">
1157    * glAttachShader() OpenGL ES manpage</a>
1158    */
1159   void attachShader(Program program, Shader shader);
1160 
1161   /*! \brief GL function to bind an attribute to a given location
1162    *
1163    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBindAttribLocation.xml">
1164    * glBindAttribLocation() OpenGL ES manpage</a>
1165    */
1166   void bindAttribLocation(Program program, unsigned index,
1167                           const std::string &name);
1168 
1169   /*! \brief GL function to bind a buffer to a target
1170    *
1171    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBindBuffer.xml">
1172    * glBindBuffer() OpenGL ES manpage</a>
1173    */
1174   void bindBuffer(GLenum target, Buffer buffer);
1175 
1176   /*! \brief GL function to bind a frame buffer to a target
1177    *
1178    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBindFramebuffer.xml">
1179    * glBindFramebuffer() OpenGL ES manpage</a>
1180    */
1181   void bindFramebuffer(GLenum target, Framebuffer framebuffer);
1182 
1183   /*! \brief GL function to bind a render buffer to a target
1184    *
1185    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBindRenderbuffer.xml">
1186    * glBindRenderbuffer() OpenGL ES manpage</a>
1187    */
1188   void bindRenderbuffer(GLenum target, Renderbuffer renderbuffer);
1189 
1190   /*! \brief GL function to bind a texture to a target
1191    *
1192    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBindTexture.xml">
1193    * glBindTexture() OpenGL ES manpage</a>
1194    */
1195   void bindTexture(GLenum target, Texture texture);
1196 
1197   /*! \brief GL function to set the blending color
1198    *
1199    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBlendColor.xml">
1200    * glBlendColor() OpenGL ES manpage</a>
1201    */
1202   void blendColor(double red, double green, double blue, double alpha);
1203 
1204   /*! \brief GL function to set the blending equation
1205    *
1206    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBlendEquation.xml">
1207    * glBlendEquation() OpenGL ES manpage</a>
1208    */
1209   void blendEquation(GLenum mode);
1210 
1211   /*! \brief GL function that sets separate blending functions for RGB and alpha
1212    *
1213    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBlendEquationSeparate.xml">
1214    * glBlendEquationSeparate() OpenGL ES manpage</a>
1215    */
1216   void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
1217 
1218   /*! \brief GL function to configure the blending function
1219    *
1220    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBlendFunc.xml">
1221    * glBlendFunc() OpenGL ES manpage</a>
1222    */
1223   void blendFunc(GLenum sfactor, GLenum dfactor);
1224 
1225   /*! \brief GL function that configures the blending function
1226    *
1227    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBlendFuncSeparate.xml">
1228    * glBlendFuncSeparate() OpenGL ES manpage</a>
1229    */
1230   void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
1231                          GLenum srcAlpha, GLenum dstAlpha);
1232 
1233   /*! \brief glBufferData - create and initialize a buffer object's data store
1234    *
1235    * Set the size of the currently bound WebGLBuffer object for the passed target.
1236    * The buffer is initialized to 0.
1237    *
1238    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferData.xml">
1239    * glBufferData() OpenGL ES manpage</a>
1240    */
1241   void bufferData(GLenum target, int size, GLenum usage);
1242 
1243   /*! \brief glBufferData - create and initialize a buffer object's data store
1244    *         from an ArrayBuffer
1245    *
1246    * Set the size and contents of the currently bound WebGLBuffer object to
1247    * be a copy of the given ArrayBuffer.
1248    *
1249    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferData.xml">
1250    * glBufferData() OpenGL ES manpage</a>
1251    *
1252    * Note: an ArrayBuffer refers to a javascript object, which cannot be
1253    * used for server-side rendering. If a server-side fallback will be used,
1254    * then bufferDatafv() should be used with the additional boolean argument to
1255    * indicate binary transfer of the data in case of client-side rendering.
1256    *
1257    * \sa createAndLoadArrayBuffer
1258    */
1259   void bufferData(GLenum target, ArrayBuffer res, GLenum usage);
1260 
1261   /*! \brief glBufferData - create and initialize a buffer object's data store
1262    *         from an ArrayBuffer
1263    *
1264    * Set the size of the currently bound WebGLBuffer object to
1265    * arrayBufferSize, and copy the contents of the ArrayBuffer to
1266    * the buffer, starting at the given offset.
1267    *
1268    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferData.xml">
1269    * glBufferData() OpenGL ES manpage</a>
1270    *
1271    * Note: not functional for a server-side fall-back (see bufferData(GLenum target, ArrayBuffer res, GLenum usage) for more info)
1272    *
1273    * \sa createAndLoadArrayBuffer
1274    */
1275   void bufferData(GLenum target, ArrayBuffer res, unsigned arrayBufferOffset,
1276                   unsigned arrayBufferSize, GLenum usage);
1277 
1278   /*! \brief Initialize a buffer object's data store from an ArrayBuffer
1279    *
1280    * Load the data of the currently bound WebGLBuffer object from
1281    * the given ArrayBuffer. The first byte of the resource data will
1282    * be written at the given offset of the currently bound buffer.
1283    *
1284    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferSubData.xml">
1285    * glBufferSubData() OpenGL ES manpage</a>
1286    *
1287    * Note: not functional for a server-side fall-back (see bufferData(GLenum target, ArrayBuffer res, GLenum usage) for more info)
1288    *
1289    * \sa createAndLoadArrayBuffer
1290    */
1291   void bufferSubData(GLenum target, unsigned offset, ArrayBuffer res);
1292 
1293   /*! \brief Initialize a buffer object's data store from an ArrayBuffer
1294    *
1295    * Load the data of the currently bound WebGLBuffer object from
1296    * the given ArrayBuffer. The byte at position arrayBufferOffset
1297    * will be written to the currently bound buffer at position offset.
1298    *
1299    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferSubData.xml">
1300    * glBufferSubData() OpenGL ES manpage</a>
1301    *
1302    * Note: not functional for a server-side fall-back (see bufferData(GLenum target, ArrayBuffer res, GLenum usage) for more info)
1303    *
1304    * \sa createAndLoadArrayBuffer
1305    */
1306   void bufferSubData(GLenum target, unsigned offset, ArrayBuffer res,
1307                      unsigned arrayBufferOffset, unsigned size);
1308 
1309 #if !defined(WT_TARGET_JAVA)
1310   /*! \brief GL function that loads float or double data in a VBO
1311    *
1312    * Unlike the C version, we can't accept a void * here. We must be able
1313    * to interpret the buffer's data in order to transmit it to the JS side.
1314    *
1315    * Later we may also want versions with strides and offsets to cope with
1316    * more complex buffer layouts that we typically see on desktop WebGL apps;
1317    * suggestions to improve this are welcome
1318    *
1319    * Note: prefer bufferDatafv(GLenum target, const std::vector<float> &buffer, GLenum usage, bool binary)
1320    *
1321    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferData.xml">
1322    * glBufferData() OpenGL ES manpage</a>
1323    */
1324   template<typename Iterator>
1325     void bufferDatafv(GLenum target, const Iterator begin, const Iterator end, GLenum usage, bool binary = false) {
1326     std::vector<float> data;
1327     data.reserve(end-begin);
1328     for (Iterator i = begin; i != end; ++i) {
1329       data.push_back((float)*i);
1330     }
1331 
1332     bufferDatafv(target, data, usage, binary);
1333   }
1334 
1335   /*! \brief GL function that loads integer data in a VBO
1336    *
1337    * Note: prefer bufferDataiv(GLenum target, std::vector<int> &buffer, GLenum usage, GLenum type)
1338    *
1339    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferData.xml">
1340    * glBufferData() OpenGL ES manpage</a>
1341    */
1342   template<typename Iterator>
bufferDataiv(GLenum target,const Iterator begin,const Iterator end,GLenum usage,GLenum type)1343   void bufferDataiv(GLenum target, const Iterator begin, const Iterator end,
1344                     GLenum usage, GLenum type)
1345   {
1346     std::vector<int> data;
1347     data.reserve(end-begin);
1348     for (Iterator i = begin; i != end; i++)
1349       data.push_back(*i);
1350 
1351     bufferDataiv(target, data, usage, type);
1352   }
1353 
1354   /*! \brief GL function that updates an existing VBO with new float or double
1355    * data
1356    *
1357    * Note: prefer bufferSubDatafv(GLenum target, unsigned offset, const std::vector<float> &buffer, bool binary)
1358    *
1359    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferSubData.xml">
1360    * glBufferSubData() OpenGL ES manpage</a>
1361    */
1362   template<typename Iterator>
1363   void bufferSubDatafv(GLenum target, unsigned offset, const Iterator begin, const Iterator end, bool binary = false)
1364   {
1365     std::vector<float> data;
1366     data.reserve(end-begin);
1367     for (Iterator i = begin; i != end; ++i)
1368       data.push_back(*i);
1369 
1370     bufferSubDatafv(target, offset, data, binary);
1371   }
1372 
1373   /*! \brief GL function that updates an existing VBO with new integer data
1374    *
1375    * Note: prefer void bufferSubDataiv(GLenum target, unsigned offset, std::vector<int> &buffer, GLenum type)
1376    *
1377    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glBufferSubData.xml">
1378    * glBufferSubData() OpenGL ES manpage</a>
1379    */
1380   template<typename Iterator>
bufferSubDataiv(GLenum target,unsigned offset,const Iterator begin,Iterator end,GLenum type)1381   void bufferSubDataiv(GLenum target, unsigned offset, const Iterator begin, Iterator end, GLenum type)
1382   {
1383     std::vector<int> data;
1384     data.reserve(end-begin);
1385     for (Iterator i = begin; i != end; i++)
1386       data.push_back(*i);
1387 
1388     bufferSubDataiv(target, offset, data, type);
1389   }
1390 #endif
1391 
1392   /*! \brief GL function that loads float or double data in a VBO
1393    *
1394    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/glBufferData.xml">
1395    * glBufferData() OpenGL ES manpage</a>
1396    */
1397 #ifdef WT_TARGET_JAVA
1398   void bufferDatafv(GLenum target, const FloatBuffer &buffer, GLenum usage, bool binary = false);
1399   void bufferDatafv(GLenum target, const FloatNotByteBuffer &buffer, GLenum usage);
1400 #else
1401   void bufferDatafv(GLenum target, const std::vector<float> &buffer, GLenum usage, bool binary = false);
1402 #endif
1403 
1404   /*! \brief remove all binary buffer resources
1405    *
1406    * Removes all WMemoryResources that were allocated when calling
1407    * bufferDatafv with binary=true. This is not required, since the resources
1408    * are also managed, but if you are sure they will not be used anymore in
1409    * the client, this can help free some memory.
1410    */
1411   void clearBinaryResources();
1412 
1413   /*! \brief GL function that updates an existing VBO with new integer data
1414    *
1415    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/glBufferData.xml">
1416    * glBufferData() OpenGL ES manpage</a>
1417    */
1418 #ifdef WT_TARGET_JAVA
1419   void bufferDataiv(GLenum target, IntBuffer &buffer, GLenum usage,
1420 		    GLenum type);
1421 #else
1422   void bufferDataiv(GLenum target, std::vector<int> &buffer, GLenum usage,
1423 		    GLenum type);
1424 #endif
1425 
1426   /*! \brief GL function that updates an existing VBO with new float data
1427    *
1428    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/glBufferSubData.xml">
1429    * glBufferSubData() OpenGL ES manpage</a>
1430    */
1431 #ifdef WT_TARGET_JAVA
1432   void bufferSubDatafv(GLenum target, unsigned offset,
1433 		       const FloatBuffer &buffer, bool binary = false);
1434 
1435   void bufferSubDatafv(GLenum target, unsigned offset,
1436 		       const FloatNotByteBuffer &buffer);
1437 #else
1438   void bufferSubDatafv(GLenum target, unsigned offset,
1439 		       const std::vector<float> &buffer, bool binary = false);
1440 #endif
1441 
1442   /*! \brief GL function that loads integer data in a VBO
1443    *
1444    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/glBufferSubData.xml">
1445    * glBufferSubData() OpenGL ES manpage</a>
1446    */
1447 #ifdef WT_TARGET_JAVA
1448   void bufferSubDataiv(GLenum target,
1449 		       unsigned offset, IntBuffer &buffer,
1450 		       GLenum type);
1451 #else
1452   void bufferSubDataiv(GLenum target,
1453 		       unsigned offset, std::vector<int> &buffer,
1454 		       GLenum type);
1455 #endif
1456 
1457   //GLenum checkFramebufferStatus(GLenum target);
1458 
1459   /*! \brief GL function that clears the given buffers
1460    *
1461    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glClear.xml">
1462    * glClear() OpenGL ES manpage</a>
1463    */
1464   void clear(WFlags<GLenum> mask);
1465 
1466   /*! \brief GL function that sets the clear color of the color buffer
1467    *
1468    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glClearColor.xml">
1469    * glClearColor() OpenGL ES manpage</a>
1470    */
1471   void clearColor(double r, double g, double b, double a);
1472 
1473   /*! \brief GL function that configures the depth to be set when the
1474    * depth buffer is cleared
1475    *
1476    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glClearDepthf.xml">
1477    * glClearDepthf() OpenGL ES manpage</a>
1478    */
1479   void clearDepth(double depth);
1480 
1481   /*! \brief GL function
1482    *
1483    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glClearStencil.xml">
1484    * glClearStencil() OpenGL ES manpage</a>
1485    */
1486   void clearStencil(int s);
1487 
1488   /*! \brief GL function
1489    *
1490    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glColorMask.xml">
1491    * glColorMask() OpenGL ES manpage</a>
1492    */
1493   void colorMask(bool red, bool green, bool blue, bool alpha);
1494 
1495   /*! \brief GL function to compile a shader
1496    *
1497    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCompileShader.xml">
1498    * glCompileShader() OpenGL ES manpage</a>
1499    */
1500   void compileShader(Shader shader);
1501 
1502   /*! \brief GL function to copy a texture image
1503    *
1504    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCopyTexImage2D.xml">
1505    * glCopyTexImage2D() OpenGL ES manpage</a>
1506    */
1507   void copyTexImage2D(GLenum target, int level,
1508                       GLenum internalformat,
1509                       int x, int y,
1510                       unsigned width, unsigned height,
1511                       int border);
1512 
1513   /*! \brief GL function that copies a part of a texture image
1514    *
1515    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCopyTexSubImage2D.xml">
1516    * glCopyTexSubImage2D() OpenGL ES manpage</a>
1517    */
1518   void copyTexSubImage2D(GLenum target, int level,
1519                          int xoffset, int yoffset,
1520                          int x, int y,
1521                          unsigned width, unsigned height);
1522 
1523   /*! \brief GL function that creates an empty VBO
1524    *
1525    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenBuffers.xml">
1526    * glGenBuffers() OpenGL ES manpage</a>
1527    */
1528   Buffer createBuffer();
1529 
1530   /*! \brief GL function that creates a frame buffer object
1531    *
1532    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenFramebuffers.xml">
1533    * glGenFramebuffers() OpenGL ES manpage</a>
1534    */
1535   Framebuffer createFramebuffer();
1536 
1537   /*! \brief GL function that creates an empty program
1538    *
1539    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCreateProgram.xml">
1540    * glCreateProgram() OpenGL ES manpage</a>
1541    */
1542   Program createProgram();
1543 
1544   /*! \brief GL function that creates a render buffer object
1545    *
1546    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenRenderbuffers.xml">
1547    * glGenRenderbuffers() OpenGL ES manpage</a>
1548    */
1549   Renderbuffer createRenderbuffer();
1550 
1551   /*! \brief GL function that creates an empty shader
1552    *
1553    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCreateShader.xml">
1554    * glCreateShader() OpenGL ES manpage</a>
1555    */
1556   Shader createShader(GLenum shader);
1557 
1558   /*! \brief GL function that creates an empty texture
1559    *
1560    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenTextures.xml">
1561    * glGenTextures() OpenGL ES manpage</a>
1562    */
1563   Texture createTexture();
1564 
1565   /*! \brief GL function that creates an image texture
1566    *
1567    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenTextures.xml">
1568    * glGenTextures() OpenGL ES manpage</a>
1569    */
1570   Texture createTextureAndLoad(const std::string &url);
1571 
1572   /*! \brief returns an paintdevice that can be used to paint a GL texture
1573    *
1574    * If the client has a webGL enabled browser this function returns a
1575    * WCanvasPaintDevice.
1576    *
1577    * \if cpp
1578    * If server-side rendering is used as fallback then
1579    * this function returns a WRasterImage.
1580    * \endif
1581    * \if java
1582    * If server-side rendering is used as fallback then
1583    * this function returns a {@link WRasterPaintDevice}.
1584    * \endif
1585    */
1586   std::unique_ptr<WPaintDevice> createPaintDevice(const WLength& width,
1587 						  const WLength& height);
1588 
1589   /*! \brief GL function that configures the backface culling mode
1590    *
1591    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glCullFace.xml">
1592    * glCullFace() OpenGL ES manpage</a>
1593    */
1594   void cullFace(GLenum mode);
1595 
1596   /*! \brief GL function that deletes a VBO
1597    *
1598    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDeleteBuffers.xml">
1599    * glDeleteBuffers() OpenGL ES manpage</a>
1600    */
1601   void deleteBuffer(Buffer buffer);
1602 
1603   /*! \brief GL function that deletes a frame buffer
1604    *
1605    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDeleteFramebuffers.xml">
1606    * glDeleteFramebuffers() OpenGL ES manpage</a>
1607    */
1608   void deleteFramebuffer(Framebuffer framebuffer);
1609 
1610   /*! \brief GL function that deletes a program
1611    *
1612    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDeleteProgram.xml">
1613    * glDeleteProgram() OpenGL ES manpage</a>
1614    */
1615   void deleteProgram(Program program);
1616 
1617   /*! \brief GL function that deletes a render buffer
1618    *
1619    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDeleteRenderbuffers.xml">
1620    * glDeleteRenderbuffers() OpenGL ES manpage</a>
1621    */
1622   void deleteRenderbuffer(Renderbuffer renderbuffer);
1623 
1624   /*! \brief GL function that depetes a shader
1625    *
1626    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDeleteShader.xml">
1627    * glDeleteShader() OpenGL ES manpage</a>
1628    */
1629   void deleteShader(Shader shader);
1630 
1631   /*! \brief GL function that deletes a texture
1632    *
1633    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDeleteTextures.xml">
1634    * glDeleteTextures() OpenGL ES manpage</a>
1635    */
1636   void deleteTexture(Texture texture);
1637 
1638   /*! \brief GL function to set the depth test function
1639    *
1640    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDepthFunc.xml">
1641    * glDepthFunc() OpenGL ES manpage</a>
1642    */
1643   void depthFunc(GLenum func);
1644 
1645   /*! \brief GL function that enables or disables writing to the depth buffer
1646    *
1647    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDepthMask.xml">
1648    * glDepthMask() OpenGL ES manpage</a>
1649    */
1650   void depthMask(bool flag);
1651 
1652   /*! \brief GL function that specifies to what range the normalized [-1,1] z
1653    * values should match.
1654    *
1655    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDepthRangef.xml">
1656    * glDepthRangef() OpenGL ES manpage</a>
1657    */
1658   void depthRange(double zNear, double zFar);
1659 
1660   /*! \brief GL function that detaches a shader from a program
1661    *
1662    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDetachShader.xml">
1663    * glDetachShader() OpenGL ES manpage</a>
1664    */
1665   void detachShader(Program program, Shader shader);
1666 
1667   /*! \brief GL function to disable features
1668    *
1669    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDisable.xml">
1670    * glDisable() OpenGL ES manpage</a>
1671    */
1672   void disable(GLenum cap);
1673 
1674   /*! \brief GL function to disable the vertex attribute array
1675    *
1676    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDisableVertexAttribArray.xml">
1677    * glDisableVertexAttribArray() OpenGL ES manpage</a>
1678    */
1679   void disableVertexAttribArray(AttribLocation index);
1680 
1681   /*! \brief GL function to draw a VBO
1682    *
1683    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDrawArrays.xml">
1684    * glDrawArrays() OpenGL ES manpage</a>
1685    */
1686   void drawArrays(GLenum mode, int first, unsigned count);
1687 
1688   /*! \brief GL function to draw indexed VBOs
1689    *
1690    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glDrawElements.xml">
1691    * glDrawElements() OpenGL ES manpage</a>
1692    */
1693   void drawElements(GLenum mode, unsigned count, GLenum type, unsigned offset);
1694 
1695   /*! \brief GL function to enable features
1696    *
1697    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glEnable.xml">
1698    * glEnable() OpenGL ES manpage</a>
1699    */
1700   void enable(GLenum cap);
1701 
1702   /*! \brief GL function to enable the vertex attribute array
1703    *
1704    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glEnableVertexAttribArray.xml">
1705    * glEnableVertexAttribArray() OpenGL ES manpage</a>
1706    */
1707   void enableVertexAttribArray(AttribLocation index);
1708 
1709   /*! \brief GL function to wait until given commands are executed
1710    *
1711    * This call is transfered to JS, but the server will never wait on
1712    * this call.
1713    *
1714    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glFinish.xml">
1715    * glFinish() OpenGL ES manpage</a>
1716    */
1717   void finish();
1718 
1719   /*! \brief GL function to force execution of GL commands in finite time.
1720    *
1721    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glFlush.xml">
1722    * glFlush() OpenGL ES manpage</a>
1723    */
1724   void flush();
1725 
1726   /*! \brief GL function to attach the given renderbuffer to the currently
1727    *         bound frame buffer.
1728    *
1729    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glFramebufferRenderbuffer.xml">
1730    * glFramebufferRenderbuffer() OpenGL ES manpage</a>
1731    */
1732   void framebufferRenderbuffer(GLenum target, GLenum attachment,
1733                                GLenum renderbuffertarget,
1734                                Renderbuffer renderbuffer);
1735 
1736   /*! \brief GL function to render directly into a texture image.
1737    *
1738    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glFramebufferTexture2D.xml">
1739    * glFramebufferTexture2D() OpenGL ES manpage</a>
1740    */
1741   void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget,
1742                             Texture texture, int level);
1743 
1744   /*! \brief GL function that specifies which side of a triangle is the
1745    * front side
1746    *
1747    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glFrontFace.xml">
1748    * glFrontFace() OpenGL ES manpage</a>
1749    */
1750   void frontFace(GLenum mode);
1751 
1752   /*! \brief GL function that generates a set of mipmaps for a texture
1753    * object.
1754    *
1755    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGenerateMipmap.xml">
1756    * glGenerateMipmap() OpenGL ES manpage</a>
1757    */
1758   void generateMipmap(GLenum target);
1759 
1760   //WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index);
1761   //WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index);
1762   //WebGLShader[ ] getAttachedShaders(WebGLProgram program);
1763 
1764   /*! \brief GL function to retrieve an attribute's location in a Program
1765    *
1766    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGetAttribLocation.xml">
1767    * glGetAttribLocation() OpenGL ES manpage</a>
1768    */
1769   AttribLocation getAttribLocation(Program program, const std::string &attrib);
1770 
1771   //any getParameter(GLenum pname);
1772   //any getBufferParameter(GLenum target, GLenum pname);
1773 
1774   //GLenum getError();
1775 
1776   //any getFramebufferAttachmentParameter(GLenum target, GLenum attachment,
1777   //                                      GLenum pname);
1778   //any getProgramParameter(WebGLProgram program, GLenum pname);
1779   //DOMString getProgramInfoLog(WebGLProgram program);
1780   //any getRenderbufferParameter(GLenum target, GLenum pname);
1781   //any getShaderParameter(WebGLShader shader, GLenum pname);
1782   //DOMString getShaderInfoLog(WebGLShader shader);
1783 
1784   //DOMString getShaderSource(WebGLShader shader);
1785 
1786   //any getTexParameter(GLenum target, GLenum pname);
1787 
1788   //any getUniform(WebGLProgram program, WebGLUniformLocation location);
1789 
1790   /*! \brief GL function to retrieve a Uniform's location in a Program.
1791    *
1792    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glGetUniformLocation.xml">
1793    * glGetUniformLocation() OpenGL ES manpage</a>
1794    */
1795   UniformLocation getUniformLocation(Program program, const std::string &location);
1796 
1797   //any getVertexAttrib(GLuint index, GLenum pname);
1798 
1799   //GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
1800 
1801   /*! \brief GL function to give hints to the render pipeline
1802    *
1803    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glHint.xml">
1804    * glHint() OpenGL ES manpage</a>
1805    */
1806   void hint(GLenum target, GLenum mode);
1807 
1808   //GLboolean isBuffer(WebGLBuffer buffer);
1809   //GLboolean isEnabled(GLenum cap);
1810   //GLboolean isFramebuffer(WebGLFramebuffer framebuffer);
1811   //GLboolean isProgram(WebGLProgram program);
1812   //GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer);
1813   //GLboolean isShader(WebGLShader shader);
1814   //GLboolean isTexture(WebGLTexture texture);
1815 
1816   /*! \brief GL function to set the line width
1817    *
1818    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glLineWidth.xml">
1819    * glLineWidth() OpenGL ES manpage</a>
1820    */
1821   void lineWidth(double width);
1822 
1823   /*! \brief GL function to link a program
1824    *
1825    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glLinkProgram.xml">
1826    * glLinkProgram() OpenGL ES manpage</a>
1827    */
1828   void linkProgram(Program program);
1829 
1830   /*! \brief GL function to set the pixel storage mode
1831    *
1832    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glPixelStorei.xml">
1833    * glPixelStorei() OpenGL ES manpage</a>
1834    */
1835   void pixelStorei(GLenum pname, int param);
1836 
1837   /*! \brief GL function to apply modifications to Z values
1838    *
1839    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glPolygonOffset.xml">
1840    * glPolygonOffset() OpenGL ES manpage</a>
1841    */
1842   void polygonOffset(double factor, double units);
1843 
1844   //void readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1845   //                GLenum format, GLenum type, ArrayBufferView pixels);
1846 
1847   /*! \brief GL function to allocate the appropriate amount of memory for
1848    *         a render buffer
1849    *
1850    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glRenderbufferStorage.xml">
1851    * glSampleCoverage() OpenGL ES manpage</a>
1852    */
1853   void renderbufferStorage(GLenum target, GLenum internalformat,
1854                            unsigned width, unsigned height);
1855 
1856   /*! \brief GL function to set multisample parameters
1857    *
1858    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glSampleCoverage.xml">
1859    * glSampleCoverage() OpenGL ES manpage</a>
1860    */
1861   void sampleCoverage(double value, bool invert);
1862 
1863   /*! \brief GL function to define the scissor box
1864    *
1865    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glScissor.xml">
1866    * glScissor() OpenGL ES manpage</a>
1867    */
1868   void scissor(int x, int y, unsigned width, unsigned height);
1869 
1870   /*! \brief GL function to set a shader's source code
1871    *
1872    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glShaderSource.xml">
1873    * glShaderSource() OpenGL ES manpage</a>
1874    */
1875   void shaderSource(Shader shader, const std::string &src);
1876 
1877   /*! \brief GL function to set stencil test parameters
1878    *
1879    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glStencilFunc.xml">
1880    * glStencilFunc() OpenGL ES manpage</a>
1881    */
1882   void stencilFunc(GLenum func, int ref, unsigned mask);
1883 
1884   /*! \brief GL function to set stencil test parameters for front and/or
1885    * back stencils
1886    *
1887    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glStencilFuncSeparate.xml">
1888    * glStencilFuncSeparate() OpenGL ES manpage</a>
1889    */
1890   void stencilFuncSeparate(GLenum face, GLenum func, int ref, unsigned mask);
1891 
1892   /*! \brief GL function to control which bits are to be written in the stencil
1893    * buffer
1894    *
1895    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glStencilMask.xml">
1896    * glStencilMask() OpenGL ES manpage</a>
1897    */
1898   void stencilMask(unsigned mask);
1899 
1900   /*! \brief GL function to control which bits are written to the front and/or
1901    * back stencil buffers
1902    *
1903    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glStencilMaskSeparate.xml">
1904    * glStencilMaskSeparate() OpenGL ES manpage</a>
1905    */
1906   void stencilMaskSeparate(GLenum face, unsigned mask);
1907 
1908   /*! \brief GL function to set stencil test actions
1909    *
1910    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glStencilOp.xml">
1911    * glStencilOp() OpenGL ES manpage</a>
1912    */
1913   void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
1914 
1915   /*! \brief GL function to set front and/or back stencil test actions
1916    * separately
1917    *
1918    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glStencilOpSeparate.xml">
1919    * glStencilOpSeparate() OpenGL ES manpage</a>
1920    */
1921   void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
1922 
1923   //void texImage2D(TextureTargetEnum target, int level, PixelFormatEnum internalformat,
1924   //                GLsizei width, GLsizei height, GLint border, PixelFormatEnum format,
1925   //                GLenum type, ArrayBufferView pixels);
1926   /*! \brief GL function to reserve space for a 2D texture, without specifying its
1927    *         contents.
1928    *
1929    * This corresponds to calling the WebGL function
1930    * void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width,
1931    * GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView pixels)
1932    * with null as last parameters. The value of 'type' is then of no importance and is
1933    * therefore omitted from this function.
1934    *
1935    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexImage2D.xml">
1936    * glTexImage2D() OpenGL ES manpage</a>
1937    */
1938   void texImage2D(GLenum target, int level, GLenum internalformat,
1939                   unsigned width, unsigned height, int border, GLenum format);
1940 
1941   //void texImage2D(TextureTargetEnum target, int level, PixelFormatEnum internalformat,
1942   //                PixelFormatEnum format, GLenum type, ImageData pixels);
1943 
1944   /*! \brief GL function to load a 2D texture from a WImage
1945    *
1946    * Note: WImage must be loaded before this function is executed.
1947    *
1948    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexImage2D.xml">
1949    * glTexImage2D() OpenGL ES manpage</a>
1950    */
1951   void texImage2D(GLenum target, int level, GLenum internalformat,
1952                   GLenum format, GLenum type, WImage *image);
1953 
1954   //void texImage2D(TextureTargetEnum target, int level, PixelFormatEnum internalformat,
1955   //                PixelFormatEnum format, GLenum type, HTMLCanvasElement canvas);
1956 
1957   /*! \brief GL function to load a 2D texture from a WVideo
1958    *
1959    * Note: the video must be loaded prior to calling this function. The
1960    * current frame is used as texture image.
1961    *
1962    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexImage2D.xml">
1963    * glTexImage2D() OpenGL ES manpage</a>
1964    */
1965   void texImage2D(GLenum target, int level, GLenum internalformat,
1966 		  GLenum format, GLenum type, WVideo *video);
1967 
1968   /*! \brief GL function to load a 2D texture from a file
1969    *
1970    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexImage2D.xml">
1971    * glTexImage2D() OpenGL ES manpage</a>
1972    */
1973   void texImage2D(GLenum target, int level, GLenum internalformat,
1974                   GLenum format, GLenum type, std::string filename);
1975 
1976   /*! \brief GL function to load a 2D texture from a WPaintDevice
1977    *
1978    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexImage2D.xml">
1979    * glTexImage2D() OpenGL ES manpage</a>
1980    *
1981    * \sa createPaintDevice()
1982    */
1983   void texImage2D(GLenum target, int level, GLenum internalformat,
1984 		  GLenum format, GLenum type,
1985 		  WPaintDevice *paintdevice);
1986 
1987   /*! \brief GL function to load a 2D texture loaded with createTextureAndLoad()
1988    *
1989    * This function must only be used for textures created with
1990    * createTextureAndLoad()
1991    *
1992    * Note: the WGLWidget implementation will delay rendering until
1993    * all textures created with createTextureAndLoad() are loaded in the
1994    * browser.
1995    *
1996    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexImage2D.xml">
1997    * glTexImage2D() OpenGL ES manpage</a>
1998    */
1999   void texImage2D(GLenum target, int level, GLenum internalformat,
2000                   GLenum format, GLenum type, Texture texture);
2001 
2002   //void texParameterf(TextureTargetEnum target,
2003   //                   TextureParameterNameEnum pname, double param);
2004 
2005   /*! \brief GL function to set texture parameters
2006    *
2007    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glTexParameter.xml">
2008    * glTexParameter() OpenGL ES manpage</a>
2009    */
2010   void texParameteri(GLenum target, GLenum pname, GLenum param);
2011 
2012   //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
2013   //                   GLsizei width, GLsizei height,
2014   //                   GLenum format, GLenum type, ArrayBufferView pixels);
2015   //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
2016   //                   GLenum format, GLenum type, ImageData pixels);
2017   //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
2018   //                   GLenum format, GLenum type, HTMLImageElement image);
2019   //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
2020   //                   GLenum format, GLenum type, HTMLCanvasElement canvas);
2021   //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
2022   //                   GLenum format, GLenum type, HTMLVideoElement video);
2023 
2024 
2025   /*! \brief GL function to set the value of a uniform variable of the current
2026    * program
2027    *
2028    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2029    * glUniform() OpenGL ES manpage</a>
2030    */
2031   void uniform1f(const UniformLocation &location, double x);
2032 
2033   /*! \brief GL function to set the value of a uniform variable of the current
2034    * program
2035    *
2036    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2037    * glUniform() OpenGL ES manpage</a>
2038    */
WT_WGL_TEMPLATE(typename FloatArray)2039   WT_WGL_TEMPLATE(typename FloatArray)
2040   void uniform1fv(const UniformLocation &location,
2041 		  const WT_ARRAY FloatArray *value)
2042 #ifndef WT_TARGET_JAVA
2043  {
2044     float out[1];
2045     for (int i=0; i<1; i++) {
2046       out[i] = (float)value[i];
2047     }
2048 
2049     uniform1fv(location, out);
2050   }
2051 
2052   /// \cond
2053   void uniform1fv(const UniformLocation &location,
2054 		  const WT_ARRAY float *value);
2055   /// \endcond
2056 #else
2057   ;
2058 #endif
2059 
2060   /*! \brief GL function to set the value of a uniform variable of the current
2061    * program
2062    *
2063    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2064    * glUniform() OpenGL ES manpage</a>
2065    */
2066   void uniform1fv(const UniformLocation &location,
2067 		  const JavaScriptVector &v);
2068 
2069   /*! \brief GL function to set the value of a uniform variable of the current
2070    * program
2071    *
2072    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2073    * glUniform() OpenGL ES manpage</a>
2074    */
2075   void uniform1i(const UniformLocation &location, int x);
2076 
2077   /*! \brief GL function to set the value of a uniform variable of the current
2078    * program
2079    *
2080    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2081    * glUniform() OpenGL ES manpage</a>
2082    */
WT_WGL_TEMPLATE(typename IntArray)2083   WT_WGL_TEMPLATE(typename IntArray)
2084   void uniform1iv(const UniformLocation &location,
2085 		  const WT_ARRAY IntArray *value)
2086 #ifndef WT_TARGET_JAVA
2087 {
2088     int out[1];
2089     for (int i=0; i<1; i++) {
2090       out[i] = (int)value[i];
2091     }
2092 
2093     uniform1iv(location, out);
2094   }
2095 
2096   /// \cond
2097   void uniform1iv(const UniformLocation &location,
2098 		  const WT_ARRAY int *value);
2099   /// \endcond
2100 #else
2101   ;
2102 #endif
2103 
2104   /*! \brief GL function to set the value of a uniform variable of the current
2105    * program
2106    *
2107    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2108    * glUniform() OpenGL ES manpage</a>
2109    */
2110   void uniform2f(const UniformLocation &location, double x, double y);
2111 
2112   /*! \brief GL function to set the value of a uniform variable of the current
2113    * program
2114    *
2115    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2116    * glUniform() OpenGL ES manpage</a>
2117    */
WT_WGL_TEMPLATE(typename FloatArray)2118   WT_WGL_TEMPLATE(typename FloatArray)
2119   void uniform2fv(const UniformLocation &location,
2120 		  const WT_ARRAY FloatArray *value)
2121 #ifndef WT_TARGET_JAVA
2122 {
2123   float out[2];
2124   for (int i=0; i<2; i++) {
2125     out[i] = (float)value[i];
2126   }
2127 
2128   uniform2fv(location, out);
2129 }
2130 
2131   /// \cond
2132 void uniform2fv(const UniformLocation &location,
2133 		const WT_ARRAY float *value);
2134 /// \endcond
2135 #else
2136 ;
2137 #endif
2138 
2139   /*! \brief GL function to set the value of a uniform variable of the current
2140    * program
2141    *
2142    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2143    * glUniform() OpenGL ES manpage</a>
2144    */
2145   void uniform2fv(const UniformLocation &location,
2146 		  const JavaScriptVector &v);
2147 
2148   /*! \brief GL function to set the value of a uniform variable of the current
2149    * program
2150    *
2151    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2152    * glUniform() OpenGL ES manpage</a>
2153    */
2154   void uniform2i(const UniformLocation &location, int x, int y);
2155 
2156   /*! \brief GL function to set the value of a uniform variable of the current
2157    * program
2158    *
2159    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2160    * glUniform() OpenGL ES manpage</a>
2161    */
WT_WGL_TEMPLATE(typename IntArray)2162   WT_WGL_TEMPLATE(typename IntArray)
2163   void uniform2iv(const UniformLocation &location,
2164 		  const WT_ARRAY IntArray *value)
2165 #ifndef WT_TARGET_JAVA
2166   {
2167     int out[2];
2168     for (int i=0; i<2; i++) {
2169       out[i] = (int)value[i];
2170     }
2171 
2172     uniform2iv(location, out);
2173   }
2174 
2175 /// \cond
2176 void uniform2iv(const UniformLocation &location,
2177 		  const WT_ARRAY int *value);
2178 /// \endcond
2179 #else
2180 ;
2181 #endif
2182 
2183   /*! \brief GL function to set the value of a uniform variable of the current
2184    * program
2185    *
2186    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2187    * glUniform() OpenGL ES manpage</a>
2188    */
2189   void uniform3f(const UniformLocation &location,
2190                  double x, double y, double z);
2191 
2192   /*! \brief GL function to set the value of a uniform variable of the current
2193    * program
2194    *
2195    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2196    * glUniform() OpenGL ES manpage</a>
2197    */
WT_WGL_TEMPLATE(typename FloatArray)2198   WT_WGL_TEMPLATE(typename FloatArray)
2199   void uniform3fv(const UniformLocation &location,
2200 		  const WT_ARRAY FloatArray *value)
2201 #ifndef WT_TARGET_JAVA
2202   {
2203     float out[3];
2204     for (int i=0; i<3; i++) {
2205       out[i] = (float)value[i];
2206     }
2207 
2208     uniform3fv(location, out);
2209   }
2210 
2211 /// \cond
2212   void uniform3fv(const UniformLocation &location,
2213 		  const WT_ARRAY float *value);
2214 /// \endcond
2215 #else
2216 ;
2217 #endif
2218 
2219   /*! \brief GL function to set the value of a uniform variable of the current
2220    * program
2221    *
2222    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2223    * glUniform() OpenGL ES manpage</a>
2224    */
2225   void uniform3fv(const UniformLocation &location,
2226 		  const JavaScriptVector &v);
2227 
2228   /*! \brief GL function to set the value of a uniform variable of the current
2229    * program
2230    *
2231    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2232    * glUniform() OpenGL ES manpage</a>
2233    */
2234   void uniform3i(const UniformLocation &location, int x, int y, int z);
2235 
2236   /*! \brief GL function to set the value of a uniform variable of the current
2237    * program
2238    *
2239    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2240    * glUniform() OpenGL ES manpage</a>
2241    */
WT_WGL_TEMPLATE(typename IntArray)2242   WT_WGL_TEMPLATE(typename IntArray)
2243   void uniform3iv(const UniformLocation &location,
2244 		  const WT_ARRAY IntArray *value)
2245 #ifndef WT_TARGET_JAVA
2246   {
2247     int out[3];
2248     for (int i=0; i<3; i++) {
2249       out[i] = (int)value[i];
2250     }
2251 
2252     uniform3iv(location, out);
2253   }
2254 
2255 /// \cond
2256   void uniform3iv(const UniformLocation &location,
2257 		  const WT_ARRAY int *value);
2258 /// \endcond
2259 #else
2260 ;
2261 #endif
2262 
2263   /*! \brief GL function to set the value of a uniform variable of the current
2264    * program
2265    *
2266    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2267    * glUniform() OpenGL ES manpage</a>
2268    */
2269   void uniform4f(const UniformLocation &location,
2270                  double x, double y, double z, double w);
2271 
2272   /*! \brief GL function to set the value of a uniform variable of the current
2273    * program
2274    *
2275    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2276    * glUniform() OpenGL ES manpage</a>
2277    */
WT_WGL_TEMPLATE(typename FloatArray)2278   WT_WGL_TEMPLATE(typename FloatArray)
2279   void uniform4fv(const UniformLocation &location,
2280 		  const WT_ARRAY FloatArray *value)
2281 #ifndef WT_TARGET_JAVA
2282   {
2283     float out[4];
2284     for (int i=0; i<4; i++) {
2285       out[i] = (float)value[i];
2286     }
2287 
2288     uniform4fv(location, out);
2289   }
2290 
2291 /// \cond
2292   void uniform4fv(const UniformLocation &location,
2293 		  const WT_ARRAY float *value);
2294 /// \endcond
2295 #else
2296 ;
2297 #endif
2298 
2299   /*! \brief GL function to set the value of a uniform variable of the current
2300    * program
2301    *
2302    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2303    * glUniform() OpenGL ES manpage</a>
2304    */
2305   void uniform4fv(const UniformLocation &location,
2306 		  const JavaScriptVector &v);
2307 
2308   /*! \brief GL function to set the value of a uniform variable of the current
2309    * program
2310    *
2311    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2312    * glUniform() OpenGL ES manpage</a>
2313    */
2314   void uniform4i(const UniformLocation &location, int x, int y, int z, int w);
2315 
2316   /*! \brief GL function to set the value of a uniform variable of the current
2317    * program
2318    *
2319    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2320    * glUniform() OpenGL ES manpage</a>
2321    */
WT_WGL_TEMPLATE(typename IntArray)2322   WT_WGL_TEMPLATE(typename IntArray)
2323   void uniform4iv(const UniformLocation &location,
2324 		  const WT_ARRAY IntArray *value)
2325 #ifndef WT_TARGET_JAVA
2326   {
2327     int out[4];
2328     for (int i=0; i<4; i++) {
2329       out[i] = (int)value[i];
2330     }
2331 
2332     uniform4iv(location, out);
2333   }
2334 
2335 /// \cond
2336   void uniform4iv(const UniformLocation &location,
2337 		  const WT_ARRAY int *value);
2338 /// \endcond
2339 #else
2340 ;
2341 #endif
2342 
2343   /*! \brief GL function to set the value of a uniform matrix of the current
2344    * program
2345    *
2346    * Attention: The OpenGL ES specification states that transpose MUST be
2347    * false.
2348    *
2349    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2350    * glUniform() OpenGL ES manpage</a>
2351    */
WT_WGL_TEMPLATE(typename MatrixType)2352   WT_WGL_TEMPLATE(typename MatrixType)
2353   void uniformMatrix2fv(const UniformLocation &location,
2354                         bool transpose,
2355 			const WT_ARRAY MatrixType *value)
2356 #ifndef WT_TARGET_JAVA
2357   {
2358     double out[4];
2359     for (int i=0; i<4; i++) {
2360       out[i] = (double)value[i];
2361     }
2362     uniformMatrix2fv(location, transpose, out);
2363   }
2364 
2365 /// \cond
2366   void uniformMatrix2fv(const UniformLocation &location,
2367                         bool transpose,
2368 			const WT_ARRAY double *value);
2369 /// \endcond
2370 #else
2371 ;
2372 #endif
2373 
2374   /*! \brief GL function to set the value of a uniform matrix of the current
2375    * program
2376    *
2377    * This function renders the matrix in the proper row/column order.
2378    *
2379    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2380    * glUniform() OpenGL ES manpage</a>
2381    */
WT_WGL_TEMPLATE(typename MatrixType)2382   WT_WGL_TEMPLATE(typename MatrixType)
2383   void uniformMatrix2(const UniformLocation &location,
2384                       const WGenericMatrix<MatrixType, 2, 2> &m)
2385 #ifndef WT_TARGET_JAVA
2386   {
2387     WGenericMatrix<double, 2, 2> out;
2388     for (int i=0; i<2; i++) {
2389       for (int j=0; j<2; j++) {
2390 	out.at(i, j) = (double)m.at(i, j);
2391       }
2392     }
2393     uniformMatrix2(location, out);
2394   }
2395 
2396 /// \cond
2397   void uniformMatrix2(const UniformLocation &location,
2398                       const WGenericMatrix<double, 2, 2> &m);
2399 /// \endcond
2400 #else
2401 ;
2402 #endif
2403 
2404   /*! \brief GL function to set the value of a uniform matrix of the current
2405    * program
2406    *
2407    * Attention: The OpenGL ES specification states that transpose MUST be
2408    * false.
2409    *
2410    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2411    * glUniform() OpenGL ES manpage</a>
2412    */
WT_WGL_TEMPLATE(typename MatrixType)2413   WT_WGL_TEMPLATE(typename MatrixType)
2414   void uniformMatrix3fv(const UniformLocation &location, bool transpose,
2415 			const WT_ARRAY MatrixType *value)
2416 #ifndef WT_TARGET_JAVA
2417   {
2418     double out[9];
2419     for (int i=0; i<9; i++) {
2420       out[i] = (double)value[i];
2421     }
2422     uniformMatrix3fv(location, transpose, out);
2423   }
2424 
2425 /// \cond
2426   void uniformMatrix3fv(const UniformLocation &location, bool transpose,
2427 			const WT_ARRAY double *value);
2428 /// \endcond
2429 #else
2430 ;
2431 #endif
2432 
2433   /*! \brief GL function to set the value of a uniform matrix of the current
2434    * program
2435    *
2436    * This function renders the matrix in the proper row/column order.
2437    *
2438    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2439    * glUniform() OpenGL ES manpage</a>
2440    */
WT_WGL_TEMPLATE(typename MatrixType)2441   WT_WGL_TEMPLATE(typename MatrixType)
2442   void uniformMatrix3(const UniformLocation &location,
2443 		      const WGenericMatrix<MatrixType, 3, 3> &m)
2444 #ifndef WT_TARGET_JAVA
2445   {
2446     WGenericMatrix<double, 3, 3> out;
2447     for (int i=0; i<3; i++) {
2448       for (int j=0; j<3; j++) {
2449 	out.at(i, j) = (double)m.at(i, j);
2450       }
2451     }
2452     uniformMatrix3(location, out);
2453   }
2454 
2455 /// \cond
2456   void uniformMatrix3(const UniformLocation &location,
2457 		      const WGenericMatrix<double, 3, 3> &m);
2458 /// \endcond
2459 #else
2460 ;
2461 #endif
2462 
2463   /*! \brief GL function to set the value of a uniform matrix of the current
2464    * program
2465    *
2466    * Attention: The OpenGL ES specification states that transpose MUST be
2467    * false.
2468    *
2469    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2470    * glUniform() OpenGL ES manpage</a>
2471    */
WT_WGL_TEMPLATE(typename MatrixType)2472   WT_WGL_TEMPLATE(typename MatrixType)
2473   void uniformMatrix4fv(const UniformLocation &location, bool transpose,
2474                         const WT_ARRAY MatrixType *value)
2475 #ifndef WT_TARGET_JAVA
2476   {
2477     double out[16];
2478     for (int i=0; i<16; i++) {
2479       out[i] = (double)value[i];
2480     }
2481     uniformMatrix4fv(location, transpose, out);
2482   }
2483 
2484 /// \cond
2485   void uniformMatrix4fv(const UniformLocation &location, bool transpose,
2486                         const WT_ARRAY double *value);
2487 /// \endcond
2488 #else
2489 ;
2490 #endif
2491 
2492   /*! \brief GL function to set the value of a uniform matrix of the current
2493    * program
2494    *
2495    * This function renders the matrix in the proper row/column order.
2496    *
2497    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2498    * glUniform() OpenGL ES manpage</a>
2499    */
WT_WGL_TEMPLATE(typename MatrixType)2500   WT_WGL_TEMPLATE(typename MatrixType)
2501   void uniformMatrix4(const UniformLocation &location,
2502                       const WGenericMatrix<MatrixType, 4, 4> &m)
2503 #ifndef WT_TARGET_JAVA
2504   {
2505     WGenericMatrix<double, 4, 4> out;
2506     for (int i=0; i<4; i++) {
2507       for (int j=0; j<4; j++) {
2508 	out.at(i, j) = (double)m.at(i, j);
2509       }
2510     }
2511     uniformMatrix4(location, out);
2512   }
2513 
2514 /// \cond
2515   void uniformMatrix4(const UniformLocation &location,
2516                       const WGenericMatrix<double, 4, 4> &m);
2517 /// \endcond
2518 #else
2519 ;
2520 #endif
2521 
2522   /*! \brief GL function to set the value of a uniform matrix of the current
2523    * program
2524    *
2525    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUniform.xml">
2526    * glUniform() OpenGL ES manpage</a>
2527    */
2528   void uniformMatrix4(const UniformLocation &location,
2529                       const JavaScriptMatrix4x4 &m);
2530 
2531 
2532   /*! \brief GL function to set the current active shader program
2533    *
2534    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glUseProgram.xml">
2535    * glUseProgram() OpenGL ES manpage</a>
2536    */
2537   void useProgram(Program program);
2538 
2539   /*! \brief GL function to validate a program
2540    *
2541    * implementation note: there is currently not yet a method to read
2542    * out the validation result.
2543    *
2544    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glValidateProgram.xml">
2545    * glValidateProgram() OpenGL ES manpage</a>
2546    */
2547   void validateProgram(Program program);
2548 
2549   /*! \brief GL function to set the value of an attribute of the current program
2550    *
2551    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2552    * glVertexAttrib() OpenGL ES manpage</a>
2553    */
2554   void vertexAttrib1f(AttribLocation location, double x);
2555 
2556 #ifndef WT_TARGET_JAVA
2557   /*! \brief GL function to set the value of an attribute of the current program
2558    *
2559    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2560    * glVertexAttrib() OpenGL ES manpage</a>
2561    */
WT_WGL_TEMPLATE(typename FloatArray)2562   WT_WGL_TEMPLATE(typename FloatArray)
2563   void vertexAttrib1fv(AttribLocation location,
2564 		       const WT_ARRAY FloatArray *values) {
2565     vertexAttrib1f(location, values[0]);
2566   }
2567 #endif
2568 
2569   /*! \brief GL function to set the value of an attribute of the current program
2570    *
2571    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2572    * glVertexAttrib() OpenGL ES manpage</a>
2573    */
2574   void vertexAttrib2f(AttribLocation location, double x, double y);
2575 
2576   /*! \brief GL function to set the value of an attribute of the current program
2577    *
2578    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2579    * glVertexAttrib() OpenGL ES manpage</a>
2580    */
WT_WGL_TEMPLATE(typename FloatArray)2581   WT_WGL_TEMPLATE(typename FloatArray)
2582   void vertexAttrib2fv(AttribLocation location,
2583 		       const WT_ARRAY FloatArray *values) {
2584     vertexAttrib2f(location, values[0], values[1]);
2585   }
2586 
2587   /*! \brief GL function to set the value of an attribute of the current program
2588    *
2589    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2590    * glVertexAttrib() OpenGL ES manpage</a>
2591    */
2592   void vertexAttrib3f(AttribLocation location, double x, double y, double z);
2593 
2594   /*! \brief GL function to set the value of an attribute of the current program
2595    *
2596    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2597    * glVertexAttrib() OpenGL ES manpage</a>
2598    */
WT_WGL_TEMPLATE(typename FloatArray)2599   WT_WGL_TEMPLATE(typename FloatArray)
2600   void vertexAttrib3fv(AttribLocation location,
2601 		       const WT_ARRAY FloatArray *values) {
2602     vertexAttrib3f(location, values[0], values[1], values[2]);
2603   }
2604 
2605   /*! \brief GL function to set the value of an attribute of the current program
2606    *
2607    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2608    * glVertexAttrib() OpenGL ES manpage</a>
2609    */
2610   void vertexAttrib4f(AttribLocation location,
2611                       double x, double y, double z, double w);
2612 
2613   /*! \brief GL function to set the value of an attribute of the current program
2614    *
2615    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttrib.xml">
2616    * glVertexAttrib() OpenGL ES manpage</a>
2617    */
WT_WGL_TEMPLATE(typename FloatArray)2618   WT_WGL_TEMPLATE(typename FloatArray)
2619   void vertexAttrib4fv(AttribLocation location,
2620 		       const WT_ARRAY FloatArray *values) {
2621     vertexAttrib4f(location, values[0], values[1], values[2], values[3]);
2622   }
2623 
2624   /*! \brief GL function to bind a VBO to an attribute
2625    *
2626    * This function links the given attribute to the VBO currently bound
2627    * to the ARRAY_BUFFER target.
2628    *
2629    * The size parameter specifies the number of components per attribute (1
2630    * to 4). The type parameter is also used to determine the size of each
2631    * component.
2632    *
2633    * The size of a float is 8 bytes.
2634    *
2635    * In WGLWidget, the size of an int is 4 bytes.
2636    *
2637    * The stride is in bytes.
2638    *
2639    * The maximum stride is 255.
2640    *
2641    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glVertexAttribPointer.xml">
2642    * glVertexAttribPointer() OpenGL ES manpage</a>
2643    */
2644   void vertexAttribPointer(AttribLocation location, int size,
2645     GLenum type, bool normalized, unsigned stride, unsigned offset);
2646 
2647   /*! \brief GL function to set the viewport
2648    *
2649    * <a href="http://www.khronos.org/opengles/sdk/2.0/docs/man/xhtml/glViewport.xml">
2650    * glViewport() OpenGL ES manpage</a>
2651    */
2652   void viewport(int x, int y, unsigned width, unsigned height);
2653 
2654   //!@}
2655 
2656   /*! @name Client-side vectors and matrices
2657    *
2658    * These methods can be used to modify
2659    * vectors and matrices client-side, to change
2660    * the GL uniforms without a roundtrip to the server.
2661    * @{
2662    */
2663 
2664   /*! \brief Create a matrix that can be manipulated in client-side
2665    * JavaScript
2666    *
2667    * This is a shorthand for creating a JavaScriptMatrix4x4,
2668    * then adding it to a WGLWidget with addJavaScriptMatrix4,
2669    * and initializing it with initJavaScriptMatrix4.
2670    *
2671    * This method should only be called in initializeGL(),
2672    * updateGL() or resizeGL().
2673    */
2674   JavaScriptMatrix4x4 createJavaScriptMatrix4();
2675 
2676   /*! \brief Register a matrix with this WGLWidget.
2677    *
2678    * You can call this outside of resizeGL(), paintGL(), updateGL()
2679    * or initializeGL() methods. After a JavaScriptMatrix4x4 is
2680    * added to a WGLWidget, its jsRef() becomes valid, and can be
2681    * used in a JSlot, for example.
2682    */
2683   void addJavaScriptMatrix4(JavaScriptMatrix4x4 &m);
2684 
2685   /*! \brief Initialize the client-side JavaScript for the
2686    * given JavaScriptMatrix4x4
2687    *
2688    * If the given matrix is not associated with a widget yet,
2689    * it will be added to this widget.
2690    *
2691    * If the given matrix has already been added to a WGLWidget,
2692    * then this WGLWidget should be the same as the one you call
2693    * initJavaScriptMatrix4 on.
2694    *
2695    * This method should only be called in initializeGL(),
2696    * updateGL() or resizeGL().
2697    */
2698   void initJavaScriptMatrix4(JavaScriptMatrix4x4 &m);
2699 
2700   /*! \brief Set the value of a client-side JavaScript matrix created by
2701    * createJavaScriptMatrix4x4()
2702    *
2703    * This method should only be called in initializeGL(),
2704    * updateGL() or resizeGL().
2705    */
WT_WGL_TEMPLATE(typename MatrixType)2706   WT_WGL_TEMPLATE(typename MatrixType)
2707   void setJavaScriptMatrix4(JavaScriptMatrix4x4 &jsm,
2708                             const WGenericMatrix<MatrixType, 4, 4> &m)
2709 #ifndef WT_TARGET_JAVA
2710   {
2711     WGenericMatrix<double, 4, 4> out;
2712     for (int i=0; i<4; i++) {
2713       for (int j=0; j<4; j++) {
2714 	out.at(i, j) = (double)m.at(i, j);
2715       }
2716     }
2717     setJavaScriptMatrix4(jsm, out);
2718   }
2719 
2720 /// \cond
2721   void setJavaScriptMatrix4(JavaScriptMatrix4x4 &jsm,
2722                             const WGenericMatrix<double, 4, 4> &m);
2723 /// \endcond
2724 #else
2725 ;
2726 #endif
2727 
2728   /*! \brief Create a vector of a certain length that can be manipulated
2729    * in client-side JavaScript
2730    *
2731    * This is a shorthand for creating a JavaScriptVector,
2732    * then adding it to a WGLWidget with addJavaScriptVector,
2733    * and initializing it with initJavaScriptVector.
2734    *
2735    * This method should only be called in initializeGL(),
2736    * updateGL() or resizeGL().
2737    */
2738   JavaScriptVector createJavaScriptVector(unsigned length);
2739 
2740   /*! \brief Register a vector with this WGLWidget.
2741    *
2742    * You can call this outside of resizeGL(), paintGL(), updateGL()
2743    * or initializeGL() methods. After a JavaScriptVector is
2744    * added to a WGLWidget, its jsRef() becomes valid, and can be
2745    * used in a JSlot, for example.
2746    */
2747   void addJavaScriptVector(JavaScriptVector &v);
2748 
2749   /*! \brief Initialize the client-side JavaScript for the
2750    * given JavaScriptVector
2751    *
2752    * If the given vector is not associated with a widget yet,
2753    * it will be added to this widget.
2754    *
2755    * If the given vector has already been added to a WGLWidget,
2756    * then this WGLWidget should be the same as the one you call
2757    * initJavaScriptVector on.
2758    *
2759    * This method should only be called in initializeGL(),
2760    * updateGL() or resizeGL().
2761    */
2762   void initJavaScriptVector(JavaScriptVector &v);
2763 
2764   /*! \brief Set the value of a client-side JavaScript vector created by
2765    * createJavaScriptVector()
2766    *
2767    * This method should only be called in initializeGL(),
2768    * updateGL() or resizeGL().
2769    */
2770   void setJavaScriptVector(JavaScriptVector &jsv,
2771 			   const std::vector<float> &v);
2772 
2773   //!@}
2774 
2775   /*! \brief Set a custom mouse handler based on the given JavaScript code.
2776    *
2777    * The handler code should be JavaScript code that produces an object when evaluated.
2778    *
2779    * A mouse handler is an object that can implement one or more of the following functions:
2780    *
2781    * - <b>setTarget(target)</b>: This is called immediately when the mouse handler is added with an
2782    *                       object that uniquely identifies the WGLWidget, and a paintGL() method.
2783    * - <b>mouseDown(o, event)</b>: To handle the \c mousedown event. \c o is the \c &lt;canvas> (client-side rendering)
2784    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2785    *			    the \c MouseEvent.
2786    * - <b>mouseUp(o, event)</b>: To handle the \c mouseup event. \c o is the \c &lt;canvas> (client-side rendering)
2787    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2788    *			    the \c MouseEvent.
2789    * - <b>mouseDrag(o, event)</b>: Called when the mouse is dragged. \c o is the \c &lt;canvas> (client-side rendering)
2790    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2791    *			    the \c MouseEvent.
2792    * - <b>mouseMove(o, event)</b>: Called when the mouse is moved. \c o is the \c &lt;canvas> (client-side rendering)
2793    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2794    *			    the \c MouseEvent.
2795    * - <b>mouseWheel(o, event)</b>: Called when the mouse wheel is used. \c o is the \c &lt;canvas> (client-side rendering)
2796    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2797    *			    the \c MouseEvent.
2798    * - <b>touchStart(o, event)</b>: To handle the \c touchstart event. \c o is the \c &lt;canvas> (client-side rendering)
2799    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2800    *			    the \c TouchEvent.
2801    * - <b>touchEnd(o, event)</b>: To handle the \c touchend event. \c o is this \c &lt;canvas> (client-side rendering)
2802    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2803    *			    the \c TouchEvent.
2804    * - <b>touchMoved(o, event)</b>: To handle the \c touchmove event. \c o is this \c &lt;canvas> (client-side rendering)
2805    *			    or \c &lt;img> (server-side rendering) element corresponding to this WGLWidget. \c event is
2806    *			    the \c TouchEvent.
2807    *
2808    *
2809    * For example, if we wanted to scale some object when we scroll, we could create
2810    * a JavaScriptMatrix4x4 called \p transform_:
2811    *
2812    * \if cpp
2813    * \code
2814 private:
2815   JavaScriptMatrix4x4 transform_;
2816      \endcode
2817    * \endif
2818    *
2819    * \if java
2820    * \code
2821 private JavaScriptMatrix4x4 transform_;
2822      \endcode
2823    * \endif
2824    *
2825    * We can add this in the constructor:
2826    *
2827    * \if cpp
2828    * \code
2829 addJavaScriptMatrix4(transform_);
2830      \endcode
2831    * \endif
2832    *
2833    * \if java
2834    * \code
2835 transform_ = new JavaScriptMatrix4x4();
2836 addJavaScriptMatrix4(transform_);
2837      \endcode
2838    * \endif
2839    *
2840    * Then, in initializeGL(), we can initialize it and set the value:
2841    *
2842    * \if cpp
2843    * \code
2844 initJavaScriptMatrix4(transform_);
2845 setJavaScriptMatrix4(transform_, WMatrix4x4()); // Set to identity matrix
2846      \endcode
2847    * \endif
2848    *
2849    * \if java
2850    * \code
2851 initJavaScriptMatrix4(transform_);
2852 setJavaScriptMatrix4(transform_, new WMatrix4x4()); // Set to identity matrix
2853      \endcode
2854    * \endif
2855    *
2856    * Then, still in initializeGL(), we can set a mouse handler as such:
2857    *
2858    * \if cpp
2859    * \code
2860 setClientSideMouseHandler(std::string("(function(){") +
2861   "var MouseHandler = function(transform) {"
2862     "var target = null;"
2863     "this.setTarget = function(newTarget) {"
2864       "target = newTarget;"
2865     "};"
2866     "this.mouseWheel = function(o, event) {"
2867       "var fix = jQuery.event.fix(event);"
2868       "fix.preventDefault();"
2869       "fix.stopPropagation();"
2870       "var d = wheelDelta(event);"
2871       "var s = Math.pow(1.2, d);"
2872       "transform[0] *= s;" // Scale X
2873       "transform[5] *= s;" // Scale Y
2874       "transform[10] *= s;" // Scale Z
2875       "target.paintGL();" // Repaint
2876     "};"
2877     "function wheelDelta(e) {"
2878       "var delta = 0;"
2879       "if (e.wheelDelta) {"
2880 	"delta = e.wheelDelta > 0 ? 1 : -1;"
2881       "} else if (e.detail) {"
2882 	"delta = e.detail < 0 ? 1 : -1;"
2883       "}"
2884       "return delta;"
2885     "}"
2886   "};"
2887   "return new MouseHandler(" + transform_.jsRef() + ");"
2888 "})()");
2889      \endcode
2890    * \endif
2891    *
2892    * \if java
2893    * \code
2894 setClientSideMouseHandler("(function(){") +
2895   "var MouseHandler = function(transform) {" +
2896     "var target = null;" +
2897     "this.setTarget = function(newTarget) {" +
2898       "target = newTarget;" +
2899     "};" +
2900     "this.mouseWheel = function(o, event) {" +
2901       "var fix = jQuery.event.fix(event);" +
2902       "fix.preventDefault();" +
2903       "fix.stopPropagation();" +
2904       "var d = wheelDelta(event);" +
2905       "var s = Math.pow(1.2, d);" +
2906       "transform[0] *= s;" + // Scale X
2907       "transform[5] *= s;" + // Scale Y
2908       "transform[10] *= s;" + // Scale Z
2909       "target.paintGL();" + // Repaint
2910     "};" +
2911     "function wheelDelta(e) {" +
2912       "var delta = 0;" +
2913       "if (e.wheelDelta) {" +
2914 	"delta = e.wheelDelta > 0 ? 1 : -1;" +
2915       "} else if (e.detail) {" +
2916 	"delta = e.detail < 0 ? 1 : -1;" +
2917       "}" +
2918       "return delta;" +
2919     "}" +
2920   "};" +
2921   "return new MouseHandler(" + transform_.jsRef() + ");" +
2922 "})()");
2923      \endcode
2924    * \endif
2925    *
2926    * All that's left to do then is to use this transform somewhere as a uniform variable,
2927    * see getUniformLocation() and uniformMatrix4().
2928    */
2929   void setClientSideMouseHandler(const std::string& handlerCode);
2930 
2931   /*! \brief Add a mouse handler to the widget that looks at a given point
2932    *
2933    * This will allow a user to change client-side matrix m with the
2934    * mouse. M is a model transformation matrix, representing the viewpoint of
2935    * the camera.
2936    *
2937    * Through mouse operations, the camera can be changed by the user, but
2938    * (lX, lY, lZ) will always be at the center of the display, (uX, uY, uZ)
2939    * is considered to be the up direction, and the distance of the camera to
2940    * (lX, lY, lZ) will never change.
2941    *
2942    * Pressing the left mouse button and moving the mouse left/right will
2943    * rotate the camera around the up (uX, uY, uZ) direction. Moving up/down
2944    * will tilt the camera (causing it to move up/down to keep the lookpoint
2945    * centered). The scroll wheel simulates zooming by scaling the scene.
2946    *
2947    * pitchRate and yawRate control how much the camera will move per mouse
2948    * pixel.
2949    *
2950    * Usually this method is called after setting a camera transformation
2951    * with a client-side matrix in initializeGL(). However, this function
2952    * may also be called from outside the intializeGL()/paintGL()/updateGL()
2953    * methods (but not before m was initialized).
2954    */
2955   void setClientSideLookAtHandler(const JavaScriptMatrix4x4 &m,
2956                                   double lX, double lY, double lZ,
2957                                   double uX, double uY, double uZ,
2958                                   double pitchRate, double yawRate);
2959 
2960   /*! \brief Add a mouse handler to the widget that allows 'walking' in
2961    * the scene
2962    *
2963    * This will allow a user to change client-side matrix m with the
2964    * mouse. M is a model transformation matrix, representing the viewpoint of
2965    * the camera.
2966    *
2967    * Through mouse operations, the camera can be changed by the user, as if
2968    * he is walking around on a plane.
2969    *
2970    * Pressing the left mouse button and moving the mouse left/right will
2971    * rotate the camera around Y axis. Moving the mouse up/down will move
2972    * the camera in the Z direction (walking forward/backward).
2973    * centered).
2974    *
2975    * frontStep and rotStep control how much the camera will move per mouse
2976    * pixel.
2977    */
2978   void setClientSideWalkHandler(const JavaScriptMatrix4x4 &m,
2979                                 double frontStep, double rotStep);
2980 
2981   /*! \brief Sets the content to be displayed when WebGL is not available.
2982    *
2983    * If %Wt cannot create a working WebGL context, this content will be
2984    * shown to the user. This may be a text explanation, or a pre-rendered
2985    * image, or a video, a flash movie, ...
2986    *
2987    * The default is a widget that explains to the user that he has no
2988    * WebGL support.
2989    */
2990   void setAlternativeContent(std::unique_ptr<WWidget> alternative);
2991 
2992   /*! \brief A JavaScript slot that repaints the widget when triggered.
2993    *
2994    * This is useful for client-side initiated repaints. You may e.g. use this
2995    * if you write your own client-side mouse handler, or if you updated
2996    * a texture, or if you're playing a video texture.
2997    */
repaintSlot()2998   JSlot &repaintSlot() { return repaintSlot_; }
2999 
3000   /*! \brief enable client-side error messages (read detailed doc!)
3001    *
3002    * This option will add client-side code to check the result of every
3003    * WebGL call, and will popup an error dialog if a WebGL call returned
3004    * an error. The JavaScript then invokes the client-side debugger. This
3005    * code is intended to test your application, and should not be used in
3006    * production.
3007    */
3008   void enableClientErrorChecks(bool enable = true);
3009 
3010   /*! \brief Inject JavaScript into the current js-stream.
3011    *
3012    * Careful: this method directly puts the given jsString into
3013    * the JavaScript stream, whatever state it current has.
3014    * For example, if called in initGL(), it will put the jsString
3015    * into the client-side initGL() code.
3016    */
3017   void injectJS(const std::string & jsString);
3018 
3019   void webglNotAvailable();
3020 
3021 protected:
3022   virtual DomElementType domElementType() const override;
3023   virtual DomElement *createDomElement(WApplication *app) override;
3024   virtual void getDomChanges(std::vector<DomElement *>& result, WApplication *app) override;
3025   virtual void updateDom(DomElement &element, bool all) override;
3026 
3027   virtual void render(WFlags<RenderFlag> flags) override;
3028   virtual std::string renderRemoveJs(bool recursive) override;
3029 
3030   virtual void layoutSizeChanged(int width, int height) override;
3031 
3032   virtual void setFormData(const FormData& formData) override;
3033 
3034   virtual void contextRestored();
3035 
3036 private:
3037 
3038   WFlags<GLRenderOption> renderOptions_;
3039   std::unique_ptr<WAbstractGLImplementation> pImpl_;
3040   struct jsMatrixMap {
3041     int id;
3042     WMatrix4x4 serverSideCopy;
3043 
jsMatrixMapjsMatrixMap3044     jsMatrixMap(int matId, const WMatrix4x4& ssCopy)
3045       : id(matId), serverSideCopy(ssCopy)
3046     {}
3047   };
3048   struct jsVectorMap {
3049     int id;
3050     std::vector<float> serverSideCopy;
3051 
jsVectorMapjsVectorMap3052     jsVectorMap(int vecId, const std::vector<float> &ssCopy)
3053       : id(vecId), serverSideCopy(ssCopy)
3054     {}
3055   };
3056   std::vector<jsMatrixMap> jsMatrixList_;
3057   std::vector<jsVectorMap> jsVectorList_;
3058   unsigned jsValues_;
3059   std::stringstream js_;
3060   JSignal<> repaintSignal_;
3061 
3062   std::string glObjJsRef() const;
3063 
3064   std::unique_ptr<WWidget> alternative_;
3065 
3066   // If client detects that a WebGL context cannot be created, it fires this
3067   // signal, and the handler sets wegGlNotAvailable_ to true. If this happens,
3068   // the client side will have deleted the canvas widget.
3069   JSignal<> webglNotAvailable_;
3070   bool webGlNotAvailable_;
3071 
3072   JSignal<> contextRestored_;
3073   bool restoringContext_;
3074 
3075   bool valueChanged_;
3076 
3077   JSlot mouseWentDownSlot_;
3078   JSlot mouseWentUpSlot_;
3079   JSlot mouseDraggedSlot_;
3080   JSlot mouseMovedSlot_;
3081   JSlot mouseWheelSlot_;
3082   JSlot touchStarted_;
3083   JSlot touchEnded_;
3084   JSlot touchMoved_;
3085   JSlot repaintSlot_;
3086 
3087   void defineJavaScript();
3088 
3089 #ifdef WT_TARGET_JAVA
3090 static void renderfv(std::ostream &os, WGenericMatrix<MatrixType, 4, 4> t,
3091 		     JsArrayType type);
3092 #endif
3093 
3094   friend class WGLWidget::JavaScriptMatrix4x4;
3095   friend class WClientGLWidget;
3096   friend class WServerGLWidget;
3097 };
3098 
3099 W_DECLARE_OPERATORS_FOR_FLAGS(WGLWidget::GLenum)
3100 W_DECLARE_OPERATORS_FOR_FLAGS(GLClientSideRenderer)
3101 W_DECLARE_OPERATORS_FOR_FLAGS(GLRenderOption)
3102 }
3103 
3104 #undef WT_WGL_TEMPLATE
3105 
3106 #endif
3107