1 /*
2  * Copyright (C) 2013 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 #include "Wt/WClientGLWidget.h"
7 #include "WebUtils.h"
8 #include "Wt/WApplication.h"
9 #include "Wt/WEnvironment.h"
10 #include "Wt/WFileResource.h"
11 #include "Wt/WWebWidget.h"
12 #include "Wt/WMemoryResource.h"
13 #include "Wt/WCanvasPaintDevice.h"
14 #include "Wt/WRasterImage.h"
15 #include "Wt/WImage.h"
16 #include "Wt/WVideo.h"
17 
18 #include <ostream>
19 #include <fstream>
20 #include <limits>
21 
22 namespace Wt {
23 
WClientGLWidget(WGLWidget * glInterface)24 WClientGLWidget::WClientGLWidget(WGLWidget *glInterface)
25   : WAbstractGLImplementation(glInterface),
26     shaders_(0),
27     programs_(0),
28     attributes_(0),
29     uniforms_(0),
30     buffers_(0),
31     arrayBuffers_(0),
32     framebuffers_(0),
33     renderbuffers_(0),
34     textures_(0),
35     images_(1), // id 0 is reserved for the deprecated preloading with
36                 // createTextureAndLoad()
37     canvas_(0)
38 {}
39 
40 #ifndef WT_TARGET_JAVA
makeFloat(double d,char * buf)41 const char *WClientGLWidget::makeFloat(double d, char *buf)
42 {
43   return Utils::round_js_str(d, 6, buf);
44 }
45 
makeInt(int i,char * buf)46 const char *WClientGLWidget::makeInt(int i, char *buf)
47 {
48   return Utils::itoa(i, buf);
49 }
50 #endif
51 
toString(WGLWidget::GLenum e)52 const char *WClientGLWidget::toString(WGLWidget::GLenum e)
53 {
54   switch(e) {
55     case WGLWidget::DEPTH_BUFFER_BIT: return "ctx.DEPTH_BUFFER_BIT";
56     case WGLWidget::STENCIL_BUFFER_BIT: return "ctx.STENCIL_BUFFER_BIT";
57     case WGLWidget::COLOR_BUFFER_BIT: return "ctx.COLOR_BUFFER_BIT";
58     case WGLWidget::POINTS: return "ctx.POINTS";
59     case WGLWidget::LINES: return "ctx.LINES";
60     case WGLWidget::LINE_LOOP: return "ctx.LINE_LOOP";
61     case WGLWidget::LINE_STRIP: return "ctx.LINE_STRIP";
62     case WGLWidget::TRIANGLES: return "ctx.TRIANGLES";
63     case WGLWidget::TRIANGLE_STRIP: return "ctx.TRIANGLE_STRIP";
64     case WGLWidget::TRIANGLE_FAN: return "ctx.TRIANGLE_FAN";
65     //case WGLWidget::ZERO: return "ctx.ZERO";
66     //case WGLWidget::ONE: return "ctx.ONE";
67     case WGLWidget::SRC_COLOR: return "ctx.SRC_COLOR";
68     case WGLWidget::ONE_MINUS_SRC_COLOR: return "ctx.ONE_MINUS_SRC_COLOR";
69     case WGLWidget::SRC_ALPHA: return "ctx.SRC_ALPHA";
70     case WGLWidget::ONE_MINUS_SRC_ALPHA: return "ctx.ONE_MINUS_SRC_ALPHA";
71     case WGLWidget::DST_ALPHA: return "ctx.DST_ALPHA";
72     case WGLWidget::ONE_MINUS_DST_ALPHA: return "ctx.ONE_MINUS_DST_ALPHA";
73     case WGLWidget::DST_COLOR: return "ctx.DST_COLOR";
74     case WGLWidget::ONE_MINUS_DST_COLOR: return "ctx.ONE_MINUS_DST_COLOR";
75     case WGLWidget::SRC_ALPHA_SATURATE: return "ctx.SRC_ALPHA_SATURATE";
76     case WGLWidget::FUNC_ADD: return "ctx.FUNC_ADD";
77     case WGLWidget::BLEND_EQUATION: return "ctx.BLEND_EQUATION";
78     //case WGLWidget::BLEND_EQUATION_RGB: return "ctx.BLEND_EQUATION_RGB";
79     case WGLWidget::BLEND_EQUATION_ALPHA: return "ctx.BLEND_EQUATION_ALPHA";
80     case WGLWidget::FUNC_SUBTRACT: return "ctx.FUNC_SUBTRACT";
81     case WGLWidget::FUNC_REVERSE_SUBTRACT: return "ctx.FUNC_REVERSE_SUBTRACT";
82     case WGLWidget::BLEND_DST_RGB: return "ctx.BLEND_DST_RGB";
83     case WGLWidget::BLEND_SRC_RGB: return "ctx.BLEND_SRC_RGB";
84     case WGLWidget::BLEND_DST_ALPHA: return "ctx.BLEND_DST_ALPHA";
85     case WGLWidget::BLEND_SRC_ALPHA: return "ctx.BLEND_SRC_ALPHA";
86     case WGLWidget::CONSTANT_COLOR: return "ctx.CONSTANT_COLOR";
87     case WGLWidget::ONE_MINUS_CONSTANT_COLOR: return "ctx.ONE_MINUS_CONSTANT_COLOR";
88     case WGLWidget::CONSTANT_ALPHA: return "ctx.CONSTANT_ALPHA";
89     case WGLWidget::ONE_MINUS_CONSTANT_ALPHA: return "ctx.ONE_MINUS_CONSTANT_ALPHA";
90     case WGLWidget::BLEND_COLOR: return "ctx.BLEND_COLOR";
91     case WGLWidget::ARRAY_BUFFER: return "ctx.ARRAY_BUFFER";
92     case WGLWidget::ELEMENT_ARRAY_BUFFER: return "ctx.ELEMENT_ARRAY_BUFFER";
93     case WGLWidget::ARRAY_BUFFER_BINDING: return "ctx.ARRAY_BUFFER_BINDING";
94     case WGLWidget::ELEMENT_ARRAY_BUFFER_BINDING: return "ctx.ELEMENT_ARRAY_BUFFER_BINDING";
95     case WGLWidget::STREAM_DRAW: return "ctx.STREAM_DRAW";
96     case WGLWidget::STATIC_DRAW: return "ctx.STATIC_DRAW";
97     case WGLWidget::DYNAMIC_DRAW: return "ctx.DYNAMIC_DRAW";
98     case WGLWidget::BUFFER_SIZE: return "ctx.BUFFER_SIZE";
99     case WGLWidget::BUFFER_USAGE: return "ctx.BUFFER_USAGE";
100     case WGLWidget::CURRENT_VERTEX_ATTRIB: return "ctx.CURRENT_VERTEX_ATTRIB";
101     case WGLWidget::FRONT: return "ctx.FRONT";
102     case WGLWidget::BACK: return "ctx.BACK";
103     case WGLWidget::FRONT_AND_BACK: return "ctx.FRONT_AND_BACK";
104     case WGLWidget::CULL_FACE: return "ctx.CULL_FACE";
105     case WGLWidget::BLEND: return "ctx.BLEND";
106     case WGLWidget::DITHER: return "ctx.DITHER";
107     case WGLWidget::STENCIL_TEST: return "ctx.STENCIL_TEST";
108     case WGLWidget::DEPTH_TEST: return "ctx.DEPTH_TEST";
109     case WGLWidget::SCISSOR_TEST: return "ctx.SCISSOR_TEST";
110     case WGLWidget::POLYGON_OFFSET_FILL: return "ctx.POLYGON_OFFSET_FILL";
111     case WGLWidget::SAMPLE_ALPHA_TO_COVERAGE: return "ctx.SAMPLE_ALPHA_TO_COVERAGE";
112     case WGLWidget::SAMPLE_COVERAGE: return "ctx.SAMPLE_COVERAGE";
113     //case WGLWidget::NO_ERROR: return "ctx.NO_ERROR";
114     case WGLWidget::INVALID_ENUM: return "ctx.INVALID_ENUM";
115     case WGLWidget::INVALID_VALUE: return "ctx.INVALID_VALUE";
116     case WGLWidget::INVALID_OPERATION: return "ctx.INVALID_OPERATION";
117     case WGLWidget::OUT_OF_MEMORY: return "ctx.OUT_OF_MEMORY";
118     case WGLWidget::CW: return "ctx.CW";
119     case WGLWidget::CCW: return "ctx.CCW";
120     case WGLWidget::LINE_WIDTH: return "ctx.LINE_WIDTH";
121     case WGLWidget::ALIASED_POINT_SIZE_RANGE: return "ctx.ALIASED_POINT_SIZE_RANGE";
122     case WGLWidget::ALIASED_LINE_WIDTH_RANGE: return "ctx.ALIASED_LINE_WIDTH_RANGE";
123     case WGLWidget::CULL_FACE_MODE: return "ctx.CULL_FACE_MODE";
124     case WGLWidget::FRONT_FACE: return "ctx.FRONT_FACE";
125     case WGLWidget::DEPTH_RANGE: return "ctx.DEPTH_RANGE";
126     case WGLWidget::DEPTH_WRITEMASK: return "ctx.DEPTH_WRITEMASK";
127     case WGLWidget::DEPTH_CLEAR_VALUE: return "ctx.DEPTH_CLEAR_VALUE";
128     case WGLWidget::DEPTH_FUNC: return "ctx.DEPTH_FUNC";
129     case WGLWidget::STENCIL_CLEAR_VALUE: return "ctx.STENCIL_CLEAR_VALUE";
130     case WGLWidget::STENCIL_FUNC: return "ctx.STENCIL_FUNC";
131     case WGLWidget::STENCIL_FAIL: return "ctx.STENCIL_FAIL";
132     case WGLWidget::STENCIL_PASS_DEPTH_FAIL: return "ctx.STENCIL_PASS_DEPTH_FAIL";
133     case WGLWidget::STENCIL_PASS_DEPTH_PASS: return "ctx.STENCIL_PASS_DEPTH_PASS";
134     case WGLWidget::STENCIL_REF: return "ctx.STENCIL_REF";
135     case WGLWidget::STENCIL_VALUE_MASK: return "ctx.STENCIL_VALUE_MASK";
136     case WGLWidget::STENCIL_WRITEMASK: return "ctx.STENCIL_WRITEMASK";
137     case WGLWidget::STENCIL_BACK_FUNC: return "ctx.STENCIL_BACK_FUNC";
138     case WGLWidget::STENCIL_BACK_FAIL: return "ctx.STENCIL_BACK_FAIL";
139     case WGLWidget::STENCIL_BACK_PASS_DEPTH_FAIL: return "ctx.STENCIL_BACK_PASS_DEPTH_FAIL";
140     case WGLWidget::STENCIL_BACK_PASS_DEPTH_PASS: return "ctx.STENCIL_BACK_PASS_DEPTH_PASS";
141     case WGLWidget::STENCIL_BACK_REF: return "ctx.STENCIL_BACK_REF";
142     case WGLWidget::STENCIL_BACK_VALUE_MASK: return "ctx.STENCIL_BACK_VALUE_MASK";
143     case WGLWidget::STENCIL_BACK_WRITEMASK: return "ctx.STENCIL_BACK_WRITEMASK";
144     case WGLWidget::VIEWPORT: return "ctx.VIEWPORT";
145     case WGLWidget::SCISSOR_BOX: return "ctx.SCISSOR_BOX";
146     case WGLWidget::COLOR_CLEAR_VALUE: return "ctx.COLOR_CLEAR_VALUE";
147     case WGLWidget::COLOR_WRITEMASK: return "ctx.COLOR_WRITEMASK";
148     case WGLWidget::UNPACK_ALIGNMENT: return "ctx.UNPACK_ALIGNMENT";
149     case WGLWidget::PACK_ALIGNMENT: return "ctx.PACK_ALIGNMENT";
150     case WGLWidget::MAX_TEXTURE_SIZE: return "ctx.MAX_TEXTURE_SIZE";
151     case WGLWidget::MAX_VIEWPORT_DIMS: return "ctx.MAX_VIEWPORT_DIMS";
152     case WGLWidget::SUBPIXEL_BITS: return "ctx.SUBPIXEL_BITS";
153     case WGLWidget::RED_BITS: return "ctx.RED_BITS";
154     case WGLWidget::GREEN_BITS: return "ctx.GREEN_BITS";
155     case WGLWidget::BLUE_BITS: return "ctx.BLUE_BITS";
156     case WGLWidget::ALPHA_BITS: return "ctx.ALPHA_BITS";
157     case WGLWidget::DEPTH_BITS: return "ctx.DEPTH_BITS";
158     case WGLWidget::STENCIL_BITS: return "ctx.STENCIL_BITS";
159     case WGLWidget::POLYGON_OFFSET_UNITS: return "ctx.POLYGON_OFFSET_UNITS";
160     case WGLWidget::POLYGON_OFFSET_FACTOR: return "ctx.POLYGON_OFFSET_FACTOR";
161     case WGLWidget::TEXTURE_BINDING_2D: return "ctx.TEXTURE_BINDING_2D";
162     case WGLWidget::SAMPLE_BUFFERS: return "ctx.SAMPLE_BUFFERS";
163     case WGLWidget::SAMPLES: return "ctx.SAMPLES";
164     case WGLWidget::SAMPLE_COVERAGE_VALUE: return "ctx.SAMPLE_COVERAGE_VALUE";
165     case WGLWidget::SAMPLE_COVERAGE_INVERT: return "ctx.SAMPLE_COVERAGE_INVERT";
166     case WGLWidget::NUM_COMPRESSED_TEXTURE_FORMATS: return "ctx.NUM_COMPRESSED_TEXTURE_FORMATS";
167     case WGLWidget::COMPRESSED_TEXTURE_FORMATS: return "ctx.COMPRESSED_TEXTURE_FORMATS";
168     case WGLWidget::DONT_CARE: return "ctx.DONT_CARE";
169     case WGLWidget::FASTEST: return "ctx.FASTEST";
170     case WGLWidget::NICEST: return "ctx.NICEST";
171     case WGLWidget::GENERATE_MIPMAP_HINT: return "ctx.GENERATE_MIPMAP_HINT";
172     case WGLWidget::BYTE: return "ctx.BYTE";
173     case WGLWidget::UNSIGNED_BYTE: return "ctx.UNSIGNED_BYTE";
174     case WGLWidget::SHORT: return "ctx.SHORT";
175     case WGLWidget::UNSIGNED_SHORT: return "ctx.UNSIGNED_SHORT";
176     case WGLWidget::INT: return "ctx.INT";
177     case WGLWidget::UNSIGNED_INT: return "ctx.UNSIGNED_INT";
178     case WGLWidget::FLOAT: return "ctx.FLOAT";
179     case WGLWidget::DEPTH_COMPONENT: return "ctx.DEPTH_COMPONENT";
180     case WGLWidget::ALPHA: return "ctx.ALPHA";
181     case WGLWidget::RGB: return "ctx.RGB";
182     case WGLWidget::RGBA: return "ctx.RGBA";
183     case WGLWidget::LUMINANCE: return "ctx.LUMINANCE";
184     case WGLWidget::LUMINANCE_ALPHA: return "ctx.LUMINANCE_ALPHA";
185     case WGLWidget::UNSIGNED_SHORT_4_4_4_4: return "ctx.UNSIGNED_SHORT_4_4_4_4";
186     case WGLWidget::UNSIGNED_SHORT_5_5_5_1: return "ctx.UNSIGNED_SHORT_5_5_5_1";
187     case WGLWidget::UNSIGNED_SHORT_5_6_5: return "ctx.UNSIGNED_SHORT_5_6_5";
188     case WGLWidget::FRAGMENT_SHADER: return "ctx.FRAGMENT_SHADER";
189     case WGLWidget::VERTEX_SHADER: return "ctx.VERTEX_SHADER";
190     case WGLWidget::MAX_VERTEX_ATTRIBS: return "ctx.MAX_VERTEX_ATTRIBS";
191     case WGLWidget::MAX_VERTEX_UNIFORM_VECTORS: return "ctx.MAX_VERTEX_UNIFORM_VECTORS";
192     case WGLWidget::MAX_VARYING_VECTORS: return "ctx.MAX_VARYING_VECTORS";
193     case WGLWidget::MAX_COMBINED_TEXTURE_IMAGE_UNITS: return "ctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS";
194     case WGLWidget::MAX_VERTEX_TEXTURE_IMAGE_UNITS: return "ctx.MAX_VERTEX_TEXTURE_IMAGE_UNITS";
195     case WGLWidget::MAX_TEXTURE_IMAGE_UNITS: return "ctx.MAX_TEXTURE_IMAGE_UNITS";
196     case WGLWidget::MAX_FRAGMENT_UNIFORM_VECTORS: return "ctx.MAX_FRAGMENT_UNIFORM_VECTORS";
197     case WGLWidget::SHADER_TYPE: return "ctx.SHADER_TYPE";
198     case WGLWidget::DELETE_STATUS: return "ctx.DELETE_STATUS";
199     case WGLWidget::LINK_STATUS: return "ctx.LINK_STATUS";
200     case WGLWidget::VALIDATE_STATUS: return "ctx.VALIDATE_STATUS";
201     case WGLWidget::ATTACHED_SHADERS: return "ctx.ATTACHED_SHADERS";
202     case WGLWidget::ACTIVE_UNIFORMS: return "ctx.ACTIVE_UNIFORMS";
203     case WGLWidget::ACTIVE_UNIFORM_MAX_LENGTH: return "ctx.ACTIVE_UNIFORM_MAX_LENGTH";
204     case WGLWidget::ACTIVE_ATTRIBUTES: return "ctx.ACTIVE_ATTRIBUTES";
205     case WGLWidget::ACTIVE_ATTRIBUTE_MAX_LENGTH: return "ctx.ACTIVE_ATTRIBUTE_MAX_LENGTH";
206     case WGLWidget::SHADING_LANGUAGE_VERSION: return "ctx.SHADING_LANGUAGE_VERSION";
207     case WGLWidget::CURRENT_PROGRAM: return "ctx.CURRENT_PROGRAM";
208     case WGLWidget::NEVER: return "ctx.NEVER";
209     case WGLWidget::LESS: return "ctx.LESS";
210     case WGLWidget::EQUAL: return "ctx.EQUAL";
211     case WGLWidget::LEQUAL: return "ctx.LEQUAL";
212     case WGLWidget::GREATER: return "ctx.GREATER";
213     case WGLWidget::NOTEQUAL: return "ctx.NOTEQUAL";
214     case WGLWidget::GEQUAL: return "ctx.GEQUAL";
215     case WGLWidget::ALWAYS: return "ctx.ALWAYS";
216     case WGLWidget::KEEP: return "ctx.KEEP";
217     case WGLWidget::REPLACE: return "ctx.REPLACE";
218     case WGLWidget::INCR: return "ctx.INCR";
219     case WGLWidget::DECR: return "ctx.DECR";
220     case WGLWidget::INVERT: return "ctx.INVERT";
221     case WGLWidget::INCR_WRAP: return "ctx.INCR_WRAP";
222     case WGLWidget::DECR_WRAP: return "ctx.DECR_WRAP";
223     case WGLWidget::VENDOR: return "ctx.VENDOR";
224     case WGLWidget::RENDERER: return "ctx.RENDERER";
225     case WGLWidget::VERSION: return "ctx.VERSION";
226     case WGLWidget::NEAREST: return "ctx.NEAREST";
227     case WGLWidget::LINEAR: return "ctx.LINEAR";
228     case WGLWidget::NEAREST_MIPMAP_NEAREST: return "ctx.NEAREST_MIPMAP_NEAREST";
229     case WGLWidget::LINEAR_MIPMAP_NEAREST: return "ctx.LINEAR_MIPMAP_NEAREST";
230     case WGLWidget::NEAREST_MIPMAP_LINEAR: return "ctx.NEAREST_MIPMAP_LINEAR";
231     case WGLWidget::LINEAR_MIPMAP_LINEAR: return "ctx.LINEAR_MIPMAP_LINEAR";
232     case WGLWidget::TEXTURE_MAG_FILTER: return "ctx.TEXTURE_MAG_FILTER";
233     case WGLWidget::TEXTURE_MIN_FILTER: return "ctx.TEXTURE_MIN_FILTER";
234     case WGLWidget::TEXTURE_WRAP_S: return "ctx.TEXTURE_WRAP_S";
235     case WGLWidget::TEXTURE_WRAP_T: return "ctx.TEXTURE_WRAP_T";
236     case WGLWidget::TEXTURE_2D: return "ctx.TEXTURE_2D";
237     case WGLWidget::TEXTURE: return "ctx.TEXTURE";
238     case WGLWidget::TEXTURE_CUBE_MAP: return "ctx.TEXTURE_CUBE_MAP";
239     case WGLWidget::TEXTURE_BINDING_CUBE_MAP: return "ctx.TEXTURE_BINDING_CUBE_MAP";
240     case WGLWidget::TEXTURE_CUBE_MAP_POSITIVE_X: return "ctx.TEXTURE_CUBE_MAP_POSITIVE_X";
241     case WGLWidget::TEXTURE_CUBE_MAP_NEGATIVE_X: return "ctx.TEXTURE_CUBE_MAP_NEGATIVE_X";
242     case WGLWidget::TEXTURE_CUBE_MAP_POSITIVE_Y: return "ctx.TEXTURE_CUBE_MAP_POSITIVE_Y";
243     case WGLWidget::TEXTURE_CUBE_MAP_NEGATIVE_Y: return "ctx.TEXTURE_CUBE_MAP_NEGATIVE_Y";
244     case WGLWidget::TEXTURE_CUBE_MAP_POSITIVE_Z: return "ctx.TEXTURE_CUBE_MAP_POSITIVE_Z";
245     case WGLWidget::TEXTURE_CUBE_MAP_NEGATIVE_Z: return "ctx.TEXTURE_CUBE_MAP_NEGATIVE_Z";
246     case WGLWidget::MAX_CUBE_MAP_TEXTURE_SIZE: return "ctx.MAX_CUBE_MAP_TEXTURE_SIZE";
247     case WGLWidget::TEXTURE0: return "ctx.TEXTURE0";
248     case WGLWidget::TEXTURE1: return "ctx.TEXTURE1";
249     case WGLWidget::TEXTURE2: return "ctx.TEXTURE2";
250     case WGLWidget::TEXTURE3: return "ctx.TEXTURE3";
251     case WGLWidget::TEXTURE4: return "ctx.TEXTURE4";
252     case WGLWidget::TEXTURE5: return "ctx.TEXTURE5";
253     case WGLWidget::TEXTURE6: return "ctx.TEXTURE6";
254     case WGLWidget::TEXTURE7: return "ctx.TEXTURE7";
255     case WGLWidget::TEXTURE8: return "ctx.TEXTURE8";
256     case WGLWidget::TEXTURE9: return "ctx.TEXTURE9";
257     case WGLWidget::TEXTURE10: return "ctx.TEXTURE10";
258     case WGLWidget::TEXTURE11: return "ctx.TEXTURE11";
259     case WGLWidget::TEXTURE12: return "ctx.TEXTURE12";
260     case WGLWidget::TEXTURE13: return "ctx.TEXTURE13";
261     case WGLWidget::TEXTURE14: return "ctx.TEXTURE14";
262     case WGLWidget::TEXTURE15: return "ctx.TEXTURE15";
263     case WGLWidget::TEXTURE16: return "ctx.TEXTURE16";
264     case WGLWidget::TEXTURE17: return "ctx.TEXTURE17";
265     case WGLWidget::TEXTURE18: return "ctx.TEXTURE18";
266     case WGLWidget::TEXTURE19: return "ctx.TEXTURE19";
267     case WGLWidget::TEXTURE20: return "ctx.TEXTURE20";
268     case WGLWidget::TEXTURE21: return "ctx.TEXTURE21";
269     case WGLWidget::TEXTURE22: return "ctx.TEXTURE22";
270     case WGLWidget::TEXTURE23: return "ctx.TEXTURE23";
271     case WGLWidget::TEXTURE24: return "ctx.TEXTURE24";
272     case WGLWidget::TEXTURE25: return "ctx.TEXTURE25";
273     case WGLWidget::TEXTURE26: return "ctx.TEXTURE26";
274     case WGLWidget::TEXTURE27: return "ctx.TEXTURE27";
275     case WGLWidget::TEXTURE28: return "ctx.TEXTURE28";
276     case WGLWidget::TEXTURE29: return "ctx.TEXTURE29";
277     case WGLWidget::TEXTURE30: return "ctx.TEXTURE30";
278     case WGLWidget::TEXTURE31: return "ctx.TEXTURE31";
279     case WGLWidget::ACTIVE_TEXTURE: return "ctx.ACTIVE_TEXTURE";
280     case WGLWidget::REPEAT: return "ctx.REPEAT";
281     case WGLWidget::CLAMP_TO_EDGE: return "ctx.CLAMP_TO_EDGE";
282     case WGLWidget::MIRRORED_REPEAT: return "ctx.MIRRORED_REPEAT";
283     case WGLWidget::FLOAT_VEC2: return "ctx.FLOAT_VEC2";
284     case WGLWidget::FLOAT_VEC3: return "ctx.FLOAT_VEC3";
285     case WGLWidget::FLOAT_VEC4: return "ctx.FLOAT_VEC4";
286     case WGLWidget::INT_VEC2: return "ctx.INT_VEC2";
287     case WGLWidget::INT_VEC3: return "ctx.INT_VEC3";
288     case WGLWidget::INT_VEC4: return "ctx.INT_VEC4";
289     case WGLWidget::BOOL: return "ctx.BOOL";
290     case WGLWidget::BOOL_VEC2: return "ctx.BOOL_VEC2";
291     case WGLWidget::BOOL_VEC3: return "ctx.BOOL_VEC3";
292     case WGLWidget::BOOL_VEC4: return "ctx.BOOL_VEC4";
293     case WGLWidget::FLOAT_MAT2: return "ctx.FLOAT_MAT2";
294     case WGLWidget::FLOAT_MAT3: return "ctx.FLOAT_MAT3";
295     case WGLWidget::FLOAT_MAT4: return "ctx.FLOAT_MAT4";
296     case WGLWidget::SAMPLER_2D: return "ctx.SAMPLER_2D";
297     case WGLWidget::SAMPLER_CUBE: return "ctx.SAMPLER_CUBE";
298     case WGLWidget::VERTEX_ATTRIB_ARRAY_ENABLED: return "ctx.VERTEX_ATTRIB_ARRAY_ENABLED";
299     case WGLWidget::VERTEX_ATTRIB_ARRAY_SIZE: return "ctx.VERTEX_ATTRIB_ARRAY_SIZE";
300     case WGLWidget::VERTEX_ATTRIB_ARRAY_STRIDE: return "ctx.VERTEX_ATTRIB_ARRAY_STRIDE";
301     case WGLWidget::VERTEX_ATTRIB_ARRAY_TYPE: return "ctx.VERTEX_ATTRIB_ARRAY_TYPE";
302     case WGLWidget::VERTEX_ATTRIB_ARRAY_NORMALIZED: return "ctx.VERTEX_ATTRIB_ARRAY_NORMALIZED";
303     case WGLWidget::VERTEX_ATTRIB_ARRAY_POINTER: return "ctx.VERTEX_ATTRIB_ARRAY_POINTER";
304     case WGLWidget::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: return "ctx.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING";
305     case WGLWidget::COMPILE_STATUS: return "ctx.COMPILE_STATUS";
306     case WGLWidget::INFO_LOG_LENGTH: return "ctx.INFO_LOG_LENGTH";
307     case WGLWidget::SHADER_SOURCE_LENGTH: return "ctx.SHADER_SOURCE_LENGTH";
308     case WGLWidget::LOW_FLOAT: return "ctx.LOW_FLOAT";
309     case WGLWidget::MEDIUM_FLOAT: return "ctx.MEDIUM_FLOAT";
310     case WGLWidget::HIGH_FLOAT: return "ctx.HIGH_FLOAT";
311     case WGLWidget::LOW_INT: return "ctx.LOW_INT";
312     case WGLWidget::MEDIUM_INT: return "ctx.MEDIUM_INT";
313     case WGLWidget::HIGH_INT: return "ctx.HIGH_INT";
314     case WGLWidget::FRAMEBUFFER: return "ctx.FRAMEBUFFER";
315     case WGLWidget::RENDERBUFFER: return "ctx.RENDERBUFFER";
316     case WGLWidget::RGBA4: return "ctx.RGBA4";
317     case WGLWidget::RGB5_A1: return "ctx.RGB5_A1";
318     case WGLWidget::RGB565: return "ctx.RGB565";
319     case WGLWidget::DEPTH_COMPONENT16: return "ctx.DEPTH_COMPONENT16";
320     case WGLWidget::STENCIL_INDEX: return "ctx.STENCIL_INDEX";
321     case WGLWidget::STENCIL_INDEX8: return "ctx.STENCIL_INDEX8";
322     case WGLWidget::DEPTH_STENCIL: return "ctx.DEPTH_STENCIL";
323     case WGLWidget::RENDERBUFFER_WIDTH: return "ctx.RENDERBUFFER_WIDTH";
324     case WGLWidget::RENDERBUFFER_HEIGHT: return "ctx.RENDERBUFFER_HEIGHT";
325     case WGLWidget::RENDERBUFFER_INTERNAL_FORMAT: return "ctx.RENDERBUFFER_INTERNAL_FORMAT";
326     case WGLWidget::RENDERBUFFER_RED_SIZE: return "ctx.RENDERBUFFER_RED_SIZE";
327     case WGLWidget::RENDERBUFFER_GREEN_SIZE: return "ctx.RENDERBUFFER_GREEN_SIZE";
328     case WGLWidget::RENDERBUFFER_BLUE_SIZE: return "ctx.RENDERBUFFER_BLUE_SIZE";
329     case WGLWidget::RENDERBUFFER_ALPHA_SIZE: return "ctx.RENDERBUFFER_ALPHA_SIZE";
330     case WGLWidget::RENDERBUFFER_DEPTH_SIZE: return "ctx.RENDERBUFFER_DEPTH_SIZE";
331     case WGLWidget::RENDERBUFFER_STENCIL_SIZE: return "ctx.RENDERBUFFER_STENCIL_SIZE";
332     case WGLWidget::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: return "ctx.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE";
333     case WGLWidget::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: return "ctx.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME";
334     case WGLWidget::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: return "ctx.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL";
335     case WGLWidget::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: return "ctx.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE";
336     case WGLWidget::COLOR_ATTACHMENT0: return "ctx.COLOR_ATTACHMENT0";
337     case WGLWidget::DEPTH_ATTACHMENT: return "ctx.DEPTH_ATTACHMENT";
338     case WGLWidget::STENCIL_ATTACHMENT: return "ctx.STENCIL_ATTACHMENT";
339     case WGLWidget::DEPTH_STENCIL_ATTACHMENT: return "ctx.DEPTH_STENCIL_ATTACHMENT";
340     //case WGLWidget::NONE: return "ctx.NONE";
341     case WGLWidget::FRAMEBUFFER_COMPLETE: return "ctx.FRAMEBUFFER_COMPLETE";
342     case WGLWidget::FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "ctx.FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
343     case WGLWidget::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "ctx.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
344     case WGLWidget::FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return "ctx.FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
345     case WGLWidget::FRAMEBUFFER_UNSUPPORTED: return "ctx.FRAMEBUFFER_UNSUPPORTED";
346     case WGLWidget::FRAMEBUFFER_BINDING: return "ctx.FRAMEBUFFER_BINDING";
347     case WGLWidget::RENDERBUFFER_BINDING: return "ctx.RENDERBUFFER_BINDING";
348     case WGLWidget::MAX_RENDERBUFFER_SIZE: return "ctx.MAX_RENDERBUFFER_SIZE";
349     case WGLWidget::INVALID_FRAMEBUFFER_OPERATION: return "ctx.INVALID_FRAMEBUFFER_OPERATION";
350     case WGLWidget::UNPACK_FLIP_Y_WEBGL: return "ctx.UNPACK_FLIP_Y_WEBGL";
351     case WGLWidget::UNPACK_PREMULTIPLY_ALPHA_WEBGL: return "ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL";
352     case WGLWidget::CONTEXT_LOST_WEBGL: return "ctx.CONTEXT_LOST_WEBGL";
353     case WGLWidget::UNPACK_COLORSPACE_CONVERSION_WEBGL: return "ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL";
354     case WGLWidget::BROWSER_DEFAULT_WEBGL: return "ctx.BROWSER_DEFAULT_WEBGL";
355   }
356   return "BAD_GL_ENUM";
357 }
358 
debugger()359 void WClientGLWidget::debugger()
360 {
361   js_ << "debugger;\n";
362 }
363 
activeTexture(WGLWidget::GLenum texture)364 void WClientGLWidget::activeTexture(WGLWidget::GLenum texture)
365 {
366   js_ << "ctx.activeTexture(" << toString(texture) << ");";
367   GLDEBUG;
368 }
369 
attachShader(WGLWidget::Program program,WGLWidget::Shader shader)370 void WClientGLWidget::attachShader(WGLWidget::Program program,
371 				   WGLWidget::Shader shader)
372 {
373   js_ << "ctx.attachShader(" << program.jsRef()
374       << ", " << shader.jsRef() << ");";
375   GLDEBUG;
376 }
377 
bindAttribLocation(WGLWidget::Program program,unsigned index,const std::string & name)378 void WClientGLWidget::bindAttribLocation(WGLWidget::Program program,
379 					 unsigned index,
380 					 const std::string &name)
381 {
382   js_ << "ctx.bindAttribLocation(" << program.jsRef() << "," << index
383       << "," << WWebWidget::jsStringLiteral(name) << ");";
384   GLDEBUG;
385 }
386 
bindBuffer(WGLWidget::GLenum target,WGLWidget::Buffer buffer)387 void WClientGLWidget::bindBuffer(WGLWidget::GLenum target,
388 				 WGLWidget::Buffer buffer)
389 {
390   js_ << "ctx.bindBuffer(" << toString(target) << "," << buffer.jsRef() << ");";
391   currentlyBoundBuffer_ = buffer;
392   GLDEBUG;
393 }
394 
bindFramebuffer(WGLWidget::GLenum target,WGLWidget::Framebuffer buffer)395 void WClientGLWidget::bindFramebuffer(WGLWidget::GLenum target,
396 				      WGLWidget::Framebuffer buffer)
397 {
398   js_ << "ctx.bindFramebuffer(" << toString(target) << "," << buffer.jsRef() << ");";
399   GLDEBUG;
400 }
401 
bindRenderbuffer(WGLWidget::GLenum target,WGLWidget::Renderbuffer buffer)402 void WClientGLWidget::bindRenderbuffer(WGLWidget::GLenum target,
403 				       WGLWidget::Renderbuffer buffer)
404 {
405   js_ << "ctx.bindRenderbuffer(" << toString(target) << "," << buffer.jsRef() << ");";
406   GLDEBUG;
407 }
408 
bindTexture(WGLWidget::GLenum target,WGLWidget::Texture texture)409 void WClientGLWidget::bindTexture(WGLWidget::GLenum target,
410 				  WGLWidget::Texture texture)
411 {
412   js_ << "ctx.bindTexture(" << toString(target) << ","
413       << texture.jsRef() << ");";
414   currentlyBoundTexture_ = texture;
415   GLDEBUG;
416 }
417 
blendColor(double red,double green,double blue,double alpha)418 void WClientGLWidget::blendColor(double red, double green, double blue,
419 				 double alpha)
420 {
421   char buf[30];
422   js_ << "ctx.blendColor(" << makeFloat(red, buf) << ",";
423   js_ << makeFloat(green, buf) << ",";
424   js_ << makeFloat(blue, buf) << ",";
425   js_ << makeFloat(alpha, buf) << ");";
426   GLDEBUG;
427 }
428 
blendEquation(WGLWidget::GLenum mode)429 void WClientGLWidget::blendEquation(WGLWidget::GLenum mode)
430 {
431   js_ << "ctx.blendEquation(" << toString(mode) << ");";
432   GLDEBUG;
433 }
434 
blendEquationSeparate(WGLWidget::GLenum modeRGB,WGLWidget::GLenum modeAlpha)435 void WClientGLWidget::blendEquationSeparate(WGLWidget::GLenum modeRGB,
436 					    WGLWidget::GLenum modeAlpha)
437 {
438   js_ << "ctx.blendEquationSeparate(" << toString(modeRGB) << ","
439     << toString(modeAlpha) << ");";
440   GLDEBUG;
441 }
442 
blendFunc(WGLWidget::GLenum sfactor,WGLWidget::GLenum dfactor)443 void WClientGLWidget::blendFunc(WGLWidget::GLenum sfactor,
444 				WGLWidget::GLenum dfactor)
445 {
446   js_ << "ctx.blendFunc(" << toString(sfactor) << ","
447     << toString(dfactor) << ");";
448   GLDEBUG;
449 }
450 
blendFuncSeparate(WGLWidget::GLenum srcRGB,WGLWidget::GLenum dstRGB,WGLWidget::GLenum srcAlpha,WGLWidget::GLenum dstAlpha)451 void WClientGLWidget::blendFuncSeparate(WGLWidget::GLenum srcRGB,
452 					WGLWidget::GLenum dstRGB,
453 					WGLWidget::GLenum srcAlpha,
454 					WGLWidget::GLenum dstAlpha)
455 {
456   js_ << "ctx.blendFuncSeparate(" << toString(srcRGB) << ","
457     << toString(dstRGB) << "," << toString(srcAlpha) << ","
458     << toString(dstAlpha) << ");";
459   GLDEBUG;
460 }
461 
bufferData(WGLWidget::GLenum target,WGLWidget::ArrayBuffer res,WGLWidget::GLenum usage)462 void WClientGLWidget::bufferData(WGLWidget::GLenum target,
463 				 WGLWidget::ArrayBuffer res,
464 				 WGLWidget::GLenum usage)
465 {
466   js_ << "ctx.bufferData(" << toString(target) << ",";
467   js_ << res.jsRef() << ".data, ";
468   js_ << toString(usage) << ");";
469   GLDEBUG;
470 }
471 
bufferData(WGLWidget::GLenum target,WGLWidget::ArrayBuffer res,unsigned bufferResourceOffset,unsigned bufferResourceSize,WGLWidget::GLenum usage)472 void WClientGLWidget::bufferData(WGLWidget::GLenum target,
473 				 WGLWidget::ArrayBuffer res,
474 				 unsigned bufferResourceOffset,
475 				 unsigned bufferResourceSize,
476 				 WGLWidget::GLenum usage)
477 {
478   js_ << "ctx.bufferData(" << toString(target) << ",";
479   js_ << res.jsRef() << ".data.slice(" << bufferResourceOffset << ","
480       << bufferResourceOffset + bufferResourceSize << "),";
481   js_ << toString(usage) << ");";
482   GLDEBUG;
483 }
484 
bufferSubData(WGLWidget::GLenum target,unsigned offset,WGLWidget::ArrayBuffer res)485 void WClientGLWidget::bufferSubData(WGLWidget::GLenum target, unsigned offset,
486 				    WGLWidget::ArrayBuffer res)
487 {
488   js_ << "ctx.bufferSubData(" << toString(target) << ",";
489   js_ << offset << ",";
490   js_ << res.jsRef() << ".data);";
491   GLDEBUG;
492 }
493 
bufferSubData(WGLWidget::GLenum target,unsigned offset,WGLWidget::ArrayBuffer res,unsigned bufferResourceOffset,unsigned bufferResourceSize)494 void WClientGLWidget::bufferSubData(WGLWidget::GLenum target, unsigned offset,
495 				    WGLWidget::ArrayBuffer res,
496 				    unsigned bufferResourceOffset,
497 				    unsigned bufferResourceSize)
498 {
499   js_ << "ctx.bufferSubData(" << toString(target) << ",";
500   js_ << offset << ",";
501   js_ << res.jsRef() << ".data.slice("<< bufferResourceOffset <<", "
502       << bufferResourceOffset + bufferResourceSize << "));";
503   GLDEBUG;
504 }
505 
bufferData(WGLWidget::GLenum target,int size,WGLWidget::GLenum usage)506 void WClientGLWidget::bufferData(WGLWidget::GLenum target, int size,
507 				 WGLWidget::GLenum usage)
508 {
509   js_ << "ctx.bufferData(" << toString(target) << ",";
510   js_ << size << ",";
511   js_ << toString(usage) << ");";
512   GLDEBUG;
513 }
514 
bufferDatafv(WGLWidget::GLenum target,const FloatBuffer & v,WGLWidget::GLenum usage,bool binary)515 void WClientGLWidget::bufferDatafv(WGLWidget::GLenum target,
516 				   const FloatBuffer &v,
517 				   WGLWidget::GLenum usage,
518 				   bool binary)
519 {
520   if (binary) {
521     std::unique_ptr<WMemoryResource> res
522       (new WMemoryResource("application/octet"));
523     auto resPtr = res.get();
524     res->setData(Utils::toCharPointer(v), v.size()*sizeof(float));
525     binaryResources_.push_back(std::move(res));
526     preloadArrayBuffers_.push_back(PreloadArrayBuffer(currentlyBoundBuffer_.jsRef(), resPtr->url()));
527 
528     js_ << "ctx.bufferData(" << toString(target) << ",";
529     js_ << currentlyBoundBuffer_.jsRef() << ".data, ";
530     js_ << toString(usage) << ");";
531   } else {
532 #ifdef WT_TARGET_JAVA
533     bufferDatafv(target, v.asFloatBuffer(), usage);
534 #else
535     js_ << "ctx.bufferData(" << toString(target) << ",";
536     js_ << "new Float32Array([";
537     char buf[30];
538     for (unsigned i = 0; i < v.size(); i++) {
539       js_ << (i == 0 ? "" : ",") << makeFloat(v[i], buf);
540     }
541     js_ << "])";
542     js_ << ","<< toString(usage) << ");";
543 #endif
544   }
545   GLDEBUG;
546 }
547 
548 #ifdef WT_TARGET_JAVA
bufferDatafv(WGLWidget::GLenum target,const FloatNotByteBuffer & buffer,WGLWidget::GLenum usage)549   void WClientGLWidget::bufferDatafv(WGLWidget::GLenum target, const FloatNotByteBuffer &buffer, WGLWidget::GLenum usage)
550   {
551     js_ << "ctx.bufferData(" << toString(target) << ",";
552     js_ << "new Float32Array([";
553     char buf[30];
554     for (int i=0; i < buffer.size(); i++) {
555       js_ << (i == 0 ? "" : ",") << makeFloat(buffer[i], buf);
556     }
557     js_ << "])";
558     js_ << ","<< toString(usage) << ");";
559   }
560 #endif
561 
bufferDataiv(WGLWidget::GLenum target,IntBuffer & buffer,WGLWidget::GLenum usage,WGLWidget::GLenum type)562 void WClientGLWidget::bufferDataiv(WGLWidget::GLenum target, IntBuffer &buffer, WGLWidget::GLenum usage, WGLWidget::GLenum type)
563 {
564   js_ << "ctx.bufferData(" << toString(target) << ",";
565   renderiv(js_, buffer, type);
566   js_ << ","<< toString(usage) << ");";
567   GLDEBUG;
568 }
569 
bufferSubDatafv(WGLWidget::GLenum target,unsigned offset,const FloatBuffer & buffer,bool binary)570 void WClientGLWidget::bufferSubDatafv(WGLWidget::GLenum target, unsigned offset, const FloatBuffer &buffer, bool binary)
571 {
572   if (binary) {
573     std::unique_ptr<WMemoryResource> res
574       (new WMemoryResource("application/octet"));
575     res->setData(Utils::toCharPointer(buffer), buffer.size()*sizeof(float));
576     preloadArrayBuffers_.push_back(PreloadArrayBuffer(currentlyBoundBuffer_.jsRef(), res->url()));
577     binaryResources_.push_back(std::move(res));
578 
579     js_ << "ctx.bufferSubData(" << toString(target) << ",";
580     js_ << offset << ",";
581     js_ << currentlyBoundBuffer_.jsRef() << ".data);";
582   } else {
583 #ifdef WT_TARGET_JAVA
584     bufferSubDatafv(target, offset, buffer.asFloatBuffer());
585 #else
586     js_ << "ctx.bufferSubData(" << toString(target) << ",";
587     js_ << offset << ",";
588     js_ << "new Float32Array([";
589     char buf[30];
590     for (unsigned i = 0; i < buffer.size(); i++) {
591       js_ << (i == 0 ? "" : ",") << makeFloat(buffer[i], buf);
592     }
593     js_ << "])";
594     js_ << ");";
595 #endif
596   }
597   GLDEBUG;
598 }
599 
600 #ifdef WT_TARGET_JAVA
bufferSubDatafv(WGLWidget::GLenum target,unsigned offset,const FloatNotByteBuffer & buffer)601 void WClientGLWidget::bufferSubDatafv(WGLWidget::GLenum target, unsigned offset, const FloatNotByteBuffer &buffer)
602 {
603   js_ << "ctx.bufferSubData(" << toString(target) << ",";
604   js_ << offset << ",";
605   js_ << "new Float32Array([";
606   char buf[30];
607   for (int i=0; i < buffer.size(); i++) {
608     js_ << (i == 0 ? "" : ",") << makeFloat(buffer[i], buf);
609   }
610   js_ << "])";
611   js_ << ");";
612 }
613 #endif
614 
bufferSubDataiv(WGLWidget::GLenum target,unsigned offset,IntBuffer & buffer,WGLWidget::GLenum type)615 void WClientGLWidget::bufferSubDataiv(WGLWidget::GLenum target,
616 				      unsigned offset, IntBuffer &buffer,
617 				      WGLWidget::GLenum type)
618 {
619   js_ << "ctx.bufferSubData(" << toString(target) << "," << offset << ",";
620   renderiv(js_, buffer, type);
621   js_ << ");";
622   GLDEBUG;
623 }
624 
clearBinaryResources()625 void WClientGLWidget::clearBinaryResources()
626 {
627   binaryResources_.clear();
628 }
629 
clear(WFlags<WGLWidget::GLenum> mask)630 void WClientGLWidget::clear(WFlags<WGLWidget::GLenum> mask)
631 {
632   js_ << "ctx.clear(";
633   if (mask & WGLWidget::COLOR_BUFFER_BIT) js_ << "ctx.COLOR_BUFFER_BIT|";
634   if (mask & WGLWidget::DEPTH_BUFFER_BIT) js_ << "ctx.DEPTH_BUFFER_BIT|";
635   if (mask & WGLWidget::STENCIL_BUFFER_BIT) js_ << "ctx.STENCIL_BUFFER_BIT|";
636 
637   js_ << "0);";
638   GLDEBUG;
639 }
640 
clearColor(double r,double g,double b,double a)641 void WClientGLWidget::clearColor(double r, double g, double b, double a)
642 {
643   char buf[30];
644   js_ << "ctx.clearColor(" << makeFloat(r, buf) << ",";
645   js_ << makeFloat(g, buf) << ",";
646   js_ << makeFloat(b, buf) << ",";
647   js_ << makeFloat(a, buf) << ");";
648   GLDEBUG;
649 }
650 
clearDepth(double depth)651 void WClientGLWidget::clearDepth(double depth)
652 {
653   char buf[30];
654   js_ << "ctx.clearDepth(" << makeFloat(depth, buf) << ");";
655   GLDEBUG;
656 }
657 
clearStencil(int s)658 void WClientGLWidget::clearStencil(int s)
659 {
660   js_ << "ctx.clearStencil(" << s << ");";
661   GLDEBUG;
662 }
663 
colorMask(bool red,bool green,bool blue,bool alpha)664 void WClientGLWidget::colorMask(bool red, bool green, bool blue, bool alpha)
665 {
666   js_ << "ctx.colorMask(" << (red ? "true" : "false") << ","
667       << (green ? "true" : "false") << ","
668       << (blue ? "true" : "false") << ","
669       << (alpha ? "true" : "false") << ");";
670   GLDEBUG;
671 }
672 
compileShader(WGLWidget::Shader shader)673 void WClientGLWidget::compileShader(WGLWidget::Shader shader)
674 {
675   js_ << "ctx.compileShader(" << shader.jsRef() << ");";
676   js_ << "if (!ctx.getShaderParameter(" << shader.jsRef()
677       << ", ctx.COMPILE_STATUS)) {"
678       << "alert(ctx.getShaderInfoLog(" << shader.jsRef() << "));}";
679   GLDEBUG;
680 }
681 
copyTexImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalFormat,int x,int y,unsigned width,unsigned height,int border)682 void WClientGLWidget::copyTexImage2D(WGLWidget::GLenum target, int level,
683 				     WGLWidget::GLenum internalFormat,
684 				     int x, int y,
685 				     unsigned width, unsigned height,
686 				     int border)
687 {
688   js_ << "ctx.copyTexImage2D(" << toString(target) << "," << level << ","
689     << toString(internalFormat) << "," << x << "," << y << ","
690     << width << "," << height << "," << border << ");";
691   GLDEBUG;
692 }
693 
copyTexSubImage2D(WGLWidget::GLenum target,int level,int xoffset,int yoffset,int x,int y,unsigned width,unsigned height)694 void WClientGLWidget::copyTexSubImage2D(WGLWidget::GLenum target, int level,
695 					int xoffset, int yoffset,
696 					int x, int y,
697 					unsigned width, unsigned height)
698 {
699   js_ << "ctx.copyTexSubImage2D(" << toString(target) << "," << level << ","
700     << xoffset << "," << yoffset << "," << x << "," << y << ","
701     << width << "," << height << ");";
702   GLDEBUG;
703 }
704 
createBuffer()705 WGLWidget::Buffer WClientGLWidget::createBuffer()
706 {
707   WGLWidget::Buffer retval(buffers_++);
708   js_ << "if (!" << retval.jsRef() << "){";
709   js_ << retval.jsRef() << "=ctx.createBuffer();";
710   js_ << "\n}";
711   GLDEBUG;
712   return retval;
713 }
714 
createAndLoadArrayBuffer(const std::string & url)715 WGLWidget::ArrayBuffer WClientGLWidget::createAndLoadArrayBuffer(const std::string &url)
716 {
717   WGLWidget::ArrayBuffer retval(arrayBuffers_++);
718   preloadArrayBuffers_.push_back(PreloadArrayBuffer(retval.jsRef(), url));
719   return retval;
720 }
721 
createFramebuffer()722 WGLWidget::Framebuffer WClientGLWidget::createFramebuffer()
723 {
724   WGLWidget::Framebuffer retval(framebuffers_++);
725   js_ << retval.jsRef() << "=ctx.createFramebuffer();";
726   GLDEBUG;
727   return retval;
728 }
729 
createProgram()730 WGLWidget::Program WClientGLWidget::createProgram()
731 {
732   WGLWidget::Program retval(programs_++);
733   js_ << retval.jsRef() << "=ctx.createProgram();";
734   GLDEBUG;
735   return retval;
736 }
737 
createRenderbuffer()738 WGLWidget::Renderbuffer WClientGLWidget::createRenderbuffer()
739 {
740   WGLWidget::Renderbuffer retval(renderbuffers_++);
741   js_ << retval.jsRef() << "=ctx.createRenderbuffer();";
742   GLDEBUG;
743   return retval;
744 }
745 
createShader(WGLWidget::GLenum shader)746 WGLWidget::Shader WClientGLWidget::createShader(WGLWidget::GLenum shader)
747 {
748   WGLWidget::Shader retval(shaders_++);
749   js_ << retval.jsRef() << "=ctx.createShader(" << toString(shader) << ");";
750   GLDEBUG;
751   return retval;
752 }
753 
createTexture()754 WGLWidget::Texture WClientGLWidget::createTexture()
755 {
756   WGLWidget::Texture retval(textures_++);
757   js_ << "if (!" << retval.jsRef() << "){";
758   js_ << retval.jsRef() << "=ctx.createTexture();";
759   js_ << "\n}";
760   GLDEBUG;
761   return retval;
762 }
763 
createTextureAndLoad(const std::string & url)764 WGLWidget::Texture WClientGLWidget::createTextureAndLoad(const std::string &url)
765 {
766   WGLWidget::Texture retval(textures_++);
767   preloadImages_.push_back(PreloadImage(retval.jsRef(), url, 0));
768   return retval;
769 }
770 
771 std::unique_ptr<WPaintDevice>
createPaintDevice(const WLength & width,const WLength & height)772 WClientGLWidget::createPaintDevice(const WLength& width,
773 				   const WLength& height)
774 {
775   return std::unique_ptr<WPaintDevice>(new WCanvasPaintDevice(width, height));
776 }
777 
cullFace(WGLWidget::GLenum mode)778 void WClientGLWidget::cullFace(WGLWidget::GLenum mode)
779 {
780   js_ << "ctx.cullFace(" << toString(mode) << ");";
781   GLDEBUG;
782 }
783 
deleteBuffer(WGLWidget::Buffer buffer)784 void WClientGLWidget::deleteBuffer(WGLWidget::Buffer buffer)
785 {
786   if ((unsigned)buffer.getId() >= buffers_) return;
787   js_ << "ctx.deleteBuffer(" << buffer.jsRef() << ");";
788   js_ << "delete " << buffer.jsRef() << ";";
789   GLDEBUG;
790 }
791 
deleteFramebuffer(WGLWidget::Framebuffer buffer)792 void WClientGLWidget::deleteFramebuffer(WGLWidget::Framebuffer buffer)
793 {
794   if ((unsigned)buffer.getId() >= framebuffers_) return;
795   js_ << "ctx.deleteFramebuffer(" << buffer.jsRef() << ");";
796   js_ << "delete " << buffer.jsRef() << ";";
797   GLDEBUG;
798 }
799 
deleteProgram(WGLWidget::Program program)800 void WClientGLWidget::deleteProgram(WGLWidget::Program program)
801 {
802   if ((unsigned)program.getId() >= programs_) return;
803   js_ << "ctx.deleteProgram(" << program.jsRef() << ");";
804   js_ << "delete " << program.jsRef() << ";";
805   GLDEBUG;
806 }
807 
deleteRenderbuffer(WGLWidget::Renderbuffer buffer)808 void WClientGLWidget::deleteRenderbuffer(WGLWidget::Renderbuffer buffer)
809 {
810   if ((unsigned)buffer.getId() >= renderbuffers_) return;
811   js_ << "ctx.deleteRenderbuffer(" << buffer.jsRef() << ");";
812   js_ << "delete " << buffer.jsRef() << ";";
813   GLDEBUG;
814 }
815 
deleteShader(WGLWidget::Shader shader)816 void WClientGLWidget::deleteShader(WGLWidget::Shader shader)
817 {
818   if ((unsigned)shader.getId() >= shaders_) return;
819   js_ << "ctx.deleteShader(" << shader.jsRef() << ");";
820   js_ << "delete " << shader.jsRef() << ";";
821   GLDEBUG;
822 }
823 
deleteTexture(WGLWidget::Texture texture)824 void WClientGLWidget::deleteTexture(WGLWidget::Texture texture)
825 {
826   if ((unsigned)texture.getId() >= textures_) return;
827   js_ << "ctx.deleteTexture(" << texture.jsRef() << ");";
828   js_ << "delete " << texture.jsRef() << ";";
829   GLDEBUG;
830 }
831 
depthFunc(WGLWidget::GLenum func)832 void WClientGLWidget::depthFunc(WGLWidget::GLenum func)
833 {
834   js_ << "ctx.depthFunc(" << toString(func) << ");";
835   GLDEBUG;
836 }
837 
depthMask(bool flag)838 void WClientGLWidget::depthMask(bool flag)
839 {
840   js_ << "ctx.depthMask(" << (flag ? "true" : "false") << ");";
841   GLDEBUG;
842 }
843 
depthRange(double zNear,double zFar)844 void WClientGLWidget::depthRange(double zNear, double zFar)
845 {
846   char buf[30];
847   js_ << "ctx.depthRange(" << makeFloat(zNear, buf) << ",";
848   js_ << makeFloat(zFar, buf) << ");";
849   GLDEBUG;
850 }
851 
detachShader(WGLWidget::Program program,WGLWidget::Shader shader)852 void WClientGLWidget::detachShader(WGLWidget::Program program,
853 				   WGLWidget::Shader shader)
854 {
855   if ((unsigned)program.getId() >= programs_ ||
856       (unsigned)shader.getId() >= shaders_)
857     return;
858   js_ << "if (" << program.jsRef() << " && " << shader.jsRef() << ") { ctx.detachShader(" << program.jsRef() << "," << shader.jsRef() << "); }";
859   GLDEBUG;
860 }
861 
disable(WGLWidget::GLenum cap)862 void WClientGLWidget::disable(WGLWidget::GLenum cap)
863 {
864   js_ << "ctx.disable(" << toString(cap) << ");";
865   GLDEBUG;
866 }
867 
disableVertexAttribArray(WGLWidget::AttribLocation index)868 void WClientGLWidget::disableVertexAttribArray(WGLWidget::AttribLocation index)
869 {
870   js_ << "ctx.disableVertexAttribArray(" << index.jsRef() << ");";
871   GLDEBUG;
872 }
873 
drawArrays(WGLWidget::GLenum mode,int first,unsigned count)874 void WClientGLWidget::drawArrays(WGLWidget::GLenum mode,
875 				 int first, unsigned count)
876 {
877   js_ << "ctx.drawArrays(" << toString(mode) << "," << first << "," << count << ");";
878   GLDEBUG;
879 }
880 
drawElements(WGLWidget::GLenum mode,unsigned count,WGLWidget::GLenum type,unsigned offset)881 void WClientGLWidget::drawElements(WGLWidget::GLenum mode, unsigned count, WGLWidget::GLenum type, unsigned offset)
882 {
883   js_ << "ctx.drawElements(" << toString(mode) << "," << count << ","
884       << toString(type) << "," << offset << ");";
885   GLDEBUG;
886 }
887 
enable(WGLWidget::GLenum cap)888 void WClientGLWidget::enable(WGLWidget::GLenum cap)
889 {
890   js_ << "ctx.enable(" << toString(cap) << ");";
891   GLDEBUG;
892 }
893 
enableVertexAttribArray(WGLWidget::AttribLocation index)894 void WClientGLWidget::enableVertexAttribArray(WGLWidget::AttribLocation index)
895 {
896   js_ << "ctx.enableVertexAttribArray(" << index.jsRef() << ");";
897   GLDEBUG;
898 }
899 
finish()900 void WClientGLWidget::finish()
901 {
902   js_ << "ctx.finish();";
903   GLDEBUG;
904 }
905 
flush()906 void WClientGLWidget::flush()
907 {
908   js_ << "ctx.flush();";
909   GLDEBUG;
910 }
911 
912 void WClientGLWidget
framebufferRenderbuffer(WGLWidget::GLenum target,WGLWidget::GLenum attachment,WGLWidget::GLenum renderbuffertarget,WGLWidget::Renderbuffer renderbuffer)913 ::framebufferRenderbuffer(WGLWidget::GLenum target,
914 			  WGLWidget::GLenum attachment,
915 			  WGLWidget::GLenum renderbuffertarget,
916 			  WGLWidget::Renderbuffer renderbuffer)
917 {
918   js_ << "ctx.framebufferRenderbuffer(" << toString(target) << ","
919       << toString(attachment) << "," << toString(renderbuffertarget) << ","
920       << renderbuffer.jsRef() << ");";
921   GLDEBUG;
922 }
923 
framebufferTexture2D(WGLWidget::GLenum target,WGLWidget::GLenum attachment,WGLWidget::GLenum textarget,WGLWidget::Texture texture,int level)924 void WClientGLWidget::framebufferTexture2D(WGLWidget::GLenum target,
925 					   WGLWidget::GLenum attachment,
926 					   WGLWidget::GLenum textarget,
927 					   WGLWidget::Texture texture,
928 					   int level)
929 {
930   js_ << "ctx.framebufferTexture2D(" << toString(target) << ","
931       << toString(attachment) << "," << toString(textarget) << ","
932       << texture.jsRef() << "," << level << ");";
933   GLDEBUG;
934 }
935 
frontFace(WGLWidget::GLenum mode)936 void WClientGLWidget::frontFace(WGLWidget::GLenum mode)
937 {
938   js_ << "ctx.frontFace(" << toString(mode) << ");";
939   GLDEBUG;
940 }
941 
generateMipmap(WGLWidget::GLenum target)942 void WClientGLWidget::generateMipmap(WGLWidget::GLenum target)
943 {
944   js_ << "ctx.generateMipmap(" << toString(target) << ");";
945   GLDEBUG;
946 }
947 
getAttribLocation(WGLWidget::Program program,const std::string & attrib)948 WGLWidget::AttribLocation WClientGLWidget::getAttribLocation(WGLWidget::Program program, const std::string &attrib)
949 {
950   WGLWidget::AttribLocation retval(attributes_++);
951   js_ << retval.jsRef() << "=ctx.getAttribLocation(" << program.jsRef()
952       << "," << WWebWidget::jsStringLiteral(attrib) << ");";
953   GLDEBUG;
954   return retval;
955 }
956 
getUniformLocation(WGLWidget::Program program,const std::string & location)957 WGLWidget::UniformLocation WClientGLWidget::getUniformLocation(WGLWidget::Program program, const std::string &location)
958 {
959   WGLWidget::UniformLocation retval(uniforms_++);
960   js_ << retval.jsRef() << "=ctx.getUniformLocation(" << program.jsRef()
961       << "," << WWebWidget::jsStringLiteral(location) << ");";
962   GLDEBUG;
963   return retval;
964 }
965 
hint(WGLWidget::GLenum target,WGLWidget::GLenum mode)966 void WClientGLWidget::hint(WGLWidget::GLenum target, WGLWidget::GLenum mode)
967 {
968   js_ << "ctx.hint(" << toString(target) << "," << toString(mode) << ");";
969   GLDEBUG;
970 }
971 
lineWidth(double width)972 void WClientGLWidget::lineWidth(double width)
973 {
974   char buf[30];
975   if (!wApp->environment().agentIsIE())
976     js_ << "ctx.lineWidth(" << makeFloat(width, buf) << ");";
977   GLDEBUG;
978 }
979 
linkProgram(WGLWidget::Program program)980 void WClientGLWidget::linkProgram(WGLWidget::Program program)
981 {
982   js_ << "ctx.linkProgram(" << program.jsRef() << ");";
983   js_ << "if(!ctx.getProgramParameter(" << program.jsRef()
984       << ",ctx.LINK_STATUS)){"
985       << "alert('Could not initialize shaders: ' + ctx.getProgramInfoLog("
986       << program.jsRef() << "));}";
987   GLDEBUG;
988 }
989 
pixelStorei(WGLWidget::GLenum pname,int param)990 void WClientGLWidget::pixelStorei(WGLWidget::GLenum pname, int param)
991 {
992   js_ << "ctx.pixelStorei(" << toString(pname) << "," << param << ");";
993   GLDEBUG;
994 }
995 
polygonOffset(double factor,double units)996 void WClientGLWidget::polygonOffset(double factor, double units) {
997   char buf[30];
998   js_ << "ctx.polygonOffset(" << makeFloat(factor, buf) << ",";
999   js_ << makeFloat(units, buf) << ");";
1000   GLDEBUG;
1001 }
1002 
renderbufferStorage(WGLWidget::GLenum target,WGLWidget::GLenum internalformat,unsigned width,unsigned height)1003 void WClientGLWidget::renderbufferStorage(WGLWidget::GLenum target,
1004 					  WGLWidget::GLenum internalformat,
1005 					  unsigned width, unsigned height)
1006 {
1007   js_ << "ctx.renderbufferStorage(" << toString(target) << ","
1008       << toString(internalformat) << "," << width << "," << height << ");";
1009   GLDEBUG;
1010 }
1011 
sampleCoverage(double value,bool invert)1012 void WClientGLWidget::sampleCoverage(double value, bool invert)
1013 {
1014   char buf[30];
1015   js_ << "ctx.sampleCoverage(" << makeFloat(value, buf) << ","
1016       << (invert ? "true" : "false") << ");";
1017   GLDEBUG;
1018 }
1019 
scissor(int x,int y,unsigned width,unsigned height)1020 void WClientGLWidget::scissor(int x, int y, unsigned width, unsigned height)
1021 {
1022   js_ << "ctx.scissor(" << x << "," << y << ","
1023       << width << "," << height << ");";
1024   GLDEBUG;
1025 }
1026 
shaderSource(WGLWidget::Shader shader,const std::string & src)1027 void WClientGLWidget::shaderSource(WGLWidget::Shader shader,
1028 				   const std::string &src)
1029 {
1030   js_ << "ctx.shaderSource(" << shader.jsRef() << ","
1031       << WWebWidget::jsStringLiteral(src) << ");";
1032   GLDEBUG;
1033 }
1034 
stencilFunc(WGLWidget::GLenum func,int ref,unsigned mask)1035 void WClientGLWidget::stencilFunc(WGLWidget::GLenum func, int ref,
1036 				  unsigned mask)
1037 {
1038   js_ << "ctx.stencilFunc(" << toString(func) << "," << ref << "," << mask << ");";
1039   GLDEBUG;
1040 }
1041 
stencilFuncSeparate(WGLWidget::GLenum face,WGLWidget::GLenum func,int ref,unsigned mask)1042 void WClientGLWidget::stencilFuncSeparate(WGLWidget::GLenum face,
1043 					  WGLWidget::GLenum func, int ref,
1044 					  unsigned mask)
1045 {
1046   js_ << "ctx.stencilFuncSeparate(" << toString(face) << "," << toString(func)
1047       << "," << ref << "," << mask << ");";
1048   GLDEBUG;
1049 }
1050 
stencilMask(unsigned mask)1051 void WClientGLWidget::stencilMask(unsigned mask)
1052 {
1053   js_ << "ctx.stencilMask(" << mask << ");";
1054   GLDEBUG;
1055 }
1056 
stencilMaskSeparate(WGLWidget::GLenum face,unsigned mask)1057 void WClientGLWidget::stencilMaskSeparate(WGLWidget::GLenum face, unsigned mask)
1058 {
1059   js_ << "ctx.stencilMaskSeparate(" << toString(face) << "," << mask << ");";
1060   GLDEBUG;
1061 }
1062 
stencilOp(WGLWidget::GLenum fail,WGLWidget::GLenum zfail,WGLWidget::GLenum zpass)1063 void WClientGLWidget::stencilOp(WGLWidget::GLenum fail, WGLWidget::GLenum zfail,
1064 				WGLWidget::GLenum zpass)
1065 {
1066   js_ << "ctx.stencilOp(" << toString(fail) << "," << toString(zfail) << ","
1067       << toString(zpass) << ");";
1068   GLDEBUG;
1069 }
1070 
stencilOpSeparate(WGLWidget::GLenum face,WGLWidget::GLenum fail,WGLWidget::GLenum zfail,WGLWidget::GLenum zpass)1071 void WClientGLWidget::stencilOpSeparate(WGLWidget::GLenum face,
1072 					WGLWidget::GLenum fail,
1073 					WGLWidget::GLenum zfail,
1074 					WGLWidget::GLenum zpass)
1075 {
1076   js_ << "ctx.stencilOpSeparate(" << toString(face) << ","
1077       << toString(fail) << "," << toString(zfail) << ","
1078       << toString(zpass) << ");";
1079   GLDEBUG;
1080 }
1081 
texImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalformat,unsigned width,unsigned height,int border,WGLWidget::GLenum format)1082 void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1083 				 WGLWidget::GLenum internalformat,
1084 				 unsigned width, unsigned height, int border,
1085 				 WGLWidget::GLenum format)
1086 {
1087   js_ << "ctx.texImage2D(" << toString(target) << "," << level << ","
1088       << toString(internalformat) << "," << width << "," << height << ","
1089       << border << "," << toString(format) << "," << toString(WGLWidget::UNSIGNED_BYTE)
1090       << ",null);";
1091   GLDEBUG;
1092 }
1093 
texImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalformat,WGLWidget::GLenum format,WGLWidget::GLenum type,WImage * image)1094 void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1095 				 WGLWidget::GLenum internalformat,
1096 				 WGLWidget::GLenum format,
1097 				 WGLWidget::GLenum type,
1098 				 WImage *image)
1099 {
1100   js_ << "ctx.texImage2D(" << toString(target) << "," << level << ","
1101       << toString(internalformat) << "," << toString(format) << "," << toString(type)
1102       << "," << image->jsRef() << ");";
1103   GLDEBUG;
1104 }
1105 
1106 
texImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalformat,WGLWidget::GLenum format,WGLWidget::GLenum type,WVideo * video)1107 void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1108 				 WGLWidget::GLenum internalformat,
1109 				 WGLWidget::GLenum format,
1110 				 WGLWidget::GLenum type,
1111 				 WVideo *video)
1112 {
1113   js_ << "if (" << video->jsMediaRef()<< ")"
1114     " ctx.texImage2D(" << toString(target) << "," << level << ","
1115       << toString(internalformat) << "," << toString(format) << "," << toString(type)
1116       << "," << video->jsMediaRef() << ");";
1117   GLDEBUG;
1118 }
1119 
1120 // // >>> Issues with CORS
1121 // void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1122 // 				 WGLWidget::GLenum internalformat,
1123 // 				 WGLWidget::GLenum format,
1124 // 				 WGLWidget::GLenum type,
1125 // 				 WLink *image)
1126 // {
1127 //   unsigned imgNb = images_++;
1128 //   preloadImages_.push_back(PreloadImage(currentlyBoundTexture_.jsRef(),
1129 // 					image->url(), imgNb));
1130 
1131 //   js_ << "ctx.texImage2D(" << toString(target) << "," << level << ","
1132 //       << toString(internalformat) << "," << toString(format)
1133 //       << "," << toString(type)
1134 //       << "," << currentlyBoundTexture_.jsRef() << ".image" << imgNb  << ");";
1135 //   GLDEBUG;
1136 // }
1137 
texImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalformat,WGLWidget::GLenum format,WGLWidget::GLenum type,std::string image)1138 void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1139 				 WGLWidget::GLenum internalformat,
1140 				 WGLWidget::GLenum format,
1141 				 WGLWidget::GLenum type,
1142 				 std::string image)
1143 {
1144   unsigned imgNb = images_++;
1145   // note: does not necessarily have to be a png (also tested jpg)
1146   std::unique_ptr<WFileResource> imgFile(new WFileResource("image/png", image));
1147   preloadImages_.push_back(PreloadImage(currentlyBoundTexture_.jsRef(),
1148 					imgFile->url(), imgNb));
1149 #ifndef WT_TARGET_JAVA
1150   addChild(std::move(imgFile));
1151 #endif // WT_TARGET_JAVA
1152 
1153   js_ << "ctx.texImage2D(" << toString(target) << "," << level << ","
1154       << toString(internalformat) << "," << toString(format)
1155       << "," << toString(type)
1156       << "," << currentlyBoundTexture_.jsRef() << ".image" << imgNb  << ");";
1157   GLDEBUG;
1158 }
1159 
texImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalformat,WGLWidget::GLenum format,WGLWidget::GLenum type,WPaintDevice * paintdevice)1160 void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1161 				 WGLWidget::GLenum internalformat,
1162 				 WGLWidget::GLenum format,
1163 				 WGLWidget::GLenum type,
1164 				 WPaintDevice *paintdevice)
1165 {
1166   unsigned imgNb = images_++;
1167   if (dynamic_cast<WCanvasPaintDevice*>(paintdevice) != nullptr) {
1168     WCanvasPaintDevice *cpd
1169       = dynamic_cast<WCanvasPaintDevice*>(paintdevice);
1170     std::string jsRef = currentlyBoundTexture_.jsRef() + "Canvas";
1171     js_ << jsRef << "=document.createElement('canvas');";
1172     js_ << jsRef << ".width=" << cpd->width().value() << ";";
1173     js_ << jsRef << ".height=" << cpd->height().value() << ";";
1174     js_ << "var f = function(myCanvas) {";
1175     cpd->renderPaintCommands(js_, "myCanvas");
1176     js_ << "};";
1177     js_ << "f(" << jsRef << ");";
1178     js_ << currentlyBoundTexture_.jsRef() << ".image" << imgNb << "=" << jsRef << ";";
1179     js_ << "delete " << jsRef << ";";
1180   }
1181 #ifdef WT_HAS_WRASTERIMAGE
1182   else if (dynamic_cast<WRasterImage*>(paintdevice) != nullptr) {
1183     WRasterImage *rpd = dynamic_cast<WRasterImage*>(paintdevice);
1184     rpd->done();
1185     std::unique_ptr<WResource> mr = rpdToMemResource(rpd);
1186     preloadImages_.push_back(PreloadImage(currentlyBoundTexture_.jsRef(),
1187 					  mr->url(), imgNb));
1188 #ifndef WT_TARGET_JAVA
1189     addChild(std::move(mr));
1190 #endif // WT_TARGET_JAVA
1191   }
1192 #endif
1193 
1194   js_ << "ctx.texImage2D(" << toString(target) << "," << level << ","
1195       << toString(internalformat) << "," << toString(format)
1196       << "," << toString(type)
1197       << "," << currentlyBoundTexture_.jsRef() << ".image" << imgNb << ");";
1198   GLDEBUG;
1199 }
1200 
1201 #ifndef WT_TARGET_JAVA
rpdToMemResource(WRasterImage * rpd)1202 std::unique_ptr<WResource> WClientGLWidget::rpdToMemResource(WRasterImage *rpd)
1203 {
1204   std::stringstream ss;
1205   rpd->write(ss);
1206   std::unique_ptr<WMemoryResource> mr(new WMemoryResource("image/png"));
1207   mr->setData(reinterpret_cast<const unsigned char*>(ss.str().c_str()),
1208 	      ss.str().size());
1209   return std::move(mr);
1210 }
1211 #endif
1212 
texImage2D(WGLWidget::GLenum target,int level,WGLWidget::GLenum internalformat,WGLWidget::GLenum format,WGLWidget::GLenum type,WGLWidget::Texture texture)1213 void WClientGLWidget::texImage2D(WGLWidget::GLenum target, int level,
1214 				 WGLWidget::GLenum internalformat,
1215 				 WGLWidget::GLenum format,
1216 				 WGLWidget::GLenum type,
1217 				 WGLWidget::Texture texture)
1218 {
1219   js_ << "ctx.texImage2D(" << toString(target) << "," << level << ","
1220       << toString(internalformat) << "," << toString(format)
1221       << "," << toString(type)
1222       << "," << texture.jsRef() << ".image0);";
1223   GLDEBUG;
1224 }
1225 
texParameteri(WGLWidget::GLenum target,WGLWidget::GLenum pname,WGLWidget::GLenum param)1226 void WClientGLWidget::texParameteri(WGLWidget::GLenum target,
1227 				    WGLWidget::GLenum pname,
1228 				    WGLWidget::GLenum param)
1229 {
1230   js_ << "ctx.texParameteri(" << toString(target) << "," << toString(pname)
1231     << "," << toString(param) << ");";
1232   GLDEBUG;
1233 }
1234 
uniform1f(const WGLWidget::UniformLocation & location,double x)1235 void WClientGLWidget::uniform1f(const WGLWidget::UniformLocation &location,
1236 				double x)
1237 {
1238   char buf[30];
1239   js_ << "ctx.uniform1f(" << location.jsRef()
1240       << "," << makeFloat(x, buf) << ");";
1241   GLDEBUG;
1242 }
1243 
uniform1fv(const WGLWidget::UniformLocation & location,const WT_ARRAY float * value)1244 void WClientGLWidget::uniform1fv(const WGLWidget::UniformLocation &location,
1245 				 const WT_ARRAY float *value)
1246 {
1247   js_ << "ctx.uniform1fv(" << location.jsRef() << ",";
1248   renderfv(js_, value, 1, JsArrayType::Float32Array);
1249   js_ << ");";
1250   GLDEBUG;
1251 }
1252 
uniform1fv(const WGLWidget::UniformLocation & location,const WGLWidget::JavaScriptVector & v)1253 void WClientGLWidget::uniform1fv(const WGLWidget::UniformLocation &location,
1254 				 const WGLWidget::JavaScriptVector &v)
1255 {
1256   js_ << "ctx.uniform1fv(" << location.jsRef() << ","
1257       << v.jsRef() << ");";
1258   GLDEBUG;
1259 }
1260 
uniform1i(const WGLWidget::UniformLocation & location,int x)1261 void WClientGLWidget::uniform1i(const WGLWidget::UniformLocation &location,
1262 				int x)
1263 {
1264   char buf[30];
1265   js_ << "ctx.uniform1i(" << location.jsRef() << ",";
1266   js_ << makeInt(x, buf) << ");";
1267   GLDEBUG;
1268 }
1269 
uniform1iv(const WGLWidget::UniformLocation & location,const WT_ARRAY int * value)1270 void WClientGLWidget::uniform1iv(const WGLWidget::UniformLocation &location,
1271 				 const WT_ARRAY int *value)
1272 {
1273   js_ << "ctx.uniform1iv(" << location.jsRef() << ",";
1274   renderiv(js_, value, 1, WGLWidget::INT);
1275   js_ << ");";
1276   GLDEBUG;
1277 }
1278 
uniform2f(const WGLWidget::UniformLocation & location,double x,double y)1279 void WClientGLWidget::uniform2f(const WGLWidget::UniformLocation &location,
1280 				double x, double y)
1281 {
1282   char buf[30];
1283   js_ << "ctx.uniform2f(" << location.jsRef() << ",";
1284   js_ << makeFloat(x, buf) << ",";
1285   js_ << makeFloat(y, buf) << ");";
1286   GLDEBUG;
1287 }
1288 
uniform2fv(const WGLWidget::UniformLocation & location,const WT_ARRAY float * value)1289 void WClientGLWidget::uniform2fv(const WGLWidget::UniformLocation &location,
1290 				 const WT_ARRAY float *value)
1291 {
1292   js_ << "ctx.uniform2fv(" << location.jsRef() << ",";
1293   renderfv(js_, value, 2, JsArrayType::Float32Array);
1294   js_ << ");";
1295   GLDEBUG;
1296 }
1297 
uniform2fv(const WGLWidget::UniformLocation & location,const WGLWidget::JavaScriptVector & v)1298 void WClientGLWidget::uniform2fv(const WGLWidget::UniformLocation &location,
1299 				 const WGLWidget::JavaScriptVector &v)
1300 {
1301   js_ << "ctx.uniform2fv(" << location.jsRef() << ","
1302       << v.jsRef() << ");";
1303   GLDEBUG;
1304 }
1305 
uniform2i(const WGLWidget::UniformLocation & location,int x,int y)1306 void WClientGLWidget::uniform2i(const WGLWidget::UniformLocation &location,
1307 				int x, int y)
1308 {
1309   char buf[30];
1310   js_ << "ctx.uniform2i(" << location.jsRef() << ",";
1311   js_ << makeInt(x, buf) << ",";
1312   js_ << makeInt(y, buf) << ");";
1313   GLDEBUG;
1314 }
1315 
uniform2iv(const WGLWidget::UniformLocation & location,const WT_ARRAY int * value)1316 void WClientGLWidget::uniform2iv(const WGLWidget::UniformLocation &location,
1317 				 const WT_ARRAY int *value)
1318 {
1319   js_ << "ctx.uniform2iv(" << location.jsRef() << ",";
1320   renderiv(js_, value, 2, WGLWidget::INT);
1321   js_ << ");";
1322   GLDEBUG;
1323 }
1324 
uniform3f(const WGLWidget::UniformLocation & location,double x,double y,double z)1325 void WClientGLWidget::uniform3f(const WGLWidget::UniformLocation &location,
1326 				double x, double y, double z)
1327 {
1328   char buf[30];
1329   js_ << "ctx.uniform3f(" << location.jsRef() << ",";
1330   js_ << makeFloat(x, buf) << ",";
1331   js_ << makeFloat(y, buf) << ",";
1332   js_ << makeFloat(z, buf) << ");";
1333   GLDEBUG;
1334 }
1335 
uniform3fv(const WGLWidget::UniformLocation & location,const WT_ARRAY float * value)1336 void WClientGLWidget::uniform3fv(const WGLWidget::UniformLocation &location,
1337 				 const WT_ARRAY float *value)
1338 {
1339   js_ << "ctx.uniform3fv(" << location.jsRef() << ",";
1340   renderfv(js_, value, 3, JsArrayType::Float32Array);
1341   js_ << ");";
1342   GLDEBUG;
1343 }
1344 
uniform3fv(const WGLWidget::UniformLocation & location,const WGLWidget::JavaScriptVector & v)1345 void WClientGLWidget::uniform3fv(const WGLWidget::UniformLocation &location,
1346 				 const WGLWidget::JavaScriptVector &v)
1347 {
1348   js_ << "ctx.uniform3fv(" << location.jsRef() << ","
1349       << v.jsRef() << ");";
1350   GLDEBUG;
1351 }
1352 
uniform3i(const WGLWidget::UniformLocation & location,int x,int y,int z)1353 void WClientGLWidget::uniform3i(const WGLWidget::UniformLocation &location,
1354 				int x, int y, int z)
1355 {
1356   char buf[30];
1357   js_ << "ctx.uniform3i(" << location.jsRef() << ",";
1358   js_ << makeInt(x, buf) << ",";
1359   js_ << makeInt(y, buf) << ",";
1360   js_ << makeInt(z, buf) << ");";
1361   GLDEBUG;
1362 }
1363 
uniform3iv(const WGLWidget::UniformLocation & location,const WT_ARRAY int * value)1364 void WClientGLWidget::uniform3iv(const WGLWidget::UniformLocation &location,
1365 				 const WT_ARRAY int *value)
1366 {
1367   js_ << "ctx.uniform3iv(" << location.jsRef() << ",";
1368   renderiv(js_, value, 3, WGLWidget::INT);
1369   js_ << ");";
1370   GLDEBUG;
1371 }
1372 
uniform4f(const WGLWidget::UniformLocation & location,double x,double y,double z,double w)1373 void WClientGLWidget::uniform4f(const WGLWidget::UniformLocation &location,
1374 				double x, double y, double z, double w)
1375 {
1376   char buf[30];
1377   js_ << "ctx.uniform4f(" << location.jsRef() << ",";
1378   js_ << makeFloat(x, buf) << ",";
1379   js_ << makeFloat(y, buf) << ",";
1380   js_ << makeFloat(z, buf) << ",";
1381   js_ << makeFloat(w, buf) << ");";
1382   GLDEBUG;
1383 }
1384 
uniform4fv(const WGLWidget::UniformLocation & location,const WT_ARRAY float * value)1385 void WClientGLWidget::uniform4fv(const WGLWidget::UniformLocation &location,
1386 				 const WT_ARRAY float *value)
1387 {
1388   js_ << "ctx.uniform4fv(" << location.jsRef() << ",";
1389   renderfv(js_, value, 4, JsArrayType::Float32Array);
1390   js_ << ");";
1391   GLDEBUG;
1392 }
1393 
uniform4fv(const WGLWidget::UniformLocation & location,const WGLWidget::JavaScriptVector & v)1394 void WClientGLWidget::uniform4fv(const WGLWidget::UniformLocation &location,
1395 				 const WGLWidget::JavaScriptVector &v)
1396 {
1397   js_ << "ctx.uniform4fv(" << location.jsRef() << ","
1398       << v.jsRef() << ");";
1399   GLDEBUG;
1400 }
1401 
uniform4i(const WGLWidget::UniformLocation & location,int x,int y,int z,int w)1402 void WClientGLWidget::uniform4i(const WGLWidget::UniformLocation &location,
1403 				int x, int y, int z, int w)
1404 {
1405   char buf[30];
1406   js_ << "ctx.uniform4i(" << location.jsRef() << ",";
1407   js_ << makeInt(x, buf) << ",";
1408   js_ << makeInt(y, buf) << ",";
1409   js_ << makeInt(z, buf) << ",";
1410   js_ << makeInt(w, buf) << ");";
1411   GLDEBUG;
1412 }
1413 
uniform4iv(const WGLWidget::UniformLocation & location,const WT_ARRAY int * value)1414 void WClientGLWidget::uniform4iv(const WGLWidget::UniformLocation &location,
1415 				 const WT_ARRAY int *value)
1416 {
1417   js_ << "ctx.uniform4iv(" << location.jsRef() << ",";
1418   renderiv(js_, value, 4, WGLWidget::INT);
1419   js_ << ");";
1420   GLDEBUG;
1421 }
1422 
uniformMatrix2fv(const WGLWidget::UniformLocation & location,bool transpose,const WT_ARRAY double * value)1423 void WClientGLWidget::uniformMatrix2fv(const WGLWidget::UniformLocation &location,
1424 				       bool transpose,
1425 				       const WT_ARRAY double *value)
1426 {
1427   js_ << "ctx.uniformMatrix2fv(" << location.jsRef() << ","
1428       << (transpose?"true":"false") << ",";
1429   renderfv(js_, value, 4, JsArrayType::Float32Array);
1430   js_ << ");";
1431   GLDEBUG;
1432 }
1433 
uniformMatrix2(const WGLWidget::UniformLocation & location,const WGenericMatrix<double,2,2> & m)1434 void WClientGLWidget::uniformMatrix2(const WGLWidget::UniformLocation &location,
1435 				     const WGenericMatrix<double, 2, 2> &m)
1436 {
1437   js_ << "ctx.uniformMatrix2fv(" << location.jsRef() << ",false,";
1438   WGenericMatrix<double, 2, 2> t(m.transposed());
1439   renderfv(js_, t, JsArrayType::Float32Array);
1440   js_ << ");";
1441   GLDEBUG;
1442 }
1443 
uniformMatrix3fv(const WGLWidget::UniformLocation & location,bool transpose,const WT_ARRAY double * value)1444 void WClientGLWidget::uniformMatrix3fv(const WGLWidget::UniformLocation &location,
1445 				       bool transpose,
1446 				       const WT_ARRAY double *value)
1447 {
1448   js_ << "ctx.uniformMatrix3fv(" << location.jsRef() << ","
1449       << (transpose?"true":"false") << ",";
1450   renderfv(js_, value, 9, JsArrayType::Float32Array);
1451   js_ << ");";
1452   GLDEBUG;
1453 }
1454 
uniformMatrix3(const WGLWidget::UniformLocation & location,const WGenericMatrix<double,3,3> & m)1455 void WClientGLWidget::uniformMatrix3(const WGLWidget::UniformLocation &location,
1456 				     const WGenericMatrix<double, 3, 3> &m)
1457 {
1458   js_ << "ctx.uniformMatrix3fv(" << location.jsRef() << ",false,";
1459   WGenericMatrix<double, 3, 3> t(m.transposed());
1460   renderfv(js_, t, JsArrayType::Float32Array);
1461   js_ << ");";
1462   GLDEBUG;
1463 }
1464 
uniformMatrix4fv(const WGLWidget::UniformLocation & location,bool transpose,const WT_ARRAY double * value)1465 void WClientGLWidget::uniformMatrix4fv(const WGLWidget::UniformLocation &location,
1466 				       bool transpose,
1467 				       const WT_ARRAY double *value)
1468 {
1469   js_ << "ctx.uniformMatrix4fv(" << location.jsRef() << ","
1470       << (transpose?"true":"false") << ",";
1471   renderfv(js_, value, 16, JsArrayType::Float32Array);
1472   js_ << ");";
1473   GLDEBUG;
1474 }
1475 
uniformMatrix4(const WGLWidget::UniformLocation & location,const WGenericMatrix<double,4,4> & m)1476 void WClientGLWidget::uniformMatrix4(const WGLWidget::UniformLocation &location,
1477 				     const WGenericMatrix<double, 4, 4> &m) {
1478   js_ << "ctx.uniformMatrix4fv(" << location.jsRef() << ",false,";
1479   js_ << "new Float32Array([";
1480   char buf[30];
1481   for (int i = 0; i < 4; i++) {
1482     for (int j = 0; j < 4; j++) { // col-major
1483       js_ << ((i == 0 && j == 0) ? "" : ",") << makeFloat(m.at(j, i), buf);
1484     }
1485   }
1486   js_ << "])";
1487   js_ << ");";
1488   GLDEBUG;
1489 }
1490 
uniformMatrix4(const WGLWidget::UniformLocation & location,const WGLWidget::JavaScriptMatrix4x4 & m)1491 void WClientGLWidget::uniformMatrix4(const WGLWidget::UniformLocation &location,
1492 				     const WGLWidget::JavaScriptMatrix4x4 &m)
1493 {
1494   js_ << "ctx.uniformMatrix4fv(" << location.jsRef() << ",false,";
1495   js_ << m.jsRef() << ");";
1496   GLDEBUG;
1497 }
1498 
useProgram(WGLWidget::Program program)1499 void WClientGLWidget::useProgram(WGLWidget::Program program)
1500 {
1501   js_ << "ctx.useProgram(" << program.jsRef() << ");";
1502   GLDEBUG;
1503 }
1504 
validateProgram(WGLWidget::Program program)1505 void WClientGLWidget::validateProgram(WGLWidget::Program program)
1506 {
1507   js_ << "ctx.validateProgram(" << program.jsRef() << ");";
1508   GLDEBUG;
1509 }
1510 
vertexAttrib1f(WGLWidget::AttribLocation location,double x)1511 void WClientGLWidget::vertexAttrib1f(WGLWidget::AttribLocation location, double x)
1512 {
1513   char buf[30];
1514   js_ << "ctx.vertexAttrib1f(" << location.jsRef() << ",";
1515   js_ << makeFloat(x, buf) << ");";
1516   GLDEBUG;
1517 }
1518 
vertexAttrib2f(WGLWidget::AttribLocation location,double x,double y)1519 void WClientGLWidget::vertexAttrib2f(WGLWidget::AttribLocation location,
1520 				     double x, double y)
1521 {
1522   char buf[30];
1523   js_ << "ctx.vertexAttrib2f(" << location.jsRef() << ",";
1524   js_ << makeFloat(x, buf) << ",";
1525   js_ << makeFloat(y, buf) << ");";
1526   GLDEBUG;
1527 }
1528 
vertexAttrib3f(WGLWidget::AttribLocation location,double x,double y,double z)1529 void WClientGLWidget::vertexAttrib3f(WGLWidget::AttribLocation location,
1530 				     double x, double y, double z)
1531 {
1532   char buf[30];
1533   js_ << "ctx.vertexAttrib3f(" << location.jsRef() << ",";
1534   js_ << makeFloat(x, buf) << ",";
1535   js_ << makeFloat(y, buf) << ",";
1536   js_ << makeFloat(z, buf) << ");";
1537   GLDEBUG;
1538 }
1539 
vertexAttrib4f(WGLWidget::AttribLocation location,double x,double y,double z,double w)1540 void WClientGLWidget::vertexAttrib4f(WGLWidget::AttribLocation location,
1541 				     double x, double y, double z, double w)
1542 {
1543   char buf[30];
1544   js_ << "ctx.vertexAttrib4f(" << location.jsRef() << ",";
1545   js_ << makeFloat(x, buf) << ",";
1546   js_ << makeFloat(y, buf) << ",";
1547   js_ << makeFloat(z, buf) << ",";
1548   js_ << makeFloat(w, buf) << ");";
1549   GLDEBUG;
1550 }
1551 
vertexAttribPointer(WGLWidget::AttribLocation location,int size,WGLWidget::GLenum type,bool normalized,unsigned stride,unsigned offset)1552 void WClientGLWidget::vertexAttribPointer(WGLWidget::AttribLocation location,
1553 					  int size,
1554 					  WGLWidget::GLenum type,
1555 					  bool normalized,
1556 					  unsigned stride, unsigned offset)
1557 {
1558   js_ << "ctx.vertexAttribPointer(" << location.jsRef() << "," << size << "," << toString(type)
1559     << "," << (normalized?"true":"false") << "," << stride << "," << offset << ");";
1560   GLDEBUG;
1561 }
1562 
viewport(int x,int y,unsigned width,unsigned height)1563 void WClientGLWidget::viewport(int x, int y, unsigned width, unsigned height)
1564 {
1565   js_ << "ctx.viewport(" << x << "," << y << "," << width << "," << height << ");";
1566   GLDEBUG;
1567 }
1568 
initJavaScriptMatrix4(WGLWidget::JavaScriptMatrix4x4 & mat)1569 void WClientGLWidget::initJavaScriptMatrix4(WGLWidget::JavaScriptMatrix4x4 &mat)
1570 {
1571   if (!mat.hasContext())
1572     glInterface_->addJavaScriptMatrix4(mat);
1573   else if (mat.context_ != glInterface_)
1574     throw WException("JavaScriptMatrix4x4: associated WGLWidget is not equal to the WGLWidget it's being initialized in");
1575 
1576   WGenericMatrix<double, 4, 4> m = mat.value();
1577   js_ << mat.jsRef() << "=";
1578   renderfv(js_, m, JsArrayType::Float32Array);
1579   js_ << ";";
1580 
1581   mat.initialize();
1582 }
1583 
setJavaScriptMatrix4(WGLWidget::JavaScriptMatrix4x4 & jsm,const WGenericMatrix<double,4,4> & m)1584 void WClientGLWidget::setJavaScriptMatrix4(WGLWidget::JavaScriptMatrix4x4 &jsm,
1585 					   const WGenericMatrix<double, 4, 4> &m)
1586 {
1587   js_ << WT_CLASS ".glMatrix.mat4.set(";
1588   WGenericMatrix<double, 4, 4> t(m.transposed());
1589   renderfv(js_, t, JsArrayType::Float32Array);
1590   js_ << ", " << jsm.jsRef() << ");";
1591 }
1592 
initJavaScriptVector(WGLWidget::JavaScriptVector & vec)1593 void WClientGLWidget::initJavaScriptVector(WGLWidget::JavaScriptVector &vec)
1594 {
1595   if (!vec.hasContext())
1596     glInterface_->addJavaScriptVector(vec);
1597   else if (vec.context_ != glInterface_)
1598     throw WException("JavaScriptVector: associated WGLWidget is not equal to the WGLWidget it's being initialized in");
1599 
1600   std::vector<float> v = vec.value();
1601   js_ << vec.jsRef() << "= new Float32Array([";
1602   for (unsigned i = 0; i < vec.length(); ++i) {
1603     std::string val;
1604     if (v[i] == std::numeric_limits<float>::infinity()) {
1605       val = "Infinity";
1606     } else if (v[i] == -std::numeric_limits<float>::infinity()) {
1607       val = "-Infinity";
1608     } else {
1609       val = std::to_string(v[i]);
1610     }
1611     if (i != 0)
1612       js_ << ",";
1613     js_ << val;
1614   }
1615   js_ << "]);";
1616 
1617   vec.initialize();
1618 }
1619 
setJavaScriptVector(WGLWidget::JavaScriptVector & jsv,const std::vector<float> & v)1620 void WClientGLWidget::setJavaScriptVector(WGLWidget::JavaScriptVector &jsv,
1621 					  const std::vector<float> &v)
1622 {
1623   if (jsv.length() != v.size())
1624     throw WException("Trying to set a JavaScriptVector with "
1625 		     "incompatible length!");
1626   for (unsigned i = 0; i < jsv.length(); ++i) {
1627     std::string val;
1628     if (v[i] == std::numeric_limits<float>::infinity()) {
1629       val = "Infinity";
1630     } else if (v[i] == -std::numeric_limits<float>::infinity()) {
1631       val = "-Infinity";
1632     } else {
1633       val = std::to_string(v[i]);
1634     }
1635     js_ << jsv.jsRef() << "[" << i << "] = " << val << ";";
1636   }
1637 }
1638 
setClientSideMouseHandler(const std::string & handlerCode)1639 void WClientGLWidget::setClientSideMouseHandler(const std::string& handlerCode)
1640 {
1641   js_ << "obj.setMouseHandler(" << handlerCode << ");";
1642 }
1643 
setClientSideLookAtHandler(const WGLWidget::JavaScriptMatrix4x4 & m,double centerX,double centerY,double centerZ,double uX,double uY,double uZ,double pitchRate,double yawRate)1644 void WClientGLWidget::setClientSideLookAtHandler(const WGLWidget::JavaScriptMatrix4x4 &m,
1645 						 double centerX, double centerY, double centerZ,
1646 						 double uX, double uY, double uZ,
1647 						 double pitchRate, double yawRate)
1648 {
1649   js_ << "obj.setMouseHandler(new obj.LookAtMouseHandler("
1650      << m.jsRef()
1651      << ",[" << centerX << "," << centerY << "," << centerZ << "],"
1652      << "[" << uX << "," << uY << "," << uZ << "],"
1653      << pitchRate << "," << yawRate << "));";
1654 }
1655 
setClientSideWalkHandler(const WGLWidget::JavaScriptMatrix4x4 & m,double frontStep,double rotStep)1656 void WClientGLWidget::setClientSideWalkHandler(const WGLWidget::JavaScriptMatrix4x4 &m,
1657 				double frontStep, double rotStep)
1658 {
1659   js_ << "obj.setMouseHandler(new obj.WalkMouseHandler("
1660       << m.jsRef() << ","
1661       << frontStep << "," << rotStep << "));";
1662 }
1663 
arrayType()1664 JsArrayType WClientGLWidget::arrayType() const
1665 {
1666   return JsArrayType::Float32Array;
1667 }
1668 
injectJS(const std::string & jsString)1669 void WClientGLWidget::injectJS(const std::string & jsString)
1670 {
1671   js_ << jsString;
1672 }
1673 
restoreContext(const std::string & jsRef)1674 void WClientGLWidget::restoreContext(const std::string &jsRef)
1675 {
1676   std::stringstream tmp;
1677   tmp << "{var o = " << glObjJsRef(jsRef) << ";\n";
1678 
1679   shaders_ = 0;
1680   programs_ = 0;
1681   attributes_ = 0;
1682   uniforms_ = 0;
1683   for (unsigned i = 0; i < buffers_; ++i) {
1684     tmp << "o.ctx.WtBuffer" << i << "=null;";
1685   }
1686   buffers_ = 0;
1687   arrayBuffers_ = 0;
1688 
1689   framebuffers_ = 0;
1690   renderbuffers_ = 0;
1691   for (unsigned i = 0; i < textures_; ++i) {
1692     tmp << "o.ctx.WtTexture" << i << "=null;";
1693   }
1694   textures_ = 0;
1695   images_ = 0;
1696   canvas_ = 0;
1697 
1698   initializeGL(jsRef, tmp);
1699   tmp << "o.initialized = false;}";
1700   WApplication::instance()->doJavaScript(tmp.str());
1701 }
1702 
initializeGL(const std::string & jsRef,std::stringstream & ss)1703 void WClientGLWidget::initializeGL(const std::string &jsRef, std::stringstream &ss)
1704 {
1705   js_.str("");
1706   glInterface_->initializeGL();
1707   ss <<
1708     """o.initializeGL=function(){\n"
1709     """var obj=" << glObjJsRef(jsRef) << ";\n"
1710     """var ctx=obj.ctx; if(!ctx) return;\n" <<
1711     "" << js_.str() <<
1712     """obj.initialized = true;\n"
1713     // updates are queued until initialization is complete
1714     """var key;\n"
1715     """for(key in obj.updates) obj.updates[key]();\n"
1716     """obj.updates = new Array();\n"
1717     // Similar, resizeGL is not executed until initialized
1718     """obj.resizeGL();\n"
1719     "};\n";
1720 }
1721 
render(const std::string & jsRef,WFlags<RenderFlag> flags)1722 void WClientGLWidget::render(const std::string& jsRef, WFlags<RenderFlag> flags)
1723 {
1724   if (flags.test(RenderFlag::Full)) {
1725     std::stringstream tmp;
1726     tmp <<
1727       "{\n"
1728       """var o = new " WT_CLASS ".WGLWidget(" << wApp->javaScriptClass() << "," << jsRef << ");\n"
1729 #ifndef WT_TARGET_JAVA
1730       """o.discoverContext(function(){" << webglNotAvailable_.createCall({})
1731 #else // WT_TARGET_JAVA
1732       """o.discoverContext(function(){" << webglNotAvailable_.createCall()
1733 #endif // WT_TARGET_JAVA
1734 	<< "}, "
1735 	<< (glInterface_->renderOptions_.test(GLRenderOption::AntiAliasing)
1736 	    ? "true" : "false") << ");\n";
1737 
1738     initializeGL(jsRef, tmp);
1739     tmp << "}\n";
1740     WApplication::instance()->doJavaScript(tmp.str());
1741   }
1742 
1743   if (updateGL_ || updateResizeGL_ || updatePaintGL_) {
1744     std::stringstream tmp;
1745     tmp <<
1746       "var o = " << glObjJsRef(jsRef) << ";\n"
1747       "if(o.ctx){\n";
1748     if (updateGL_) {
1749       js_.str("");
1750       glInterface_->updateGL();
1751       tmp << "var update =function(){\n"
1752         "var obj=" << glObjJsRef(jsRef) << ";\n"
1753         "var ctx=obj.ctx;if (!ctx) return;\n"
1754         << js_.str() << "\n};\n"
1755         // cannot execute updates before initializeGL is executed
1756         "o.updates.push(update);";
1757     }
1758     if (updateResizeGL_) {
1759       js_.str("");
1760       glInterface_->resizeGL(renderWidth_, renderHeight_);
1761       tmp << "o.resizeGL=function(){\n"
1762         "var obj=" << glObjJsRef(jsRef) << ";\n"
1763         "var ctx=obj.ctx;if (!ctx) return;\n"
1764         << js_.str() << "};";
1765     }
1766     if (updatePaintGL_) {
1767       js_.str("");
1768       glInterface_->paintGL();
1769       // TG: cannot overwrite paint before update is executed
1770       // therefore overwrite paintgl in a deferred function through the
1771       // tasks queue
1772       tmp << "var updatePaint = function(){\n";
1773       tmp << "var obj=" << glObjJsRef(jsRef) << ";\n";
1774 
1775       tmp << "obj.paintGL=function(){\n"
1776         "var obj=" << glObjJsRef(jsRef) << ";\n"
1777         "var ctx=obj.ctx;if (!ctx) return;\n"
1778         << js_.str() << "};";
1779 
1780       tmp << "};\n";
1781       tmp << "o.updates.push(updatePaint);";
1782 
1783 
1784     }
1785     js_.str("");
1786     // Make sure textures are loaded before we render
1787     tmp << "}\n";
1788 
1789     // Preloading images and buffers
1790     const bool preloadingSomething = preloadImages_.size()>0 || preloadArrayBuffers_.size() >0;
1791 
1792     if (preloadingSomething)  {
1793       if (preloadImages_.size() > 0) {
1794 	tmp <<
1795 	  "o.preloadingTextures++;"
1796 	  "new " << wApp->javaScriptClass() << "._p_.ImagePreloader([";
1797 	for (unsigned i = 0; i < preloadImages_.size(); ++i) {
1798 	  if (i != 0)
1799 	    tmp << ',';
1800 	  tmp << '\'' << wApp->resolveRelativeUrl(preloadImages_[i].url) << '\'';
1801 	}
1802 	tmp <<
1803 	  "],function(images){\n"
1804 	  "var o=" << glObjJsRef(jsRef) << ";\n"
1805 	  "var ctx=null;\n"
1806 	  "if(o) ctx=o.ctx;\n"
1807 	  "if(ctx == null) return;\n";
1808 	for (unsigned i = 0; i < preloadImages_.size(); ++i) {
1809 	  std::string texture = preloadImages_[i].jsRef;
1810 	  tmp << texture << "=ctx.createTexture();\n"
1811 	      << texture << ".image" << preloadImages_[i].id
1812 	      << "=images[" << i << "];\n";
1813 	}
1814 	tmp << "o.preloadingTextures--;\n"
1815 	  << "o.handlePreload();\n"
1816 	  << "});";
1817 
1818 	preloadImages_.clear();
1819       }
1820 
1821       // now check for buffers to preload
1822       if (preloadArrayBuffers_.size() > 0) {
1823 	tmp <<
1824 	  "o.preloadingBuffers++;"
1825 	  "new " << wApp->javaScriptClass() << "._p_.ArrayBufferPreloader([";
1826 	for (unsigned i = 0; i < preloadArrayBuffers_.size(); ++i) {
1827 	  if (i != 0)
1828 	    tmp << ',';
1829 	  tmp << '\'' << preloadArrayBuffers_[i].url << '\'';
1830 	}
1831 	tmp <<
1832 	  "],function(bufferResources){\n"
1833 	  "var o=" << glObjJsRef(jsRef) << ";\n"
1834 	  "var ctx=null;\n"
1835 	  " if(o) ctx=o.ctx;\n"
1836 	  "if(ctx == null) return;\n";
1837 	for (unsigned i = 0; i < preloadArrayBuffers_.size(); ++i) {
1838 	  std::string bufferResource = preloadArrayBuffers_[i].jsRef;
1839 	  // setup datatype
1840 	  tmp << bufferResource << " = ctx.createBuffer();";
1841 	  // set the data
1842 	  tmp << "if (bufferResources[" << i << "]==null){";
1843 	  tmp << bufferResource << ".data=[];\n";
1844 	  tmp << "}else{";
1845 	  tmp << bufferResource << ".data=bufferResources[" << i << "];\n";
1846 	  tmp << "}";
1847 	}
1848 	tmp << "o.preloadingBuffers--;"
1849 	  << "o.handlePreload();\n"
1850 	  << "});";
1851 
1852 	preloadArrayBuffers_.clear();
1853       }
1854     } else {
1855       // No textures or buffers to load - go and paint
1856       tmp << "o.handlePreload();";
1857     }
1858     WApplication::instance()->doJavaScript(tmp.str());
1859     updateGL_ = updatePaintGL_ = updateResizeGL_ = false;
1860   }
1861 
1862   //repaintGL(GLClientSideRenderer::PAINT_GL | GLClientSideRenderer::RESIZE_GL);
1863 }
1864 
glObjJsRef(const std::string & jsRef)1865 std::string WClientGLWidget::glObjJsRef(const std::string& jsRef)
1866 {
1867   return "(function(){"
1868     "var r = " + jsRef + ";"
1869     "var o = r ? r.wtObj : null;"
1870     "return o ? o : {ctx: null};"
1871     "})()";
1872 }
1873 
1874 }
1875