1 /*
  2 SpiderGL Computer Graphics Library
  3 Copyright (c) 2010, Marco Di Benedetto - Visual Computing Lab, ISTI - CNR
  4 All rights reserved.
  5 
  6 Redistribution and use in source and binary forms, with or without
  7 modification, are permitted provided that the following conditions are met:
  8     * Redistributions of source code must retain the above copyright
  9       notice, this list of conditions and the following disclaimer.
 10     * Redistributions in binary form must reproduce the above copyright
 11       notice, this list of conditions and the following disclaimer in the
 12       documentation and/or other materials provided with the distribution.
 13     * Neither the name of SpiderGL nor the
 14       names of its contributors may be used to endorse or promote products
 15       derived from this software without specific prior written permission.
 16 
 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 DISCLAIMED. IN NO EVENT SHALL PAUL BRUNT BE LIABLE FOR ANY
 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 */
 28 
 29 /**
 30  * @fileOverview WebGL
 31  */
 32 
 33 /**
 34  * The SpiderGL.WebGL namespace.
 35  *
 36  * @namespace The SpiderGL.WebGL namespace.
 37  * 
 38  * The SpiderGL.WebGL namespace gives access to WebGL functionalities in terms of context creation and enhancement, and object wrappers.
 39  * The main purpose of the module is to provide a robust and intuitive way of dealing with all native WebGL objects (e.g., textures, framebuffers, etc.).
 40  * Each specialized wrapper handles creation/destruction, edit operations (i.e. parameter settings), and binding of the underlying native WebGL object (the GL handle).
 41  * To allow low level access and integration with existing code, the native handle is exposed. On the other side, wrappers can be created for already existing native objects,
 42  * ensuring that the same wrapper will be used for multiple wraps of the same object.
 43  * To create a robust interoperability between wrapper usage and native WebGL calls on handles, wrappers must be informed whenever any single native call operates on the wrapped handle.
 44  * SpiderGL handles this task by hijacking the WebGLRenderingContext object, and installing on it a set of extensions that use callback mechanisms to report changes to wrappers.
 45  * Moreover, to overcome the bind-to-edit/bind-to-use paradigm typical of the OpenGL API family, SpiderGL injects an extension that is insired by GL_EXT_direct_state_access extension.
 46  */
 47 SpiderGL.WebGL = { };
 48 
 49 /**
 50  * The SpiderGL.WebGL.Context namespace.
 51  *
 52  * @namespace The SpiderGL.WebGL.Context namespace.
 53  */
 54 SpiderGL.WebGL.Context = { };
 55 
 56 /**
 57  * The string for obtaining a WebGLRenderingContext from a canvas.
 58  *
 59  * @constant
 60  *
 61  * @see SpiderGL.WebGL.Context.get
 62  */
 63 SpiderGL.WebGL.Context.WEBGL_STRING = "experimental-webgl";
 64 
 65 /**
 66  * Default value for pixel unpack parameter WebGLRenderingContext.UNPACK_FLIP_Y_WEBGL.
 67  *
 68  * @default true
 69  *
 70  * @see SpiderGL.WebGL.Context.DEFAULT_UNPACK_PREMULTIPLY_ALPHA
 71  * @see SpiderGL.WebGL.Context.DEFAULT_UNPACK_COLORSPACE_CONVERSION
 72  * @see SpiderGL.WebGL.Context.setStandardGLUnpack
 73  */
 74 SpiderGL.WebGL.Context.DEFAULT_UNPACK_FLIP_Y = true;
 75 
 76 /**
 77  * Default value for pixel unpack parameter WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL.
 78  *
 79  * @default true
 80  *
 81  * @see SpiderGL.WebGL.Context.DEFAULT_UNPACK_FLIP_Y
 82  * @see SpiderGL.WebGL.Context.DEFAULT_UNPACK_COLORSPACE_CONVERSION
 83  * @see SpiderGL.WebGL.Context.setStandardGLUnpack
 84  */
 85 SpiderGL.WebGL.Context.DEFAULT_UNPACK_PREMULTIPLY_ALPHA = false;
 86 
 87 /**
 88  * Default value for pixel unpack parameter WebGLRenderingContext.UNPACK_COLORSPACE_CONVERSION_WEBGL.
 89  *
 90  * @default WebGLRenderingContext.NONE
 91  *
 92  * @see SpiderGL.WebGL.Context.DEFAULT_UNPACK_FLIP_Y
 93  * @see SpiderGL.WebGL.Context.DEFAULT_UNPACK_PREMULTIPLY_ALPHA
 94  * @see SpiderGL.WebGL.Context.setStandardGLUnpack
 95  */
 96 SpiderGL.WebGL.Context.DEFAULT_UNPACK_COLORSPACE_CONVERSION = WebGLRenderingContext.NONE;
 97 
 98 /**
 99  * Retrieves the WebGLRenderingContext from a canvas.
100  *
101  * The WebGLRenderingContext is obtained by calling the getContext() method of the canvas object.
102  *
103  * @param {HTMLCanvasElement} canvas The HTMLCanvasElement from which retrieve the WebGL context.
104  * @param {object} args The optional WebGL context arguments.
105  *
106  * @returns {WebGLRenderingContext} The canvas WebGL rendering context.
107  *
108  * @see SpiderGL.WebGL.Context.hijack
109  * @see SpiderGL.WebGL.Context.getHijacked
110  */
111 SpiderGL.WebGL.Context.get = function (canvas, args) {
112 	var c = canvas;
113 	if (SpiderGL.Type.isString(c)) { c = SpiderGL.DOM.getElementById(c); }
114 	if (!SpiderGL.Type.instanceOf(c, HTMLCanvasElement)) { return null; }
115 	var ctx = c.getContext(SpiderGL.WebGL.Context.WEBGL_STRING, args);
116 	return ctx;
117 }
118 
119 SpiderGL.WebGL.Context._prepareContex = function (gl) {
120 	if (!gl) return;
121 
122 	var sgl = gl._spidergl;
123 	if (sgl) return;
124 
125 	sgl = { };
126 	gl._spidergl = sgl;
127 	sgl.TAG = 0;
128 	sgl.gl = gl;
129 
130 	var glFunctions = { };
131 	sgl.glFunctions = glFunctions;
132 	for (var f in gl) {
133 		var fn = gl[fn];
134 		if (typeof fn == "function") {
135 			glFunctions[f] = fn;
136 		}
137 	}
138 };
139 
140 SpiderGL.WebGL.Context._addExtension = function (gl, extName, propName, setupFunc) {
141 	if (!gl) return;
142 
143 	var getExtension = gl.getExtension;
144 	gl.getExtension = function (name) {
145 		if (name == extName) {
146 			var sgl = this._spidergl;
147 			if (!sgl) return null;
148 			var pubExt = sgl[propName];
149 			if (!pubExt) {
150 				pubExt = { };
151 
152 				pubExt.TAG = 0;
153 
154 				var ext = { };
155 				pubExt._ext = ext;
156 
157 				ext[propName] = pubExt;
158 				ext.sgl = sgl;
159 				ext.gl  = gl;
160 
161 				var glFunctions = { };
162 				ext.glFunctions = glFunctions;
163 
164 				if (!setupFunc(gl, pubExt)) return null;
165 
166 				sgl[propName] = pubExt;
167 			}
168 			return pubExt;
169 		}
170 		return getExtension.call(this, name);
171 	};
172 };
173 
174 SpiderGL.WebGL.Context._setup_SGL_current_binding = function (gl, pubExt) {
175 	if (!gl) return false;
176 	if (!pubExt) return false;
177 	if (!gl._spidergl) return false;
178 	if (gl._spidergl.cb) return false;
179 
180 	var cb = pubExt;
181 	var ext = cb._ext;
182 	var glFunctions = ext.glFunctions;
183 
184 
185 
186 	// buffer
187 	//////////////////////////////////////////////////////////////////////////////////////////
188 	ext.currentBuffer = { };
189 	ext.currentBuffer[gl.ARRAY_BUFFER        ] = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
190 	ext.currentBuffer[gl.ELEMENT_ARRAY_BUFFER] = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
191 
192 	ext.bufferStack = { };
193 	ext.bufferStack[gl.ARRAY_BUFFER        ] = [ ];
194 	ext.bufferStack[gl.ELEMENT_ARRAY_BUFFER] = [ ];
195 
196 	glFunctions.bindBuffer = gl.bindBuffer;
197 	gl.bindBuffer = function (target, buffer) {
198 		var ext = this._spidergl.cb._ext;
199 		var current = ext.currentBuffer[target];
200 		if (current == buffer) return;
201 		ext.currentBuffer[target] = buffer;
202 		ext.glFunctions.bindBuffer.call(this, target, buffer);
203 	};
204 
205 	cb.getCurrentBuffer = function (target) {
206 		return this._ext.currentBuffer[target];
207 	};
208 
209 	cb.pushBuffer = function (target) {
210 		var ext = this._ext;
211 		var stack  = ext.bufferStack[target];
212 		var buffer = ext.currentBuffer[target];
213 		stack.push(buffer);
214 	};
215 
216 	cb.popBuffer = function (target) {
217 		var ext = this._ext;
218 		var stack = ext.bufferStack[target];
219 		if (stack.length <= 0) return;
220 		var buffer = stack.pop();
221 		ext.gl.bindBuffer(target, buffer);
222 	};
223 	//////////////////////////////////////////////////////////////////////////////////////////
224 
225 
226 
227 	// framebuffer
228 	//////////////////////////////////////////////////////////////////////////////////////////
229 	ext.currentFramebuffer = { };
230 	ext.currentFramebuffer[gl.FRAMEBUFFER] = gl.getParameter(gl.FRAMEBUFFER_BINDING);
231 
232 	ext.framebufferStack = { };
233 	ext.framebufferStack[gl.FRAMEBUFFER] = [ ];
234 
235 	glFunctions.bindFramebuffer = gl.bindFramebuffer;
236 	gl.bindFramebuffer = function (target, framebuffer) {
237 		var ext = this._spidergl.cb._ext;
238 		var current = ext.currentFramebuffer[target];
239 		if (current == framebuffer) return;
240 		ext.currentFramebuffer[target] = framebuffer;
241 		ext.glFunctions.bindFramebuffer.call(this, target, framebuffer);
242 	};
243 
244 	cb.getCurrentFramebuffer = function (target) {
245 		return this._ext.currentFramebuffer[target];
246 	};
247 
248 	cb.pushFramebuffer = function (target) {
249 		var ext = this._ext;
250 		var stack  = ext.framebufferStack[target];
251 		var framebuffer = ext.currentFramebuffer[target];
252 		stack.push(framebuffer);
253 	};
254 
255 	cb.popFramebuffer = function (target) {
256 		var ext = this._ext;
257 		var stack = ext.framebufferStack[target];
258 		if (stack.length <= 0) return;
259 		var framebuffer = stack.pop();
260 		ext.gl.bindFramebuffer(target, framebuffer);
261 	};
262 	//////////////////////////////////////////////////////////////////////////////////////////
263 
264 
265 
266 	// program
267 	//////////////////////////////////////////////////////////////////////////////////////////
268 	ext.currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
269 
270 	ext.programStack = [ ];
271 
272 	glFunctions.useProgram = gl.useProgram;
273 	gl.useProgram = function (program) {
274 		var ext = this._spidergl.cb._ext;
275 		var current = ext.currentProgram;
276 		if (current == program) return;
277 		ext.currentProgram = program;
278 		ext.glFunctions.useProgram.call(this, program);
279 	};
280 
281 	cb.getCurrentProgram = function () {
282 		return this._ext.currentProgram;
283 	};
284 
285 	cb.pushProgram = function () {
286 		var ext = this._ext;
287 		var stack = ext.programStack;
288 		var program = ext.currentProgram;
289 		stack.push(program);
290 	};
291 
292 	cb.popProgram = function () {
293 		var ext = this._ext;
294 		var stack = ext.programStack;
295 		if (stack.length <= 0) return;
296 		var program = stack.pop();
297 		ext.gl.useProgram(program);
298 	};
299 	//////////////////////////////////////////////////////////////////////////////////////////
300 
301 
302 
303 	// renderbuffer
304 	//////////////////////////////////////////////////////////////////////////////////////////
305 	ext.currentRenderbuffer = { };
306 	ext.currentRenderbuffer[gl.RENDERBUFFER] = gl.getParameter(gl.RENDERBUFFER_BINDING);
307 
308 	ext.renderbufferStack = { };
309 	ext.renderbufferStack[gl.RENDERBUFFER] = [ ];
310 
311 	glFunctions.bindRenderbuffer = gl.bindRenderbuffer;
312 	gl.bindRenderbuffer = function (target, renderbuffer) {
313 		var ext = this._spidergl.cb._ext;
314 		var current = ext.currentRenderbuffer[target];
315 		if (current == renderbuffer) return;
316 		ext.currentRenderbuffer[target] = renderbuffer;
317 		ext.glFunctions.bindRenderbuffer.call(this, target, renderbuffer);
318 	};
319 
320 	cb.getCurrentRenderbuffer = function (target) {
321 		return this._ext.currentRenderbuffer[target];
322 	};
323 
324 	cb.pushRenderbuffer = function (target) {
325 		var ext = this._ext;
326 		var stack  = ext.renderbufferStack[target];
327 		var renderbuffer = ext.currentRenderbuffer[target];
328 		stack.push(renderbuffer);
329 	};
330 
331 	cb.popRenderbuffer = function (target) {
332 		var ext = this._ext;
333 		var stack = ext.renderbufferStack[target];
334 		if (stack.length <= 0) return;
335 		var renderbuffer = stack.pop();
336 		ext.gl.bindRenderbuffer(target, renderbuffer);
337 	};
338 	//////////////////////////////////////////////////////////////////////////////////////////
339 
340 
341 
342 	// shader
343 	//////////////////////////////////////////////////////////////////////////////////////////
344 	ext.currentShader = { };
345 	ext.currentShader[gl.VERTEX_SHADER  ] = null;
346 	ext.currentShader[gl.FRAGMENT_SHADER] = null;
347 
348 	ext.shaderStack = { };
349 	ext.shaderStack[gl.VERTEX_SHADER  ] = [ ];
350 	ext.shaderStack[gl.FRAGMENT_SHADER] = [ ];
351 
352 	ext.glFunctions.bindShader = function (target, shader) { };
353 	cb.bindShader = function (target, shader) {
354 		var ext = this._ext;
355 		var current = ext.currentShader[target];
356 		if (current == shader) return;
357 		ext.currentShader[target] = shader;
358 		ext.glFunctions.bindShader.call(ext.gl, target, shader);
359 	};
360 
361 	cb.getCurrentShader = function (target) {
362 		return this._ext.currentShader[target];
363 	};
364 
365 	cb.pushShader = function (target) {
366 		var ext = this._ext;
367 		var stack  = ext.shaderStack[target];
368 		var shader = ext.currentShader[target];
369 		stack.push(shader);
370 	};
371 
372 	cb.popShader = function (target) {
373 		var ext = this._ext;
374 		var stack = ext.shaderStack[target];
375 		if (stack.length <= 0) return;
376 		var shader = stack.pop();
377 		ext.gl.bindShader(target, shader);
378 	};
379 	//////////////////////////////////////////////////////////////////////////////////////////
380 
381 
382 
383 	// texture
384 	//////////////////////////////////////////////////////////////////////////////////////////
385 	ext.currentTexture = { };
386 
387 	var currentTextureUnit = gl.getParameter(gl.ACTIVE_TEXTURE);
388 	var textureUnitsCount  = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
389 	ext.currentTexture = { };
390 	ext.textureStack = { };
391 	ext.textureUnitStack = [ ];
392 	for (var i=0; i<textureUnitsCount; ++i) {
393 		var textureUnit = gl.TEXTURE0 + i;
394 		gl.activeTexture(textureUnit);
395 
396 		var textureBindings = { }
397 		textureBindings[gl.TEXTURE_2D      ] = gl.getParameter(gl.TEXTURE_BINDING_2D);
398 		textureBindings[gl.TEXTURE_CUBE_MAP] = gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP);
399 		ext.currentTexture[textureUnit] = textureBindings;
400 
401 		var textureStacks = { }
402 		textureStacks[gl.TEXTURE_2D      ] = [ ];
403 		textureStacks[gl.TEXTURE_CUBE_MAP] = [ ];
404 		ext.textureStack[textureUnit] = textureStacks;
405 	}
406 	gl.activeTexture(currentTextureUnit);
407 	ext.currentTextureUnit = currentTextureUnit;
408 
409 	glFunctions.activeTexture = gl.activeTexture;
410 	gl.activeTexture = function (texture) {
411 		var ext = this._spidergl.cb._ext;
412 		var current = ext.currentTextureUnit;
413 		if (current == texture) return;
414 		ext.currentTextureUnit = texture;
415 		ext.glFunctions.activeTexture.call(this, texture);
416 	};
417 
418 	cb.getCurrentTextureUnit = function () {
419 		return this._ext.currentTextureUnit;
420 	};
421 
422 	cb.pushTextureUnit = function () {
423 		var ext = this._ext;
424 		var stack  = ext.textureUnitStack;
425 		var unit = ext.currentTextureUnit;
426 		stack.push(unit);
427 	};
428 
429 	cb.popTextureUnit = function () {
430 		var ext = this._ext;
431 		var stack  = ext.textureUnitStack;
432 		if (stack.length <= 0) return;
433 		var unit = stack.pop();
434 		ext.gl.activeTexture(unit);
435 	};
436 
437 	glFunctions.bindTexture = gl.bindTexture;
438 	gl.bindTexture = function (target, texture) {
439 		var ext = this._spidergl.cb._ext;
440 		var unit = ext.currentTextureUnit;
441 		var current = ext.currentTexture[unit][target];
442 		if (current == texture) return;
443 		ext.currentTexture[unit][target] = texture;
444 		ext.glFunctions.bindTexture.call(this, target, texture);
445 	};
446 
447 	cb.getCurrentTexture = function (target) {
448 		var ext = this._ext;
449 		var unit = ext.currentTextureUnit;
450 		return ext.currentTexture[unit][target];
451 	};
452 
453 	cb.pushTexture = function (target) {
454 		var ext = this._ext;
455 		var unit = ext.currentTextureUnit;
456 		var stack  = ext.textureStack[unit][target];
457 		var texture = ext.currentTexture[unit][target];
458 		stack.push(texture);
459 	};
460 
461 	cb.popTexture = function (target) {
462 		var ext = this._ext;
463 		var unit = ext.currentTextureUnit;
464 		var stack  = ext.textureStack[unit][target];
465 		if (stack.length <= 0) return;
466 		var texture = stack.pop();
467 		ext.gl.bindTexture(target, texture);
468 	};
469 	//////////////////////////////////////////////////////////////////////////////////////////
470 
471 	return true;
472 };
473 
474 SpiderGL.WebGL.Context._setup_SGL_wrapper_notify = function (gl, pubExt) {
475 	if (!gl) return false;
476 	if (!pubExt) return false;
477 	if (!gl._spidergl) return false;
478 	if (gl._spidergl.wn) return false;
479 
480 	var wn = pubExt;
481 	var ext = wn._ext;
482 	var glFunctions = ext.glFunctions;
483 
484 	ext.cb = gl.getExtension("SGL_current_binding");
485 	if (!ext.cb) return false;
486 
487 
488 
489 	// buffer
490 	//////////////////////////////////////////////////////////////////////////////////////////
491 	glFunctions.deleteBuffer = gl.deleteBuffer;
492 	gl.deleteBuffer = function (buffer) {
493 		var ext = this._spidergl.wn._ext;
494 		ext.glFunctions.deleteBuffer.apply(this, arguments);
495 		var current = buffer;
496 		(current && current._spidergl && current._spidergl._gl_deleteBuffer.apply(current._spidergl, arguments));
497 	};
498 
499 	glFunctions.isBuffer = gl.isBuffer;
500 	gl.isBuffer = function (buffer) {
501 		var ext = this._spidergl.wn._ext;
502 		var r = ext.glFunctions.isBuffer.apply(this, arguments);
503 		var current = buffer;
504 		(current && current._spidergl && current._spidergl._gl_isBuffer.apply(current._spidergl, arguments));
505 		return r;
506 	};
507 
508 	glFunctions.bindBuffer = gl.bindBuffer;
509 	gl.bindBuffer = function (target) {
510 		var ext = this._spidergl.wn._ext;
511 		ext.glFunctions.bindBuffer.apply(this, arguments);
512 		var current = ext.cb.getCurrentBuffer(target);
513 		(current && current._spidergl && current._spidergl._gl_bindBuffer.apply(current._spidergl, arguments));
514 	};
515 
516 	glFunctions.getBufferParameter = gl.getBufferParameter;
517 	gl.getBufferParameter = function (target) {
518 		var ext = this._spidergl.wn._ext;
519 		var r = ext.glFunctions.getBufferParameter.apply(this, arguments);
520 		var current = ext.cb.getCurrentBuffer(target);
521 		(current && current._spidergl && current._spidergl._gl_getBufferParameter.apply(current._spidergl, arguments));
522 		return r;
523 	};
524 
525 	glFunctions.bufferData = gl.bufferData;
526 	gl.bufferData = function (target) {
527 		var ext = this._spidergl.wn._ext;
528 		ext.glFunctions.bufferData.apply(this, arguments);
529 		var current = ext.cb.getCurrentBuffer(target);
530 		(current && current._spidergl && current._spidergl._gl_bufferData.apply(current._spidergl, arguments));
531 	}
532 
533 	glFunctions.bufferSubData = gl.bufferSubData;
534 	gl.bufferSubData = function (target) {
535 		var ext = this._spidergl.wn._ext;
536 		ext.glFunctions.bufferSubData.apply(this, arguments);
537 		var current = ext.cb.getCurrentBuffer(target);
538 		(current && current._spidergl && current._spidergl._gl_bufferSubData.apply(current._spidergl, arguments));
539 	}
540 
541 	glFunctions.vertexAttribPointer = gl.vertexAttribPointer;
542 	gl.vertexAttribPointer = function () {
543 		var ext = this._spidergl.wn._ext;
544 		ext.glFunctions.vertexAttribPointer.apply(this, arguments);
545 		var target  = this.ARRAY_BUFFER;
546 		var current = ext.cb.getCurrentBuffer(target);
547 		(current && current._spidergl && current._spidergl._gl_vertexAttribPointer.apply(current._spidergl, arguments));
548 	};
549 
550 	glFunctions.drawElements = gl.drawElements;
551 	gl.drawElements = function (buffer, mode, count, type, offset) {
552 		var ext = this._spidergl.wn._ext;
553 		ext.glFunctions.drawElements.apply(this, arguments);
554 		var target  = this.ELEMENT_ARRAY_BUFFER;
555 		var current = ext.cb.getCurrentBuffer(target);
556 		(current && current._spidergl && current._spidergl._gl_drawElements.apply(current._spidergl, arguments));
557 	};
558 	//////////////////////////////////////////////////////////////////////////////////////////
559 
560 
561 
562 	// framebuffer
563 	//////////////////////////////////////////////////////////////////////////////////////////
564 	glFunctions.deleteFramebuffer = gl.deleteFramebuffer;
565 	gl.deleteFramebuffer = function (framebuffer) {
566 		var ext = this._spidergl.wn._ext;
567 		ext.glFunctions.deleteFramebuffer.apply(this, arguments);
568 		var current = framebuffer;
569 		(current && current._spidergl && current._spidergl._gl_deleteFramebuffer.apply(current._spidergl, arguments));
570 	};
571 
572 	glFunctions.isFramebuffer = gl.isFramebuffer;
573 	gl.isFramebuffer = function (framebuffer) {
574 		var ext = this._spidergl.wn._ext;
575 		var r = ext.glFunctions.isFramebuffer.apply(this, arguments);
576 		var current = framebuffer;
577 		(current && current._spidergl && current._spidergl._gl_isFramebuffer.apply(current._spidergl, arguments));
578 		return r;
579 	};
580 
581 	glFunctions.bindFramebuffer = gl.bindFramebuffer;
582 	gl.bindFramebuffer = function (target) {
583 		var ext = this._spidergl.wn._ext;
584 		ext.glFunctions.bindFramebuffer.apply(this, arguments);
585 		var current = ext.cb.getCurrentFramebuffer(target);
586 		(current && current._spidergl && current._spidergl._gl_bindFramebuffer.apply(current._spidergl, arguments));
587 	};
588 
589 	glFunctions.checkFramebufferStatus = gl.checkFramebufferStatus;
590 	gl.checkFramebufferStatus = function (target) {
591 		var ext = this._spidergl.wn._ext;
592 		var r = ext.glFunctions.checkFramebufferStatus.apply(this, arguments);
593 		var current = ext.cb.getCurrentFramebuffer(target);
594 		(current && current._spidergl && current._spidergl._gl_checkFramebufferStatus.apply(current._spidergl, arguments));
595 		return r;
596 	};
597 
598 	glFunctions.getFramebufferAttachmentParameter = gl.getFramebufferAttachmentParameter;
599 	gl.getFramebufferAttachmentParameter = function (target) {
600 		var ext = this._spidergl.wn._ext;
601 		var r = ext.glFunctions.getFramebufferAttachmentParameter.apply(this, arguments);
602 		var current = ext.cb.getCurrentFramebuffer(target);
603 		(current && current._spidergl && current._spidergl._gl_getFramebufferAttachmentParameter.apply(current._spidergl, arguments));
604 		return r;
605 	};
606 
607 	glFunctions.framebufferRenderbuffer = gl.framebufferRenderbuffer;
608 	gl.framebufferRenderbuffer = function (target) {
609 		var ext = this._spidergl.wn._ext;
610 		ext.glFunctions.framebufferRenderbuffer.apply(this, arguments);
611 		var current = ext.cb.getCurrentFramebuffer(target);
612 		(current && current._spidergl && current._spidergl._gl_framebufferRenderbuffer.apply(current._spidergl, arguments));
613 	}
614 
615 	glFunctions.framebufferTexture2D = gl.framebufferTexture2D;
616 	gl.framebufferTexture2D = function (target) {
617 		var ext = this._spidergl.wn._ext;
618 		ext.glFunctions.framebufferTexture2D.apply(this, arguments);
619 		var current = ext.cb.getCurrentFramebuffer(target);
620 		(current && current._spidergl && current._spidergl._gl_framebufferTexture2D.apply(current._spidergl, arguments));
621 	};
622 
623 	glFunctions.clear = gl.clear;
624 	gl.clear = function () {
625 		var ext = this._spidergl.wn._ext;
626 		ext.glFunctions.clear.apply(this, arguments);
627 		var target = this.FRAMEBUFFER;
628 		var current = ext.cb.getCurrentFramebuffer(target);
629 		(current && current._spidergl && current._spidergl._gl_clear.apply(current._spidergl, arguments));
630 	};
631 
632 	glFunctions.readPixels = gl.readPixels;
633 	gl.readPixels = function () {
634 		var ext = this._spidergl.wn._ext;
635 		ext.glFunctions.readPixels.apply(this, arguments);
636 		var target = this.FRAMEBUFFER;
637 		var current = ext.cb.getCurrentFramebuffer(target);
638 		(current && current._spidergl && current._spidergl._gl_readPixels.apply(current._spidergl, arguments));
639 	};
640 	//////////////////////////////////////////////////////////////////////////////////////////
641 
642 
643 
644 	// program
645 	//////////////////////////////////////////////////////////////////////////////////////////
646 	glFunctions.deleteProgram = gl.deleteProgram;
647 	gl.deleteProgram = function (program) {
648 		var ext = this._spidergl.wn._ext;
649 		ext.glFunctions.deleteProgram.apply(this, arguments);
650 		var current = program;
651 		(current && current._spidergl && current._spidergl._gl_deleteProgram.apply(current._spidergl, arguments));
652 	};
653 
654 	glFunctions.isProgram = gl.isProgram;
655 	gl.isProgram = function (program) {
656 		var ext = this._spidergl.wn._ext;
657 		var r = ext.glFunctions.isProgram.apply(this, arguments);
658 		var current = program;
659 		(current && current._spidergl && current._spidergl._gl_isProgram.apply(current._spidergl, arguments));
660 		return r;
661 	};
662 
663 	glFunctions.useProgram = gl.useProgram;
664 	gl.useProgram = function () {
665 		var ext = this._spidergl.wn._ext;
666 		ext.glFunctions.useProgram.apply(this, arguments);
667 		var current = ext.cb.getCurrentProgram();
668 		(current && current._spidergl && current._spidergl._gl_useProgram.apply(current._spidergl, arguments));
669 	};
670 
671 	glFunctions.getActiveAttrib = gl.getActiveAttrib;
672 	gl.getActiveAttrib = function (program) {
673 		var ext = this._spidergl.wn._ext;
674 		var r = ext.glFunctions.getActiveAttrib.apply(this, arguments);
675 		var current = program;
676 		(current && current._spidergl && current._spidergl._gl_getActiveAttrib.apply(current._spidergl, arguments));
677 		return r;
678 	};
679 
680 	glFunctions.getActiveUniform = gl.getActiveUniform;
681 	gl.getActiveUniform = function (program) {
682 		var ext = this._spidergl.wn._ext;
683 		var r = ext.glFunctions.getActiveUniform.apply(this, arguments);
684 		var current = program;
685 		(current && current._spidergl && current._spidergl._gl_getActiveUniform.apply(current._spidergl, arguments));
686 		return r;
687 	};
688 
689 	glFunctions.getAttachedShaders = gl.getAttachedShaders;
690 	gl.getAttachedShaders = function (program) {
691 		var ext = this._spidergl.wn._ext;
692 		var r = ext.glFunctions.getAttachedShaders.apply(this, arguments);
693 		var current = program;
694 		(current && current._spidergl && current._spidergl._gl_getAttachedShaders.apply(current._spidergl, arguments));
695 		return r;
696 	};
697 
698 	glFunctions.getAttribLocation = gl.getAttribLocation;
699 	gl.getAttribLocation = function (program) {
700 		var ext = this._spidergl.wn._ext;
701 		var r = ext.glFunctions.getAttribLocation.apply(this, arguments);
702 		var current = program;
703 		(current && current._spidergl && current._spidergl._gl_getAttribLocation.apply(current._spidergl, arguments));
704 		return r;
705 	};
706 
707 	glFunctions.getProgramParameter = gl.getProgramParameter;
708 	gl.getProgramParameter = function (program) {
709 		var ext = this._spidergl.wn._ext;
710 		var r = ext.glFunctions.getProgramParameter.apply(this, arguments);
711 		var current = program;
712 		(current && current._spidergl && current._spidergl._gl_getProgramParameter.apply(current._spidergl, arguments));
713 		return r;
714 	};
715 
716 	glFunctions.getProgramInfoLog = gl.getProgramInfoLog;
717 	gl.getProgramInfoLog = function (program) {
718 		var ext = this._spidergl.wn._ext;
719 		var r = ext.glFunctions.getProgramInfoLog.apply(this, arguments);
720 		var current = program;
721 		(current && current._spidergl && current._spidergl._gl_getProgramInfoLog.apply(current._spidergl, arguments));
722 		return r;
723 	};
724 
725 	glFunctions.getUniform = gl.getUniform;
726 	gl.getUniform = function (program) {
727 		var ext = this._spidergl.wn._ext;
728 		var r = ext.glFunctions.getUniform.apply(this, arguments);
729 		var current = program;
730 		(current && current._spidergl && current._spidergl._gl_getUniform.apply(current._spidergl, arguments));
731 		return r;
732 	};
733 
734 	glFunctions.getUniformLocation = gl.getUniformLocation;
735 	gl.getUniformLocation = function (program) {
736 		var ext = this._spidergl.wn._ext;
737 		var r = ext.glFunctions.getUniformLocation.apply(this, arguments);
738 		var current = program;
739 		(current && current._spidergl && current._spidergl._gl_getUniformLocation.apply(current._spidergl, arguments));
740 		return r;
741 	};
742 
743 	glFunctions.attachShader = gl.attachShader;
744 	gl.attachShader = function (program) {
745 		var ext = this._spidergl.wn._ext;
746 		ext.glFunctions.attachShader.apply(this, arguments);
747 		var current = program;
748 		(current && current._spidergl && current._spidergl._gl_attachShader.apply(current._spidergl, arguments));
749 	};
750 
751 	glFunctions.bindAttribLocation = gl.bindAttribLocation;
752 	gl.bindAttribLocation = function (program) {
753 		var ext = this._spidergl.wn._ext;
754 		ext.glFunctions.bindAttribLocation.apply(this, arguments);
755 		var current = program;
756 		(current && current._spidergl && current._spidergl._gl_bindAttribLocation.apply(current._spidergl, arguments));
757 	};
758 
759 	glFunctions.detachShader = gl.detachShader;
760 	gl.detachShader = function (program) {
761 		var ext = this._spidergl.wn._ext;
762 		ext.glFunctions.detachShader.apply(this, arguments);
763 		var current = program;
764 		(current && current._spidergl && current._spidergl._gl_detachShader.apply(current._spidergl, arguments));
765 	};
766 
767 	glFunctions.linkProgram = gl.linkProgram;
768 	gl.linkProgram = function (program) {
769 		var ext = this._spidergl.wn._ext;
770 		ext.glFunctions.linkProgram.apply(this, arguments);
771 		var current = program;
772 		(current && current._spidergl && current._spidergl._gl_linkProgram.apply(current._spidergl, arguments));
773 	};
774 
775 	glFunctions.uniform1f = gl.uniform1f;
776 	gl.uniform1f = function () {
777 		var ext = this._spidergl.wn._ext;
778 		ext.glFunctions.uniform1f.apply(this, arguments);
779 		var current = ext.cb.getCurrentProgram();
780 		(current && current._spidergl && current._spidergl._gl_uniform1f.apply(current._spidergl, arguments));
781 	};
782 
783 	glFunctions.uniform1fv = gl.uniform1fv;
784 	gl.uniform1fv = function () {
785 		var ext = this._spidergl.wn._ext;
786 		ext.glFunctions.uniform1fv.apply(this, arguments);
787 		var current = ext.cb.getCurrentProgram();
788 		(current && current._spidergl && current._spidergl._gl_uniform1fv.apply(current._spidergl, arguments));
789 	};
790 
791 	glFunctions.uniform1i = gl.uniform1i;
792 	gl.uniform1i = function () {
793 		var ext = this._spidergl.wn._ext;
794 		ext.glFunctions.uniform1i.apply(this, arguments);
795 		var current = ext.cb.getCurrentProgram();
796 		(current && current._spidergl && current._spidergl._gl_uniform1i.apply(current._spidergl, arguments));
797 	};
798 
799 	glFunctions.uniform1iv = gl.uniform1iv;
800 	gl.uniform1iv = function () {
801 		var ext = this._spidergl.wn._ext;
802 		ext.glFunctions.uniform1iv.apply(this, arguments);
803 		var current = ext.cb.getCurrentProgram();
804 		(current && current._spidergl && current._spidergl._gl_uniform1iv.apply(current._spidergl, arguments));
805 	};
806 
807 	glFunctions.uniform2f = gl.uniform2f;
808 	gl.uniform2f = function () {
809 		var ext = this._spidergl.wn._ext;
810 		ext.glFunctions.uniform2f.apply(this, arguments);
811 		var current = ext.cb.getCurrentProgram();
812 		(current && current._spidergl && current._spidergl._gl_uniform2f.apply(current._spidergl, arguments));
813 	};
814 
815 	glFunctions.uniform2fv = gl.uniform2fv;
816 	gl.uniform2fv = function () {
817 		var ext = this._spidergl.wn._ext;
818 		ext.glFunctions.uniform2fv.apply(this, arguments);
819 		var current = ext.cb.getCurrentProgram();
820 		(current && current._spidergl && current._spidergl._gl_uniform2fv.apply(current._spidergl, arguments));
821 	};
822 
823 	glFunctions.uniform2i = gl.uniform2i;
824 	gl.uniform2i = function () {
825 		var ext = this._spidergl.wn._ext;
826 		ext.glFunctions.uniform2i.apply(this, arguments);
827 		var current = ext.cb.getCurrentProgram();
828 		(current && current._spidergl && current._spidergl._gl_uniform2i.apply(current._spidergl, arguments));
829 	};
830 
831 	glFunctions.uniform2iv = gl.uniform2iv;
832 	gl.uniform2iv = function () {
833 		var ext = this._spidergl.wn._ext;
834 		ext.glFunctions.uniform2iv.apply(this, arguments);
835 		var current = ext.cb.getCurrentProgram();
836 		(current && current._spidergl && current._spidergl._gl_uniform2iv.apply(current._spidergl, arguments));
837 	};
838 
839 	glFunctions.uniform3f = gl.uniform3f;
840 	gl.uniform3f = function () {
841 		var ext = this._spidergl.wn._ext;
842 		ext.glFunctions.uniform3f.apply(this, arguments);
843 		var current = ext.cb.getCurrentProgram();
844 		(current && current._spidergl && current._spidergl._gl_uniform3f.apply(current._spidergl, arguments));
845 	};
846 
847 	glFunctions.uniform3fv = gl.uniform3fv;
848 	gl.uniform3fv = function () {
849 		var ext = this._spidergl.wn._ext;
850 		ext.glFunctions.uniform3fv.apply(this, arguments);
851 		var current = ext.cb.getCurrentProgram();
852 		(current && current._spidergl && current._spidergl._gl_uniform3fv.apply(current._spidergl, arguments));
853 	};
854 
855 	glFunctions.uniform3i = gl.uniform3i;
856 	gl.uniform3i = function () {
857 		var ext = this._spidergl.wn._ext;
858 		ext.glFunctions.uniform3i.apply(this, arguments);
859 		var current = ext.cb.getCurrentProgram();
860 		(current && current._spidergl && current._spidergl._gl_uniform3i.apply(current._spidergl, arguments));
861 	};
862 
863 	glFunctions.uniform3iv = gl.uniform3iv;
864 	gl.uniform3iv = function () {
865 		var ext = this._spidergl.wn._ext;
866 		ext.glFunctions.uniform3iv.apply(this, arguments);
867 		var current = ext.cb.getCurrentProgram();
868 		(current && current._spidergl && current._spidergl._gl_uniform3iv.apply(current._spidergl, arguments));
869 	};
870 
871 	glFunctions.uniform4f = gl.uniform4f;
872 	gl.uniform4f = function () {
873 		var ext = this._spidergl.wn._ext;
874 		ext.glFunctions.uniform4f.apply(this, arguments);
875 		var current = ext.cb.getCurrentProgram();
876 		(current && current._spidergl && current._spidergl._gl_uniform4f.apply(current._spidergl, arguments));
877 	};
878 
879 	glFunctions.uniform4fv = gl.uniform4fv;
880 	gl.uniform4fv = function () {
881 		var ext = this._spidergl.wn._ext;
882 		ext.glFunctions.uniform4fv.apply(this, arguments);
883 		var current = ext.cb.getCurrentProgram();
884 		(current && current._spidergl && current._spidergl._gl_uniform4fv.apply(current._spidergl, arguments));
885 	};
886 
887 	glFunctions.uniform4i = gl.uniform4i;
888 	gl.uniform4i = function () {
889 		var ext = this._spidergl.wn._ext;
890 		ext.glFunctions.uniform4i.apply(this, arguments);
891 		var current = ext.cb.getCurrentProgram();
892 		(current && current._spidergl && current._spidergl._gl_uniform4i.apply(current._spidergl, arguments));
893 	};
894 
895 	glFunctions.uniform4iv = gl.uniform4iv;
896 	gl.uniform4iv = function () {
897 		var ext = this._spidergl.wn._ext;
898 		ext.glFunctions.uniform4iv.apply(this, arguments);
899 		var current = ext.cb.getCurrentProgram();
900 		(current && current._spidergl && current._spidergl._gl_uniform4iv.apply(current._spidergl, arguments));
901 	};
902 
903 	glFunctions.uniformMatrix2fv = gl.uniformMatrix2fv;
904 	gl.uniformMatrix2fv = function () {
905 		var ext = this._spidergl.wn._ext;
906 		ext.glFunctions.uniformMatrix2fv.apply(this, arguments);
907 		var current = ext.cb.getCurrentProgram();
908 		(current && current._spidergl && current._spidergl._gl_uniformMatrix2fv.apply(current._spidergl, arguments));
909 	};
910 
911 	glFunctions.uniformMatrix3fv = gl.uniformMatrix3fv;
912 	gl.uniformMatrix3fv = function () {
913 		var ext = this._spidergl.wn._ext;
914 		ext.glFunctions.uniformMatrix3fv.apply(this, arguments);
915 		var current = ext.cb.getCurrentProgram();
916 		(current && current._spidergl && current._spidergl._gl_uniformMatrix3fv.apply(current._spidergl, arguments));
917 	};
918 
919 	glFunctions.uniformMatrix4fv = gl.uniformMatrix4fv;
920 	gl.uniformMatrix4fv = function () {
921 		var ext = this._spidergl.wn._ext;
922 		ext.glFunctions.uniformMatrix4fv.apply(this, arguments);
923 		var current = ext.cb.getCurrentProgram();
924 		(current && current._spidergl && current._spidergl._gl_uniformMatrix4fv.apply(current._spidergl, arguments));
925 	};
926 
927 	glFunctions.validateProgram = gl.validateProgram;
928 	gl.validateProgram = function (program) {
929 		var ext = this._spidergl.wn._ext;
930 		ext.glFunctions.validateProgram.apply(this, arguments);
931 		var current = program;
932 		(current && current._spidergl && current._spidergl._gl_validateProgram.apply(current._spidergl, arguments));
933 	};
934 	//////////////////////////////////////////////////////////////////////////////////////////
935 
936 
937 
938 	// renderbuffer
939 	//////////////////////////////////////////////////////////////////////////////////////////
940 	glFunctions.deleteRenderbuffer = gl.deleteRenderbuffer;
941 	gl.deleteRenderbuffer = function (renderbuffer) {
942 		var ext = this._spidergl.wn._ext;
943 		ext.glFunctions.deleteRenderbuffer.apply(this, arguments);
944 		var current = renderbuffer;
945 		(current && current._spidergl && current._spidergl._gl_deleteRenderbuffer.apply(current._spidergl, arguments));
946 	};
947 
948 	glFunctions.isRenderbuffer = gl.isRenderbuffer;
949 	gl.isRenderbuffer = function (renderbuffer) {
950 		var ext = this._spidergl.wn._ext;
951 		var r = ext.glFunctions.isRenderbuffer.apply(this, arguments);
952 		var current = renderbuffer;
953 		(current && current._spidergl && current._spidergl._gl_isRenderbuffer.apply(current._spidergl, arguments));
954 		return r;
955 	};
956 
957 	glFunctions.bindRenderbuffer = gl.bindRenderbuffer;
958 	gl.bindRenderbuffer = function (target) {
959 		var ext = this._spidergl.wn._ext;
960 		ext.glFunctions.bindRenderbuffer.apply(this, arguments);
961 		var current = ext.cb.getCurrentRenderbuffer(target);
962 		(current && current._spidergl && current._spidergl._gl_bindRenderbuffer.apply(current._spidergl, arguments));
963 	};
964 
965 	glFunctions.getRenderbufferParameter = gl.getRenderbufferParameter;
966 	gl.getRenderbufferParameter = function (target) {
967 		var ext = this._spidergl.wn._ext;
968 		var r = ext.glFunctions.getRenderbufferParameter.apply(this, arguments);
969 		var current = ext.cb.getCurrentRenderbuffer(target);
970 		(current && current._spidergl && current._spidergl._gl_getRenderbufferParameter.apply(current._spidergl, arguments));
971 		return r;
972 	};
973 
974 	glFunctions.renderbufferStorage = gl.renderbufferStorage;
975 	gl.renderbufferStorage = function (target) {
976 		var ext = this._spidergl.wn._ext;
977 		ext.glFunctions.renderbufferStorage.apply(this, arguments);
978 		var current = ext.cb.getCurrentRenderbuffer(target);
979 		(current && current._spidergl && current._spidergl._gl_renderbufferStorage.apply(current._spidergl, arguments));
980 	}
981 	//////////////////////////////////////////////////////////////////////////////////////////
982 
983 
984 
985 	// shader
986 	//////////////////////////////////////////////////////////////////////////////////////////
987 	glFunctions.deleteShader = gl.deleteShader;
988 	gl.deleteShader = function (shader) {
989 		var ext = this._spidergl.wn._ext;
990 		ext.glFunctions.deleteShader.apply(this, arguments);
991 		var current = shader;
992 		(current && current._spidergl && current._spidergl._gl_deleteShader.apply(current._spidergl, arguments));
993 	};
994 
995 	glFunctions.isShader = gl.isShader;
996 	gl.isShader = function (shader) {
997 		var ext = this._spidergl.wn._ext;
998 		var r = ext.glFunctions.isShader.apply(this, arguments);
999 		var current = shader;
1000 		(current && current._spidergl && current._spidergl._gl_isShader.apply(current._spidergl, arguments));
1001 		return r;
1002 	};
1003 
1004 	glFunctions.getShaderParameter = gl.getShaderParameter;
1005 	gl.getShaderParameter = function (shader) {
1006 		var ext = this._spidergl.wn._ext;
1007 		var r = ext.glFunctions.getShaderParameter.apply(this, arguments);
1008 		var current = shader;
1009 		(current && current._spidergl && current._spidergl._gl_getShaderParameter.apply(current._spidergl, arguments));
1010 		return r;
1011 	};
1012 
1013 	glFunctions.getShaderInfoLog = gl.getShaderInfoLog;
1014 	gl.getShaderInfoLog = function (shader) {
1015 		var ext = this._spidergl.wn._ext;
1016 		var r = ext.glFunctions.getShaderInfoLog.apply(this, arguments);
1017 		var current = shader;
1018 		(current && current._spidergl && current._spidergl._gl_getShaderInfoLog.apply(current._spidergl, arguments));
1019 		return r;
1020 	};
1021 
1022 	glFunctions.getShaderSource = gl.getShaderSource;
1023 	gl.getShaderSource = function (shader) {
1024 		var ext = this._spidergl.wn._ext;
1025 		var r = ext.glFunctions.getShaderSource.apply(this, arguments);
1026 		var current = shader;
1027 		(current && current._spidergl && current._spidergl._gl_getShaderSource.apply(current._spidergl, arguments));
1028 		return r;
1029 	};
1030 
1031 	glFunctions.compileShader = gl.compileShader;
1032 	gl.compileShader = function (shader) {
1033 		var ext = this._spidergl.wn._ext;
1034 		ext.glFunctions.compileShader.apply(this, arguments);
1035 		var current = shader;
1036 		(current && current._spidergl && current._spidergl._gl_compileShader.apply(current._spidergl, arguments));
1037 	}
1038 
1039 	glFunctions.shaderSource = gl.shaderSource;
1040 	gl.shaderSource = function (shader) {
1041 		var ext = this._spidergl.wn._ext;
1042 		ext.glFunctions.shaderSource.apply(this, arguments);
1043 		var current = shader;
1044 		(current && current._spidergl && current._spidergl._gl_shaderSource.apply(current._spidergl, arguments));
1045 	}
1046 	//////////////////////////////////////////////////////////////////////////////////////////
1047 
1048 
1049 
1050 	// texture
1051 	//////////////////////////////////////////////////////////////////////////////////////////
1052 	ext.textureTargetMap = { };
1053 	ext.textureTargetMap[gl.TEXTURE_2D                 ] = gl.TEXTURE_2D;
1054 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP           ] = gl.TEXTURE_CUBE_MAP;
1055 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_POSITIVE_X] = gl.TEXTURE_CUBE_MAP;
1056 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_NEGATIVE_X] = gl.TEXTURE_CUBE_MAP;
1057 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_POSITIVE_Y] = gl.TEXTURE_CUBE_MAP;
1058 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_NEGATIVE_Y] = gl.TEXTURE_CUBE_MAP;
1059 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_POSITIVE_Z] = gl.TEXTURE_CUBE_MAP;
1060 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_NEGATIVE_Z] = gl.TEXTURE_CUBE_MAP;
1061 
1062 	glFunctions.deleteTexture = gl.deleteTexture;
1063 	gl.deleteTexture = function (texture) {
1064 		var ext = this._spidergl.wn._ext;
1065 		ext.glFunctions.deleteTexture.apply(this, arguments);
1066 		var current = texture;
1067 		(current && current._spidergl && current._spidergl._gl_deleteTexture.apply(current._spidergl, arguments));
1068 	};
1069 
1070 	glFunctions.isTexture = gl.isTexture;
1071 	gl.isTexture = function (texture) {
1072 		var ext = this._spidergl.wn._ext;
1073 		var r = ext.glFunctions.isTexture.apply(this, arguments);
1074 		var current = texture;
1075 		(current && current._spidergl && current._spidergl._gl_isTexture.apply(current._spidergl, arguments));
1076 		return r;
1077 	};
1078 
1079 	glFunctions.bindTexture = gl.bindTexture;
1080 	gl.bindTexture = function (target) {
1081 		var ext = this._spidergl.wn._ext;
1082 		ext.glFunctions.bindTexture.apply(this, arguments);
1083 		var current = ext.cb.getCurrentTexture(target);
1084 		(current && current._spidergl && current._spidergl._gl_bindTexture.apply(current._spidergl, arguments));
1085 	};
1086 
1087 	glFunctions.getTexParameter = gl.getTexParameter;
1088 	gl.getTexParameter = function (target) {
1089 		var ext = this._spidergl.wn._ext;
1090 		var r = ext.glFunctions.getTexParameter.apply(this, arguments);
1091 		var current = ext.cb.getCurrentTexture(target);
1092 		(current && current._spidergl && current._spidergl._gl_getTexParameter.apply(current._spidergl, arguments));
1093 		return r;
1094 	};
1095 
1096 	glFunctions.copyTexImage2D = gl.copyTexImage2D;
1097 	gl.copyTexImage2D = function (target) {
1098 		var ext = this._spidergl.wn._ext;
1099 		ext.glFunctions.copyTexImage2D.apply(this, arguments);
1100 		var texTarget = ext.textureTargetMap[target];
1101 		var current = ext.cb.getCurrentTexture(texTarget);
1102 		(current && current._spidergl && current._spidergl._gl_copyTexImage2D.apply(current._spidergl, arguments));
1103 	}
1104 
1105 	glFunctions.copyTexSubImage2D = gl.copyTexSubImage2D;
1106 	gl.copyTexSubImage2D = function (target) {
1107 		var ext = this._spidergl.wn._ext;
1108 		ext.glFunctions.copyTexSubImage2D.apply(this, arguments);
1109 		var texTarget = ext.textureTargetMap[target];
1110 		var current = ext.cb.getCurrentTexture(texTarget);
1111 		(current && current._spidergl && current._spidergl._gl_copyTexSubImage2D.apply(current._spidergl, arguments));
1112 	}
1113 
1114 	glFunctions.generateMipmap = gl.generateMipmap;
1115 	gl.generateMipmap = function (target) {
1116 		var ext = this._spidergl.wn._ext;
1117 		ext.glFunctions.generateMipmap.apply(this, arguments);
1118 		var current = ext.cb.getCurrentTexture(target);
1119 		(current && current._spidergl && current._spidergl._gl_generateMipmap.apply(current._spidergl, arguments));
1120 	}
1121 
1122 	glFunctions.texImage2D = gl.texImage2D;
1123 	gl.texImage2D = function (target) {
1124 		var ext = this._spidergl.wn._ext;
1125 		ext.glFunctions.texImage2D.apply(this, arguments);
1126 		var texTarget = ext.textureTargetMap[target];
1127 		var current = ext.cb.getCurrentTexture(texTarget);
1128 		(current && current._spidergl && current._spidergl._gl_texImage2D.apply(current._spidergl, arguments));
1129 	}
1130 
1131 	glFunctions.texParameterf = gl.texParameterf;
1132 	gl.texParameterf = function (target) {
1133 		var ext = this._spidergl.wn._ext;
1134 		ext.glFunctions.texParameterf.apply(this, arguments);
1135 		var current = ext.cb.getCurrentTexture(target);
1136 		(current && current._spidergl && current._spidergl._gl_texParameterf.apply(current._spidergl, arguments));
1137 	}
1138 
1139 	glFunctions.texParameteri = gl.texParameteri;
1140 	gl.texParameteri = function (target) {
1141 		var ext = this._spidergl.wn._ext;
1142 		ext.glFunctions.texParameteri.apply(this, arguments);
1143 		var current = ext.cb.getCurrentTexture(target);
1144 		(current && current._spidergl && current._spidergl._gl_texParameteri.apply(current._spidergl, arguments));
1145 	}
1146 
1147 	glFunctions.texSubImage2D = gl.texSubImage2D;
1148 	gl.texSubImage2D = function (target) {
1149 		var ext = this._spidergl.wn._ext;
1150 		ext.glFunctions.texSubImage2D.apply(this, arguments);
1151 		var texTarget = ext.textureTargetMap[target];
1152 		var current = ext.cb.getCurrentTexture(texTarget);
1153 		(current && current._spidergl && current._spidergl._gl_texSubImage2D.apply(current._spidergl, arguments));
1154 	}
1155 	//////////////////////////////////////////////////////////////////////////////////////////
1156 
1157 	return true;
1158 };
1159 
1160 SpiderGL.WebGL.Context._setup_SGL_direct_state_access = function (gl, pubExt) {
1161 	if (!gl) return false;
1162 	if (!pubExt) return false;
1163 	if (!gl._spidergl) return false;
1164 	if (gl._spidergl.dsa) return false;
1165 
1166 	var dsa = pubExt;
1167 	var ext = dsa._ext;
1168 	var glFunctions = ext.glFunctions;
1169 
1170 	ext.cb = gl.getExtension("SGL_current_binding");
1171 	if (!ext.cb) return false;
1172 
1173 	// buffer
1174 	//////////////////////////////////////////////////////////////////////////////////////////
1175 	dsa.getBufferParameter = function (buffer, target, pname) {
1176 		var ext = this._ext;
1177 		var gl  = ext.gl;
1178 		var current = ext.cb.getCurrentBuffer(target);
1179 		(current != buffer) && gl.bindBuffer(target, buffer);
1180 		var r = gl.getBufferParameter(target, pname);
1181 		(current != buffer) && gl.bindBuffer(target, current);
1182 		return r;
1183 	};
1184 
1185 	dsa.bufferData = function (buffer, target, dataOrSize, usage) {
1186 		var ext = this._ext;
1187 		var gl  = ext.gl;
1188 		var current = ext.cb.getCurrentBuffer(target);
1189 		(current != buffer) && gl.bindBuffer(target, buffer);
1190 		gl.bufferData(target, dataOrSize, usage);
1191 		(current != buffer) && gl.bindBuffer(target, current);
1192 	}
1193 
1194 	dsa.bufferSubData = function (buffer, target, offset, data) {
1195 		var ext = this._ext;
1196 		var gl  = ext.gl;
1197 		var current = ext.cb.getCurrentBuffer(target);
1198 		(current != buffer) && gl.bindBuffer(target, buffer);
1199 		gl.bufferSubData(target, offset, data);
1200 		(current != buffer) && gl.bindBuffer(target, current);
1201 	}
1202 
1203 	dsa.vertexAttribPointer = function (buffer, indx, size, type, normalized, stride, offset) {
1204 		var ext = this._ext;
1205 		var gl  = ext.gl;
1206 		var target  = gl.ARRAY_BUFFER;
1207 		var current = ext.cb.getCurrentBuffer(target);
1208 		(current != buffer) && gl.bindBuffer(target, buffer);
1209 		gl.vertexAttribPointer(indx, size, type, normalized, stride, offset);
1210 		(current != buffer) && gl.bindBuffer(target, current);
1211 	};
1212 
1213 	dsa.drawElements = function (buffer, mode, count, type, offset) {
1214 		var ext = this._ext;
1215 		var gl  = ext.gl;
1216 		var target  = gl.ELEMENT_ARRAY_BUFFER;
1217 		var current = ext.cb.getCurrentBuffer(target);
1218 		(current != buffer) && gl.bindBuffer(target, buffer);
1219 		gl.drawElements(mode, count, type, offset);
1220 		(current != buffer) && gl.bindBuffer(target, current);
1221 	};
1222 	//////////////////////////////////////////////////////////////////////////////////////////
1223 
1224 
1225 
1226 	// framebuffer
1227 	//////////////////////////////////////////////////////////////////////////////////////////
1228 	dsa.checkFramebufferStatus = function (framebuffer, target) {
1229 		var ext = this._ext;
1230 		var gl  = ext.gl;
1231 		var current = ext.cb.getCurrentFramebuffer(target);
1232 		(current != framebuffer) && gl.bindFramebuffer(target, framebuffer);
1233 		var r = gl.checkFramebufferStatus(target);
1234 		(current != framebuffer) && gl.bindFramebuffer(target, current);
1235 		return r;
1236 	};
1237 
1238 	dsa.getFramebufferAttachmentParameter = function (framebuffer, target, attachment, pname) {
1239 		var ext = this._ext;
1240 		var gl  = ext.gl;
1241 		var current = ext.cb.getCurrentFramebuffer(target);
1242 		(current != framebuffer) && gl.bindFramebuffer(target, framebuffer);
1243 		var r = gl.getFramebufferAttachmentParameter(target, attachment, pname);
1244 		(current != framebuffer) && gl.bindFramebuffer(target, current);
1245 		return r;
1246 	};
1247 
1248 	dsa.framebufferRenderbuffer = function (framebuffer, target, attachment, renderbuffertarget, renderbuffer) {
1249 		var ext = this._ext;
1250 		var gl  = ext.gl;
1251 		var current = ext.cb.getCurrentFramebuffer(target);
1252 		(current != framebuffer) && gl.bindFramebuffer(target, framebuffer);
1253 		gl.framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
1254 		(current != framebuffer) && gl.bindFramebuffer(target, current);
1255 	};
1256 
1257 	dsa.framebufferTexture2D = function (framebuffer, target, attachment, textarget, texture, level) {
1258 		var ext = this._ext;
1259 		var gl  = ext.gl;
1260 		var current = ext.cb.getCurrentFramebuffer(target);
1261 		(current != framebuffer) && gl.bindFramebuffer(target, framebuffer);
1262 		gl.framebufferTexture2D(target, attachment, textarget, texture, level);
1263 		(current != framebuffer) && gl.bindFramebuffer(target, current);
1264 	};
1265 
1266 	dsa.clear = function (framebuffer, mask) {
1267 		var ext = this._ext;
1268 		var gl  = ext.gl;
1269 		var target = gl.FRAMEBUFFER
1270 		var current = ext.cb.getCurrentFramebuffer(target);
1271 		(current != framebuffer) && gl.bindFramebuffer(target, framebuffer);
1272 		gl.clear(mask);
1273 		(current != framebuffer) && gl.bindFramebuffer(target, current);
1274 	};
1275 
1276 	dsa.readPixels = function (framebuffer, x, y, width, height, format, type, pixels) {
1277 		var ext = this._ext;
1278 		var gl  = ext.gl;
1279 		var target = gl.FRAMEBUFFER
1280 		var current = ext.cb.getCurrentFramebuffer(target);
1281 		(current != framebuffer) && gl.bindFramebuffer(target, framebuffer);
1282 		gl.readPixels(x, y, width, height, format, type, pixels);
1283 		(current != framebuffer) && gl.bindFramebuffer(target, current);
1284 	};
1285 	//////////////////////////////////////////////////////////////////////////////////////////
1286 
1287 
1288 
1289 	// program
1290 	//////////////////////////////////////////////////////////////////////////////////////////
1291 	dsa.uniform1f = function (program, location, x) {
1292 		var ext = this._ext;
1293 		var gl  = ext.gl;
1294 		var current = ext.cb.getCurrentProgram();
1295 		(current != program) && gl.useProgram(program);
1296 		gl.uniform1f(location, x);
1297 		(current != program) && gl.useProgram(current);
1298 	};
1299 
1300 	dsa.uniform1fv = function (program, location, v) {
1301 		var ext = this._ext;
1302 		var gl  = ext.gl;
1303 		var current = ext.cb.getCurrentProgram();
1304 		(current != program) && gl.useProgram(program);
1305 		gl.uniform1fv(location, v);
1306 		(current != program) && gl.useProgram(current);
1307 	};
1308 
1309 	dsa.uniform1i = function (program, location, x) {
1310 		var ext = this._ext;
1311 		var gl  = ext.gl;
1312 		var current = ext.cb.getCurrentProgram();
1313 		(current != program) && gl.useProgram(program);
1314 		gl.uniform1i(location, x);
1315 		(current != program) && gl.useProgram(current);
1316 	};
1317 
1318 	dsa.uniform1iv = function (program, location, v) {
1319 		var ext = this._ext;
1320 		var gl  = ext.gl;
1321 		var current = ext.cb.getCurrentProgram();
1322 		(current != program) && gl.useProgram(program);
1323 		gl.uniform1iv(location, v);
1324 		(current != program) && gl.useProgram(current);
1325 	};
1326 
1327 	dsa.uniform2f = function (program, location, x, y) {
1328 		var ext = this._ext;
1329 		var gl  = ext.gl;
1330 		var current = ext.cb.getCurrentProgram();
1331 		(current != program) && gl.useProgram(program);
1332 		gl.uniform2f(location, x, y);
1333 		(current != program) && gl.useProgram(current);
1334 	};
1335 
1336 	dsa.uniform2fv = function (program, location, v) {
1337 		var ext = this._ext;
1338 		var gl  = ext.gl;
1339 		var current = ext.cb.getCurrentProgram();
1340 		(current != program) && gl.useProgram(program);
1341 		gl.uniform2fv(location, v);
1342 		(current != program) && gl.useProgram(current);
1343 	};
1344 
1345 	dsa.uniform2i = function (program, location, x, y) {
1346 		var ext = this._ext;
1347 		var gl  = ext.gl;
1348 		var current = ext.cb.getCurrentProgram();
1349 		(current != program) && gl.useProgram(program);
1350 		gl.uniform2i(location, x, y);
1351 		(current != program) && gl.useProgram(current);
1352 	};
1353 
1354 	dsa.uniform2iv = function (program, location, v) {
1355 		var ext = this._ext;
1356 		var gl  = ext.gl;
1357 		var current = ext.cb.getCurrentProgram();
1358 		(current != program) && gl.useProgram(program);
1359 		gl.uniform2iv(location, v);
1360 		(current != program) && gl.useProgram(current);
1361 	};
1362 
1363 	dsa.uniform3f = function (program, location, x, y, z) {
1364 		var ext = this._ext;
1365 		var gl  = ext.gl;
1366 		var current = ext.cb.getCurrentProgram();
1367 		(current != program) && gl.useProgram(program);
1368 		gl.uniform3f(location, x, y, z);
1369 		(current != program) && gl.useProgram(current);
1370 	};
1371 
1372 	dsa.uniform3fv = function (program, location, v) {
1373 		var ext = this._ext;
1374 		var gl  = ext.gl;
1375 		var current = ext.cb.getCurrentProgram();
1376 		(current != program) && gl.useProgram(program);
1377 		gl.uniform3fv(location, v);
1378 		(current != program) && gl.useProgram(current);
1379 	};
1380 
1381 	dsa.uniform3i = function (program, location, x, y, z) {
1382 		var ext = this._ext;
1383 		var gl  = ext.gl;
1384 		var current = ext.cb.getCurrentProgram();
1385 		(current != program) && gl.useProgram(program);
1386 		gl.uniform3i(location, x, y, z);
1387 		(current != program) && gl.useProgram(current);
1388 	};
1389 
1390 	dsa.uniform3iv = function (program, location, v) {
1391 		var ext = this._ext;
1392 		var gl  = ext.gl;
1393 		var current = ext.cb.getCurrentProgram();
1394 		(current != program) && gl.useProgram(program);
1395 		gl.uniform3iv(location, v);
1396 		(current != program) && gl.useProgram(current);
1397 	};
1398 
1399 	dsa.uniform4f = function (program, location, x, y, z, w) {
1400 		var ext = this._ext;
1401 		var gl  = ext.gl;
1402 		var current = ext.cb.getCurrentProgram();
1403 		(current != program) && gl.useProgram(program);
1404 		gl.uniform4f(location, x, y, z, w);
1405 		(current != program) && gl.useProgram(current);
1406 	};
1407 
1408 	dsa.uniform4fv = function (program, location, v) {
1409 		var ext = this._ext;
1410 		var gl  = ext.gl;
1411 		var current = ext.cb.getCurrentProgram();
1412 		(current != program) && gl.useProgram(program);
1413 		gl.uniform4fv(location, v);
1414 		(current != program) && gl.useProgram(current);
1415 	};
1416 
1417 	dsa.uniform4i = function (program, location, x, y, z, w) {
1418 		var ext = this._ext;
1419 		var gl  = ext.gl;
1420 		var current = ext.cb.getCurrentProgram();
1421 		(current != program) && gl.useProgram(program);
1422 		gl.uniform4i(location, x, y, z, w);
1423 		(current != program) && gl.useProgram(current);
1424 	};
1425 
1426 	dsa.uniform4iv = function (program, location, v) {
1427 		var ext = this._ext;
1428 		var gl  = ext.gl;
1429 		var current = ext.cb.getCurrentProgram();
1430 		(current != program) && gl.useProgram(program);
1431 		gl.uniform4iv(location, v);
1432 		(current != program) && gl.useProgram(current);
1433 	};
1434 
1435 	dsa.uniformMatrix2fv = function (program, location, transpose, value) {
1436 		var ext = this._ext;
1437 		var gl  = ext.gl;
1438 		var current = ext.cb.getCurrentProgram();
1439 		(current != program) && gl.useProgram(program);
1440 		gl.uniformMatrix2fv(location, transpose, value);
1441 		(current != program) && gl.useProgram(current);
1442 	};
1443 
1444 	dsa.uniformMatrix3fv = function (program, location, transpose, value) {
1445 		var ext = this._ext;
1446 		var gl  = ext.gl;
1447 		var current = ext.cb.getCurrentProgram();
1448 		(current != program) && gl.useProgram(program);
1449 		gl.uniformMatrix3fv(location, transpose, value);
1450 		(current != program) && gl.useProgram(current);
1451 	};
1452 
1453 	dsa.uniformMatrix4fv = function (program, location, transpose, value) {
1454 		var ext = this._ext;
1455 		var gl  = ext.gl;
1456 		var current = ext.cb.getCurrentProgram();
1457 		(current != program) && gl.useProgram(program);
1458 		gl.uniformMatrix4fv(location, transpose, value);
1459 		(current != program) && gl.useProgram(current);
1460 	};
1461 	//////////////////////////////////////////////////////////////////////////////////////////
1462 
1463 
1464 
1465 	// renderbuffer
1466 	//////////////////////////////////////////////////////////////////////////////////////////
1467 	dsa.getRenderbufferParameter = function (renderbuffer, target, pname) {
1468 		var ext = this._ext;
1469 		var gl  = ext.gl;
1470 		var current = ext.cb.getCurrentRenderbuffer(target);
1471 		(current != renderbuffer) && gl.bindRenderbuffer(target, renderbuffer);
1472 		var r = gl.getRenderbufferParameter.call(gl, target, pname);
1473 		(current != renderbuffer) && gl.bindRenderbuffer(target, current);
1474 		return r;
1475 	};
1476 
1477 	dsa.renderbufferStorage = function (renderbuffer, target, internalformat, width, height) {
1478 		var ext = this._ext;
1479 		var gl  = ext.gl;
1480 		var current = ext.cb.getCurrentRenderbuffer(target);
1481 		(current != renderbuffer) && gl.bindRenderbuffer(target, renderbuffer);
1482 		gl.renderbufferStorage(target, internalformat, width, height);
1483 		(current != renderbuffer) && gl.bindRenderbuffer(target, current);
1484 	};
1485 	//////////////////////////////////////////////////////////////////////////////////////////
1486 
1487 
1488 
1489 	// shader
1490 	//////////////////////////////////////////////////////////////////////////////////////////
1491 	// NO DSA FUNCTIONS
1492 	dsa.shaderIsNull = function (shader) {
1493 		return (shader == null);
1494 	};
1495 	//////////////////////////////////////////////////////////////////////////////////////////
1496 
1497 
1498 
1499 	// texture
1500 	//////////////////////////////////////////////////////////////////////////////////////////
1501 	ext.textureTargetMap = { };
1502 	ext.textureTargetMap[gl.TEXTURE_2D                 ] = gl.TEXTURE_2D;
1503 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP           ] = gl.TEXTURE_CUBE_MAP;
1504 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_POSITIVE_X] = gl.TEXTURE_CUBE_MAP;
1505 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_NEGATIVE_X] = gl.TEXTURE_CUBE_MAP;
1506 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_POSITIVE_Y] = gl.TEXTURE_CUBE_MAP;
1507 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_NEGATIVE_Y] = gl.TEXTURE_CUBE_MAP;
1508 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_POSITIVE_Z] = gl.TEXTURE_CUBE_MAP;
1509 	ext.textureTargetMap[gl.TEXTURE_CUBE_MAP_NEGATIVE_Z] = gl.TEXTURE_CUBE_MAP;
1510 
1511 	dsa.getTexParameter = function (texture, target, pname) {
1512 		var ext = this._ext;
1513 		var gl  = ext.gl;
1514 		var current = ext.cb.getCurrentTexture(target);
1515 		(current != texture) && gl.bindTexture(target, texture);
1516 		var r = gl.getTexParameter(target, pname);
1517 		(current != texture) && gl.bindTexture(target, current);
1518 		return r;
1519 	};
1520 
1521 	dsa.copyTexImage2D = function (texture, target, level, internalformat, x, y, width, height, border) {
1522 		var ext = this._ext;
1523 		var gl  = ext.gl;
1524 		var texTarget = ext.textureTargetMap[target];
1525 		var current = ext.cb.getCurrentTexture(texTarget);
1526 		(current != texture) && gl.bindTexture(texTarget, texture);
1527 		gl.copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1528 		(current != texture) && gl.bindTexture(texTarget, current);
1529 	};
1530 
1531 	dsa.copyTexSubImage2D = function (texture, target, level, xoffset, yoffset, x, y, width, height, border) {
1532 		var ext = this._ext;
1533 		var gl  = ext.gl;
1534 		var texTarget = ext.textureTargetMap[target];
1535 		var current = ext.cb.getCurrentTexture(texTarget);
1536 		(current != texture) && gl.bindTexture(texTarget, texture);
1537 		gl.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height, border);
1538 		(current != texture) && gl.bindTexture(texTarget, current);
1539 	};
1540 
1541 	dsa.generateMipmap = function (texture, target) {
1542 		var ext = this._ext;
1543 		var gl  = ext.gl;
1544 		var current = ext.cb.getCurrentTexture(target);
1545 		(current != texture) && gl.bindTexture(target, texture);
1546 		gl.generateMipmap(target);
1547 		(current != texture) && gl.bindTexture(target, current);
1548 	};
1549 
1550 	dsa.texImage2D = function (texture, target) {
1551 		var ext = this._ext;
1552 		var gl  = ext.gl;
1553 		var texTarget = ext.textureTargetMap[target];
1554 		var current = ext.cb.getCurrentTexture(texTarget);
1555 		(current != texture) && gl.bindTexture(texTarget, texture);
1556 		var args = Array.prototype.slice.call(arguments, 1);
1557 		gl.texImage2D.apply(gl, args);
1558 		(current != texture) && gl.bindTexture(texTarget, current);
1559 	};
1560 
1561 	dsa.texParameterf = function (texture, target, pname, param) {
1562 		var ext = this._ext;
1563 		var gl  = ext.gl;
1564 		var current = ext.cb.getCurrentTexture(target);
1565 		(current != texture) && gl.bindTexture(target, texture);
1566 		gl.texParameterf(target, pname, param);
1567 		(current != texture) && gl.bindTexture(target, current);
1568 	};
1569 
1570 	dsa.texParameteri = function (texture, target, pname, param) {
1571 		var ext = this._ext;
1572 		var gl  = ext.gl;
1573 		var current = ext.cb.getCurrentTexture(target);
1574 		(current != texture) && gl.bindTexture(target, texture);
1575 		gl.texParameteri(target, pname, param);
1576 		(current != texture) && gl.bindTexture(target, current);
1577 	};
1578 
1579 	dsa.texSubImage2D = function (texture, target) {
1580 		var ext = this._ext;
1581 		var gl  = ext.gl;
1582 		var texTarget = ext.textureTargetMap[target];
1583 		var current = ext.cb.getCurrentTexture(texTarget);
1584 		(current != texture) && gl.bindTexture(texTarget, texture);
1585 		var args = Array.prototype.slice.call(arguments, 1);
1586 		gl.texSubImage2D.apply(gl, args);
1587 		(current != texture) && gl.bindTexture(texTarget, current);
1588 	};
1589 
1590 	dsa.bindTexture = function (unit, target, texture) {
1591 		var ext = this._ext;
1592 		var gl  = ext.gl;
1593 		var cb = ext.cb;
1594 		var currentUnit = cb.getCurrentTextureUnit();
1595 		(currentUnit != unit) && gl.activeTexture(unit);
1596 		gl.bindTexture(target, texture);
1597 		(currentUnit != unit) && gl.activeTexture(currentUnit);
1598 	};
1599 	//////////////////////////////////////////////////////////////////////////////////////////
1600 
1601 	return true;
1602 };
1603 
1604 /**
1605  * Hijacks a WebGLRenderingContext for SpiderGL.WebGL.ObjectGL wrappers.
1606  *
1607  * The WebGLRenderingContext is modified to allow SpiderGL.WebGL.ObjectGL wrappers to be edited without explicit bind and without affecting the WebGL object bindings.
1608  * Most WebGL objects follow the "bind to edit" / "bind to use" paradigm.
1609  * This means that the object must be bound to the WebGL context to modify some parameter or its resource data.
1610  * As a side effect, binding the object just to modify it has the same result of binding it to be used during rendering.
1611  * To prevent this side effect, all the WebGLRenderingContext functions that bind and modify object parameters or data, as long as the rendering functions, are wrapped.
1612  * This allows SpiderGL wrappers (derived from {@link SpiderGL.WebGL.ObjectGL}) to be edited without affecting the binding state of the WebGLRenderingContext.
1613  * The following example clarifies how bindings are handled.
1614  *
1615  * @example
1616  * var textureA = gl.createTexture();
1617  * gl.bindTexture(gl.TEXTURE_2D, textureA);
1618  * gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
1619  * // other texture calls
1620  * var textureB = new SpiderGL.WebGL.Texture2D(gl, parameters);
1621  * textureB.minFilter = gl.LINEAR; // textureB is hiddenly bound to modify the minification filter
1622  * gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); // textureA is automatically re-bound to keep WebGL semantic
1623  * textureB.magFilter = gl.LINEAR; // textureB is hiddenly bound to modify another parameter
1624  * gl.drawArrays(gl.TRIANGLES, 0, 3); // textureA is automatically re-bound to keep WebGL semantic
1625  * textureB.bind(); // bind textureB to WebGL, breaking the binding with textureA
1626  * gl.drawArrays(gl.TRIANGLES, 0, 3); // textureA is used
1627  * 
1628  * @param {WebGLRenderingContext} gl The WebGLRenderingContext to modify.
1629  *
1630  * @returns {bool} True on success, false if the gl argument is not valid or has already been modified.
1631  *
1632  * @see SpiderGL.WebGL.Context.isHijacked
1633  * @see SpiderGL.WebGL.Context.getHijacked
1634  * @see SpiderGL.WebGL.Context.get
1635  * @see SpiderGL.WebGL.ObjectGL
1636  */
1637 SpiderGL.WebGL.Context.hijack = function (gl) {
1638 	if (!SpiderGL.Type.instanceOf(gl, WebGLRenderingContext)) { return false; }
1639 	if (gl._spidergl) { return false; }
1640 
1641 	SpiderGL.WebGL.Context._prepareContex(gl);
1642 
1643 	SpiderGL.WebGL.Context._addExtension(gl, "SGL_current_binding",     "cb",  SpiderGL.WebGL.Context._setup_SGL_current_binding);
1644 	SpiderGL.WebGL.Context._addExtension(gl, "SGL_wrapper_notify",      "wn",  SpiderGL.WebGL.Context._setup_SGL_wrapper_notify);
1645 	SpiderGL.WebGL.Context._addExtension(gl, "SGL_direct_state_access", "dsa", SpiderGL.WebGL.Context._setup_SGL_direct_state_access);
1646 
1647 	var cb  = gl.getExtension("SGL_current_binding"    );
1648 	var wn  = gl.getExtension("SGL_wrapper_notify"     );
1649 	var dsa = gl.getExtension("SGL_direct_state_access");
1650 
1651 	var hijacked = (!!cb && !!wn && !!dsa);
1652 
1653 	return hijacked;
1654 }
1655 
1656 /**
1657  * Tests whether a WebGLRenderingContext is hijacked.
1658  *
1659  * The WebGLRenderingContext is hijacked after a successful call to {@link SpiderGL.WebGL.Context.hijack}.
1660  *
1661  * @param {WebGLRenderingContext} gl The WebGLRenderingContext to test.
1662  *
1663  * @returns {bool} True on success, false if the gl argument is not valid or has already been modified.
1664  *
1665  * @see SpiderGL.WebGL.Context.hijack
1666  * @see SpiderGL.WebGL.Context.getHijacked
1667  * @see SpiderGL.WebGL.Context.get
1668  */
1669 SpiderGL.WebGL.Context.isHijacked = function (gl) {
1670 	return (SpiderGL.Type.instanceOf(gl, WebGLRenderingContext) && gl._spidergl);
1671 }
1672 
1673 /**
1674  * Creates a WebGLRenderingContext and hijacks it.
1675  *
1676  * The WebGLRenderingContext obtained from the canvas parameter with optional arguments is hijacked.
1677  *
1678  * @param {HTMLCanvasElement} canvas The HTMLCanvasElement from which retrieve the WebGL context.
1679  * @param {object} args The optional WebGL context arguments.
1680  *
1681  * @returns {WebGLRenderingContext} The hijacked canvas WebGL rendering context.
1682  *
1683  * @see SpiderGL.WebGL.Context.get
1684  * @see SpiderGL.WebGL.Context.getHijacked
1685  * @see SpiderGL.WebGL.Context.isHijacked
1686  */
1687 SpiderGL.WebGL.Context.getHijacked = function (canvas, args) {
1688 	var gl = SpiderGL.WebGL.Context.get(canvas, args);
1689 	SpiderGL.WebGL.Context.hijack(gl);
1690 	return gl;
1691 }
1692 
1693 /**
1694  * Sets pixel store unpack parameters to standard OpenGL SpiderGL values.
1695  * The parameters to be set are UNPACK_FLIP_Y_WEBGL (true), UNPACK_PREMULTIPLY_ALPHA_WEBGL (false) and UNPACK_COLORSPACE_CONVERSION_WEBGL (WebGLRenderingContext.NONE).
1696  *
1697  * @param {WebGLRenderingContext} gl The target WebGLRenderingContext.
1698  */
1699 SpiderGL.WebGL.Context.setStandardGLUnpack = function (gl) {
1700 	gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,                true);
1701 	gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,     false);
1702 	gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, WebGLRenderingContext.NONE);
1703 }
1704 
1705 /**
1706  * Creates a SpiderGL.WebGL.ObjectGL.
1707  *
1708  * SpiderGL.WebGL.ObjectGL is the base class for every WebObjectGL wrapper and must not be directly used.
1709  * In general, every SpiderGL.WebGL.ObjectGL-derived constructor takes two arguments: a hijacked WebGLRenderingContext ("gl")
1710  * and an optional object argument ("options") that is used to wrap an existing native WebObjectGL and to set object-specific parameters or data.
1711  * If the options parameter has a propery named "handle" referencing a WebObjectGL, the constructed SpiderGL.WebGL.ObjectGL will use the provided WebObjectGL as the underlying resource.
1712  * Otherwise, a new WebObjectGL is created. In both cases, the internal WebObjectGL can be accessed with the {@link handle} read-only property and directly used in WebGLRenderingContext calls.
1713  * With a notification mechanism built into the hijacked WebGLRenderingContext, every direct access is communicated to the wrapper to keep up-to-date the internal state of the wrapper.
1714  *
1715  * @example
1716  * // create a native vertex WebGLBuffer
1717  * var vbo = gl.createBuffer();
1718  * gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
1719  * // ... use buffer ...
1720  * // create a SpiderGL wrapper from an existing object;
1721  * // the native object can be accessed through the "handle" property.
1722  * var wrappedVBO = new SpiderGL.WebGL.VertexBuffer(gl, {handle: vbo});
1723  * // it is not mandatory to bind the object before setting parameters or data
1724  * as the hijacked WebGLRendering context takes care of it and does not break previous bindings
1725  * wrappedVBO.setSize(sizeInBytes, gl.STATIC_DRAW);
1726  * wrappedVBO.bind(); // equivalent to gl.bindBuffer(gl.ARRAY_BUFFER, wrappedVBO.handle)
1727  * // create another SpiderGL.WebGL.VertexBuffer without specifying an existing object,
1728  * // thus letting the wrapper to create one
1729  * var anotherVBO = new SpiderGL.WebGL.VertexBuffer(gl, {size: someSizeInBytes});
1730  *
1731  * @class The SpiderGL.WebGL.ObjectGL is the base class for all WebGL object wrappers.
1732  *
1733  * @augments SpiderGL.Core.ObjectBase
1734  *
1735  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
1736  * @param {number} target The WebObjectGL default target.
1737  * @param {object} [options] Object-specific parameters.
1738  */
1739 SpiderGL.WebGL.ObjectGL = function (gl, target, options) {
1740 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
1741 
1742 	options = SpiderGL.Utility.getDefaultObject({
1743 		handle : null
1744 	}, options);
1745 
1746 	SpiderGL.Core.ObjectBase.call(this);
1747 
1748 	var wn = gl.getExtension("SGL_wrapper_notify");
1749 
1750 	this._gl  = gl;
1751 	this._cb  = gl.getExtension("SGL_current_binding");
1752 	this._dsa = gl.getExtension("SGL_direct_state_access");
1753 
1754 	this._h = options.handle;
1755 	this._t = target;
1756 }
1757 
1758 /**
1759  * Default WebObjectGL target.
1760  *
1761  * @type number
1762  *
1763  * @default WebGLRenderingContext.NONE
1764  */
1765 SpiderGL.WebGL.ObjectGL.TARGET = WebGLRenderingContext.NONE;
1766 
1767 /**
1768  * Generic null WebObjectGL binding.
1769  *
1770  * This function is empty and provided only for completeness.
1771  *
1772  * @param {WebGLRenderingContext} gl A WebGLRenderingContext.
1773  */
1774 SpiderGL.WebGL.ObjectGL.unbind = function (gl) { };
1775 
1776 SpiderGL.WebGL.ObjectGL.prototype = {
1777 	/**
1778 	 * The WebGLRenderingContext used at costruction.
1779 	 *
1780 	 * @type WebGLRenderingContext
1781 	 *
1782 	 * @readonly
1783 	 *
1784 	 * @see #handle
1785 	 */
1786 	get gl() {
1787 		return this._gl;
1788 	},
1789 
1790 	/**
1791 	 * The native WebObjectGL.
1792 	 *
1793 	 * The native handle can be used with WebGLRenderingContext methods.
1794 	 *
1795 	 * @type WebObjectGL
1796 	 *
1797 	 * @readonly
1798 	 *
1799 	 * @see #gl
1800 	 */
1801 	get handle() {
1802 		return this._h;
1803 	},
1804 
1805 	/**
1806 	 * The WebObjectGL default target.
1807 	 *
1808 	 * @type number
1809 	 *
1810 	 * @readonly
1811 	 */
1812 	get target() {
1813 		return this._t;
1814 	},
1815 
1816 	/**
1817 	 * Tests for non-null handle.
1818 	 *
1819 	 * @type bool
1820 	 *
1821 	 * @readonly
1822 	 */
1823 	get isValid() {
1824 		return (this._h != null);
1825 	},
1826 
1827 	/* *
1828 	 * Tests for empty object.
1829 	 * It is reimplemented on each derived classes with object-specific semantic.
1830 	 *
1831 	 * @type bool
1832 	 *
1833 	 * @readonly
1834 	 */
1835 	/*
1836 	get isEmpty () {
1837 		return true;
1838 	},
1839 	*/
1840 
1841 	/**
1842 	 * Tests if the object is ready to use.
1843 	 * It is reimplemented on each derived classes with object-specific semantic.
1844 	 *
1845 	 * @type bool
1846 	 *
1847 	 * @readonly
1848 	 */
1849 	get isReady () {
1850 		return false;
1851 	},
1852 
1853 	/**
1854 	 * Destroys the wrapped WebObjectGL.
1855 	 * 
1856 	 * After calling this method, the object must not be accessed anymore.
1857 	 */
1858 	destroy : function () {
1859 	},
1860 
1861 	/**
1862 	 * Binds the object to the rendering pipeline.
1863 	 * 
1864 	 * The wrapped WebObjectGL is bound to its default target in the WebGLRenderingContext.
1865 	 */
1866 	bind : function () {
1867 	},
1868 
1869 	/**
1870 	 * Binds the null object to the rendering pipeline.
1871 	 * 
1872 	 * This method is provided for symmetry with {@link SpiderGL.WebGL.ObjectGL#bind}. It binds the null object to the per-object webGL target.
1873 	 */
1874 	unbind : function () {
1875 	}
1876 };
1877 
1878 SpiderGL.Type.extend(SpiderGL.WebGL.ObjectGL, SpiderGL.Core.ObjectBase);
1879 
1880 /**
1881  * Creates a SpiderGL.WebGL.Buffer.
1882  *
1883  * SpiderGL.WebGL.Buffer is the base class for WebGLBuffer object wrappers ({@link SpiderGL.WebGL.VertexBuffer} and {@link SpiderGL.WebGL.IndexBuffer}) and must not be directly used.
1884  * When passing data or size with the options parameter, the data field will have precedence on the size field, which will be ignored.
1885  *
1886  * @class The SpiderGL.WebGL.Buffer is the base class for all WebGLBuffer object wrappers, i.e. {@link SpiderGL.WebGL.VertexBuffer} and {@link SpiderGL.WebGL.IndexBuffer}.
1887  *
1888  * @augments SpiderGL.WebGL.ObjectGL
1889  *
1890  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
1891  * @param {number} target The WebGLBuffer target. It must be either WebGLRenderingContext.ARRAY_BUFFER or WebGLRenderingContext.ELEMENT_ARRAY_BUFFER.
1892  * @param {object} [options] Optional parameters.
1893  * @param {WebGLBuffer} [options.handle] If defined, the provided buffer will be wrapped and its size and usage attributes will be queried to the rendering context. Otherwise an internal buffer will be created.
1894  * @param {ArrayBuffer|ArrayBufferView} [options.data] Buffer content to be set with WebGLRenderingContext.bufferData (see {@link setData}). If present, the data will be set both if a handle is provided or internally created.
1895  * @param {number} [options.size] Buffer size to be set with WebGLRenderingContext.bufferData (see {@link setData}). If present, it will be set both if a handle is provided or internally created. If data parameter is present, the size field is ignored.
1896  * @param {number} [options.usage=SpiderGL.WebGL.Buffer.DEFAULT_USAGE] WebGL buffer usage hint parameter for WebGLRenderingContext.bufferData.
1897  *
1898  * @example
1899  * // create a vertex buffer with a specified size
1900  * var vbuff = new SpiderGL.WebGL.VertexBuffer(gl, {
1901  * 	size  : 2 * 1024 * 1024,  // 2 MB
1902  * 	usage : gl.STATIC_DRAW    // if omitted, defaults to SpiderGL.WebGL.Buffer.DEFAULT_USAGE
1903  * });
1904  *
1905  * // create an index buffer with content
1906  * var ibuff = new SpiderGL.WebGL.IndexBuffer(gl, {
1907  * 	data : new Uint16Array(...)  // use a typed array for setting buffer data
1908  * });
1909  *
1910  * @see SpiderGL.WebGL.ObjectGL
1911  * @see SpiderGL.WebGL.VertexBuffer
1912  * @see SpiderGL.WebGL.IndexBuffer
1913  */
1914 SpiderGL.WebGL.Buffer = function (gl, target, options) {
1915 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
1916 
1917 	if (SpiderGL.Type.instanceOf(options, WebGLBuffer)) {
1918 		options = { handle : options };
1919 	}
1920 	else if (SpiderGL.Type.instanceOf(options, ArrayBuffer) || SpiderGL.Type.isTypedArray(options)) {
1921 		options = { data : options };
1922 	}
1923 	else if (SpiderGL.Type.isNumber(options)) {
1924 		options = { size : options };
1925 	}
1926 
1927 	options = SpiderGL.Utility.getDefaultObject({
1928 		handle : null,
1929 		data   : null,
1930 		size   : 0,
1931 		usage  : SpiderGL.WebGL.Buffer.DEFAULT_USAGE
1932 	}, options);
1933 
1934 	SpiderGL.WebGL.ObjectGL.call(this, gl, target, options);
1935 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
1936 
1937 	var gl  = this._gl;
1938 	var cb  = this._cb;
1939 	var dsa = this._dsa;
1940 
1941 	var t = this._t;
1942 	var h = this._h;
1943 
1944 	cb.pushBuffer(t);
1945 	if (h) {
1946 		gl.bindBuffer(t, h);
1947 		options.size  = gl.getBufferParameter(t, gl.BUFFER_SIZE);
1948 		options.usage = gl.getBufferParameter(t, gl.BUFFER_USAGE);
1949 	}
1950 	else {
1951 		h = gl.createBuffer();
1952 		gl.bindBuffer(t, h);
1953 		this._h = h;
1954 	}
1955 	cb.popBuffer(t);
1956 	h._spidergl = this;
1957 
1958 	this._size   = options.size;
1959 	this._usage  = options.usage;
1960 
1961 	if (options.data) {
1962 		this.setData(options.data, options.usage);
1963 	}
1964 	else if (options.size) {
1965 		this.setSize(options.size, options.usage);
1966 	}
1967 }
1968 
1969 /**
1970  * Default WebGLBuffer target.
1971  *
1972  * @type number
1973  *
1974  * @default WebGLRenderingContext.NONE
1975  */
1976 SpiderGL.WebGL.Buffer.TARGET = WebGLRenderingContext.NONE;
1977 
1978 /**
1979  * Default usage hint when specifying buffer size or data.
1980  *
1981  * @type number
1982  *
1983  * @default WebGLRenderingContext.STATIC_DRAW
1984  */
1985 SpiderGL.WebGL.Buffer.DEFAULT_USAGE = WebGLRenderingContext.STATIC_DRAW;
1986 
1987 /**
1988  * Default buffer offset when specifying buffer subdata.
1989  *
1990  * @type number
1991  *
1992  * @default 0
1993  */
1994 SpiderGL.WebGL.Buffer.DEFAULT_SUB_DATA_OFFSET = 0;
1995 
1996 /**
1997  * Generic WebGLBuffer unbinding.
1998  *
1999  * This function is empty and it is provided only for completeness.
2000  *
2001  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
2002  */
2003 SpiderGL.WebGL.Buffer.unbind = function (gl) { };
2004 
2005 SpiderGL.WebGL.Buffer.prototype = {
2006 	_gl_deleteBuffer : function () {
2007 		this._h = null;
2008 	},
2009 
2010 	_gl_isBuffer : function () {
2011 	},
2012 
2013 	_gl_bindBuffer : function () {
2014 	},
2015 
2016 	_gl_getBufferParameter : function () {
2017 	},
2018 
2019 	_gl_bufferData : function () {
2020 		var sizeOrData = arguments[1];
2021 		var usage = arguments[2];
2022 		this._size = (SpiderGL.Type.isNumber(sizeOrData)) ? (sizeOrData) : (sizeOrData.byteLength);
2023 		this._usage = usage;
2024 	},
2025 
2026 	_gl_bufferSubData : function () {
2027 	},
2028 
2029 	_gl_vertexAttribPointer : function () {
2030 	},
2031 
2032 	_gl_drawElements : function () {
2033 	},
2034 
2035 	/* *
2036 	 * Tests for empty buffer.
2037 	 * It is true if the buffer size is greather than zero, false otherwise.
2038 	 *
2039 	 * @type bool
2040 	 *
2041 	 * @readonly
2042 	 */
2043 	/*
2044 	get isEmpty() { return (this._size <= 0); },
2045 	*/
2046 
2047 	/**
2048 	 * Tests if the buffer is ready to use.
2049 	 * A buffer is considered ready if its size is greater than zero.
2050 	 *
2051 	 * @type bool
2052 	 *
2053 	 * @readonly
2054 	 */
2055 	get isReady () {
2056 		return (this._size > 0);
2057 	},
2058 
2059 	/**
2060 	 * The size in bytes of the buffer.
2061 	 *
2062 	 * @type number
2063 	 *
2064 	 * @readonly
2065 	 */
2066 	get size() {
2067 		return this._size;
2068 	},
2069 
2070 	/**
2071 	 * The usage hint of the WebGLBuffer.
2072 	 * It refers to the usage hint as specified in WebGLRenderingContext.bufferData().
2073 	 *
2074 	 * @type number
2075 	 *
2076 	 * @readonly
2077 	 */
2078 	get usage() {
2079 		return this._usage;
2080 	},
2081 
2082 	/**
2083 	 * Sets the buffer size and usage.
2084 	 * The buffer is set up with specified size and usage.
2085 	 *
2086 	 * @param {number} size The buffer size.
2087 	 * @param {number} [usage=SpiderGL.WebGL.Buffer.DEFAULT_USAGE] WebGL buffer usage hint.
2088 	 *
2089 	 * @see setData
2090 	 */
2091 	setSize : function (size, usage) {
2092 		usage = SpiderGL.Utility.getDefaultValue(usage, SpiderGL.WebGL.Buffer.DEFAULT_USAGE);
2093 		this._dsa.bufferData(this._h, this._t, size, usage);
2094 	},
2095 
2096 	/**
2097 	 * Sets the buffer data and usage.
2098 	 * The buffer is set up with specified data and usage.
2099 	 *
2100 	 * @param {ArrayBuffer|ArrayBufferView} data The buffer data.
2101 	 * @param {number} [usage=SpiderGL.WebGL.Buffer.DEFAULT_USAGE] WebGL buffer usage hint.
2102 	 *
2103 	 * @see setSubData
2104 	 * @see setSize
2105 	 */
2106 	setData : function (data, usage) {
2107 		usage = SpiderGL.Utility.getDefaultValue(usage, SpiderGL.WebGL.Buffer.DEFAULT_USAGE);
2108 		this._dsa.bufferData(this._h, this._t, data, usage);
2109 	},
2110 
2111 	/**
2112 	 * Sets a range of the buffer data.
2113 	 * A range of buffer content can be set by specifying the starting offset and the typed array of values.
2114 	 *
2115 	 * @param {ArrayBuffer|ArrayBufferView} data The buffer sub data.
2116 	 * @param {number} [offset=SpiderGL.WebGL.Buffer.DEFAULT_SUB_DATA_OFFSET] The range starting offset, in bytes.
2117 	 *
2118 	 * @see setData
2119 	 */
2120 	setSubData : function (data, offset) {
2121 		offset = SpiderGL.Utility.getDefaultValue(offset, SpiderGL.WebGL.Buffer.DEFAULT_SUB_DATA_OFFSET);
2122 		this._dsa.bufferSubData(this._h, this._t, offset, data);
2123 	},
2124 
2125 	/**
2126 	 * Destroys the WebGLBuffer.
2127 	 * After destruction, the handle is set to null and this object should not be used anymore.
2128 	 *
2129 	 * @see SpiderGL.WebGL.ObjectGL#destroy
2130 	 */
2131 	destroy : function () {
2132 		this._gl.deleteBuffer(this._h);
2133 	},
2134 
2135 	/**
2136 	 * Binds the wrapped WebGLBuffer to the appropriate target.
2137 	 * The used target is set by the derived objects {@link SpiderGL.WebGL.VertexBuffer} and {@link SpiderGL.WebGL.IndexBuffer}.
2138 	 *
2139 	 * @see unbind
2140 	 */
2141 	bind : function () {
2142 		this._gl.bindBuffer(this._t, this._h);
2143 	},
2144 
2145 	/**
2146 	 * Binds "null" to the appropriate target.
2147 	 * This method is provided only for simmetry with {@link bind} and is not relative to the object state.
2148 	 *
2149 	 * @see bind
2150 	 */
2151 	unbind : function () {
2152 		this._gl.bindBuffer(this._t, null);
2153 	}
2154 };
2155 
2156 SpiderGL.Type.extend(SpiderGL.WebGL.Buffer, SpiderGL.WebGL.ObjectGL);
2157 
2158 /**
2159  * Creates a SpiderGL.WebGL.VertexBuffer.
2160  *
2161  * SpiderGL.WebGL.VertexBuffer represents a wrapper for a WebGLBuffer to be bound to the WebGLRenderingContext.ARRAY_BUFFER target.
2162  *
2163  * @class The SpiderGL.WebGL.VertexBuffer is WebGLBuffer wrapper for vertex buffers.
2164  *
2165  * @augments SpiderGL.WebGL.Buffer
2166  *
2167  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
2168  * @param {object} [options] See {@link SpiderGL.WebGL.Buffer}.
2169  *
2170  * @see SpiderGL.WebGL.Buffer
2171  * @see SpiderGL.WebGL.IndexBuffer
2172  * @see SpiderGL.WebGL.ObjectGL
2173  */
2174 SpiderGL.WebGL.VertexBuffer = function (gl, options) {
2175 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
2176 	SpiderGL.WebGL.Buffer.call(this, gl, SpiderGL.WebGL.VertexBuffer.TARGET, options);
2177 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
2178 }
2179 
2180 /**
2181  * WebGL target for vertex buffers.
2182  *
2183  * @type number
2184  *
2185  * @default WebGLRenderingContext.ARRAY_BUFFER
2186  */
2187 SpiderGL.WebGL.VertexBuffer.TARGET = WebGLRenderingContext.ARRAY_BUFFER;
2188 
2189 /**
2190  * Default vertex attribute index when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2191  *
2192  * @type number
2193  *
2194  * @default 0
2195  */
2196 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_INDEX = 0;
2197 
2198 /**
2199  * Default vertex attribute size when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2200  *
2201  * @type number
2202  *
2203  * @default 3
2204  */
2205 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_SIZE = 3;
2206 
2207 /**
2208  * Default vertex attribute type when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2209  *
2210  * @type number
2211  *
2212  * @default WebGLRenderingContext.FLOAT
2213  */
2214 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_TYPE = WebGLRenderingContext.FLOAT;
2215 
2216 /**
2217  * Default vertex attribute normalized flag when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2218  *
2219  * @type bool
2220  *
2221  * @default false
2222  */
2223 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_NORMALIZED = false;
2224 
2225 /**
2226  * Default vertex attribute stride when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2227  *
2228  * @type number
2229  *
2230  * @default 0
2231  */
2232 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_STRIDE = 0;
2233 
2234 /**
2235  * Default vertex attribute offset when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2236  *
2237  * @type number
2238  *
2239  * @default 0
2240  */
2241 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_OFFSET = 0;
2242 
2243 /**
2244  * Default enable flag for vertex attribute when using SpiderGL.WebGL.VertexBuffer#vertexAttribPointer.
2245  *
2246  * @type bool
2247  *
2248  * @default true
2249  */
2250 SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_ENABLE = true;
2251 
2252 /**
2253  * WebGLBuffer unbinding for vertex buffers.
2254  *
2255  * This function binds the null buffer to the WebGLRenderingContext.ARRAY_BUFFER target.
2256  *
2257  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
2258  */
2259 SpiderGL.WebGL.VertexBuffer.unbind = function (gl) { gl.bindBuffer(SpiderGL.WebGL.VertexBuffer.TARGET, null); };
2260 
2261 SpiderGL.WebGL.VertexBuffer.prototype = {
2262 	/**
2263 	 * Latches the WebGL vertex attribute pointer with the internal buffer.
2264 	 * The effect of this method is to bind the SpiderGL.WebGL.VertexBuffer and call WebGLRenderingContext.vertexAttribPointer() with the provided parameters.
2265 	 *
2266 	 * @param {object} [options] Vertex attribute pointer parameters.
2267 	 * @param {number} [options.index=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_INDEX] Attribute index.
2268 	 * @param {number} [options.size=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_SIZE] Attribute size.
2269 	 * @param {number} [options.type=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_TYPE] Attribute base type.
2270 	 * @param {number} [options.normalized=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_NORMALIZED] True if the attribute has an integer type and must be normalized.
2271 	 * @param {number} [options.stride=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_STRIDE] Bytes from the beginning of an element and the beginning of the next one.
2272 	 * @param {number} [options.offset=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_OFFSET] Offset (in bytes) from the start of the buffer.
2273 	 * @param {bool} [options.enable=SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_ENABLE] If true, the index-th vertex attribute array will be enabled with WebGLRenderingContext.enableVertexAttribArray(index).
2274 	 *
2275 	 * @example
2276 	 * var vb = new SpiderGL.WebGL.VertexBuffer(...); // create a vertex buffer
2277 	 * // [... set vb data ...]
2278 	 * // calling vb.vertexAttribPointer has the same effect of:
2279 	 * // vb.bind();
2280 	 * // gl.vertexAttribPointer(positionAttributeIndex, 3, gl.FLOAT, false, 0, 0);
2281 	 * // gl.enableVertexAttribArray(positionAttributeIndex);
2282 	 * vb.vertexAttribPointer({
2283 	 * 	index      : positionAttributeIndex,  // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_INDEX
2284 	 * 	size       : 3,         // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_SIZE
2285 	 * 	glType     : gl.FLOAT,  // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_TYPE
2286 	 * 	normalized : false,     // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_NORMALIZED
2287 	 * 	stride     : 0,         // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_STRIDE
2288 	 * 	offset     : 0,         // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_OFFSET
2289 	 * 	enable     : true       // if omitted, defaults to SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_ENABLE
2290 	 * });
2291 	 */
2292 	vertexAttribPointer : function (options) {
2293 		options = SpiderGL.Utility.getDefaultObject({
2294 			index      : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_INDEX,
2295 			size       : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_SIZE,
2296 			glType     : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_TYPE,
2297 			normalized : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_NORMALIZED,
2298 			stride     : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_STRIDE,
2299 			offset     : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_OFFSET,
2300 			enable     : SpiderGL.WebGL.VertexBuffer.DEFAULT_ATTRIBUTE_ENABLE
2301 		}, options);
2302 
2303 		this._dsa.vertexAttribPointer(this._h, options.index, options.size, options.glType, options.normalized, options.stride, options.offset);
2304 		if (options.enable) {
2305 			this._gl.enableVertexAttribArray(options.index);
2306 		}
2307 	}
2308 };
2309 
2310 SpiderGL.Type.extend(SpiderGL.WebGL.VertexBuffer, SpiderGL.WebGL.Buffer);
2311 
2312 
2313 /**
2314  * Creates a SpiderGL.WebGL.IndexBuffer.
2315  *
2316  * SpiderGL.WebGL.IndexBuffer represents a wrapper for a WebGLBuffer to be bound to the WebGLRenderingContext.ELEMENT_ARRAY_BUFFER target.
2317  *
2318  * @class The SpiderGL.WebGL.IndexBuffer is WebGLBuffer wrapper for index buffers.
2319  *
2320  * @augments SpiderGL.WebGL.Buffer
2321  *
2322  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
2323  * @param {object} [options] See {@link SpiderGL.WebGL.Buffer}.
2324  *
2325  * @see SpiderGL.WebGL.Buffer
2326  * @see SpiderGL.WebGL.VertexBuffer
2327  * @see SpiderGL.WebGL.ObjectGL
2328  */
2329 SpiderGL.WebGL.IndexBuffer = function (gl, options) {
2330 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
2331 	SpiderGL.WebGL.Buffer.call(this, gl, SpiderGL.WebGL.IndexBuffer.TARGET, options);
2332 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
2333 }
2334 
2335 /**
2336  * WebGL target for index buffers.
2337  *
2338  * @type number
2339  *
2340  * @default WebGLRenderingContext.ELEMENT_ARRAY_BUFFER
2341  */
2342 SpiderGL.WebGL.IndexBuffer.TARGET = WebGLRenderingContext.ELEMENT_ARRAY_BUFFER;
2343 
2344 /**
2345  * Default elements draw mode when using SpiderGL.WebGL.IndexBuffer#drawElements.
2346  *
2347  * @type number
2348  *
2349  * @default WebGLRenderingContext.TRIANGLES
2350  */
2351 SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_MODE  = WebGLRenderingContext.TRIANGLES;
2352 
2353 /**
2354  * Default elements count when using SpiderGL.WebGL.IndexBuffer#drawElements.
2355  * A negative value causes the calculation of the maximum number of elements given the buffer size, offset and index type.
2356  *
2357  * @type number
2358  *
2359  * @default -1
2360  */
2361 SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_COUNT  = -1;
2362 
2363 /**
2364  * Default index type when using SpiderGL.WebGL.IndexBuffer#drawElements.
2365  *
2366  * @type number
2367  *
2368  * @default WebGLRenderingContext.UNSIGNED_SHORT
2369  */
2370 SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_TYPE = WebGLRenderingContext.UNSIGNED_SHORT;
2371 
2372 /**
2373  * Default index buffer offset when using SpiderGL.WebGL.IndexBuffer#drawElements.
2374  *
2375  * @type number
2376  *
2377  * @default 0
2378  */
2379 SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_OFFSET = 0;
2380 
2381 /**
2382  * WebGLBuffer unbinding for index buffers.
2383  *
2384  * This function binds the null buffer to the WebGLRenderingContext.ELEMENT_ARRAY_BUFFER target.
2385  *
2386  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
2387  */
2388 SpiderGL.WebGL.IndexBuffer.unbind = function (gl) { gl.bindBuffer(SpiderGL.WebGL.IndexBuffer.TARGET, null); };
2389 
2390 SpiderGL.WebGL.IndexBuffer.prototype = {
2391 	/**
2392 	 * Binds the index buffers and calls WebGLRenderingContext.drawElements with the provided parameters.
2393 	 *
2394 	 * @param {object} [options] Draw parameters.
2395 	 * @param {number} [options.glMode=SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_MODE] The WebGL primitive type.
2396 	 * @param {number} [options.count=SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_COUNT] Number of elements to draw. If less than or equal to zero, its value will be calculated as the maximum number of stored indices, based on offset, buffer size and index type.
2397 	 * @param {number} [options.glType=SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_TYPE] Index type.
2398 	 * @param {number} [options.offset=SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_OFFSET] Offset (in bytes) from the start of the buffer.
2399 	 *
2400 	 * @example
2401 	 * var ib = new SpiderGL.WebGL.IndexBuffer(...); // create an index buffer
2402 	 * // [... set ib data ...]
2403 	 * // calling ib.drawElements has the same effect of:
2404 	 * // ib.bind();
2405 	 * // gl.drawElements(gl.TRIANGLES, (ib.size - offset) / SpiderGL.Type.SIZEOF_UINT16, gl.UNSIGNED_SHORT, offset);
2406 	 * ib.drawElements({
2407 	 * 	glMode : gl.TRIANGLES,       // if omitted, defaults to SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_MODE
2408 	 * 	count  : 0,                  // if omitted, defaults to SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_COUNT
2409 	 * 	glType : gl.UNSIGNED_SHORT,  // if omitted, defaults to SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_TYPE
2410 	 * 	offset : offset              // if omitted, defaults to SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_OFFSET
2411 	 * });
2412 	 */
2413 	drawElements : function (options) {
2414 		options = SpiderGL.Utility.getDefaultObject({
2415 			glMode : SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_MODE,
2416 			count  : SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_COUNT,
2417 			glType : SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_TYPE,
2418 			offset : SpiderGL.WebGL.IndexBuffer.DEFAULT_DRAW_ELEMENTS_OFFSET
2419 		}, options);
2420 
2421 		if (options.count < 1) {
2422 			var bytesPerElem = SpiderGL.Type.typeSizeFromGL(options.glType);
2423 			options.count = (this._size - options.offset) / bytesPerElem;
2424 		}
2425 
2426 		this._dsa.drawElements(this._h, options.glMode, options.count, options.glType, options.offset);
2427 	}
2428 };
2429 
2430 SpiderGL.Type.extend(SpiderGL.WebGL.IndexBuffer, SpiderGL.WebGL.Buffer);
2431 
2432 /**
2433  * Creates a SpiderGL.WebGL.Framebuffer.
2434  *
2435  * SpiderGL.WebGL.Framebuffer wraps a WebGLFramebuffer object.
2436  *
2437  * @class The SpiderGL.WebGL.Framebuffer is a wrapper for WebGLFramebuffer.
2438  *
2439  * @augments SpiderGL.WebGL.ObjectGL
2440  *
2441  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
2442  * @param {object} [options] Optional parameters.
2443  * @param {WebGLFramebuffer} [options.handle] A WebGLFramebuffer. If present, this object will be used as the wrapped WebGLFramebuffer. Otherwise a new one will be created.
2444  * @param {bool} [options.autoViewport=SpiderGL.WebGL.Framebuffer.DEFAULT_AUTO_VIEWPORT] The value of the {@link autoViewport} property.
2445  * @param {object} [options.color] Color attachment target (see {@link setAttachments}).
2446  * @param {object} [options.depth] Depth attachment target (see {@link setAttachments}).
2447  * @param {object} [options.stencil] Stencil attachment target (see {@link setAttachments}).
2448  * @param {object} [options.depthStencil] Depth-Stencil attachment target (see {@link setAttachments}).
2449  *
2450  * @see setAttachments
2451  * @see SpiderGL.WebGL.Texture2D
2452  * @see SpiderGL.WebGL.TextureCubeMap
2453  * @see SpiderGL.WebGL.Renderbuffer
2454  * @see SpiderGL.WebGL.ObjectGL
2455  */
2456 SpiderGL.WebGL.Framebuffer = function (gl, options) {
2457 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
2458 
2459 	if (SpiderGL.Type.instanceOf(options, WebGLFramebuffer)) {
2460 		options = { handle : options };
2461 	}
2462 
2463 	options = SpiderGL.Utility.getDefaultObject({
2464 		handle       : null,
2465 		autoViewport : SpiderGL.WebGL.Framebuffer.DEFAULT_AUTO_VIEWPORT
2466 	}, options);
2467 
2468 	var that = SpiderGL.WebGL.ObjectGL.call(this, gl, SpiderGL.WebGL.Framebuffer.TARGET, options);
2469 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
2470 
2471 	var gl  = this._gl;
2472 	var cb  = this._cb;
2473 	var dsa = this._dsa;
2474 
2475 	var t = this._t;
2476 	var h = this._h;
2477 
2478 	var imported = false;
2479 	if (h) {
2480 		imported = true;
2481 	}
2482 	else {
2483 		h = gl.createFramebuffer();
2484 		this._h = h;
2485 	}
2486 	h._spidergl = this;
2487 
2488 	this._attachments  = { };
2489 	this._status       = 0;
2490 	this._autoViewport = options.autoViewport;
2491 	this._viewport     = [ 0, 0, 1, 1 ];
2492 
2493 	cb.pushFramebuffer(t);
2494 	gl.bindFramebuffer(t, h);
2495 
2496 	if (imported) {
2497 		var resource = null;
2498 		var type     = 0;
2499 		var level    = 0;
2500 		var target   = 0;
2501 
2502 		for (var attachment in SpiderGL.WebGL.Framebuffer._attachmentName) {
2503 			resource = gl.getFramebufferAttachmentParameter(t, att, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
2504 			type     = gl.getFramebufferAttachmentParameter(t, att, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
2505 			switch (type) {
2506 				case gl.RENDERBUFFER:
2507 					target = gl.RENDERBUFFER;
2508 					this._importRenderbuffer(t, attachment, target, resource);
2509 				break;
2510 				case gl.TEXTURE:
2511 					level  = gl.getFramebufferAttachmentParameter(t, att, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
2512 					target = gl.getFramebufferAttachmentParameter(t, att, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
2513 					if (target == 0) target = gl.TEXTURE_2D;
2514 					this._importTexture(t, attachment, target, resource, level);
2515 				break;
2516 				default: break;
2517 			}
2518 		}
2519 	}
2520 
2521 	this._status = gl.checkFramebufferStatus(t);
2522 
2523 	cb.popFramebuffer(t);
2524 
2525 	this.setAttachments(options);
2526 }
2527 
2528 /**
2529  * WebGL target for framebuffers.
2530  *
2531  * @type number
2532  *
2533  * @default WebGLRenderingContext.FRAMEBUFFER
2534  */
2535 SpiderGL.WebGL.Framebuffer.TARGET = WebGLRenderingContext.FRAMEBUFFER;
2536 
2537 /**
2538  * Default value for SpiderGL.WebGL.Framebuffer#autoViewport.
2539  *
2540  * @type bool
2541  *
2542  * @default true
2543  */
2544 SpiderGL.WebGL.Framebuffer.DEFAULT_AUTO_VIEWPORT = true;
2545 
2546 /**
2547  * Default texture level to attach when using SpiderGL.WebGL.Framebuffer#setAttachments.
2548  *
2549  * @type number
2550  *
2551  * @default 0
2552  */
2553 SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_TEXTURE_LEVEL = 0;
2554 
2555 /**
2556  * Default texture cube map face to attach when using SpiderGL.WebGL.Framebuffer#setAttachments.
2557  *
2558  * @type number
2559  *
2560  * @default WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_X
2561  */
2562 SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_CUBE_MAP_FACE = WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_X;
2563 
2564 /**
2565  * Default read rectangle left coordinate (in pixels).
2566  *
2567  * @type number
2568  *
2569  * @default 0
2570  *
2571  * @see SpiderGL.WebGL.Framebuffer#readPixels
2572  */
2573 SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_X = 0;
2574 
2575 /**
2576  * Default read rectangle bottom coordinate (in pixels).
2577  *
2578  * @type number
2579  *
2580  * @default 0
2581  *
2582  * @see SpiderGL.WebGL.Framebuffer#readPixels
2583  */
2584 SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_Y = 0;
2585 
2586 /**
2587  * Default read rectangle width (in pixels).
2588  * If less than zero, the width will be set to span the whole render target (starting from read rectangle x coordinate).
2589  *
2590  * @type number
2591  *
2592  * @default -1
2593  *
2594  * @see SpiderGL.WebGL.Framebuffer#readPixels
2595  */
2596 SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_WIDTH = -1;
2597 
2598 /**
2599  * Default read rectangle height (in pixels).
2600  * If less than zero, the height will be set to span the whole render target (starting from read rectangle y coordinate).
2601  *
2602  * @type number
2603  *
2604  * @default -1
2605  *
2606  * @see SpiderGL.WebGL.Framebuffer#readPixels
2607  */
2608 SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_HEIGHT = -1;
2609 
2610 /**
2611  * The WebGL pixel format for reading framebuffer pixels.
2612  *
2613  * @type number
2614  *
2615  * @default WebGLRenderingContext.RGBA
2616  *
2617  * @see SpiderGL.WebGL.Framebuffer#readPixels
2618  */
2619 SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_FORMAT = WebGLRenderingContext.RGBA;
2620 
2621 /**
2622  * The WebGL birfield mask used for clearing the framebuffer.
2623  *
2624  * @type number
2625  *
2626  * @default (WebGLRenderingContext.COLOR_BUFFER_BIT | WebGLRenderingContext.DEPTH_BUFFER_BIT | WebGLRenderingContext.STENCIL_BUFFER_BIT)
2627  *
2628  * @see SpiderGL.WebGL.Framebuffer#clear
2629  */
2630 SpiderGL.WebGL.Framebuffer.DEFAULT_CLEAR_MASK = (WebGLRenderingContext.COLOR_BUFFER_BIT | WebGLRenderingContext.DEPTH_BUFFER_BIT | WebGLRenderingContext.STENCIL_BUFFER_BIT);
2631 
2632 /**
2633  * The WebGL pixel type for reading framebuffer pixels.
2634  *
2635  * @type number
2636  *
2637  * @default WebGLRenderingContext.UNSIGNED_BYTE
2638  *
2639  * @see SpiderGL.WebGL.Framebuffer#readPixels
2640  */
2641 SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_TYPE = WebGLRenderingContext.UNSIGNED_BYTE;
2642 
2643 /**
2644  * WebGLFramebuffer unbinding.
2645  *
2646  * This function binds the null framebuffer to the WebGLRenderingContext.FRAMEBUFFER target.
2647  *
2648  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
2649  */
2650 SpiderGL.WebGL.Framebuffer.unbind = function (gl) { gl.bindFramebuffer(SpiderGL.WebGL.Framebuffer.TARGET, null); };
2651 
2652 SpiderGL.WebGL.Framebuffer._attachmentName = { };
2653 SpiderGL.WebGL.Framebuffer._attachmentName[WebGLRenderingContext.COLOR_ATTACHMENT0]        = "color";
2654 SpiderGL.WebGL.Framebuffer._attachmentName[WebGLRenderingContext.DEPTH_ATTACHMENT]         = "depth";
2655 SpiderGL.WebGL.Framebuffer._attachmentName[WebGLRenderingContext.STENCIL_ATTACHMENT]       = "stencil";
2656 SpiderGL.WebGL.Framebuffer._attachmentName[WebGLRenderingContext.DEPTH_STENCIL_ATTACHMENT] = "depthStencil";
2657 
2658 SpiderGL.WebGL.Framebuffer.prototype = {
2659 	_gl_deleteFramebuffer : function (framebuffer) {
2660 		this._h = null;
2661 	},
2662 
2663 	_gl_isFramebuffer : function (framebuffer) {
2664 	},
2665 
2666 	_gl_bindFramebuffer : function (target, framebuffer) {
2667 	},
2668 
2669 	_gl_checkFramebufferStatus : function (target) {
2670 	},
2671 
2672 	_gl_getFramebufferAttachmentParameter : function (target, attachment, pname) {
2673 	},
2674 
2675 	_gl_framebufferRenderbuffer : function (target, attachment, renderbuffertarget, renderbuffer) {
2676 		this._importRenderbuffer.apply(this, arguments);
2677 		this._status = this._gl.checkFramebufferStatus(this._t);
2678 	},
2679 
2680 	_gl_framebufferTexture2D : function (target, attachment, textarget, texture, level) {
2681 		this._importTexture.apply(this, arguments);
2682 		this._status = this._gl.checkFramebufferStatus(this._t);
2683 	},
2684 
2685 	_gl_clear : function (mask) {
2686 	},
2687 
2688 	_gl_readPixels : function (x, y, width, height, format, type, pixels) {
2689 	},
2690 
2691 	_importTexture : function (target, attachment, textarget, texture, level) {
2692 		var name = SpiderGL.WebGL.Framebuffer._attachmentName[attachment];
2693 		if (!name) return;
2694 
2695 		if (!texture) {
2696 			delete this._attachments[name];
2697 			return;
2698 		}
2699 
2700 		var gl = this._gl;
2701 
2702 		var att = {
2703 			attachment : attachment,
2704 			resource   : null,
2705 			target     : textarget,
2706 			level      : level,
2707 			face       : gl.NONE
2708 		};
2709 
2710 		this._attachments[name] = att;
2711 
2712 		if (textarget == gl.TEXTURE_2D) {
2713 			att.resource = new SpiderGL.WebGL.Texture2D(gl, { handle : texture });
2714 		}
2715 		else {
2716 			att.resource = new SpiderGL.WebGL.TextureCubeMap(gl, { handle : texture });
2717 			att.face     = textarget;
2718 		}
2719 
2720 		this._viewport = [ 0, 0, SpiderGL.Math.max(att.resource.width, 1), SpiderGL.Math.max(att.resource.height, 1) ];
2721 	},
2722 
2723 	_importRenderbuffer : function (target, attachment, renderbuffertarget, renderbuffer) {
2724 		var name = SpiderGL.WebGL.Framebuffer._attachmentName[attachment];
2725 		if (!name) return;
2726 
2727 		if (!renderbuffer) {
2728 			delete this._attachments[name];
2729 			return;
2730 		}
2731 
2732 		var gl = this._gl;
2733 
2734 		var att = {
2735 			attachment : attachment,
2736 			resource   : null,
2737 			target     : renderbuffertarget,
2738 			level      : 0,
2739 			face       : gl.NONE
2740 		};
2741 
2742 		this._attachments[name] = att;
2743 
2744 		att.resource = new SpiderGL.WebGL.Renderbuffer(gl, { handle : renderbuffer });
2745 
2746 		this._viewport = [ 0, 0, SpiderGL.Math.max(att.resource.width, 1), SpiderGL.Math.max(att.resource.height, 1) ];
2747 	},
2748 
2749 	_setAttachment : function (attachment, nfo) {
2750 		var name = SpiderGL.WebGL.Framebuffer._attachmentName[attachment];
2751 		if (!name) return false;
2752 
2753 		var gl = this._gl;
2754 
2755 		var isNullResource = (!nfo || (("resource" in nfo) && !nfo.resource));
2756 		if  (isNullResource) {
2757 			var att = this._attachments[name];
2758 			if (att) {
2759 				if (att.target === gl.RENDERBUFFER) {
2760 					gl.framebufferRenderbuffer(t, att.attachment, gl.RENDERBUFFER, null);
2761 				}
2762 				else {
2763 					gl.framebufferTexture2D(t, att.attachment, gl.TEXTURE_2D, null, 0);
2764 				}
2765 			}
2766 			return;
2767 		}
2768 
2769 		var resourceType = gl.NONE;
2770 
2771 		if (SpiderGL.Type.instanceOf(nfo, WebGLTexture)) {
2772 			nfo = { resource : nfo };
2773 			resourceType = gl.TEXTURE;
2774 		}
2775 		else if (SpiderGL.Type.instanceOf(nfo, WebGLRenderbuffer)) {
2776 			nfo = { resource : nfo };
2777 			resourceType = gl.RENDERBUFFER;
2778 		}
2779 		else if (SpiderGL.Type.instanceOf(nfo, SpiderGL.WebGL.Texture)) {
2780 			nfo = { resource : nfo.handle };
2781 			resourceType = gl.TEXTURE;
2782 		}
2783 		else if (SpiderGL.Type.instanceOf(nfo, SpiderGL.WebGL.Renderbuffer)) {
2784 			nfo = { resource : nfo.handle };
2785 			resourceType = gl.RENDERBUFFER;
2786 		}
2787 
2788 		var cubeFaceSpecified = !!nfo && (typeof (nfo.face) != "undefined");
2789 
2790 		nfo = SpiderGL.Utility.getDefaultObject({
2791 			resource : null,
2792 			level    : SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_TEXTURE_LEVEL,
2793 			face     : SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_CUBE_MAP_FACE
2794 		}, nfo);
2795 
2796 		var t = this._t;
2797 
2798 		switch (resourceType) {
2799 			case gl.TEXTURE:
2800 				var isCubemap = SpiderGL.Type.instanceOf(nfo, SpiderGL.WebGL.TextureCubeMap) || cubeFaceSpecified;
2801 				var target = (isCubemap) ? (nfo.face) : (gl.TEXTURE_2D);
2802 				gl.framebufferTexture2D(t, attachment, target, nfo.resource, nfo.level);
2803 			break;
2804 			case gl.RENDERBUFFER:
2805 				gl.framebufferRenderbuffer(t, attachment, gl.RENDERBUFFER, nfo.resource);
2806 			break;
2807 			default: break;
2808 		}
2809 
2810 		return true;
2811 	},
2812 
2813 	/*
2814 	get isEmpty () {
2815 		return (
2816 			!this._attachments.color        &&
2817 			!this._attachments.depth        &&
2818 			!this._attachments.stencil      &&
2819 			!this._attachments.depthStencil
2820 		);
2821 	},
2822 	*/
2823 
2824 	/**
2825 	 * Tests if the framebuffer is ready to use.
2826 	 * A framebuffer is considered ready if its status is WebGLRenderingContext.FRAMEBUFFER_COMPLETE.
2827 	 *
2828 	 * @type bool
2829 	 *
2830 	 * @readonly
2831 	 *
2832 	 * @see isComplete
2833 	 */
2834 	get isReady () {
2835 		return this.isComplete;
2836 	},
2837 
2838 	/**
2839 	 * The WebGL status of the framebuffer.
2840 	 *
2841 	 * @type number
2842 	 *
2843 	 * @readonly
2844 	 *
2845 	 * @see isComplete
2846 	 */
2847 	get status() {
2848 		return this._status;
2849 	},
2850 
2851 	/**
2852 	 * Indicates if the the status of the framebuffer is WebGLRenderingContext.FRAMEBUFFER_COMPLETE.
2853 	 *
2854 	 * @type number
2855 	 *
2856 	 * @readonly
2857 	 */
2858 	get isComplete() {
2859 		return (this._status === this._gl.FRAMEBUFFER_COMPLETE);
2860 	},
2861 
2862 	/**
2863 	 * Gets a 4-component array with the viewport parameters.
2864 	 *
2865 	 * Viewport parameters are stored as [0, 0, width, height] and will be set using WebGLRenderingContext.viewport() during a {@link bind} call if {@link autoViewport} is true.
2866 	 * The width and height parameters corresponds to the width and height of the last resource attached with {@link setAttachments}.
2867 	 *
2868 	 * @type array
2869 	 *
2870 	 * @readonly
2871 	 *
2872 	 * @see autoViewport
2873 	 * @see setAttachments
2874 	 */
2875 	get viewport() {
2876 		return this._viewport.slice();
2877 	},
2878 
2879 	/**
2880 	 * Gets the width of the attached resources.
2881 	 *
2882 	 * The value represents the width of the attached resources.
2883 	 * It is equal to viewport[2].
2884 	 *
2885 	 * @type number
2886 	 *
2887 	 * @readonly
2888 	 *
2889 	 * @see height
2890 	 * @see viewport
2891 	 */
2892 	get width() {
2893 		return this._viewport[2];
2894 	},
2895 
2896 	/**
2897 	 * Gets the height of the attached resources.
2898 	 *
2899 	 * The value represents the height of the attached resources.
2900 	 * It is equal to viewport[3].
2901 	 *
2902 	 * @type number
2903 	 *
2904 	 * @readonly
2905 	 *
2906 	 * @see width
2907 	 * @see viewport
2908 	 */
2909 	get height() {
2910 		return this._viewport[3];
2911 	},
2912 
2913 	/**
2914 	 * Automatic viewport settings in a call to {@link bind}.
2915 	 *
2916 	 * If true, when calling {@link bind} the viewport will be set with a call to WebGLRenderingContext.viewport().
2917 	 *
2918 	 * @type bool
2919 	 */
2920 	get autoViewport() {
2921 		return this._autoViewport;
2922 	},
2923 
2924 	set autoViewport(on) {
2925 		this._autoViewport = !!on;
2926 	},
2927 
2928 	/**
2929 	 * Sets the framebuffer attachments.
2930 	 * It is used to attach resources (SpiderGL.WebGL.Texture2D, SpiderGL.WebGL.TextureCubeMap or SpiderGL.WebGL.Renderbuffer) as render targets.
2931 	 *
2932 	 * @param {object} attachments The resources to attach to the WebGLFramebuffer.
2933 	 * @param {object|SpiderGL.WebGL.Texture2D|SpiderGL.WebGL.TextureCubeMap|SpiderGL.WebGL.Renderbuffer} [attachments.color] The color attachment for target WebGLRenderingContext.COLOR_ATTACHMENT0; if omitted, the current color attachment is kept; if null, the current color attachment is detached.
2934 	 * @param {SpiderGL.WebGL.Texture2D|SpiderGL.WebGL.TextureCubeMap|SpiderGL.WebGL.Renderbuffer} [attachments.color.resource] The resource to use as a render target for color attachment.
2935 	 * @param {number} [attachments.color.level=SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_TEXTURE_LEVEL] If resource is SpiderGL.WebGL.Texture2D or SpiderGL.WebGL.TextureCubeMap, specifies the texture level to attach. As per WebGL specifications, level must be zero.
2936 	 * @param {number} [attachments.color.face=SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_CUBE_MAP_FACE] If resource is SpiderGL.WebGL.TextureCubeMap, specifies the texture cube map face to attach.
2937 	 * @param {object|SpiderGL.WebGL.Renderbuffer} [attachments.depth] Same as attachments.color but for WebGLRenderingContext.DEPTH_ATTACHMENT. To ensure the restrictions of the WebGL specifications, stencil and depthStencil attachments are detached.
2938 	 * @param {object|SpiderGL.WebGL.Renderbuffer} [attachments.stencil] Same as attachments.color but for WebGLRenderingContext.STENCIL_ATTACHMENT. To ensure the restrictions of the WebGL specifications, depth and depthStencil attachments are detached.
2939 	 * @param {object|SpiderGL.WebGL.Renderbuffer} [attachments.depthStencil] Same as attachments.color but for WebGLRenderingContext.DEPTH_STENCIL_ATTACHMENT. To ensure the restrictions of the WebGL specifications, depth and stencil attachments are detached.
2940 	 *
2941 	 * @returns {bool} True if the framebuffer is complete, false otherwise.
2942 	 *
2943 	 * @example
2944 	 * var t2D = new SpiderGL.WebGL.Texture2D(...);
2945 	 * var tCM = new SpiderGL.WebGL.TextureCubeMap(...);
2946 	 * var rb  = new SpiderGL.WebGL.Renderbuffer(...);
2947 	 *
2948 	 * var fb = new SpiderGL.WebGL.Framebuffer(gl, {
2949 	 * 	color : {resource: t2D, level: 0 }, // alternatively: color: t2D; in this case level would default to SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_TEXTURE_LEVEL
2950 	 * 	depth : rb                          // alternatively: depth: {resource: rb}; renderbuffers do not have mipmap levels
2951 	 * };
2952 	 * // use fb
2953 	 * // ...
2954 	 * 
2955 	 * // change attachment
2956 	 * fb.setAttachments({
2957 	 * 	color: {resource: tCM, face: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z} // if face is omitted, defaults to SpiderGL.WebGL.Framebuffer.DEFAULT_ATTACHMENT_CUBE_MAP_FACE
2958 	 * })
2959 	 *
2960 	 * @see getAttachments
2961 	 */
2962 	setAttachments : function (attachments) {
2963 		attachments = attachments || { };
2964 
2965 		var gl = this._gl;
2966 		var cb = this._cb;
2967 
2968 		var t = this._t;
2969 		var h = this._h;
2970 
2971 		cb.pushFramebuffer(t);
2972 		gl.bindFramebuffer(t, h);
2973 
2974 		if ("color" in attachments) {
2975 			this._setAttachment(gl.COLOR_ATTACHMENT0, attachments.color);
2976 		}
2977 
2978 		if ("depthStencil" in attachments) {
2979 			this._setAttachment(gl.DEPTH_ATTACHMENT,         null                    );
2980 			this._setAttachment(gl.STENCIL_ATTACHMENT,       null                    );
2981 			this._setAttachment(gl.DEPTH_STENCIL_ATTACHMENT, attachments.depthStencil);
2982 		}
2983 		else if ("depth" in attachments) {
2984 			this._setAttachment(gl.DEPTH_STENCIL_ATTACHMENT, null                    );
2985 			this._setAttachment(gl.STENCIL_ATTACHMENT,       null                    );
2986 			this._setAttachment(gl.DEPTH_ATTACHMENT,         attachments.depth       );
2987 		}
2988 		else if ("stencil" in attachments) {
2989 			this._setAttachment(gl.DEPTH_STENCIL_ATTACHMENT, null                    );
2990 			this._setAttachment(gl.DEPTH_ATTACHMENT,         null                    );
2991 			this._setAttachment(gl.STENCIL_ATTACHMENT,       attachments.stencil     );
2992 		}
2993 
2994 		this._status = gl.checkFramebufferStatus(t);
2995 
2996 		cb.popFramebuffer(t);
2997 
2998 		return this.isComplete;
2999 	},
3000 
3001 	/**
3002 	 * Retrieves the attached resources.
3003 	 * This method returns a new object containing the attachments information.
3004 	 *
3005 	 * @returns {object} The attachments data. The object fields may be: color, depth, stencil and depthStencil.
3006 	 *
3007 	 * @see setAttachments
3008 	 */
3009 	getAttachments : function () {
3010 		var rAtts = { };
3011 		var att   = null;
3012 		for (var a in this._attachments) {
3013 			att = this._attachments[a];
3014 			rAtts[a] = {
3015 				attachment : att.attachment,
3016 				resource   : att.resource,
3017 				target     : att.target,
3018 				level      : att.level
3019 			};
3020 		}
3021 		return rAtts;
3022 	},
3023 
3024 	/**
3025 	 * Detaches all attached resources.
3026 	 *
3027 	 * @see setAttachments
3028 	 */
3029 	detachAll : function () {
3030 		this.setAttachments({
3031 			color        : null,
3032 			depthStencil : null
3033 		});
3034 	},
3035 
3036 	/**
3037 	 * Gets/Sets the resource attached to the color attachment.
3038 	 * If no resource is attached the result is null.
3039 	 * When setting, default attaching parameters are used.
3040 	 *
3041 	 * @type SpiderGL.WebGL.Texture|SpiderGL.WebGL.Renderbuffer
3042 	 *
3043 	 * @readonly
3044 	 *
3045 	 * @see depthTarget
3046 	 * @see stencilTarget
3047 	 * @see depthStencilTarget
3048 	 */
3049 	get colorTarget() {
3050 		var att = this._attachments.color;
3051 		if (!att) return null
3052 		return att.resource;
3053 	},
3054 
3055 	set colorTarget(rt) {
3056 		this.setAttachments({ color : rt });
3057 	},
3058 
3059 	/**
3060 	 * Gets/Sets the resource attached to the depth attachment.
3061 	 * If no resource is attached the result is null.
3062 	 * When setting, default attaching parameters are used.
3063 	 *
3064 	 * @type SpiderGL.WebGL.Texture|SpiderGL.WebGL.Renderbuffer
3065 	 *
3066 	 * @readonly
3067 	 *
3068 	 * @see colorTarget
3069 	 * @see stencilTarget
3070 	 * @see depthStencilTarget
3071 	 */
3072 	get depthTarget() {
3073 		var att = this._attachments.depth;
3074 		if (!att) return null
3075 		return att.resource;
3076 	},
3077 
3078 	set depthTarget(rt) {
3079 		this.setAttachments({ depth : rt });
3080 	},
3081 
3082 	/**
3083 	 * Gets/Sets the resource attached to the stencil attachment.
3084 	 * If no resource is attached the result is null.
3085 	 * When setting, default attaching parameters are used.
3086 	 *
3087 	 * @type SpiderGL.WebGL.Texture|SpiderGL.WebGL.Renderbuffer
3088 	 *
3089 	 * @readonly
3090 	 *
3091 	 * @see colorTarget
3092 	 * @see depthTarget
3093 	 * @see depthStencilTarget
3094 	 */
3095 	get stencilTarget() {
3096 		var att = this._attachments.stencil;
3097 		if (!att) return null
3098 		return att.resource;
3099 	},
3100 
3101 	set stencilTarget(rt) {
3102 		this.setAttachments({ stencil : rt });
3103 	},
3104 
3105 	/**
3106 	 * Gets/Sets the resource attached to the depthStencil attachment.
3107 	 * If no resource is attached the result is null.
3108 	 * When setting, default attaching parameters are used.
3109 	 *
3110 	 * @type SpiderGL.WebGL.Texture|SpiderGL.WebGL.Renderbuffer
3111 	 *
3112 	 * @readonly
3113 	 *
3114 	 * @see colorTarget
3115 	 * @see depthTarget
3116 	 * @see stencilTarget
3117 	 */
3118 	get depthStencilTarget() {
3119 		var att = this._attachments.depthStencil;
3120 		if (!att) return null
3121 		return att.resource;
3122 	},
3123 
3124 	set depthStencilTarget(rt) {
3125 		this.setAttachments({ depthStencil : rt });
3126 	},
3127 
3128 	/**
3129 	 * Clears the framebuffer using current clear values.
3130 	 *
3131 	 * @param {number} mask The clear mask as for WebGLRenderingContext.clear.
3132 	 */
3133 	clear : function (mask) {
3134 		mask = SpiderGL.Utility.getDefaultValue(mask, SpiderGL.WebGL.Framebuffer.DEFAULT_CLEAR_MASK);
3135 		this._dsa.clear(this._h, mask);
3136 	},
3137 
3138 	/**
3139 	 * Reads the pixels from a rectangular region of the framebuffer.
3140 	 *
3141 	 * @param {ArrayBufferView} buffer The destination buffer in which pixels will be written.
3142 	 * @param {object} [options] Optional parameters.
3143 	 * @param {number} [options.x=SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_X] The rectangle left coordinate (in pixels).
3144 	 * @param {number} [options.y=SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_X] The rectangle bottom coordinate (in pixels).
3145 	 * @param {number} [options.width=SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_WIDTH] The rectangle width (in pixels). If less than zero, the width will be set to span the whole render target (starting from rectangle x coordinate).
3146 	 * @param {number} [options.height=SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_HEIGHT] The rectangle height (in pixels). If less than zero, the height will be set to span the whole render target (starting from rectangle y coordinate).
3147 	 * @param {number} [options.format=SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_FORMAT] The WebGL pixel format.
3148 	 * @param {number} [options.type=SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_TYPE] The WebGL pixel type.
3149 	 */
3150 	readPixels : function (buffer, options) {
3151 		options = SpiderGL.Utility.getDefaultObject({
3152 			x      : SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_X,
3153 			y      : SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_Y,
3154 			width  : SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_WIDTH,
3155 			height : SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_HEIGHT,
3156 			format : SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_FORMAT,
3157 			type   : SpiderGL.WebGL.Framebuffer.DEFAULT_READ_PIXELS_TYPE
3158 		}, options);
3159 
3160 		if (options.width  < 0) { options.width  = this._viewport[2]; }
3161 		if (options.height < 0) { options.height = this._viewport[3]; }
3162 
3163 		this._dsa.readPixels(this._h, options.x, options.y, options.width, options.height, options.format, options.type, buffer);
3164 	},
3165 
3166 	/**
3167 	 * Sets the WebGL viewport to the framebuffer viewport rectangle.
3168 	 *
3169 	 * @see viewport
3170 	 * @see autoViewport
3171 	 * @see setAttachments
3172 	 */
3173 	applyViewport : function () {
3174 		var gl = this._gl;
3175 		var vp = this._viewport;
3176 		gl.viewport(vp[0], vp[1], vp[2], vp[3]);
3177 	},
3178 
3179 	/**
3180 	 * Destroys the WebGLFramebuffer.
3181 	 * After destruction, the handle is set to null and this object should not be used anymore.
3182 	 *
3183 	 * @see SpiderGL.WebGL.ObjectGL#destroy
3184 	 */
3185 	destroy : function () {
3186 		this._gl.deleteFramebuffer(this._h);
3187 	},
3188 
3189 	/**
3190 	 * Binds the wrapped WebGLFramebuffer to the WebGLRenderingContex.FRAMEBUFFER target.
3191 	 * If setViewport is not specified and autoViewport is true, the stored viewport is set with WebGLRenderingContext.viewport().
3192 	 *
3193 	 * @param {bool} [setViewport] If specified, overrides the value of autoViewport.
3194 	 *
3195 	 * @see unbind
3196 	 * @see autoViewport
3197 	 */
3198 	bind : function (setViewport) {
3199 		var gl = this._gl;
3200 		gl.bindFramebuffer(this._t, this._h);
3201 		var svp = SpiderGL.Utility.getDefaultValue(setViewport, this._autoViewport);
3202 		if (svp) {
3203 			var vp = this._viewport;
3204 			gl.viewport(vp[0], vp[1], vp[2], vp[3]);
3205 		}
3206 	},
3207 
3208 	/**
3209 	 * Binds "null" to the WebGLRenderingContex.FRAMEBUFFER target.
3210 	 * This method is provided only for simmetry with {@link bind} and is not relative to the object state.
3211 	 *
3212 	 * @see bind
3213 	 */
3214 	unbind : function () {
3215 		this._gl.bindFramebuffer(this._t, null);
3216 	}
3217 };
3218 
3219 SpiderGL.Type.extend(SpiderGL.WebGL.Framebuffer, SpiderGL.WebGL.ObjectGL);
3220 
3221 /**
3222  * Creates a SpiderGL.WebGL.Program.
3223  *
3224  * SpiderGL.WebGL.Program is a wrapper for WebGLProgram objects.
3225  *
3226  * @class The SpiderGL.WebGL.Program is a wrapper for WebGLProgram objects.
3227  *
3228  * @augments SpiderGL.WebGL.ObjectGL
3229  *
3230  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
3231  * @param {object} [options] Optional parameters.
3232  * @param {WebGLProgram} [options.handle] A WebGLProgram. If present, this object will be used as the wrapped WebGLProgram and the attached shaders will be queried. Otherwise a new one will be created.
3233  * @param {bool} [options.autoLink=SpiderGL.WebGL.Program.DEFAULT_AUTO_LINK] If true, the program will be linked automatically whenever shaders are added or removed, or vertex attribute indices change.
3234  * @param {array} [options.shaders] An array of SpiderGL.WebGL.Shader objects to attach to the program.
3235  * @param {object} [options.attributes] An object where each property has the name of a vertex shader attribute and whose value is the attribute index to wich the vertex attribute will be bound.
3236  * @param {object} [options.uniforms] An object where each property has the name of a program uniform and whose value is the uniform value.
3237  *
3238  * @example
3239  * var vertexShader   = new SpiderGL.WebGL.VertexShader   (gl, {source: vertexShaderSrc  });
3240  * var fragmentShader = new SpiderGL.WebGL.FragmentShader (gl, {source: fragmentShaderSrc});
3241  *
3242  * var program = new SpiderGL.WebGL.Program(gl, {
3243  * 	autoLink : true, // if true, the program is automatically linked whenever shaders are added or removed, or whenever attribute indices are changed.
3244  * 	shaders  : [vertexShader, fragmentShader],
3245  * 	attributes : {
3246  * 		aPosition : 0, // the vertex shader aPosition attribute will be bound to the vertex attribute at index 0
3247  * 		aNormal   : 1  // the vertex shader aNormal attribute will be bound to the vertex attribute at index 1
3248  * 	},
3249  * 	uniforms : {
3250  * 		uDiffuseMap  : 0,  // index of the texture unit for diffuse color textures
3251  * 		uScaleFactor : 2.0
3252  * 	}
3253  * };
3254  *
3255  * // uniforms can also be set when the program is not bound
3256  * program.setUniforms({
3257  *	uModelViewProjection : getMVP(),
3258  *	uShininess           : getShininess()
3259  * });
3260  *
3261  * program.bind();
3262  * // render
3263  *
3264  * @see setShaders
3265  * @see setAttributes
3266  * @see setUniforms
3267  * @see autoLink
3268  * @see SpiderGL.WebGL.Shader
3269  * @see SpiderGL.WebGL.ObjectGL
3270  */
3271 SpiderGL.WebGL.Program = function (gl, options) {
3272 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
3273 
3274 	if (SpiderGL.Type.instanceOf(options, WebGLProgram)) {
3275 		options = { handle : options };
3276 	}
3277 
3278 	options = SpiderGL.Utility.getDefaultObject({
3279 		handle   : null,
3280 		autoLink : SpiderGL.WebGL.Program.DEFAULT_AUTO_LINK
3281 	}, options);
3282 
3283 	SpiderGL.WebGL.ObjectGL.call(this, gl, SpiderGL.WebGL.Program.TARGET, options);
3284 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
3285 
3286 	var gl  = this._gl;
3287 	var cb  = this._cb;
3288 	var dsa = this._dsa;
3289 
3290 	var h = this._h;
3291 
3292 	var linked    = false;
3293 	var log       = "";
3294 
3295 	var imported = false;
3296 	if (h) {
3297 		imported = true;
3298 		linked   = !!gl.getProgramParameter(h, gl.LINK_STATUS);
3299 		log      = gl.getProgramInfoLog(h);
3300 		if (!log) { log = ""; }
3301 	}
3302 	else {
3303 		h = gl.createProgram();
3304 		this._h = h;
3305 	}
3306 	h._spidergl = this;
3307 
3308 	this._shaders    = [ ];
3309 	this._linked     = linked;
3310 	this._log        = log;
3311 	this._autoLink   = options.autoLink;
3312 	this._attributes = { };
3313 	this._uniforms   = { };
3314 
3315 	if (imported) {
3316 		var shaders = gl.getAttachedShaders(h);
3317 		for (var i=0,n=shaders.length; i<n; ++i) {
3318 			this._importShader(shaders[i]);
3319 		}
3320 	}
3321 
3322 	var mustLink = false;
3323 	if (this._addShaders(options.shaders))       { mustLink = true; }
3324 	if (this._setAttributes(options.attributes)) { mustLink = true; }
3325 
3326 	if (mustLink && this._autoLink) { this.link(); }
3327 	else if (imported) { this._postLink(); }
3328 
3329 	this.setUniforms(options.uniforms);
3330 }
3331 
3332 /**
3333  * Dummy WebGL target for programs.
3334  * It is equal to WebGLRenderingContext.NONE and is provided only for completeness with other WebGL wrappers.
3335  *
3336  * @type number
3337  *
3338  * @default WebGLRenderingContext.NONE
3339  */
3340 SpiderGL.WebGL.Program.TARGET = WebGLRenderingContext.NONE;
3341 
3342 /**
3343  * Default value for SpiderGL.WebGL.Program#autoLink.
3344  *
3345  * @type bool
3346  *
3347  * @default true
3348  */
3349 SpiderGL.WebGL.Program.DEFAULT_AUTO_LINK = true;
3350 
3351 /**
3352  * WebGLProgram unbinding.
3353  *
3354  * This function binds the null program with WebGLRenderingContext.useProgram(null).
3355  *
3356  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
3357  */
3358 SpiderGL.WebGL.Program.unbind = function (gl) { gl.useProgram(null); };
3359 
3360 SpiderGL.WebGL.Program._uniformSetFunctions = { };
3361 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.BOOL        ] = function (dsa, h, v) { dsa.uniform1i        (h, this.location,        v); };
3362 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.BOOL_VEC2   ] = function (dsa, h, v) { dsa.uniform2iv       (h, this.location,        v); };
3363 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.BOOL_VEC3   ] = function (dsa, h, v) { dsa.uniform3iv       (h, this.location,        v); };
3364 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.BOOL_VEC4   ] = function (dsa, h, v) { dsa.uniform4iv       (h, this.location,        v); };
3365 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.INT         ] = function (dsa, h, v) { dsa.uniform1i        (h, this.location,        v); };
3366 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.INT_VEC2    ] = function (dsa, h, v) { dsa.uniform2iv       (h, this.location,        v); };
3367 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.INT_VEC3    ] = function (dsa, h, v) { dsa.uniform3iv       (h, this.location,        v); };
3368 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.INT_VEC4    ] = function (dsa, h, v) { dsa.uniform4iv       (h, this.location,        v); };
3369 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT       ] = function (dsa, h, v) { dsa.uniform1f        (h, this.location,        v); };
3370 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT_VEC2  ] = function (dsa, h, v) { dsa.uniform2fv       (h, this.location,        v); };
3371 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT_VEC3  ] = function (dsa, h, v) { dsa.uniform3fv       (h, this.location,        v); };
3372 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT_VEC4  ] = function (dsa, h, v) { dsa.uniform4fv       (h, this.location,        v); };
3373 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT_MAT2  ] = function (dsa, h, v) { dsa.uniformMatrix2fv (h, this.location, false, v); };
3374 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT_MAT3  ] = function (dsa, h, v) { dsa.uniformMatrix3fv (h, this.location, false, v); };
3375 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.FLOAT_MAT4  ] = function (dsa, h, v) { dsa.uniformMatrix4fv (h, this.location, false, v); };
3376 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.SAMPLER_2D  ] = function (dsa, h, v) { dsa.uniform1i        (h, this.location,        v); };
3377 SpiderGL.WebGL.Program._uniformSetFunctions[WebGLRenderingContext.SAMPLER_CUBE] = function (dsa, h, v) { dsa.uniform1i        (h, this.location,        v); };
3378 
3379 SpiderGL.WebGL.Program.prototype = {
3380 	_gl_deleteProgram : function (program) {
3381 		this._h = null;
3382 	},
3383 
3384 	_gl_isProgram : function (program) {
3385 	},
3386 
3387 	_gl_useProgram : function (program) {
3388 	},
3389 
3390 	_gl_getActiveAttrib : function (program, index) {
3391 	},
3392 
3393 	_gl_getActiveUniform : function (program, index) {
3394 	},
3395 
3396 	_gl_getAttachedShaders : function (program) {
3397 	},
3398 
3399 	_gl_getAttribLocation : function (program, name) {
3400 	},
3401 
3402 	_gl_getProgramParameter : function (program, pname) {
3403 	},
3404 
3405 	_gl_getProgramInfoLog : function (program) {
3406 	},
3407 
3408 	_gl_getUniform : function (program, location) {
3409 	},
3410 
3411 	_gl_getUniformLocation : function (program, name) {
3412 	},
3413 
3414 	_gl_attachShader : function (program, shader) {
3415 		this._importShader(shader);
3416 	},
3417 
3418 	_gl_bindAttribLocation : function (program, index, name) {
3419 	},
3420 
3421 	_gl_detachShader : function (program, shader) {
3422 		if (!shader) { return; }
3423 		var idx = this._shaderHandleIndex(shader);
3424 		if (idx < 0) { return; }
3425 		this._shaders.splice(idx, 1);
3426 	},
3427 
3428 	_gl_linkProgram : function (program) {
3429 		this._postLink();
3430 	},
3431 
3432 	_gl_uniform1f : function (location, x) {
3433 	},
3434 
3435 	_gl_uniform1fv : function (location, v) {
3436 	},
3437 
3438 	_gl_uniform1i : function (location, x) {
3439 	},
3440 
3441 	_gl_uniform1iv : function (location, v) {
3442 	},
3443 
3444 	_gl_uniform2f : function (location, x, y) {
3445 	},
3446 
3447 	_gl_uniform2fv : function (location, v) {
3448 	},
3449 
3450 	_gl_uniform2i : function (location, x, y) {
3451 	},
3452 
3453 	_gl_uniform2iv : function (location, v) {
3454 	},
3455 
3456 	_gl_uniform3f : function (location, x, y, z) {
3457 	},
3458 
3459 	_gl_uniform3fv : function (location, v) {
3460 	},
3461 
3462 	_gl_uniform3i : function (location, x, y, z) {
3463 	},
3464 
3465 	_gl_uniform3iv : function (location, v) {
3466 	},
3467 
3468 	_gl_uniform4f : function (location, x, y, z, w) {
3469 	},
3470 
3471 	_gl_uniform4fv : function (location, v) {
3472 	},
3473 
3474 	_gl_uniform4i : function (location, x, y, z, w) {
3475 	},
3476 
3477 	_gl_uniform4iv : function (location, v) {
3478 	},
3479 
3480 	_gl_uniformMatrix2fv : function (location, transpose, value) {
3481 	},
3482 
3483 	_gl_uniformMatrix3fv : function (location, transpose, value) {
3484 	},
3485 
3486 	_gl_uniformMatrix4fv : function (location, transpose, value) {
3487 	},
3488 
3489 	_gl_validateProgram : function (program) {
3490 	},
3491 
3492 	_shaderHandleIndex : function (shader) {
3493 		for (var i=0,n=this._shaders.length; i<n; ++i) {
3494 			if (this._shaders[i].handle === shader) {
3495 				return i;
3496 			}
3497 		}
3498 		return -1;
3499 	},
3500 
3501 	_shaderIndex : function (shader) {
3502 		if (this._shaders.indexOf) { return this._shaders.indexOf(shader); }
3503 		else {
3504 			for (var i=0,n=this._shaders.length; i<n; ++i) {
3505 				if (this._shaders[i] === shader) {
3506 					return i;
3507 				}
3508 			}
3509 			return -1;
3510 		}
3511 	},
3512 
3513 	_importShader : function (shader) {
3514 		if (!shader) { return; }
3515 		if (this._shaderHandleIndex(shader) >= 0) { return; }
3516 
3517 		var gl = this._gl;
3518 		var shd = shader._spidergl;
3519 		if (!shd) {
3520 			var type = gl.getShaderParameter(shader, gl.SHADER_TYPE);
3521 			switch (type) {
3522 				case gl.VERTEX_SHADER   : shd = new SpiderGL.WebGL.VertexShader   (gl, { handle : shader }); break;
3523 				case gl.FRAGMENT_SHADER : shd = new SpiderGL.WebGL.FragmentShader (gl, { handle : shader }); break;
3524 				default : return; break;
3525 			}
3526 		}
3527 		this._shaders.push(shd);
3528 	},
3529 
3530 	_updateActiveInfo : function () {
3531 		var gl = this._gl;
3532 		var h = this._h;
3533 
3534 		var n    = 0;
3535 		var nfo  = null;
3536 		var name = null;
3537 		var loc  = null;
3538 
3539 		var attributes = { };
3540 		n = gl.getProgramParameter(h, gl.ACTIVE_ATTRIBUTES);
3541 		for (var i=0; i<n; ++i) {
3542 			nfo  = gl.getActiveAttrib(h, i);
3543 			name = nfo.name;
3544 			loc  = gl.getAttribLocation(h, name);
3545 			attributes[name] = {
3546 				index    : i,
3547 				name     : name,
3548 				size     : nfo.size,
3549 				type     : nfo.type,
3550 				location : loc
3551 			};
3552 		}
3553 
3554 		var uniforms = { };
3555 		n = gl.getProgramParameter(h, gl.ACTIVE_UNIFORMS);
3556 		for (var i=0; i<n; ++i) {
3557 			nfo = gl.getActiveUniform(h, i);
3558 			name = nfo.name;
3559 			loc  = gl.getUniformLocation(h, name);
3560 			uniforms[name] = {
3561 				index    : i,
3562 				name     : name,
3563 				size     : nfo.size,
3564 				type     : nfo.type,
3565 				location : loc,
3566 				setValue : SpiderGL.WebGL.Program._uniformSetFunctions[nfo.type]
3567 			};
3568 		}
3569 
3570 		this._attributes = attributes;
3571 		this._uniforms   = uniforms;
3572 	},
3573 
3574 	_postLink : function () {
3575 		var gl = this._gl;
3576 		var h = this._h;
3577 		this._linked = !!gl.getProgramParameter(h, gl.LINK_STATUS);
3578 		this._log = gl.getProgramInfoLog(h);
3579 		if (!this._log) { this._log = ""; }
3580 		this._updateActiveInfo();
3581 	},
3582 
3583 	_addShaders : function (shaders) {
3584 		if (!shaders) { return false; }
3585 
3586 		var gl = this._gl;
3587 		var h = this._h;
3588 		var shd = null;
3589 		var hshd = null;
3590 
3591 		for (var i=0,n=shaders.length; i<n; ++i) {
3592 			shd = shaders[i];
3593 			hshd = null;
3594 			if (SpiderGL.Type.instanceOf(shd, SpiderGL.WebGL.Shader)) {
3595 				hshd = shd.handle;
3596 			}
3597 			if (SpiderGL.Type.instanceOf(shd, WebGLShader)) {
3598 				hshd = shd;
3599 			}
3600 			if (hshd) {
3601 				gl.attachShader(h, hshd);
3602 			}
3603 		}
3604 
3605 		return true;
3606 	},
3607 
3608 	_removeShaders : function (shaders) {
3609 		if (!shaders) { return false; }
3610 
3611 		var gl = this._gl;
3612 		var h = this._h;
3613 		var shd = null;
3614 		var hshd = null;
3615 
3616 		for (var i=0,n=shaders.length; i<n; ++i) {
3617 			shd = shaders[i];
3618 			hshd = null;
3619 			if (SpiderGL.Type.instanceOf(shd, SpiderGL.WebGL.Shader)) {
3620 				hshd = shd.handle;
3621 			}
3622 			if (SpiderGL.Type.instanceOf(shd, SpiderGL.WebGL.Shader)) {
3623 				hshd = shd;
3624 			}
3625 			if (hshd) {
3626 				gl.detachShader(h, hshd);
3627 			}
3628 		}
3629 
3630 		return true;
3631 	},
3632 
3633 	_setAttributes : function (attributes) {
3634 		if (!attributes) { return false; }
3635 		var gl = this._gl;
3636 		var h = this._h;
3637 		for (var a in attributes) {
3638 			gl.bindAttribLocation(h, attributes[a], a);
3639 		}
3640 		return true;
3641 	},
3642 
3643 	/*
3644 	get isEmpty     () { return (this._shaders.length <= 0); },
3645 	*/
3646 
3647 	/**
3648 	 * Tests if the program is ready to use.
3649 	 * A program is considered ready if it is succesfully linked.
3650 	 *
3651 	 * @type bool
3652 	 *
3653 	 * @readonly
3654 	 *
3655 	 * @see isLinked
3656 	 */
3657 	get isReady() {
3658 		return this.isLinked;
3659 	},
3660 
3661 	/**
3662 	 * Tests if the program is linked.
3663 	 *
3664 	 * @type bool
3665 	 *
3666 	 * @readonly
3667 	 *
3668 	 * @see isReady
3669 	 */
3670 	get isLinked() {
3671 		return this._linked;
3672 	},
3673 
3674 	/*
3675 	get isValidated() {
3676 		return this._validated;
3677 	},
3678 	*/
3679 
3680 	/**
3681 	 * Gets the program info log.
3682 	 *
3683 	 * @type bool
3684 	 *
3685 	 * @readonly
3686 	 */
3687 	get log() {
3688 		return this._log;
3689 	},
3690 
3691 	/**
3692 	 * Gets/Sets if the program will be linked automatically whenever shaders are added or removed, or vertex attribute indices change.
3693 	 *
3694 	 * @type bool
3695 	 *
3696 	 * @see link
3697 	 */
3698 	get autoLink() {
3699 		return this._autoLink;
3700 	},
3701 
3702 	set autoLink(on) { 
3703 		this._autoLink = !!on;
3704 	},
3705 
3706 	/**
3707 	 * Attaches the provided shaders to the program.
3708 	 * If link is not specified and autoLink is true, the program is automatically linked.
3709 	 *
3710 	 * @param {array|SpiderGL.WebGL.Shader} shaders An array of SpiderGL.WebGL.Shader or a single SpiderGL.WebGL.Shader to attach.
3711 	 * @param {bool} [link] If specified, overrides the value of autoLink.
3712 	 *
3713 	 * @returns {bool} If the program has been linked, returns whether the program is linked, otherwise always returns true.
3714 	 *
3715 	 * @see isLinked
3716 	 */
3717 	addShaders : function (shaders, link) {
3718 		var mustLink = this._addShaders(shaders);
3719 		if (!mustLink) { return true; };
3720 		mustLink = SpiderGL.Utility.getDefaultValue(link, this._autoLink);
3721 		if (!mustLink) { return true; }
3722 		return this.link()
3723 	},
3724 
3725 	/**
3726 	 * Detaches the provided shaders to the program.
3727 	 * If link is not specified and autoLink is true, the program is automatically linked.
3728 	 *
3729 	 * @param {array|SpiderGL.WebGL.Shader} shaders An array of SpiderGL.WebGL.Shader or a single SpiderGL.WebGL.Shader to detach.
3730 	 * @param {bool} [link] If specified, overrides the value of autoLink.
3731 	 *
3732 	 * @returns {bool} If the program has been linked, returns whether the program is linked, otherwise always returns true.
3733 	 */
3734 	removeShaders : function (shaders, link) {
3735 		var mustLink = this._removeShaders(shaders);
3736 		if (!mustLink) { return true; };
3737 		mustLink = SpiderGL.Utility.getDefaultValue(link, this._autoLink);
3738 		if (!mustLink) { return true; }
3739 		return this.link()
3740 	},
3741 
3742 	/**
3743 	 * Tests whether the passed shader is attached to the program.
3744 	 *
3745 	 * @param {SpiderGL.WebGL.Shader} shader The shader to test for attachment.
3746 	 *
3747 	 * @returns {bool} If the shader is attached, false otherwise.
3748 	 */
3749 	hasShader : function (shader) {
3750 		return (this._shaderIndex(shader) >= 0);
3751 	},
3752 
3753 	/**
3754 	 * Gets the attached shaders.
3755 	 *
3756 	 * @returns {array} An array with the attached SpiderGL.WebGL.Shader objects.
3757 	 */
3758 	getShaders : function () {
3759 		return this._shaders.slice();
3760 	},
3761 
3762 	/**
3763 	 * Links the program.
3764 	 *
3765 	 * @returns {bool} True if the program has been succesfully linked, false otherwise.
3766 	 */
3767 	link : function () {
3768 		this._gl.linkProgram(this._h);
3769 		return this._linked;
3770 	},
3771 
3772 	/**
3773 	 * Validates the program with the current attribute indices, uniforms and WebGLRenderingContext state
3774 	 * It is performed using WebGLRenderingContext.validateProgram().
3775 	 *
3776 	 * @returns {bool} True if the program has been succesfully validated, false otherwise.
3777 	 */
3778 	validate : function () {
3779 		var gl = this._gl;
3780 		var h = this._h;
3781 		gl.validateProgram(h);
3782 		var validated = !!gl.getProgramParameter(h, gl.VALIDATE_STATUS);
3783 		return validated;
3784 	},
3785 
3786 	/**
3787 	 * Sets the indices of vertex shader attributes.
3788 	 * Only the recognized attributes (i.e. the active attributes in vertex shaders) will be set.
3789 	 * The attribute binding indices will take effect only when the program is linked again.
3790 	 * If autoLink is true, the program is automatically linked.
3791 	 *
3792 	 * @param {object} attributes The attributes to set. For each attribute index to set, the object must contain a property whose name is the name of the vertex attribute and whose value is a non-negative integer specifying the attribute bind index.
3793 	 *
3794 	 * @example
3795 	 * var vertexShaderSrc = "" +
3796 	 * 	"..." + 
3797 	 * 	"attribute vec3 aPosition; \n" +
3798 	 * 	"attribute vec3 aNormal;   \n" +
3799 	 * 	"...";
3800 	 *
3801 	 * // setup the program (attribute indices can also be set at construction)
3802 	 * // ...
3803 	 *
3804 	 * // set attributes indices;
3805 	 * // if autoLink is true, the program will be automatically linked;
3806 	 * // otherwise it must be explicitly linked with program.link()
3807 	 * program.setAttributes({
3808 	 * 	aPosition : 3,  // bind attribute aPosition to vertex attribute 3
3809 	 * 	aNormal   : 1   // bind attribute aNormal to vertex attribute 1
3810 	 * 	aColor    : 2   // this attribute is not set because it is not an active attribute
3811 	 * });
3812 	 *
3813 	 * @returns {bool} True if the attributes have been set, false otherwise.
3814 	 *
3815 	 * @see getAttributesIndices
3816 	 * @see getAttributesInfo
3817 	 * @see setUniforms
3818 	 * @see link
3819 	 * @see autoLink
3820 	 */
3821 	setAttributes : function (attributes) {
3822 		if (!this._setAttributes(attributes)) return false;
3823 		if (this._autoLink) return this.link();
3824 		return true;
3825 	},
3826 
3827 	/**
3828 	 * Gets vertex attributes names.
3829 	 *
3830 	 * @returns {array} An array containing the names of all active vertex shader attributes.
3831 	 *
3832 	 * @see getAttributesIndices
3833 	 * @see getAttributesInfo
3834 	 */
3835 	getAttributesNames : function () {
3836 		var attributes  = this._attributes;
3837 		var rAttributes = [ ];
3838 		for (var a in attributes) {
3839 			rAttributes.push(attributes[a].name);
3840 		}
3841 		return rAttributes;
3842 	},
3843 
3844 	/**
3845 	 * Gets the vertex attributes binding indices.
3846 	 *
3847 	 * @returns {object} An object with one property for each active vertex attribute. The name of the property is the name of the attribute in the vertex shader and its value is a non-negative integer representing the attribute bind index.
3848 	 *
3849 	 * @see getAttributesInfo
3850 	 * @see setAttributes
3851 	 */
3852 	getAttributesIndices : function () {
3853 		var attributes  = this._attributes;
3854 		var rAttributes = { };
3855 		for (var a in attributes) {
3856 			rAttributes[a] = attributes[a].location;
3857 		}
3858 		return rAttributes;
3859 	},
3860 
3861 	/**
3862 	 * Gets the vertex attributes informations.
3863 	 *
3864 	 * @returns {object} An object where each property has the name of a vertex shader attribute and whose value is an object containing attribute information. The attribute index is in the "location" property.
3865 	 *
3866 	 * @see getAttributesIndices
3867 	 * @see setAttributes
3868 	 */
3869 	getAttributesInfo : function () {
3870 		var attributes  = this._attributes;
3871 		var attribute   = null;
3872 		var rAttributes = { };
3873 		for (var a in attributes) {
3874 			attribute = attributes[a];
3875 			rAttributes[a] = {
3876 				index    : attribute.index,
3877 				name     : attribute.name,
3878 				size     : attribute.size,
3879 				type     : attribute.type,
3880 				location : attribute.location
3881 			};
3882 		}
3883 		return rAttributes;
3884 	},
3885 
3886 	/**
3887 	 * Sets the program uniforms.
3888 	 * Only the recognized uniforms are set.
3889 	 *
3890 	 * @param {object} uniforms An object where each property has the name of the uniform to set and whose value is the uniform value.
3891 	 *
3892 	 * @example
3893 	 * var vertexShaderSrc = "" +
3894 	 * 	"..." + 
3895 	 * 	"uniform mat4  uMVP;      \n" +
3896 	 * 	"uniform float uScale;    \n" +
3897 	 * 	"uniform vec3  uLightPos; \n" +
3898 	 * 	"...";
3899 	 *
3900 	 * // setup the program (uniforms can also be set at construction)
3901 	 * // ...
3902 	 *
3903 	 * // set uniform values;
3904 	 * program.setUniforms({
3905 	 * 	uMVP      : getModelViewProjection(),
3906 	 * 	uScale    : 2.3,
3907 	 * 	uLightPos : [0, 0.5, 4.7], // can be a typed array: new Float32Array([0, 0.5, 4.7])
3908 	 * 	uOther    : 1.0 // this uniform is not set because it is not an active uniform
3909 	 * });
3910 	 *
3911 	 * @returns {bool} True if the uniforms have been set succesfully, false otherwise.
3912 	 */
3913 	setUniforms : function (uniforms) {
3914 		if (!uniforms) { return false; }
3915 
3916 		var gl  = this._gl;
3917 		var cb  = this._cb;
3918 		var dsa = this._dsa;
3919 
3920 		var h = this._h;
3921 
3922 		cb.pushProgram();
3923 		gl.useProgram(h);
3924 
3925 		var _uniforms = this._uniforms;
3926 		var uniform = null;
3927 		var value   = null;
3928 		for (var u in uniforms) {
3929 			uniform = _uniforms[u];
3930 			if (uniform) {
3931 				uniform.setValue(dsa, h, uniforms[u]);
3932 			}
3933 		}
3934 
3935 		cb.popProgram();
3936 
3937 		return true;
3938 	},
3939 
3940 	/**
3941 	 * Gets uniforms names.
3942 	 *
3943 	 * @returns {array} An array containing the names of all active uniforms.
3944 	 *
3945 	 * @see getUniformsValues
3946 	 * @see getUniformsInfo
3947 	 */
3948 	getUniformsNames : function () {
3949 		var uniforms  = this._uniforms;
3950 		var rUniforms = [ ];
3951 		for (var u in uniforms) {
3952 			rUniforms.push(uniforms[u].name);
3953 		}
3954 		return rUniforms;
3955 	},
3956 
3957 	/**
3958 	 * Gets the values of the program uniforms.
3959 	 *
3960 	 * @returns {object} An object with one property for each active uniform. The name of the property is the name of the uniform and its value is the uniform value, which can be a number, an array or a typed array.
3961 	 */
3962 	getUniformsValues : function () {
3963 		var gl = this._gl;
3964 		var h = this._h;
3965 		var uniforms  = this._uniforms;
3966 		var rUniforms = { };
3967 		for (var u in uniforms) {
3968 			rUniforms[u] = gl.getUniform(h, uniforms[u].location);
3969 		}
3970 		return rUniforms;
3971 	},
3972 
3973 	/**
3974 	 * Gets the program uniforms informations.
3975 	 *
3976 	 * @returns {object} An object where each property has the name of a program uniform and whose value is an object containing uinformation.
3977 	 */
3978 	getUniformsInfo : function () {
3979 		var uniforms  = this._uniforms;
3980 		var uniform   = null;
3981 		var value     = null;
3982 		var rUniforms = { };
3983 		for (var u in uniforms) {
3984 			uniform = uniforms[u];
3985 			rUniforms[u] = {
3986 				index    : uniform.index,
3987 				name     : uniform.name,
3988 				size     : uniform.size,
3989 				type     : uniform.type,
3990 				location : uniform.location
3991 			};
3992 		}
3993 		return rUniforms;
3994 	},
3995 
3996 	/**
3997 	 * Destroys the WebGLProgram.
3998 	 * After destruction, the handle is set to null and this object should not be used anymore.
3999 	 *
4000 	 * @see SpiderGL.WebGL.ObjectGL#destroy
4001 	 */
4002 	destroy : function () {
4003 		this._gl.deleteProgram(this._h);
4004 	},
4005 
4006 	/**
4007 	 * Binds the wrapped WebGLProgram with WebGLRenderingContext.useProgram().
4008 	 *
4009 	 * @see unbind
4010 	 */
4011 	bind : function () {
4012 		this._gl.useProgram(this._h);
4013 	},
4014 
4015 	/**
4016 	 * Binds the "null" program with WebGLRenderingContext.useProgram(null).
4017 	 * This method is provided only for simmetry with {@link bind} and is not relative to the object state.
4018 	 *
4019 	 * @see bind
4020 	 */
4021 	unbind : function () {
4022 		this._gl.useProgram(null);
4023 	}
4024 };
4025 
4026 SpiderGL.Type.extend(SpiderGL.WebGL.Program, SpiderGL.WebGL.ObjectGL);
4027 
4028 /**
4029  * Creates a SpiderGL.WebGL.Renderbuffer.
4030  *
4031  * SpiderGL.WebGL.Renderbuffer is a wrapper for WebGLRenderbuffer.
4032  *
4033  * @class The SpiderGL.WebGL.Renderbuffer is a wrapper for WebGLRenderbuffer.
4034  *
4035  * @augments SpiderGL.WebGL.ObjectGL
4036  *
4037  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
4038  * @param {object} [options] Optional parameters.
4039  * @param {WebGLRenderbuffer} [options.handle] A WebGLRenderbuffer. If present, this object will be used as the wrapped WebGLRenderbuffer. Otherwise a new one will be created.
4040  * @param {number} [options.internalFormat] The WebGL enumeration specifying the renderbuffer internal format.
4041  * @param {object} [options.width] The width of the renderbuffer.
4042  * @param {object} [options.height] The height of the renderbuffer.
4043  *
4044  * @example
4045  * var rb = new SpiderGL.WebGL.Renderbuffer(gl, {
4046  * 	internalFormat : gl.RGBA,
4047  * 	width  : 800,
4048  * 	height : 600
4049  * });
4050  *
4051  * @see setStorage
4052  * @see SpiderGL.WebGL.Framebuffer
4053  * @see SpiderGL.WebGL.ObjectGL
4054  */
4055 SpiderGL.WebGL.Renderbuffer = function (gl, options) {
4056 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
4057 
4058 	if (SpiderGL.Type.instanceOf(h, WebGLRenderbuffer)) {
4059 		options = { handle : options };
4060 	}
4061 
4062 	options = SpiderGL.Utility.getDefaultObject({
4063 		handle : null,
4064 	}, options);
4065 
4066 	SpiderGL.WebGL.ObjectGL.call(this, gl, SpiderGL.WebGL.Renderbuffer.TARGET, options);
4067 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
4068 
4069 	var gl  = this._gl;
4070 	var cb  = this._cb;
4071 	var dsa = this._dsa;
4072 
4073 	var t = this._t;
4074 	var h = this._h;
4075 
4076 	var format = gl.NONE;
4077 	var width  = 0;
4078 	var height = 0;
4079 
4080 	if (h) {
4081 		cb.pushRenderbuffer(t);
4082 		gl.bindRenderbuffer(t, h);
4083 		format = gl.getRenderbufferParameter(t, gl.RENDERBUFFER_INTERNAL_FORMAT);
4084 		width  = gl.getRenderbufferParameter(t, gl.RENDERBUFFER_WIDTH);
4085 		height = gl.getRenderbufferParameter(t, gl.RENDERBUFFER_HEIGHT);
4086 		cb.popRenderbuffer(t);
4087 	}
4088 	else {
4089 		h = gl.createRenderbuffer();
4090 		this._h = h;
4091 	}
4092 	h._spidergl = this;
4093 
4094 	this._width  = width;
4095 	this._height = height;
4096 	this._format = format;
4097 
4098 	if (SpiderGL.Type.isNumber(options.internalFormat) && SpiderGL.Type.isNumber(options.width) && SpiderGL.Type.isNumber(options.height)) {
4099 		this.setStorage(options.internalFormat, options.width, options.height, options.format);
4100 	}
4101 }
4102 
4103 /**
4104  * WebGL target for renderbuffers.
4105  *
4106  * @type number
4107  *
4108  * @default WebGLRenderingContext.RENDERBUFFER
4109  */
4110 SpiderGL.WebGL.Renderbuffer.TARGET = WebGLRenderingContext.RENDERBUFFER;
4111 
4112 /**
4113  * WebGLRenderbuffer unbinding.
4114  *
4115  * This function binds the null renderbuffer to the WebGLRenderingContext.RENDERBUFFER target.
4116  *
4117  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
4118  */
4119 SpiderGL.WebGL.Renderbuffer.unbind = function (gl) { gl.bindRenderbuffer(SpiderGL.WebGL.Renderbuffer.TARGET, null); };
4120 
4121 SpiderGL.WebGL.Renderbuffer.prototype = {
4122 	_gl_deleteRenderbuffer : function (renderbuffer) {
4123 		this._h = null;
4124 	},
4125 
4126 	_gl_isRenderbuffer : function (renderbuffer) {
4127 	},
4128 
4129 	_gl_bindRenderbuffer : function (target, renderbuffer) {
4130 	},
4131 
4132 	_gl_getRenderbufferParameter : function (target, pname) {
4133 	},
4134 
4135 	_gl_renderbufferStorage : function (target, internalformat, width, height) {
4136 		this._format = internalformat;
4137 		this._width  = width;
4138 		this._height = height;
4139 	},
4140 
4141 	/*
4142 	get isEmpty () { return ((this._width <= 0) || (this._height <= 0)); },
4143 	*/
4144 
4145 	/**
4146 	 * Tests if the renderbuffer is ready to use.
4147 	 * A renderbuffer is considered ready if its width and height are greater than zero.
4148 	 *
4149 	 * @type bool
4150 	 *
4151 	 * @readonly
4152 	 */
4153 	get isReady() {
4154 		return ((this._width > 0) && (this._height > 0));
4155 	},
4156 
4157 	/**
4158 	 * Gets the WebGL internal format of the renderbuffer.
4159 	 *
4160 	 * @type number
4161 	 *
4162 	 * @readonly
4163 	 */
4164 	get format() {
4165 		return this._format;
4166 	},
4167 
4168 	/**
4169 	 * Gets the width in pixels of the renderbuffer.
4170 	 *
4171 	 * @type number
4172 	 *
4173 	 * @readonly
4174 	 */
4175 	get width() {
4176 		return this._width;
4177 	},
4178 
4179 	/**
4180 	 * Gets the height in pixels of the renderbuffer.
4181 	 *
4182 	 * @type number
4183 	 *
4184 	 * @readonly
4185 	 */
4186 	get height() {
4187 		return this._height;
4188 	},
4189 
4190 	/**
4191 	 * Setups the renderbuffer storage configuration.
4192 	 *
4193 	 * @param {number} internalFormat The WebGL enumeration for the internal pixel format.
4194 	 * @param {number} width The width in pixels of the renderbuffer.
4195 	 * @param {number} height The height in pixels of the renderbuffer.
4196 	 */
4197 	setStorage : function (internalFormat, width, height) {
4198 		this._dsa.renderbufferStorage(this._h, this._t, internalFormat, width, height);
4199 	},
4200 
4201 	/**
4202 	 * Destroys the WebGLRenderbuffer.
4203 	 * After destruction, the handle is set to null and this object should not be used anymore.
4204 	 *
4205 	 * @see SpiderGL.WebGL.ObjectGL#destroy
4206 	 */
4207 	destroy : function () {
4208 		this._gl.deleteRenderbuffer(this._h);
4209 	},
4210 
4211 	/**
4212 	 * Binds the wrapped WebGLRenderbuffer to the WebGLRenderingContex.RENDERBUFFER target.
4213 	 *
4214 	 * @see unbind
4215 	 */
4216 	bind : function () {
4217 		this._gl.bindRenderbuffer(this._t, this._h);
4218 	},
4219 
4220 	/**
4221 	 * Binds "null" to the WebGLRenderingContex.RENDERBUFFER target.
4222 	 * This method is provided only for simmetry with {@link bind} and is not relative to the object state.
4223 	 *
4224 	 * @see bind
4225 	 */
4226 	unbind : function () {
4227 		this._gl.bindRenderbuffer(this._t, null);
4228 	}
4229 };
4230 
4231 SpiderGL.Type.extend(SpiderGL.WebGL.Renderbuffer, SpiderGL.WebGL.ObjectGL);
4232 
4233 /**
4234  * Creates a SpiderGL.WebGL.Shader.
4235  *
4236  * SpiderGL.WebGL.Shader is the base class for WebGLShader object wrappers and must not be directly used.
4237  *
4238  * @class The SpiderGL.WebGL.Shader is the base class for all WebGLShader object wrappers, i.e. {@link SpiderGL.WebGL.Shader} and {@link SpiderGL.WebGL.FragmentShader}.
4239  *
4240  * @augments SpiderGL.WebGL.ObjectGL
4241  *
4242  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
4243  * @param {number} target Not used.
4244  * @param {number} type WebGL shader type.
4245  * @param {object} [options] Optional parameters.
4246  * @param {WebGLShader} [options.handle] If defined, the provided shader will be wrapped and its source code will be queried to the rendering context. Otherwise an internal shader will be created.
4247  * @param {bool} [options.autoCompile=SpiderGL.WebGL.Shader.DEFAULT_AUTO_COMPILE] If true, the shader is automatically compiled whenever its source code changes.
4248  * @param {string} [options.source] Shader source code. If autoCompile is true, the shader will be automatically compiled.
4249  *
4250  * @see autoCompile
4251  * @see source
4252  * @see compile
4253  * @see SpiderGL.WebGL.VertexShader
4254  * @see SpiderGL.WebGL.FragmentShader
4255  * @see SpiderGL.WebGL.Program
4256  * @see SpiderGL.WebGL.ObjectGL
4257  */
4258 SpiderGL.WebGL.Shader = function (gl, target, type, options) {
4259 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
4260 
4261 	if (SpiderGL.Type.instanceOf(options, WebGLShader)) {
4262 		options = { handle : options };
4263 	}
4264 	else if (SpiderGL.Type.isString(options)) {
4265 		options = { source : options };
4266 	}
4267 
4268 	options = SpiderGL.Utility.getDefaultObject({
4269 		handle      : null,
4270 		source      : null,
4271 		autoCompile : SpiderGL.WebGL.Shader.DEFAULT_AUTO_COMPILE
4272 	}, options);
4273 
4274 	SpiderGL.WebGL.ObjectGL.call(this, gl, target, options);
4275 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
4276 
4277 	var gl  = this._gl;
4278 	var cb  = this._cb;
4279 	var dsa = this._dsa;
4280 
4281 	var source   = "";
4282 	var compiled = false;
4283 	var deleted  = false;
4284 	var log      = "";
4285 
4286 	var h = this._h;
4287 	if (h) {
4288 		source   = gl.getShaderSource(h);
4289 		if (!source) { source = ""; }
4290 		compiled = !!gl.getShaderParameter(h, gl.COMPILE_STATUS);
4291 		deleted  = !!gl.getShaderParameter(h, gl.DELETE_STATUS);
4292 		log      = gl.getShaderInfoLog(h);
4293 		if (!log) { log = ""; }
4294 	}
4295 	else {
4296 		h = gl.createShader(type);
4297 		this._h = h;
4298 	}
4299 	h._spidergl = this;
4300 
4301 	this._source      = source;
4302 	this._compiled    = compiled;
4303 	this._log         = log;
4304 	this._autoCompile = options.autoCompile;
4305 
4306 	if (options.source) { this.setSource(options.source); }
4307 }
4308 
4309 /**
4310  * Dummy WebGL target for shaders.
4311  *
4312  * It is equal to WebGLRenderingContext.NONE and is provided only for completeness with other WebGL wrappers.
4313  *
4314  * @type number
4315  *
4316  * @default WebGLRenderingContext.NONE
4317  */
4318 SpiderGL.WebGL.Shader.TARGET = WebGLRenderingContext.NONE;
4319 
4320 /**
4321  * Default value for SpiderGL.WebGL.Shader#autoCompile.
4322  *
4323  * @type bool
4324  *
4325  * @default true
4326  */
4327 SpiderGL.WebGL.Shader.DEFAULT_AUTO_COMPILE = true;
4328 
4329 /**
4330  * Dummy shader unbinding.
4331  *
4332  * This function does nothing and it is provided only for simmetry with other wrappers.
4333  *
4334  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
4335  */
4336 SpiderGL.WebGL.Shader.unbind = function (gl) { };
4337 
4338 SpiderGL.WebGL.Shader.prototype = {
4339 	_gl_deleteShader : function (shader) {
4340 		this._h = null;
4341 	},
4342 
4343 	_gl_isShader : function (shader) {
4344 	},
4345 
4346 	_gl_getShaderParameter : function (shader, pname) {
4347 	},
4348 
4349 	_gl_getShaderInfoLog : function (shader) {
4350 	},
4351 
4352 	_gl_getShaderSource : function (shader) {
4353 	},
4354 
4355 	_gl_compileShader : function (shader) {
4356 		this._postCompile();
4357 	},
4358 
4359 	_gl_shaderSource : function (shader, source) {
4360 		this._source = source;
4361 		if (!this._source) { this._source = ""; }
4362 	},
4363 
4364 	_postCompile : function () {
4365 		var gl = this._gl;
4366 		var h = this._h;
4367 		this._compiled = !!gl.getShaderParameter(h, gl.COMPILE_STATUS);
4368 		this._log      = gl.getShaderInfoLog(h);
4369 		if (!this._log) { this._log = ""; }
4370 	},
4371 
4372 	/*
4373 	get isEmpty () { return (this._source.length <= 0); },
4374 	*/
4375 
4376 	/**
4377 	 * Tests if the shader is ready to use.
4378 	 * A shader is considered ready if it is successfully compiled.
4379 	 *
4380 	 * @type bool
4381 	 *
4382 	 * @readonly
4383 	 *
4384 	 * @see isCompiled
4385 	 */
4386 	get isReady() {
4387 		return this.isCompiled;
4388 	},
4389 
4390 	/**
4391 	 * Tests if the shader is successfully compiled.
4392 	 *
4393 	 * @type bool
4394 	 *
4395 	 * @readonly
4396 	 *
4397 	 * @see isReady
4398 	 */
4399 	get isCompiled() {
4400 		return this._compiled;
4401 	},
4402 
4403 	/**
4404 	 * Gets the log output generated by the shader compiler.
4405 	 *
4406 	 * @type string
4407 	 *
4408 	 * @readonly
4409 	 *
4410 	 * @see compile
4411 	 */
4412 	get log() {
4413 		return this._log;
4414 	},
4415 
4416 	/**
4417 	 * Gets/Sets if the shader will be compiled automatically whenever the source code is changed.
4418 	 *
4419 	 * @type bool
4420 	 *
4421 	 * @see source
4422 	 * @see compile
4423 	 */
4424 	get autoCompile() {
4425 		return this._autoCompile;
4426 	},
4427 
4428 	set autoCompile(on) {
4429 		this._autoCompile = !!on;
4430 	},
4431 
4432 	/**
4433 	 * Sets the shader source code.
4434 	 * If compile is not specified and autoCompile is true, the shader is automatically compiled.
4435 	 *
4436 	 * @param {string} src The shader source code.
4437 	 * @param {bool} [compile] If specified, overrides the value of autoCompile.
4438 	 *
4439 	 * @see compile
4440 	 * @see autoCompile
4441 	 */
4442 	setSource : function (src, compile) {
4443 		var gl = this._gl;
4444 		var h = this._h;
4445 
4446 		gl.shaderSource(h, src);
4447 
4448 		var c = SpiderGL.Utility.getDefaultValue(compile, this._autoCompile);
4449 		if (!c) { true; }
4450 		return this.compile();
4451 	},
4452 
4453 	/**
4454 	 * Gets/Sets the shader source code.
4455 	 * If autoCompile is true, the shader is automatically compiled when the source code string is changed.
4456 	 *
4457 	 * @type string
4458 	 *
4459 	 * @see setSource
4460 	 * @see compile
4461 	 * @see autoCompile
4462 	 */
4463 	get source() {
4464 		return this._source;
4465 	},
4466 
4467 	set source(src) {
4468 		this.setSource(src);
4469 	},
4470 
4471 	/**
4472 	 * Compiles the shader.
4473 	 *
4474 	 * @returns {bool} True if the shader has been successfully compiled, false otherwise.
4475 	 *
4476 	 * @see source
4477 	 * @see autoCompile
4478 	 * @see log
4479 	 */
4480 	compile : function () {
4481 		this._gl.compileShader(this._h);
4482 		return this._compiled;
4483 	},
4484 
4485 	/**
4486 	 * Destroys the WebGLShader.
4487 	 * After destruction, the handle is set to null and this object should not be used anymore.
4488 	 *
4489 	 * @see SpiderGL.WebGL.ObjectGL#destroy
4490 	 */
4491 	destroy : function () {
4492 		this._gl.deleteShader(this._h);
4493 	},
4494 
4495 	/**
4496 	 * Dummy bind method.
4497 	 * It is provided for simmetry with other WebGL object wrappers.
4498 	 *
4499 	 * @see unbind
4500 	 */
4501 	bind : function () {
4502 	},
4503 
4504 	/**
4505 	 * Dummy unbind method.
4506 	 * It is provided for simmetry with other WebGL object wrappers.
4507 	 *
4508 	 * @see bind
4509 	 */
4510 	unbind : function () {
4511 	}
4512 };
4513 
4514 SpiderGL.Type.extend(SpiderGL.WebGL.Shader, SpiderGL.WebGL.ObjectGL);
4515 
4516 /**
4517  * Creates a SpiderGL.WebGL.VertexShader.
4518  *
4519  * SpiderGL.WebGL.VertexShader represents a wrapper for a WebGLShader whose type is type WebGLRenderingContext.VERTEX_SHADER.
4520  *
4521  * @class The SpiderGL.WebGL.VertexShader is a WebGLShader wrapper for vertex shaders.
4522  *
4523  * @augments SpiderGL.WebGL.Shader
4524  *
4525  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
4526  * @param {object} [options] See {@link SpiderGL.WebGL.Shader}.
4527  *
4528  * @see SpiderGL.WebGL.Shader
4529  * @see SpiderGL.WebGL.FragmentShader
4530  * @see SpiderGL.WebGL.Program
4531  * @see SpiderGL.WebGL.ObjectGL
4532  */
4533 SpiderGL.WebGL.VertexShader = function (gl, options) {
4534 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
4535 	SpiderGL.WebGL.Shader.call(this, gl, SpiderGL.WebGL.VertexShader.TARGET, gl.VERTEX_SHADER, options);
4536 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
4537 }
4538 
4539 /**
4540  * Dummy WebGL target for vertex shaders.
4541  *
4542  * It is equal to WebGLRenderingContext.NONE and is provided only for completeness with other WebGL wrappers.
4543  *
4544  * @type number
4545  *
4546  * @default WebGLRenderingContext.NONE
4547  */
4548 SpiderGL.WebGL.VertexShader.TARGET = WebGLRenderingContext.NONE;
4549 
4550 /**
4551  * Dummy vertex shader unbinding.
4552  *
4553  * This function does nothing and it is provided only for simmetry with other wrappers.
4554  *
4555  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
4556  */
4557 SpiderGL.WebGL.VertexShader.unbind = function (gl) { };
4558 
4559 SpiderGL.WebGL.VertexShader.prototype = { };
4560 
4561 SpiderGL.Type.extend(SpiderGL.WebGL.VertexShader, SpiderGL.WebGL.Shader);
4562 
4563 /**
4564  * Creates a SpiderGL.WebGL.FragmentShader.
4565  *
4566  * SpiderGL.WebGL.FragmentShader represents a wrapper for a WebGLShader whose type is type WebGLRenderingContext.FRAGMENT_SHADER.
4567  *
4568  * @class The SpiderGL.WebGL.FragmentShader is a WebGLShader wrapper for fragment shaders.
4569  *
4570  * @augments SpiderGL.WebGL.Shader
4571  *
4572  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
4573  * @param {object} [options] See {@link SpiderGL.WebGL.Shader}.
4574  *
4575  * @see SpiderGL.WebGL.Shader
4576  * @see SpiderGL.WebGL.VertexShader
4577  * @see SpiderGL.WebGL.Program
4578  * @see SpiderGL.WebGL.ObjectGL
4579  */
4580 SpiderGL.WebGL.FragmentShader = function (gl, options) {
4581 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
4582 	SpiderGL.WebGL.Shader.call(this, gl, SpiderGL.WebGL.FragmentShader.TARGET, gl.FRAGMENT_SHADER, options);
4583 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
4584 }
4585 
4586 /**
4587  * Dummy WebGL target for fragment shaders.
4588  *
4589  * It is equal to WebGLRenderingContext.NONE and is provided only for completeness with other WebGL wrappers.
4590  *
4591  * @type number
4592  *
4593  * @default WebGLRenderingContext.NONE
4594  */
4595 SpiderGL.WebGL.FragmentShader.TARGET = WebGLRenderingContext.NONE;
4596 
4597 /**
4598  * Dummy fragment shader unbinding.
4599  *
4600  * This function does nothing and it is provided only for simmetry with other wrappers.
4601  *
4602  * @param  {WebGLRenderingContext} gl A WebGLRenderingContext.
4603  */
4604 SpiderGL.WebGL.FragmentShader.unbind = function (gl) { };
4605 
4606 SpiderGL.WebGL.FragmentShader.prototype = { };
4607 
4608 SpiderGL.Type.extend(SpiderGL.WebGL.FragmentShader, SpiderGL.WebGL.Shader);
4609 
4610 /**
4611  * Creates a SpiderGL.WebGL.Texture.
4612  *
4613  * SpiderGL.WebGL.Texture is the base class for WebGLTexture object wrappers ({@link SpiderGL.WebGL.Texture2D} and {@link SpiderGL.WebGL.TextureCubeMap}) and must not be directly used.
4614  *
4615  * @class The SpiderGL.WebGL.Texture is the base class for all WebGLTexture object wrappers, i.e. {@link SpiderGL.WebGL.Texture2D} and {@link SpiderGL.WebGL.TextureCubeMap}.
4616  *
4617  * @augments SpiderGL.WebGL.ObjectGL
4618  *
4619  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
4620  * @param {number} target Texture-specific target.
4621  * @param {object} [options] Optional parameters.
4622  * @param {WebGLTexture} [options.handle] If defined, the provided texture will be wrapped and its sampling parameters will be queried to the rendering context; as texture image base level width and height can not be retrieved, they should be specified with the width and height optional parameters. If handle is not specified, an internal texture will be created.
4623  * @param {string|array} [options.url] The url of the texture image to load. It has precedence over the data optional parameter. For SpiderGL.Texture.Texture2D, url is a string. For SpiderGL.Texture.TextureCubeMap, url is an array of six strings, one for each cube map face, in the order [+X, -X, +Y, -Y, +Z, -Z].
4624  * @param {ArrayBuffer|ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [options.data] The texture image pixel data.
4625  * @param {number} [options.internalFormat=SpiderGL.WebGL.Texture.DEFAULT_INTERNAL_FORMAT] The texture internal format.
4626  * @param {number} [options.width] If data is null or a typed array, specifies the texture image width. If handle is provided, the width parameter will supply the width information, not querable to the WebGLRenderingContext.
4627  * @param {number} [options.height] If data is null or a typed array, specifies the texture image height. If handle is provided, the width parameter will supply the height information, not querable to the WebGLRenderingContext.
4628  * @param {number} [options.border=SpiderGL.WebGL.Texture.DEFAULT_BORDER] Texture border.
4629  * @param {number} [options.format=SpiderGL.WebGL.Texture.DEFAULT_FORMAT] The format parameter used for WebGLRenderingContext.texImage2D.
4630  * @param {number} [options.type=SpiderGL.WebGL.Texture.DEFAULT_TYPE] The type parameter used for WebGLRenderingContext.texImage2D.
4631  * @param {number} [options.magFilter=SpiderGL.WebGL.Texture.DEFAULT_MAG_FILTER] Texture magnification filter (see {@link SpiderGL.WebGL.Texture#magFilter}).
4632  * @param {number} [options.minFilter=SpiderGL.WebGL.Texture.DEFAULT_MIN_FILTER] Texture minnification filter (see {@link SpiderGL.WebGL.Texture#minFilter}).
4633  * @param {number} [options.wrapS=SpiderGL.WebGL.Texture.DEFAULT_WRAP_S] Texture horizontal wrap mode (see {@link SpiderGL.WebGL.Texture#wrapS}).
4634  * @param {number} [options.wrapT=SpiderGL.WebGL.Texture.DEFAULT_WRAP_T] Texture vertical wrap mode (see {@link SpiderGL.WebGL.Texture#wrapT}).
4635  * @param {bool} [options.autoMipmap=SpiderGL.WebGL.Texture.DEFAULT_AUTO_GENERATE_MIPMAP] If true, mipmaps are automatically generated when calling setImage or setSubImage (see {@link SpiderGL.WebGL.Texture#autoMipmap}).
4636  * @param {bool} [options.generateMipmap] If specified, overrides autoMipmap for this call.
4637  * @param {bool} [options.flipYPolicy=SpiderGL.WebGL.Texture.DEFAULT_UNPACK_FLIP_Y] WebGL unpack flip Y policy (see SpiderGL.WebGL.Texture#flipYPolicy).
4638  * @param {bool} [options.flipY] If specified, overrides flipYPolicy for this call.
4639  * @param {bool} [options.premultiplyAlphaPolicy=SpiderGL.WebGL.Texture.DEFAULT_UNPACK_PREMULTIPLY_ALPHA] WebGL unpack premultiply alpha policy (see SpiderGL.WebGL.Texture#premultiplyAlphaPolicy).
4640  * @param {bool} [options.premultiplyAlpha] If specified, overrides premultiplyAlphaPolicy for this call.
4641  * @param {number} [options.colorspaceConversionPolicy=SpiderGL.WebGL.Texture.DEFAULT_UNPACK_COLORSPACE_CONVERSION] WebGL unpack colorspace conversion policy (see SpiderGL.WebGL.Texture#colorspaceConversionPolicy).
4642  * @param {number} [options.colorspaceConversion] If specified, overrides colorspaceConversionPolicy for this call.
4643  * @param {function} [options.onCancel] If url is specified, this function will be called if image data loading is cancelled.
4644  * @param {function} [options.onError] If url is specified, this function will be called if an error occurs when loading image data.
4645  * @param {function} [options.onProgress] If url is specified, this function will be called during the image loading progress.
4646  * @param {function} [options.onSuccess] If url is specified, this function will be called when image data has been successfully loaded.
4647  *
4648  * @example
4649  * var tex1 = new SpiderGL.WebGL.Texture2D(gl, {
4650  * 	internalFormat : gl.RGBA,              // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_INTERNAL_FORMAT
4651  * 	width          : 256,
4652  * 	height         : 128,
4653  * 	border         : 0,                    // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_BORDER
4654  * 	format         : gl.RGBA,              // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_FORMAT
4655  * 	type           : gl.UNSIGNED_BYTE,     // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_TYPE
4656  * 	data           : new Uint8Array(...),  // if omitted or null, the texture is initialized to zero by the WebGLRenderingContext
4657  * 	magFilter      : gl.LINEAR,            // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_MAG_FILTER
4658  * 	minFilter      : gl.LINEAR,            // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_MIN_FILTER
4659  * 	wrapS          : gl.CLAMP_TO_EDGE,     // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_WRAP_S
4660  * 	wrapT          : gl.CLAMP_TO_EDGE,     // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_WRAP_T
4661  * 	autoMipmap     : true,                 // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_AUTO_GENERATE_MIPMAP
4662  * 	generateMipmap : false,                // if specified, overrides autoMipmap for this implicit call to setImage
4663  * 	flipYPolicy                : true,     // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_UNPACK_FLIP_Y
4664  * 	flipY                      : false,    // if specified, overrides flipYPolicy for this implicit call to setImage
4665  * 	premultiplyAlphaPolicy     : true,     // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_UNPACK_PREMULTIPLY_ALPHA
4666  * 	premultiplyAlpha           : false,    // if specified, overrides premultiplyAlphaPolicy for this implicit call to setImage
4667  * 	colorspaceConversionPolicy : true,     // if omitted, defaults to SpiderGL.WebGL.Texture.DEFAULT_UNPACK_COLORSPACE_CONVERSION
4668  * 	colorspaceConversion       : false     // if specified, overrides colorspaceConversionPolicy for this implicit call to setImage
4669  * });
4670  *
4671  * var tex2 = new SpiderGL.WebGL.TextureCubeMap(gl, {
4672  * 	url : [
4673  * 		http://someurl.org/cubemap_pos_x.png,
4674  * 		http://someurl.org/cubemap_neg_x.png,
4675  * 		http://someurl.org/cubemap_pos_y.png,
4676  * 		http://someurl.org/cubemap_neg_y.png,
4677  * 		http://someurl.org/cubemap_pos_z.png,
4678  * 		http://someurl.org/cubemap_neg_z.png
4679  * 	],
4680  * 	onCancel   : function () { ... },
4681  * 	onError    : function () { ... },
4682  * 	onProgress : function () { ... },
4683  * 	onLoad     : function () { ... },
4684  * 	wrapS      : gl.REPEAT,
4685  * 	magFilter  : gl.NEAREST
4686  * });
4687  *
4688  * @see SpiderGL.WebGL.Texture2D
4689  * @see SpiderGL.WebGL.TextureCubeMap
4690  * @see SpiderGL.WebGL.Framebuffer
4691  * @see SpiderGL.WebGL.ObjectGL
4692  */
4693 SpiderGL.WebGL.Texture = function (gl, target, options) {
4694 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
4695 
4696 	if (SpiderGL.Type.instanceOf(options, WebGLTexture)) {
4697 		options = { handle : options };
4698 	}
4699 	else if (SpiderGL.Type.isString(options)) {
4700 		options = { url : options };
4701 	}
4702 
4703 	options = SpiderGL.Utility.getDefaultObject({
4704 		handle                     : null,
4705 		magFilter                  : SpiderGL.WebGL.Texture.DEFAULT_MAG_FILTER,
4706 		minFilter                  : SpiderGL.WebGL.Texture.DEFAULT_MIN_FILTER,
4707 		wrapS                      : SpiderGL.WebGL.Texture.DEFAULT_WRAP_S,
4708 		wrapT                      : SpiderGL.WebGL.Texture.DEFAULT_WRAP_T,
4709 		flipYPolicy                : SpiderGL.WebGL.Context.DEFAULT_UNPACK_FLIP_Y,
4710 		premultiplyAlphaPolicy     : SpiderGL.WebGL.Context.DEFAULT_UNPACK_PREMULTIPLY_ALPHA,
4711 		colorspaceConversionPolicy : SpiderGL.WebGL.Context.DEFAULT_UNPACK_COLORSPACE_CONVERSION,
4712 		autoMipmap                 : SpiderGL.WebGL.Texture.DEFAULT_AUTO_GENERATE_MIPMAP,
4713 		format                     : gl.NONE,
4714 		width                      : 0,
4715 		height                     : 0
4716 	}, options);
4717 
4718 	SpiderGL.WebGL.ObjectGL.call(this, gl, target, options);
4719 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
4720 
4721 	var gl  = this._gl;
4722 	var cb  = this._cb;
4723 	var dsa = this._dsa;
4724 
4725 	var t = this._t;
4726 	var h = this._h;
4727 
4728 	if (!h) {
4729 		h = gl.createTexture();
4730 		this._h = h;
4731 	}
4732 
4733 	cb.pushTexture(t);
4734 	gl.bindTexture(t, h);
4735 	this._magFilter = gl.getTexParameter(t, gl.TEXTURE_MAG_FILTER);
4736 	this._minFilter = gl.getTexParameter(t, gl.TEXTURE_MIN_FILTER);
4737 	this._wrapS     = gl.getTexParameter(t, gl.TEXTURE_WRAP_S);
4738 	this._wrapT     = gl.getTexParameter(t, gl.TEXTURE_WRAP_T);
4739 	cb.popTexture(t);
4740 	h._spidergl = this;
4741 
4742 	this._format               = options.format;
4743 	this._width                = options.width;
4744 	this._height               = options.height;
4745 	this._flipY                = options.flipYPolicy;
4746 	this._premultiplyAlpha     = options.premultiplyAlphaPolicy;
4747 	this._colorspaceConversion = options.colorspaceConversionPolicy;
4748 	this._autoMipmap           = options.autoMipmap;
4749 
4750 	this._missingFaces = SpiderGL.WebGL.Texture._FACE_ALL_BITS;
4751 
4752 	this.setSampler(options);
4753 }
4754 
4755 SpiderGL.WebGL.Texture.TARGET = WebGLRenderingContext.NONE;
4756 
4757 /**
4758  * Default texture border when calling setImage
4759  *
4760  * @type number
4761  *
4762  * @default 0
4763  */
4764 SpiderGL.WebGL.Texture.DEFAULT_BORDER = 0;
4765 
4766 /**
4767  * Default texture input data format when calling setImage or setSubImage.
4768  *
4769  * @type number
4770  *
4771  * @default WebGLRenderingContext.RGBA
4772  */
4773 SpiderGL.WebGL.Texture.DEFAULT_FORMAT = WebGLRenderingContext.RGBA;
4774 
4775 /**
4776  * Default value for SpiderGL.WebGL.Texture#autoMipmap
4777  *
4778  * @type bool
4779  *
4780  * @default false
4781  */
4782 SpiderGL.WebGL.Texture.DEFAULT_AUTO_GENERATE_MIPMAP = false;
4783 
4784 /**
4785  * Default texture internal format when calling setImage.
4786  *
4787  * @type number
4788  *
4789  * @default WebGLRenderingContext.RGBA
4790  */
4791 SpiderGL.WebGL.Texture.DEFAULT_INTERNAL_FORMAT = WebGLRenderingContext.RGBA;
4792 
4793 /**
4794  * Default texture level when calling setImage.
4795  *
4796  * @type number
4797  *
4798  * @default 0
4799  */
4800 SpiderGL.WebGL.Texture.DEFAULT_LEVEL = 0;
4801 
4802 /**
4803  * Default texture magnification filter.
4804  *
4805  * @type number
4806  *
4807  * @default WebGLRenderingContext.LINEAR
4808  */
4809 SpiderGL.WebGL.Texture.DEFAULT_MAG_FILTER = WebGLRenderingContext.LINEAR;
4810 
4811 /**
4812  * Default texture minification filter.
4813  *
4814  * @type number
4815  *
4816  * @default WebGLRenderingContext.LINEAR
4817  */
4818 SpiderGL.WebGL.Texture.DEFAULT_MIN_FILTER = WebGLRenderingContext.LINEAR;
4819 
4820 /**
4821  * Default texture input data type when calling setImage or setSubImage.
4822  *
4823  * @type number
4824  *
4825  * @default WebGLRenderingContext.UNSIGNED_BYTE
4826  */
4827 SpiderGL.WebGL.Texture.DEFAULT_TYPE = WebGLRenderingContext.UNSIGNED_BYTE;
4828 
4829 /**
4830  * Default texture wrap mode in horizontal direction.
4831  *
4832  * @type number
4833  *
4834  * @default WebGLRenderingContext.REPEAT
4835  */
4836 SpiderGL.WebGL.Texture.DEFAULT_WRAP_S = WebGLRenderingContext.REPEAT;
4837 
4838 /**
4839  * Default texture wrap mode in vertical direction.
4840  *
4841  * @type number
4842  *
4843  * @default WebGLRenderingContext.REPEAT
4844  */
4845 SpiderGL.WebGL.Texture.DEFAULT_WRAP_T = WebGLRenderingContext.REPEAT;
4846 
4847 /**
4848  * Default texture sub-image x offset when calling setSubImage.
4849  *
4850  * @type number
4851  *
4852  * @default 0
4853  */
4854 SpiderGL.WebGL.Texture.DEFAULT_X_OFFSET = 0;
4855 
4856 /**
4857  * Default texture sub-image y offset when calling setSubImage.
4858  *
4859  * @type number
4860  *
4861  * @default 0
4862  */
4863 SpiderGL.WebGL.Texture.DEFAULT_Y_OFFSET = 0;
4864 
4865 /**
4866  * Default value for pixel unpack parameter WebGLRenderingContext.UNPACK_FLIP_Y_WEBGL when calling setImage or setSubImage.
4867  *
4868  * @default true
4869  *
4870  * @see SpiderGL.WebGL.Texture.DEFAULT_UNPACK_PREMULTIPLY_ALPHA
4871  * @see SpiderGL.WebGL.Texture.DEFAULT_UNPACK_COLORSPACE_CONVERSION
4872  */
4873 SpiderGL.WebGL.Texture.DEFAULT_UNPACK_FLIP_Y = true;
4874 
4875 /**
4876  * Default value for pixel unpack parameter WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL when calling setImage or setSubImage.
4877  *
4878  * @default true
4879  *
4880  * @see SpiderGL.WebGL.Texture.DEFAULT_UNPACK_FLIP_Y
4881  * @see SpiderGL.WebGL.Texture.DEFAULT_UNPACK_COLORSPACE_CONVERSION
4882  */
4883 SpiderGL.WebGL.Texture.DEFAULT_UNPACK_PREMULTIPLY_ALPHA = false;
4884 
4885 /**
4886  * Default value for pixel unpack parameter WebGLRenderingContext.UNPACK_COLORSPACE_CONVERSION_WEBGL when calling setImage or setSubImage.
4887  *
4888  * @default WebGLRenderingContext.NONE
4889  *
4890  * @see SpiderGL.WebGL.Texture.DEFAULT_UNPACK_FLIP_Y
4891  * @see SpiderGL.WebGL.Texture.DEFAULT_UNPACK_PREMULTIPLY_ALPHA
4892  */
4893 SpiderGL.WebGL.Texture.DEFAULT_UNPACK_COLORSPACE_CONVERSION = WebGLRenderingContext.NONE;
4894 
4895 SpiderGL.WebGL.Texture.unbind = function (gl) { };
4896 
4897 SpiderGL.WebGL.Texture._FACE_POSITIVE_X_BIT = (1 << 0);
4898 SpiderGL.WebGL.Texture._FACE_NEGATIVE_X_BIT = (1 << 1);
4899 SpiderGL.WebGL.Texture._FACE_POSITIVE_Y_BIT = (1 << 2);
4900 SpiderGL.WebGL.Texture._FACE_NEGATIVE_Y_BIT = (1 << 3);
4901 SpiderGL.WebGL.Texture._FACE_POSITIVE_Z_BIT = (1 << 4);
4902 SpiderGL.WebGL.Texture._FACE_NEGATIVE_Z_BIT = (1 << 5);
4903 SpiderGL.WebGL.Texture._FACE_ALL_BITS       = (SpiderGL.WebGL.Texture._FACE_POSITIVE_X_BIT | SpiderGL.WebGL.Texture._FACE_NEGATIVE_X_BIT | SpiderGL.WebGL.Texture._FACE_POSITIVE_Y_BIT | SpiderGL.WebGL.Texture._FACE_NEGATIVE_Y_BIT | SpiderGL.WebGL.Texture._FACE_POSITIVE_Z_BIT | SpiderGL.WebGL.Texture._FACE_NEGATIVE_Z_BIT);
4904 
4905 SpiderGL.WebGL.Texture._faceBits = { };
4906 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_2D                 ] = SpiderGL.WebGL.Texture._FACE_ALL_BITS;
4907 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP           ] = SpiderGL.WebGL.Texture._FACE_ALL_BITS;
4908 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_X] = SpiderGL.WebGL.Texture._FACE_POSITIVE_X_BIT;
4909 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_X] = SpiderGL.WebGL.Texture._FACE_NEGATIVE_X_BIT;
4910 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Y] = SpiderGL.WebGL.Texture._FACE_POSITIVE_Y_BIT;
4911 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Y] = SpiderGL.WebGL.Texture._FACE_NEGATIVE_Y_BIT;
4912 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Z] = SpiderGL.WebGL.Texture._FACE_POSITIVE_Z_BIT;
4913 SpiderGL.WebGL.Texture._faceBits[WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Z] = SpiderGL.WebGL.Texture._FACE_NEGATIVE_Z_BIT;
4914 
4915 SpiderGL.WebGL.Texture.prototype = {
4916 	_gl_deleteTexture : function (texture) {
4917 		this._h = null;
4918 	},
4919 
4920 	_gl_isTexture : function (texture) {
4921 	},
4922 
4923 	_gl_bindTexture : function (target, texture) {
4924 	},
4925 
4926 	_gl_getTexParameter : function (target, pname) {
4927 	},
4928 
4929 	_gl_copyTexImage2D : function (target, level, internalformat, x, y, width, height, border) {
4930 		if (level == 0) {
4931 			this._format = internalformat;
4932 			this._width  = width;
4933 			this._height = height;
4934 		}
4935 	},
4936 
4937 	_gl_copyTexSubImage2D : function (target, level, xoffset, yoffset, x, y, width, height, border) {
4938 	},
4939 
4940 	_gl_generateMipmap : function (target) {
4941 	},
4942 
4943 	_gl_texImage2D : function (target) {
4944 		var n = arguments.length;
4945 		if (n === 6) {
4946 			if (arguments[1] === 0) {
4947 				this._format = arguments[2];
4948 				this._width  = arguments[5].width;
4949 				this._height = arguments[5].height;
4950 			}
4951 		}
4952 		else if (n === 9) {
4953 			if (arguments[1] === 0) {
4954 				this._format = arguments[2];
4955 				this._width  = arguments[3];
4956 				this._height = arguments[4];
4957 			}
4958 		}
4959 	},
4960 
4961 	_gl_texParameterf : function (target, pname, param) {
4962 		this._setTexParameter(pname, param);
4963 	},
4964 
4965 	_gl_texParameteri : function (target, pname, param) {
4966 		this._setTexParameter(pname, param);
4967 	},
4968 
4969 	_gl_texSubImage2D : function (target) {
4970 	},
4971 
4972 	_setTexParameter : function (pname, param) {
4973 		var gl = this._gl;
4974 
4975 		switch (pname) {
4976 			case gl.TEXTURE_MAG_FILTER : this._magFilter = param; break;
4977 			case gl.TEXTURE_MIN_FILTER : this._minFilter = param; break;
4978 			case gl.TEXTURE_WRAP_S     : this._wrapS     = param; break;
4979 			case gl.TEXTURE_WRAP_T     : this._wrapT     = param; break;
4980 			default : break;
4981 		}
4982 	},
4983 
4984 	_setImageData : function (fullImage, target, options) {
4985 		options = SpiderGL.Utility.getDefaultObject({
4986 			internalFormat       : SpiderGL.WebGL.Texture.DEFAULT_INTERNAL_FORMAT,
4987 			border               : SpiderGL.WebGL.Texture.DEFAULT_BORDER,
4988 			xoffset              : SpiderGL.WebGL.Texture.DEFAULT_X_OFFSET,
4989 			yoffset              : SpiderGL.WebGL.Texture.DEFAULT_Y_OFFSET,
4990 			level                : SpiderGL.WebGL.Texture.DEFAULT_LEVEL,
4991 			format               : SpiderGL.WebGL.Texture.DEFAULT_FORMAT,
4992 			type                 : SpiderGL.WebGL.Texture.DEFAULT_TYPE,
4993 			width                : 0,
4994 			height               : 0,
4995 			generateMipmap       : this._autoMipmap,
4996 			flipY                : this._flipY,
4997 			premultiplyAlpha     : this._premultiplyAlpha,
4998 			colorspaceConversion : this._colorspaceConversion,
4999 			data                 : null,
5000 			url                  : null,
5001 			onCancel             : null,
5002 			onError              : null,
5003 			onProgress           : null,
5004 			onSuccess            : null
5005 		}, options);
5006 
5007 		var isURL     = !!options.url;
5008 		var isData    = false;
5009 		if (!isURL) { isData = (!options.data || SpiderGL.Type.isTypedArray(options.data)); /* (!options.data || SpiderGL.Type.instanceOf(options.data, ArrayBufferView)) */ }
5010 		var isElement = false;
5011 		if (!isURL && !isData) {
5012 			// [WORKAROUND]
5013 			// Firefox does not define ImageData
5014 			// /* correct */ isElement = (SpiderGL.Type.instanceOf(data, ImageData) || SpiderGL.Type.instanceOf(data, HTMLImageElement) || SpiderGL.Type.instanceOf(data, HTMLCanvasElement) || SpiderGL.Type.instanceOf(data, HTMLVideoElement));
5015 			isElement = (SpiderGL.Type.instanceOf(options.data, HTMLImageElement) || SpiderGL.Type.instanceOf(options.data, HTMLCanvasElement) || SpiderGL.Type.instanceOf(options.data, HTMLVideoElement));
5016 			if (!isElement) {
5017 				if (typeof ImageData != "undefined") {
5018 					isElement = SpiderGL.Type.instanceOf(options.data, ImageData);
5019 				}
5020 			}
5021 		}
5022 
5023 		var gl  = this._gl;
5024 		var cb  = this._cb;
5025 		var dsa = this._dsa;
5026 
5027 		var t = target;
5028 		var h = this._h;
5029 
5030 		var userFlipY                = -1;
5031 		var flipY                    = -1;
5032 		var userPremultiplyAlpha     = -1;
5033 		var premultiplyAlpha         = -1;
5034 		var userColorspaceConversion = -1;
5035 		var colorspaceConversion     = -1;
5036 
5037 		if (isData || isElement) {
5038 			userFlipY = options.flipY;
5039 			if (userFlipY != SpiderGL.Core.DONT_CARE) {
5040 				flipY = gl.getParameter(gl.UNPACK_FLIP_Y_WEBGL);
5041 				if (userFlipY == flipY) { flipY = -1; }
5042 				else { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, userFlipY); }
5043 			}
5044 
5045 			userPremultiplyAlpha = options.premultiplyAlpha;
5046 			if (userPremultiplyAlpha != SpiderGL.Core.DONT_CARE) {
5047 				premultiplyAlpha = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL);
5048 				if (userPremultiplyAlpha == premultiplyAlpha) { premultiplyAlpha = -1; }
5049 				else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, userPremultiplyAlpha); }
5050 			}
5051 
5052 			userColorspaceConversion = options.colorspaceConversion;
5053 			if (userColorspaceConversion != SpiderGL.Core.DONT_CARE) {
5054 				colorspaceConversion = gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL);
5055 				if (userColorspaceConversion == colorspaceConversion) { colorspaceConversion = -1; }
5056 				else { gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, userColorspaceConversion); }
5057 			}
5058 		}
5059 
5060 		var imageUpdated = false;
5061 
5062 		if (isURL) {
5063 			var opts = {
5064 				internalFormat       : options.internalFormat,
5065 				border               : options.border,
5066 				xoffset              : options.xoffset,
5067 				yoffset              : options.yoffset,
5068 				level                : options.level,
5069 				format               : options.format,
5070 				type                 : options.type,
5071 				generateMipmap       : options.generateMipmap,
5072 				flipY                : options.flipY,
5073 				premultiplyAlpha     : options.premultiplyAlpha,
5074 				colorspaceConversion : options.colorspaceConversion,
5075 				data                 : null
5076 			};
5077 
5078 			var that = this;
5079 			var onSuccess = options.onSuccess;
5080 
5081 			var req = new SpiderGL.IO.ImageRequest(options.url, {
5082 				onCancel   : options.onCancel,
5083 				onError    : options.onError,
5084 				onProgress : options.onProgress,
5085 				onSuccess  : function () {
5086 					opts.data = req.image;
5087 					if (fullImage) {
5088 						that._setImage(target, opts);
5089 					}
5090 					else {
5091 						that._setSubImage(target, opts);
5092 					}
5093 					if (onSuccess) { onSuccess(); }
5094 				},
5095 				send : true
5096 			});
5097 
5098 			return true;
5099 		}
5100 		else if (isData) {
5101 			if ((options.width <= 0) || (options.height <= 0)) { return false; }
5102 			if (fullImage) {
5103 				dsa.texImage2D(h, t, options.level, options.internalFormat, options.width, options.height, options.border, options.format, options.type, options.data);
5104 				imageUpdated = true;
5105 			}
5106 			else {
5107 				dsa.texSubImage2D(h, t, options.level, options.xoffset, options.yoffset, options.width, options.height, options.format, options.type, options.data);
5108 			}
5109 		}
5110 		else if (isElement) {
5111 			if (fullImage) {
5112 				dsa.texImage2D(h, t, options.level, options.internalFormat, options.format, options.type, options.data);
5113 				imageUpdated = true;
5114 			}
5115 			else {
5116 				dsa.texSubImage2D(h, t, options.level, options.xoffset, options.yoffset, options.format, options.type, options.data);
5117 			}
5118 		}
5119 		else {
5120 			return false;
5121 		}
5122 
5123 		if (imageUpdated) {
5124 			this._missingFaces &= ~(SpiderGL.WebGL.Texture._faceBits[t]);
5125 		}
5126 
5127 		if (isData || isElement) {
5128 			if (flipY                != -1) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,                flipY);                }
5129 			if (premultiplyAlpha     != -1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,     premultiplyAlpha);     }
5130 			if (colorspaceConversion != -1) { gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, colorspaceConversion); }
5131 		}
5132 
5133 		if (options.generateMipmap) {
5134 			this.generateMipmap();
5135 		}
5136 
5137 		return true;
5138 	},
5139 
5140 	_setImage : function (target, options) {
5141 		return this._setImageData(true, target, options);
5142 	},
5143 
5144 	_setSubImage : function (target, options) {
5145 		return this._setImageData(false, target, options);
5146 	},
5147 
5148 	/*
5149 	get isEmpty () { return ((this._width <= 0) || (this._height <= 0)); },
5150 	*/
5151 
5152 	/**
5153 	 * Tests if the texture is ready to use.
5154 	 * A texture is considered ready if all its associated images (one for 2D textures, six for cube maps) have width and height greater than zero.
5155 	 *
5156 	 * @type bool
5157 	 *
5158 	 * @readonly
5159 	 */
5160 	get isReady() {
5161 		return ((this._missingFaces == 0) && (this._width > 0) && (this._height > 0));
5162 	},
5163 
5164 	/**
5165 	 * Gets/Sets the flip Y policy.
5166 	 * It specifies the image data vertical flipping policy when unpacking pixel data in setData or setSubData.
5167 	 * If set to true, the WebGL pixel unpack parameter WebGLRenderingContext.UNPACK_FLIP_Y will be set to true
5168 	 * If set to false, the WebGL pixel unpack parameter WebGLRenderingContext.UNPACK_FLIP_Y will be set to false 
5169 	 * In either case, the unpack parameter will be restored.
5170 	 * If set to SpiderGL.Core.DONT_CARE, the current WebGLRenderingContext setting will be used (i.e. nothing will be changed).
5171 	 *
5172 	 * @type bool
5173 	 *
5174 	 * @default SpiderGL.WebGL.Context.DEFAULT_UNPACK_FLIP_Y
5175 	 */
5176 	get flipYPolicy() {
5177 		return this._flipY;
5178 	},
5179 
5180 	set flipYPolicy(x) {
5181 		this._flipY = SpiderGL.Utility.getDefaultValue(x, SpiderGL.WebGL.Context.DEFAULT_UNPACK_FLIP_Y);
5182 	},
5183 
5184 	/**
5185 	 * Gets/Sets the premultiply alpha policy.
5186 	 * It specifies the image data premultiply alpha policy when unpacking pixel data in setData or setSubData.
5187 	 * If set to true, the WebGL pixel unpack parameter WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA will be set to true
5188 	 * If set to false, the WebGL pixel unpack parameter WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA will be set to false 
5189 	 * In either case, the unpack parameter will be restored after image data has been set
5190 	 * If set to SpiderGL.Core.DONT_CARE, the current WebGLRenderingContext setting will be used (i.e. nothing will be changed).
5191 	 *
5192 	 * @type bool
5193 	 *
5194 	 * @default SpiderGL.WebGL.Context.DEFAULT_UNPACK_PREMULTIPLY_ALPHA
5195 	 */
5196 	get premultuplyAlphaPolicy() {
5197 		return this._premultuplyAlpha;
5198 	},
5199 
5200 	set premultuplyAlphaPolicy(x) {
5201 		this._premultuplyAlpha = SpiderGL.Utility.getDefaultValue(x, SpiderGL.WebGL.Context.DEFAULT_UNPACK_PREMULTIPLY_ALPHA);
5202 	},
5203 
5204 	/**
5205 	 * Gets/Sets the colorspace conversionpolicy.
5206 	 * It specifies the image data colorpsce conversion policy when unpacking pixel data in setData or setSubData.
5207 	 * If set to SpiderGL.Core.DONT_CARE, the current WebGLRenderingContext setting will be used (i.e. nothing will be changed).
5208 	 * Otherwise, the specified value will be used and then restored after image data has been set.
5209 	 *
5210 	 * @type number
5211 	 *
5212 	 * @default SpiderGL.WebGL.Context.DEFAULT_UNPACK_COLORSPACE_CONVERSION
5213 	 */
5214 	get colorspaceConversionPolicy() {
5215 		return this._colorspaceConversion;
5216 	},
5217 
5218 	set colorspaceConversionPolicy(x) {
5219 		this._colorspaceConversion = SpiderGL.Utility.getDefaultValue(x, SpiderGL.WebGL.Context.DEFAULT_UNPACK_COLORSPACE_CONVERSION);
5220 	},
5221 
5222 	/**
5223 	 * Gets/Sets the automatic mipmap generation.
5224 	 *
5225 	 * @type bool
5226 	 *
5227 	 * @default SpiderGL.WebGL.Texture.DEFAULT_AUTO_GENERATE_MIPMAP
5228 	 */
5229 	get autoMipmap() {
5230 		return this._autoMipmap;
5231 	},
5232 
5233 	set autoMipmap(on) {
5234 		this._autoMipmap = on;
5235 	},
5236 
5237 	/**
5238 	 * Gets the texture image internal format.
5239 	 *
5240 	 * @type number
5241 	 *
5242 	 * @readonly
5243 	 */
5244 	get format() {
5245 		return this._format;
5246 	},
5247 
5248 	/**
5249 	 * Gets the texture image width.
5250 	 *
5251 	 * @type number
5252 	 *
5253 	 * @readonly
5254 	 */
5255 	get width() {
5256 		return this._width;
5257 	},
5258 
5259 	/**
5260 	 * Gets the texture image height.
5261 	 *
5262 	 * @type number
5263 	 *
5264 	 * @readonly
5265 	 */
5266 	get height() {
5267 		return this._height;
5268 	},
5269 
5270 	/**
5271 	 * Gets/Sets the texture magnification filter.
5272 	 *
5273 	 * @type number
5274 	 */
5275 	get magFilter() {
5276 		return this._magFilter;
5277 	},
5278 
5279 	set magFilter(f) {
5280 		f = SpiderGL.Utility.getDefaultValue(w, SpiderGL.WebGL.Texture.DEFAULT_MAG_FILTER);
5281 		this._dsa.texParameteri(this._h, this._t, gl.TEXTURE_MAG_FILTER, f);
5282 	},
5283 
5284 	/**
5285 	 * Gets/Sets the texture minification filter.
5286 	 *
5287 	 * @type number
5288 	 */
5289 	get minFilter() {
5290 		return this._minFilter;
5291 	},
5292 
5293 	set minFilter (f) {
5294 		f = SpiderGL.Utility.getDefaultValue(w, SpiderGL.WebGL.Texture.DEFAULT_MIN_FILTER);
5295 		this._dsa.texParameteri(this._h, this._t, gl.TEXTURE_MIN_FILTER, f);
5296 	},
5297 
5298 	/**
5299 	 * Gets/Sets the texture horizontal wrap mode.
5300 	 *
5301 	 * @type number
5302 	 */
5303 	get wrapS() {
5304 		return this._wrapS;
5305 	},
5306 
5307 	set wrapS(w) {
5308 		w = SpiderGL.Utility.getDefaultValue(w, SpiderGL.WebGL.Texture.DEFAULT_WRAP_S);
5309 		this._dsa.texParameteri(this._h, this._t, gl.TEXTURE_WRAP_S, w);
5310 	},
5311 
5312 	/**
5313 	 * Gets/Sets the texture vertical wrap mode.
5314 	 *
5315 	 * @type number
5316 	 */
5317 	get wrapT() {
5318 		return this._wrapT;
5319 	},
5320 
5321 	set wrapT(w) {
5322 		w = SpiderGL.Utility.getDefaultValue(w, SpiderGL.WebGL.Texture.DEFAULT_WRAP_T);
5323 		this._dsa.texParameteri(this._h, this._t, gl.TEXTURE_WRAP_T, w);
5324 	},
5325 
5326 	/**
5327 	 * Sets the texture sampling (filtering and addressing) mode.
5328 	 * It is a utility function to specify the addressing and filtering parameters at once.
5329 	 * Only the specified properties will be changed.
5330 	 * To restore the default value, specify the property with value SpiderGL.Core.DEFAULT.
5331 	 *
5332 	 * @param {object} sampler The sampling options.
5333 	 * @param {number} [sampler.magFilter] Texture magnification filter (see {@link SpiderGL.WebGL.Texture#magFilter}).
5334 	 * @param {number} [sampler.minFilter] Texture minnification filter (see {@link SpiderGL.WebGL.Texture#minFilter}).
5335 	 * @param {number} [sampler.wrapS] Texture horizontal wrap mode (see {@link SpiderGL.WebGL.Texture#wrapS}).
5336 	 * @param {number} [sampler.wrapT] Texture vertical wrap mode (see {@link SpiderGL.WebGL.Texture#wrapT}).
5337 	 */
5338 	setSampler : function (sampler) {
5339 		if (!sampler) return false;
5340 
5341 		var gl  = this._gl;
5342 		var cb  = this._cb;
5343 		var dsa = this._dsa;
5344 
5345 		var t = this._t;
5346 		var h = this._h;
5347 
5348 		cb.pushTexture(t);
5349 		gl.bindTexture(t, h);
5350 
5351 		var p = 0;
5352 
5353 		if ("magFilter" in sampler) {
5354 			p = SpiderGL.Utility.getDefaultValue(sampler.magFilter, SpiderGL.WebGL.Texture.DEFAULT_MAG_FILTER);
5355 			gl.texParameteri(t, gl.TEXTURE_MAG_FILTER, p);
5356 		}
5357 
5358 		if ("minFilter" in sampler) {
5359 			p = SpiderGL.Utility.getDefaultValue(sampler.minFilter, SpiderGL.WebGL.Texture.DEFAULT_MIN_FILTER);
5360 			gl.texParameteri(t, gl.TEXTURE_MIN_FILTER, p);
5361 		}
5362 
5363 		if ("wrapS" in sampler) {
5364 			p = SpiderGL.Utility.getDefaultValue(sampler.wrapS, SpiderGL.WebGL.Texture.DEFAULT_WRAP_S);
5365 			gl.texParameteri(t, gl.TEXTURE_WRAP_S, p);
5366 		}
5367 
5368 		if ("wrapT" in sampler) {
5369 			p = SpiderGL.Utility.getDefaultValue(sampler.wrapT, SpiderGL.WebGL.Texture.DEFAULT_WRAP_T);
5370 			gl.texParameteri(t, gl.TEXTURE_WRAP_T, p);
5371 		}
5372 
5373 		cb.popTexture(t);
5374 
5375 		return true;
5376 	},
5377 
5378 	/**
5379 	 * Gets the texture sampling (filtering and addressing) mode.
5380 	 *
5381 	 * @returns {object} The sampling options. The returned object will have the following properties: magFilter, minFilter, wrapS, wrapT.
5382 	 */
5383 	getSampler : function () {
5384 		return {
5385 			magFilter : this._magFilter,
5386 			minFilter : this._minFilter,
5387 			wrapS     : this._wrapS,
5388 			wrapT     : this._wrapT
5389 		};
5390 	},
5391 
5392 	/**
5393 	 * Generates the mipmap pyramid.
5394 	 */
5395 	generateMipmap : function () {
5396 		if (this._missingFaces != 0) return;
5397 		this._dsa.generateMipmap(this._h, this._t);
5398 	},
5399 
5400 	/**
5401 	 * Destroys the WebGLTexture.
5402 	 * After destruction, the handle is set to null and this object should not be used anymore.
5403 	 *
5404 	 * @see SpiderGL.WebGL.ObjectGL#destroy
5405 	 */
5406 	destroy : function () {
5407 		this._gl.deleteTexture(this._h);
5408 	},
5409 
5410 	/**
5411 	 * Binds the texture to the appropriate target for SpiderGL.WebGL.Texture2D and SpiderGL.WebGL.TextureCubeMap.
5412 	 *
5413 	 * @param {number} unit The unit (zero-based index) to which bind the texture. If not specified, the current texture unit is used.
5414 	 *
5415 	 * @see unbind
5416 	 */
5417 	bind : function (unit) {
5418 		var gl  = this._gl;
5419 		var cb  = this._cb;
5420 		var dsa = this._dsa;
5421 		if (typeof unit == "undefined") {
5422 			gl.bindTexture(this._t, this._h);
5423 		}
5424 		else {
5425 			dsa.bindTexture(gl.TEXTURE0 + unit, this._t, this._h);
5426 		}
5427 	},
5428 
5429 	/**
5430 	 * Binds "null" to the appropriate texture target for SpiderGL.WebGL.Texture2D and SpiderGL.WebGL.TextureCubeMap.
5431 	 * This method is provided only for simmetry with {@link bind} and is not relative to the object state.
5432 	 *
5433 	 * @param {number} unit The unit (zero-based index) to which bind the null texture. If not specified, the current texture unit is used.
5434 	 *
5435 	 * @see bind
5436 	 */
5437 	unbind : function (unit) {
5438 		var gl  = this._gl;
5439 		var cb  = this._cb;
5440 		var dsa = this._dsa;
5441 		if (typeof unit == "undefined") {
5442 			gl.bindTexture(this._t, null);
5443 		}
5444 		else {
5445 			dsa.bindTexture(gl.TEXTURE0 + unit, this._t, null);
5446 		}
5447 	}
5448 };
5449 
5450 SpiderGL.Type.extend(SpiderGL.WebGL.Texture, SpiderGL.WebGL.ObjectGL);
5451 
5452 /**
5453  * Creates a SpiderGL.WebGL.Texture2D.
5454  *
5455  * SpiderGL.WebGL.Texture2D is a wrapper for 2D WebGLTexture objects.
5456  *
5457  * @class The SpiderGL.WebGL.Texture2D is a wrapper for 2D WebGLTexture objects
5458  *
5459  * @augments SpiderGL.WebGL.Texture
5460  *
5461  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
5462  * @param {object} [options] Optional parameters (see SpiderGL.WebGL.Texture constructor).
5463  *
5464  * @see SpiderGL.WebGL.Texture
5465  * @see SpiderGL.WebGL.TextureCubeMap
5466  * @see SpiderGL.WebGL.Framebuffer
5467  * @see SpiderGL.WebGL.ObjectGL
5468  */
5469 SpiderGL.WebGL.Texture2D = function (gl, options) {
5470 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
5471 	SpiderGL.WebGL.Texture.call(this, gl, SpiderGL.WebGL.Texture2D.TARGET, options);
5472 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
5473 
5474 	options = options || { };
5475 	if (SpiderGL.Type.instanceOf(options, WebGLTexture)) {
5476 		options = { handle : options };
5477 	}
5478 	else if (SpiderGL.Type.isString(options)) {
5479 		options = { url : options };
5480 	}
5481 
5482 	if (("url" in options) || ("data" in options) || (("width" in options) && ("height" in options))) { this.setImage(options); }
5483 }
5484 
5485 SpiderGL.WebGL.Texture2D.TARGET = WebGLRenderingContext.TEXTURE_2D;
5486 
5487 SpiderGL.WebGL.Texture2D.unbind = function (gl, unit) {
5488 	var cb  = gl.getExtension("SGL_current_binding");
5489 	var dsa = gl.getExtension("SGL_direct_state_access");
5490 	if (typeof unit == "undefined") {
5491 		gl.bindTexture(SpiderGL.WebGL.Texture2D.TARGET, null);
5492 	}
5493 	else {
5494 		dsa.bindTexture(gl.TEXTURE0 + unit, SpiderGL.WebGL.Texture2D.TARGET, null);
5495 	}
5496 };
5497 
5498 SpiderGL.WebGL.Texture2D.prototype = {
5499 	/**
5500 	 * Sets the texture image.
5501 	 *
5502 	 * @param {object} options The image data and type parameters (see SpiderGL.WebGL.Texture constructor).
5503 	 * @param {ArrayBuffer|ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [options.data] The texture image pixel data.
5504 	 * @param {number} [options.internalFormat=SpiderGL.WebGL.Texture.DEFAULT_INTERNAL_FORMAT] The texture internal format.
5505 	 * @param {number} [options.level=SpiderGL.WebGL.Texture.DEFAULT_LEVEL] The texture image mip level.
5506 	 * @param {number} [options.width] If data is null or a typed array, specifies the texture image width. If handle is provided, the width parameter will supply the width information, not querable to the WebGLRenderingContext.
5507 	 * @param {number} [options.height] If data is null or a typed array, specifies the texture image height. If handle is provided, the width parameter will supply the height information, not querable to the WebGLRenderingContext.
5508 	 * @param {number} [options.border=SpiderGL.WebGL.Texture.DEFAULT_BORDER] Texture border.
5509 	 * @param {number} [options.format=SpiderGL.WebGL.Texture.DEFAULT_FORMAT] The format parameter used for WebGLRenderingContext.texImage2D.
5510 	 * @param {number} [options.type=SpiderGL.WebGL.Texture.DEFAULT_TYPE] The type parameter used for WebGLRenderingContext.texImage2D.
5511 	 * @param {bool} [options.generateMipmap] If specified, overrides autoMipmap.
5512 	 * @param {bool} [options.flipY] If specified, overrides flipYPolicy.
5513 	 * @param {bool} [options.premultiplyAlpha] If specified, overrides premultiplyAlphaPolicy.
5514 	 * @param {number} [options.colorspaceConversion] If specified, overrides colorspaceConversionPolicy.
5515 	 * @param {function} [options.onAbort] If url is specified, this function will be called if image data loading is aborted.
5516 	 * @param {function} [options.onError] If url is specified, this function will be called if an error occurs when loading image data.
5517 	 * @param {function} [options.onLoad] If url is specified, this function will be called when image data has been loaded.
5518 	 *
5519 	 * @see setSubImage
5520 	 * @see SpiderGL.WebGL.Texture
5521 	 */
5522 	setImage : function (options) {
5523 		return this._setImage(this._t, options);
5524 	},
5525 
5526 	/**
5527 	 * Sets a region of the texture image.
5528 	 *
5529 	 * @param {object} options The image data and type parameters (see SpiderGL.WebGL.Texture constructor).
5530 	 * @param {ArrayBuffer|ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [options.data] The texture sub-image pixel data.
5531 	 * @param {number} [options.xoffset=SpiderGL.WebGL.Texture.DEFAULT_X_OFFSET] The sub-image x offset.
5532 	 * @param {number} [options.yoffset=SpiderGL.WebGL.Texture.DEFAULT_Y_OFFSET] The sub-image y offset.
5533 	 * @param {number} [options.width] If data is null or a typed array, specifies the texture image width. If handle is provided, the width parameter will supply the width information, not querable to the WebGLRenderingContext.
5534 	 * @param {number} [options.height] If data is null or a typed array, specifies the texture image height. If handle is provided, the width parameter will supply the height information, not querable to the WebGLRenderingContext.
5535 	 * @param {number} [options.border=SpiderGL.WebGL.Texture.DEFAULT_BORDER] Texture border.
5536 	 * @param {number} [options.format=SpiderGL.WebGL.Texture.DEFAULT_FORMAT] The format parameter used for WebGLRenderingContext.texSubImage2D.
5537 	 * @param {number} [options.type=SpiderGL.WebGL.Texture.DEFAULT_TYPE] The type parameter used for WebGLRenderingContext.texSubImage2D.
5538 	 * @param {bool} [options.generateMipmap] If specified, overrides autoMipmap.
5539 	 * @param {bool} [options.flipY] If specified, overrides flipYPolicy.
5540 	 * @param {bool} [options.premultiplyAlpha] If specified, overrides premultiplyAlphaPolicy.
5541 	 * @param {number} [options.colorspaceConversion] If specified, overrides colorspaceConversionPolicy.
5542 	 * @param {function} [options.onAbort] If url is specified, this function will be called if image data loading is aborted.
5543 	 * @param {function} [options.onError] If url is specified, this function will be called if an error occurs when loading image data.
5544 	 * @param {function} [options.onLoad] If url is specified, this function will be called when image data has been loaded.
5545 	 *
5546 	 * @see setImage
5547 	 * @see SpiderGL.WebGL.Texture
5548 	 */
5549 	setSubImage : function (options) {
5550 		return this._setSubImage(this._t, options);
5551 	}
5552 };
5553 
5554 SpiderGL.Type.extend(SpiderGL.WebGL.Texture2D, SpiderGL.WebGL.Texture);
5555 
5556 /**
5557  * Creates a SpiderGL.WebGL.TextureCubeMap.
5558  *
5559  * SpiderGL.WebGL.TextureCubeMap is a wrapper for cube map WebGLTexture objects.
5560  *
5561  * @class The SpiderGL.WebGL.TextureCubeMap is a wrapper for cube map WebGLTexture objects
5562  *
5563  * @augments SpiderGL.WebGL.Texture
5564  *
5565  * @param {WebGLRenderingContext} gl A WebGLRenderingContext hijacked with {@link SpiderGL.WebGL.Context.hijack}.
5566  * @param {object} [options] Optional parameters (see SpiderGL.WebGL.Texture constructor). This constructor accepts only the url options as an array of six strings, or internalFormat, width, height, format and type, ignoring the data property.
5567  *
5568  * @see SpiderGL.WebGL.Texture
5569  * @see SpiderGL.WebGL.Texture2D
5570  * @see SpiderGL.WebGL.Framebuffer
5571  * @see SpiderGL.WebGL.ObjectGL
5572  */
5573 SpiderGL.WebGL.TextureCubeMap = function (gl, options) {
5574 	if (!SpiderGL.WebGL.Context.isHijacked(gl)) { return null; }
5575 	SpiderGL.WebGL.Texture.call(this, gl, SpiderGL.WebGL.TextureCubeMap.TARGET, options);
5576 	if (!!this._h && !!this._h._spidergl && (this._h._spidergl != this)) return this._h._spidergl;
5577 
5578 	options = options || { };
5579 	if (SpiderGL.Type.instanceOf(options, WebGLTexture)) {
5580 		options = { handle : options };
5581 	}
5582 	else if (SpiderGL.Type.isString(options)) {
5583 		options = { url : options };
5584 	}
5585 
5586 	var faceTargets = SpiderGL.WebGL.TextureCubeMap._faceTargets;
5587 
5588 	if (options.url) {
5589 		var urls = options.url;
5590 		for (var i=0; i<6; ++i) {
5591 			options.url = urls[i];
5592 			this.setImage(faceTargets[i], options);
5593 		}
5594 	}
5595 	else if (options.data) {
5596 		var datas = options.data;
5597 		for (var i=0; i<6; ++i) {
5598 			options.data = datas[i];
5599 			this.setImage(faceTargets[i], options);
5600 		}
5601 	}
5602 	else if ((options.width > 0) && (options.height > 0)) {
5603 		for (var i=0; i<6; ++i) {
5604 			this.setImage(faceTargets[i], options);
5605 		}
5606 	}
5607 }
5608 
5609 SpiderGL.WebGL.TextureCubeMap.TARGET = WebGLRenderingContext.TEXTURE_CUBE_MAP;
5610 
5611 SpiderGL.WebGL.TextureCubeMap.unbind = function (gl, unit) {
5612 	var cb  = gl.getExtension("SGL_current_binding");
5613 	var dsa = gl.getExtension("SGL_direct_state_access");
5614 	if (typeof unit == "undefined") {
5615 		gl.bindTexture(SpiderGL.WebGL.TextureCubeMap.TARGET, null);
5616 	}
5617 	else {
5618 		dsa.bindTexture(gl.TEXTURE0 + unit, SpiderGL.WebGL.TextureCubeMap.TARGET, null);
5619 	}
5620 };
5621 
5622 SpiderGL.WebGL.TextureCubeMap._faceTargets = [
5623 	WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_X,
5624 	WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_X,
5625 	WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Y,
5626 	WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Y,
5627 	WebGLRenderingContext.TEXTURE_CUBE_MAP_POSITIVE_Z,
5628 	WebGLRenderingContext.TEXTURE_CUBE_MAP_NEGATIVE_Z
5629 ];
5630 
5631 SpiderGL.WebGL.TextureCubeMap.prototype = {
5632 	/**
5633 	 * Sets the texture image for a cube face.
5634 	 *
5635 	 * @param {number} face The cube map face to set.
5636 	 * @param {object} options The image data and type parameters (see SpiderGL.WebGL.Texture constructor).
5637 	 * @param {ArrayBuffer|ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [options.data] The texture image pixel data.
5638 	 * @param {number} [options.internalFormat=SpiderGL.WebGL.Texture.DEFAULT_INTERNAL_FORMAT] The texture internal format.
5639 	 * @param {number} [options.width] If data is null or a typed array, specifies the texture image width. If handle is provided, the width parameter will supply the width information, not querable to the WebGLRenderingContext.
5640 	 * @param {number} [options.height] If data is null or a typed array, specifies the texture image height. If handle is provided, the width parameter will supply the height information, not querable to the WebGLRenderingContext.
5641 	 * @param {number} [options.border=SpiderGL.WebGL.Texture.DEFAULT_BORDER] Texture border.
5642 	 * @param {number} [options.format=SpiderGL.WebGL.Texture.DEFAULT_FORMAT] The format parameter used for WebGLRenderingContext.texImage2D.
5643 	 * @param {number} [options.type=SpiderGL.WebGL.Texture.DEFAULT_TYPE] The type parameter used for WebGLRenderingContext.texImage2D.
5644 	 * @param {bool} [options.generateMipmap] If specified, overrides autoMipmap.
5645 	 * @param {bool} [options.flipY] If specified, overrides flipYPolicy.
5646 	 * @param {bool} [options.premultiplyAlpha] If specified, overrides premultiplyAlphaPolicy.
5647 	 * @param {number} [options.colorspaceConversion] If specified, overrides colorspaceConversionPolicy.
5648 	 * @param {function} [options.onAbort] If url is specified, this function will be called if image data loading is aborted.
5649 	 * @param {function} [options.onError] If url is specified, this function will be called if an error occurs when loading image data.
5650 	 * @param {function} [options.onLoad] If url is specified, this function will be called when image data has been loaded.
5651 	 *
5652 	 * @see setSubImage
5653 	 * @see SpiderGL.WebGL.Texture
5654 	 */
5655 	setImage : function (face, options) {
5656 		/*
5657 		var b = SpiderGL.WebGL.TextureCubeMap._faceBits[face];
5658 		if (!b) return false;
5659 		var r = this._setImage(face, options);
5660 		if (r) { this._missingFaces &= ~b; }
5661 		return r;
5662 		*/
5663 		return this._setImage(face, options);
5664 	},
5665 
5666 	/**
5667 	 * Sets a region of the texture image for a cube face.
5668 	 *
5669 	 * @param {number} face The cube map face to set.
5670 	 * @param {object} options The image data and type parameters (see SpiderGL.WebGL.Texture constructor).
5671 	 * @param {ArrayBuffer|ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [options.data] The texture sub-image pixel data.
5672 	 * @param {number} [options.xoffset=SpiderGL.WebGL.Texture.DEFAULT_X_OFFSET] The sub-image x offset.
5673 	 * @param {number} [options.yoffset=SpiderGL.WebGL.Texture.DEFAULT_Y_OFFSET] The sub-image y offset.
5674 	 * @param {number} [options.width] If data is null or a typed array, specifies the texture image width. If handle is provided, the width parameter will supply the width information, not querable to the WebGLRenderingContext.
5675 	 * @param {number} [options.height] If data is null or a typed array, specifies the texture image height. If handle is provided, the width parameter will supply the height information, not querable to the WebGLRenderingContext.
5676 	 * @param {number} [options.border=SpiderGL.WebGL.Texture.DEFAULT_BORDER] Texture border.
5677 	 * @param {number} [options.format=SpiderGL.WebGL.Texture.DEFAULT_FORMAT] The format parameter used for WebGLRenderingContext.texSubImage2D.
5678 	 * @param {number} [options.type=SpiderGL.WebGL.Texture.DEFAULT_TYPE] The type parameter used for WebGLRenderingContext.texSubImage2D.
5679 	 * @param {bool} [options.generateMipmap] If specified, overrides autoMipmap.
5680 	 * @param {bool} [options.flipY] If specified, overrides flipYPolicy.
5681 	 * @param {bool} [options.premultiplyAlpha] If specified, overrides premultiplyAlphaPolicy.
5682 	 * @param {number} [options.colorspaceConversion] If specified, overrides colorspaceConversionPolicy.
5683 	 * @param {function} [options.onAbort] If url is specified, this function will be called if image data loading is aborted.
5684 	 * @param {function} [options.onError] If url is specified, this function will be called if an error occurs when loading image data.
5685 	 * @param {function} [options.onLoad] If url is specified, this function will be called when image data has been loaded.
5686 	 *
5687 	 * @see setImage
5688 	 * @see SpiderGL.WebGL.Texture
5689 	 */
5690 	setSubImage : function (face, options) {
5691 		return this._setSubImage(face, options);
5692 	}
5693 };
5694 
5695 SpiderGL.Type.extend(SpiderGL.WebGL.TextureCubeMap, SpiderGL.WebGL.Texture);
5696 
5697