// Class: openfl._internal.renderer.opengl.GLGraphics

var $global = typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this

$global.Object.defineProperty(exports, "__esModule", {value: true});

var __map_reserved = {};

// Imports

var $hxClasses = require("./../../../../hxClasses_stub").default;
var $import = require("./../../../../import_stub").default;
function openfl_display_BitmapData() {return require("./../../../../openfl/display/BitmapData");}
function openfl_geom_ColorTransform() {return require("./../../../../openfl/geom/ColorTransform");}
function openfl__$internal_renderer_DrawCommandReader() {return require("./../../../../openfl/_internal/renderer/DrawCommandReader");}
function openfl_geom_Rectangle() {return require("./../../../../openfl/geom/Rectangle");}
function openfl_geom_Matrix() {return require("./../../../../openfl/geom/Matrix");}
function Type() {return require("./../../../../Type");}
function openfl__$internal_renderer_canvas_CanvasGraphics() {return require("./../../../../openfl/_internal/renderer/canvas/CanvasGraphics");}
function Std() {return require("./../../../../Std");}
function lime_graphics__$WebGLRenderContext_WebGLRenderContext_$Impl_$() {return require("./../../../../lime/graphics/_WebGLRenderContext/WebGLRenderContext_Impl_");}

// Constructor

var GLGraphics = function(){}

// Meta

GLGraphics.__name__ = ["openfl","_internal","renderer","opengl","GLGraphics"];
GLGraphics.prototype = {
	
};
GLGraphics.prototype.__class__ = GLGraphics.prototype.constructor = $hxClasses["openfl._internal.renderer.opengl.GLGraphics"] = GLGraphics;

// Init



// Statics

GLGraphics.buildBuffer = function(graphics,renderer) {
	var bufferLength = 0;
	var bufferPosition = 0;
	var data = new (openfl__$internal_renderer_DrawCommandReader().default)(graphics.__commands);
	var gl = renderer.__context.webgl;
	var tileRect = (openfl_geom_Rectangle().default).__pool.get();
	var tileTransform = (openfl_geom_Matrix().default).__pool.get();
	var bitmap = null;
	var _g = 0;
	var _g1 = graphics.__commands.types;
	while(_g < _g1.length) {
		var type = _g1[_g];
		++_g;
		switch((Type().default).enumIndex(type)) {
		case 0:
			var c = data.readBeginBitmapFill();
			bitmap = c.obj(0);
			break;
		case 1:
			bitmap = null;
			data.skip(type);
			break;
		case 3:
			var c1 = data.readBeginShaderFill();
			var shaderBuffer = c1.obj(0);
			if(shaderBuffer == null || shaderBuffer.shader == null || shaderBuffer.shader.__bitmap == null) {
				bitmap = null;
			} else {
				bitmap = c1.obj(0).shader.__bitmap.input;
			}
			break;
		case 8:
			if(bitmap != null) {
				var c2 = data.readDrawQuads();
				var rects = c2.obj(0);
				var indices = c2.obj(1);
				var transforms = c2.obj(2);
				var hasIndices = indices != null;
				var transformABCD = false;
				var transformXY = false;
				var length = hasIndices ? indices.get_length() : Math.floor(rects.get_length() / 4);
				if(length == 0) {
					return;
				}
				if(transforms != null) {
					if(transforms.get_length() >= length * 6) {
						transformABCD = true;
						transformXY = true;
					} else if(transforms.get_length() >= length * 4) {
						transformABCD = true;
					} else if(transforms.get_length() >= length * 2) {
						transformXY = true;
					}
				}
				var dataLength = 4;
				var stride = dataLength * 6;
				var bufferLength1 = length * stride;
				GLGraphics.resizeBuffer(graphics,bufferPosition + length * stride);
				var offset = bufferPosition;
				var alpha = 1.0;
				var tileData;
				var id;
				var bitmapWidth;
				var bitmapHeight;
				var tileWidth;
				var tileHeight;
				var uvX;
				var uvY;
				var uvWidth;
				var uvHeight;
				var x;
				var y;
				var x2;
				var y2;
				var x3;
				var y3;
				var x4;
				var y4;
				var ri;
				var ti;
				var __bufferData = graphics.__bufferData;
				bitmapWidth = bitmap.width;
				bitmapHeight = bitmap.height;
				var sourceRect = bitmap.rect;
				var _g3 = 0;
				var _g2 = length;
				while(_g3 < _g2) {
					var i = _g3++;
					offset = bufferPosition + i * stride;
					if(hasIndices) {
						ri = indices[i] * 4;
					} else {
						ri = i * 4;
					}
					if(ri < 0) {
						continue;
					}
					tileRect.setTo(rects[ri],rects[ri + 1],rects[ri + 2],rects[ri + 3]);
					tileWidth = tileRect.width;
					tileHeight = tileRect.height;
					if(tileWidth <= 0 || tileHeight <= 0) {
						continue;
					}
					if(transformABCD && transformXY) {
						ti = i * 6;
						tileTransform.setTo(transforms[ti],transforms[ti + 1],transforms[ti + 2],transforms[ti + 3],transforms[ti + 4],transforms[ti + 5]);
					} else if(transformABCD) {
						ti = i * 4;
						tileTransform.setTo(transforms[ti],transforms[ti + 1],transforms[ti + 2],transforms[ti + 3],tileRect.x,tileRect.y);
					} else if(transformXY) {
						ti = i * 2;
						tileTransform.tx = transforms[ti];
						tileTransform.ty = transforms[ti + 1];
					} else {
						tileTransform.tx = tileRect.x;
						tileTransform.ty = tileRect.y;
					}
					uvX = tileRect.x / bitmapWidth;
					uvY = tileRect.y / bitmapHeight;
					uvWidth = tileRect.get_right() / bitmapWidth;
					uvHeight = tileRect.get_bottom() / bitmapHeight;
					x = tileTransform.__transformX(0,0);
					y = tileTransform.__transformY(0,0);
					x2 = tileTransform.__transformX(tileWidth,0);
					y2 = tileTransform.__transformY(tileWidth,0);
					x3 = tileTransform.__transformX(0,tileHeight);
					y3 = tileTransform.__transformY(0,tileHeight);
					x4 = tileTransform.__transformX(tileWidth,tileHeight);
					y4 = tileTransform.__transformY(tileWidth,tileHeight);
					__bufferData[offset] = x;
					__bufferData[offset + 1] = y;
					__bufferData[offset + 2] = uvX;
					__bufferData[offset + 3] = uvY;
					__bufferData[offset + dataLength] = x2;
					__bufferData[offset + dataLength + 1] = y2;
					__bufferData[offset + dataLength + 2] = uvWidth;
					__bufferData[offset + dataLength + 3] = uvY;
					__bufferData[offset + dataLength * 2] = x3;
					__bufferData[offset + dataLength * 2 + 1] = y3;
					__bufferData[offset + dataLength * 2 + 2] = uvX;
					__bufferData[offset + dataLength * 2 + 3] = uvHeight;
					__bufferData[offset + dataLength * 3] = x3;
					__bufferData[offset + dataLength * 3 + 1] = y3;
					__bufferData[offset + dataLength * 3 + 2] = uvX;
					__bufferData[offset + dataLength * 3 + 3] = uvHeight;
					__bufferData[offset + dataLength * 4] = x2;
					__bufferData[offset + dataLength * 4 + 1] = y2;
					__bufferData[offset + dataLength * 4 + 2] = uvWidth;
					__bufferData[offset + dataLength * 4 + 3] = uvY;
					__bufferData[offset + dataLength * 5] = x4;
					__bufferData[offset + dataLength * 5 + 1] = y4;
					__bufferData[offset + dataLength * 5 + 2] = uvWidth;
					__bufferData[offset + dataLength * 5 + 3] = uvHeight;
				}
				bufferPosition += length * stride;
			}
			break;
		case 12:
			var c3 = data.readDrawTriangles();
			var vertices = c3.obj(0);
			var indices1 = c3.obj(1);
			var uvtData = c3.obj(2);
			var culling = c3.obj(3);
			var hasIndices1 = indices1 != null;
			var numVertices = Math.floor(vertices.get_length() / 2);
			var length1 = hasIndices1 ? indices1.get_length() : numVertices;
			var hasUVData = uvtData != null;
			var hasUVTData = hasUVData && uvtData.get_length() >= numVertices * 3;
			var vertLength = hasUVTData ? 4 : 2;
			var uvStride = hasUVTData ? 3 : 2;
			var stride1 = vertLength + 2;
			var offset1 = bufferPosition;
			GLGraphics.resizeBuffer(graphics,bufferPosition + length1 * stride1);
			var __bufferData1 = graphics.__bufferData;
			var vertOffset;
			var uvOffset;
			var t;
			var _g31 = 0;
			var _g21 = length1;
			while(_g31 < _g21) {
				var i1 = _g31++;
				offset1 = bufferPosition + i1 * stride1;
				if(hasIndices1) {
					vertOffset = indices1[i1] * 2;
				} else {
					vertOffset = i1 * 2;
				}
				if(hasIndices1) {
					uvOffset = indices1[i1] * uvStride;
				} else {
					uvOffset = i1 * uvStride;
				}
				if(hasUVTData) {
					t = uvtData[uvOffset + 2];
					__bufferData1[offset1] = vertices[vertOffset] / t;
					__bufferData1[offset1 + 1] = vertices[vertOffset + 1] / t;
					__bufferData1[offset1 + 2] = 0;
					__bufferData1[offset1 + 3] = 1 / t;
				} else {
					__bufferData1[offset1] = vertices[vertOffset];
					__bufferData1[offset1 + 1] = vertices[vertOffset + 1];
				}
				__bufferData1[offset1 + vertLength] = hasUVData ? uvtData[uvOffset] : 0;
				__bufferData1[offset1 + vertLength + 1] = hasUVData ? uvtData[uvOffset + 1] : 0;
			}
			bufferPosition += length1 * stride1;
			break;
		case 13:
			bitmap = null;
			break;
		default:
			data.skip(type);
		}
	}
	(openfl_geom_Rectangle().default).__pool.release(tileRect);
	(openfl_geom_Matrix().default).__pool.release(tileTransform);
}
GLGraphics.isCompatible = function(graphics) {
	var data = new (openfl__$internal_renderer_DrawCommandReader().default)(graphics.__commands);
	var hasColorFill = false;
	var hasBitmapFill = false;
	var hasShaderFill = false;
	var _g = 0;
	var _g1 = graphics.__commands.types;
	while(_g < _g1.length) {
		var type = _g1[_g];
		++_g;
		switch((Type().default).enumIndex(type)) {
		case 0:
			hasBitmapFill = true;
			hasColorFill = false;
			hasShaderFill = false;
			data.skip(type);
			break;
		case 1:
			hasBitmapFill = false;
			hasColorFill = true;
			hasShaderFill = false;
			data.skip(type);
			break;
		case 3:
			hasBitmapFill = false;
			hasColorFill = false;
			hasShaderFill = true;
			data.skip(type);
			break;
		case 8:
			if(hasBitmapFill || hasShaderFill) {
				data.skip(type);
			} else {
				data.destroy();
				return false;
			}
			break;
		case 9:
			if(hasColorFill) {
				data.skip(type);
			} else {
				data.destroy();
				return false;
			}
			break;
		case 12:
			if(hasBitmapFill || hasShaderFill) {
				data.skip(type);
			} else {
				data.destroy();
				return false;
			}
			break;
		case 13:
			hasBitmapFill = false;
			hasColorFill = false;
			hasShaderFill = false;
			data.skip(type);
			break;
		case 18:
			data.skip(type);
			break;
		default:
			data.destroy();
			return false;
		}
	}
	data.destroy();
	return true;
}
GLGraphics.render = function(graphics,renderer) {
	if(!graphics.__visible || graphics.__commands.get_length() == 0) {
		return;
	}
	if(graphics.__bitmap != null && !graphics.__dirty || !GLGraphics.isCompatible(graphics)) {
		if(graphics.__buffer != null) {
			graphics.__bufferData = null;
			graphics.__buffer = null;
		}
		var cacheTransform = renderer.__softwareRenderer.__worldTransform;
		renderer.__softwareRenderer.__worldTransform = renderer.__worldTransform;
		(openfl__$internal_renderer_canvas_CanvasGraphics().default).render(graphics,renderer.__softwareRenderer);
		renderer.__softwareRenderer.__worldTransform = cacheTransform;
	} else {
		graphics.__bitmap = null;
		graphics.__update(renderer.__worldTransform);
		var bounds = graphics.__bounds;
		var width = graphics.__width;
		var height = graphics.__height;
		if(bounds != null && width >= 1 && height >= 1) {
			var updatedBuffer = false;
			if(graphics.__dirty || graphics.__bufferData == null) {
				GLGraphics.buildBuffer(graphics,renderer);
				updatedBuffer = true;
			}
			var data = new (openfl__$internal_renderer_DrawCommandReader().default)(graphics.__commands);
			var gl = renderer.__context.webgl;
			var matrix = (openfl_geom_Matrix().default).__pool.get();
			var shaderBuffer = null;
			var bitmap = null;
			var repeat = false;
			var smooth = false;
			var fill = null;
			var positionX = 0.0;
			var positionY = 0.0;
			var bufferPosition = 0;
			var _g = 0;
			var _g1 = graphics.__commands.types;
			while(_g < _g1.length) {
				var type = _g1[_g];
				++_g;
				switch((Type().default).enumIndex(type)) {
				case 0:
					var c = data.readBeginBitmapFill();
					bitmap = c.obj(0);
					repeat = c.bool(0);
					smooth = c.bool(1);
					shaderBuffer = null;
					fill = null;
					break;
				case 1:
					var c1 = data.readBeginFill();
					var color = (Std().default)["int"](c1["int"](0));
					var alpha = (Std().default)["int"](c1["float"](0) * 255);
					fill = color & 16777215 | alpha << 24;
					shaderBuffer = null;
					bitmap = null;
					break;
				case 3:
					var c2 = data.readBeginShaderFill();
					shaderBuffer = c2.obj(0);
					if(shaderBuffer == null || shaderBuffer.shader == null || shaderBuffer.shader.__bitmap == null) {
						bitmap = null;
					} else {
						bitmap = shaderBuffer.shader.__bitmap.input;
					}
					fill = null;
					break;
				case 8:
					if(bitmap != null) {
						var c3 = data.readDrawQuads();
						var rects = c3.obj(0);
						var indices = c3.obj(1);
						var transforms = c3.obj(2);
						var hasIndices = indices != null;
						var length = hasIndices ? indices.get_length() : Math.floor(rects.get_length() / 4);
						var uMatrix = renderer.__getMatrix(graphics.__owner.__renderTransform);
						var shader;
						if(shaderBuffer != null && !GLGraphics.maskRender) {
							shader = renderer.__initShaderBuffer(shaderBuffer);
							renderer.__setShaderBuffer(shaderBuffer);
							renderer.applyMatrix(uMatrix);
							renderer.applyBitmapData(bitmap,false,repeat);
							renderer.applyAlpha(graphics.__owner.__worldAlpha);
							renderer.applyColorTransform(graphics.__owner.__worldColorTransform);
							renderer.__updateShaderBuffer();
						} else {
							if(GLGraphics.maskRender) {
								shader = renderer.__maskShader;
							} else {
								shader = renderer.__initGraphicsShader(null);
							}
							renderer.useShader(shader);
							renderer.applyMatrix(uMatrix);
							renderer.applyBitmapData(bitmap,renderer.__allowSmoothing && smooth,repeat);
							renderer.applyAlpha(graphics.__owner.__worldAlpha);
							renderer.applyColorTransform(graphics.__owner.__worldColorTransform);
							renderer.updateShader();
						}
						if(graphics.__buffer == null || graphics.__bufferContext != renderer.__context) {
							graphics.__bufferContext = renderer.__context;
							graphics.__buffer = gl.createBuffer();
						}
						renderer.bindBuffer(gl.ARRAY_BUFFER,graphics.__buffer);
						if(updatedBuffer) {
							(lime_graphics__$WebGLRenderContext_WebGLRenderContext_$Impl_$().default).bufferData(gl,gl.ARRAY_BUFFER,graphics.__bufferData,gl.DYNAMIC_DRAW);
						}
						if(shader.__position != null) {
							gl.vertexAttribPointer(shader.__position.index,2,gl.FLOAT,false,16,bufferPosition * 4);
						}
						if(shader.__textureCoord != null) {
							gl.vertexAttribPointer(shader.__textureCoord.index,2,gl.FLOAT,false,16,(bufferPosition + 2) * 4);
						}
						gl.drawArrays(gl.TRIANGLES,0,length * 6);
						bufferPosition += 4 * length * 6;
						renderer.__clearShader();
					}
					break;
				case 9:
					if(fill != null) {
						var c4 = data.readDrawRect();
						var x = c4["float"](0);
						var y = c4["float"](1);
						var width1 = c4["float"](2);
						var height1 = c4["float"](3);
						var color1 = fill;
						GLGraphics.tempColorTransform.redOffset = color1 >>> 16 & 255;
						GLGraphics.tempColorTransform.greenOffset = color1 >>> 8 & 255;
						GLGraphics.tempColorTransform.blueOffset = color1 & 255;
						GLGraphics.tempColorTransform.__combine(graphics.__owner.__worldColorTransform);
						matrix.identity();
						matrix.scale(width1,height1);
						matrix.tx = x;
						matrix.ty = y;
						matrix.concat(graphics.__owner.__renderTransform);
						var shader1 = GLGraphics.maskRender ? renderer.__maskShader : renderer.__initGraphicsShader(null);
						renderer.useShader(shader1);
						renderer.applyMatrix(renderer.__getMatrix(matrix));
						renderer.applyBitmapData(GLGraphics.blankBitmapData,renderer.__allowSmoothing,repeat);
						renderer.applyAlpha((color1 >>> 24 & 255) / 255 * graphics.__owner.__worldAlpha);
						renderer.applyColorTransform(GLGraphics.tempColorTransform);
						renderer.updateShader();
						renderer.bindBuffer(gl.ARRAY_BUFFER,GLGraphics.blankBitmapData.getBuffer(renderer));
						if(shader1.__position != null) {
							gl.vertexAttribPointer(shader1.__position.index,3,gl.FLOAT,false,56,0);
						}
						if(shader1.__textureCoord != null) {
							gl.vertexAttribPointer(shader1.__textureCoord.index,2,gl.FLOAT,false,56,12);
						}
						gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
						renderer.__clearShader();
					}
					break;
				case 12:
					var c5 = data.readDrawTriangles();
					var vertices = c5.obj(0);
					var indices1 = c5.obj(1);
					var uvtData = c5.obj(2);
					var culling = c5.obj(3);
					var hasIndices1 = indices1 != null;
					var numVertices = Math.floor(vertices.get_length() / 2);
					var length1 = hasIndices1 ? indices1.get_length() : numVertices;
					var hasUVData = uvtData != null;
					var hasUVTData = hasUVData && uvtData.get_length() >= numVertices * 3;
					var vertLength = hasUVTData ? 4 : 2;
					var uvStride = hasUVTData ? 3 : 2;
					var stride = vertLength + 2;
					var uMatrix1 = renderer.__getMatrix(graphics.__owner.__renderTransform);
					var shader2;
					if(shaderBuffer != null && !GLGraphics.maskRender) {
						shader2 = renderer.__initShaderBuffer(shaderBuffer);
						renderer.__setShaderBuffer(shaderBuffer);
						renderer.applyMatrix(uMatrix1);
						renderer.applyBitmapData(bitmap,false,repeat);
						renderer.applyAlpha(1);
						renderer.applyColorTransform(null);
						renderer.__updateShaderBuffer();
					} else {
						if(GLGraphics.maskRender) {
							shader2 = renderer.__maskShader;
						} else {
							shader2 = renderer.__initGraphicsShader(null);
						}
						renderer.useShader(shader2);
						renderer.applyMatrix(uMatrix1);
						renderer.applyBitmapData(bitmap,renderer.__allowSmoothing && smooth,repeat);
						renderer.applyAlpha(graphics.__owner.__worldAlpha);
						renderer.applyColorTransform(graphics.__owner.__worldColorTransform);
						renderer.updateShader();
					}
					if(graphics.__buffer == null || graphics.__bufferContext != renderer.__context) {
						graphics.__bufferContext = renderer.__context;
						graphics.__buffer = gl.createBuffer();
					}
					renderer.bindBuffer(gl.ARRAY_BUFFER,graphics.__buffer);
					if(updatedBuffer) {
						(lime_graphics__$WebGLRenderContext_WebGLRenderContext_$Impl_$().default).bufferData(gl,gl.ARRAY_BUFFER,graphics.__bufferData,gl.DYNAMIC_DRAW);
					}
					if(shader2.__position != null) {
						gl.vertexAttribPointer(shader2.__position.index,vertLength,gl.FLOAT,false,stride * 4,bufferPosition * 4);
					}
					if(shader2.__textureCoord != null) {
						gl.vertexAttribPointer(shader2.__textureCoord.index,2,gl.FLOAT,false,stride * 4,(bufferPosition + vertLength) * 4);
					}
					switch(culling) {
					case "negative":
						renderer.enable(gl.CULL_FACE);
						renderer.cullFace(gl.BACK);
						break;
					case "positive":
						renderer.enable(gl.CULL_FACE);
						renderer.cullFace(gl.FRONT);
						break;
					default:
					}
					gl.drawArrays(gl.TRIANGLES,0,length1);
					bufferPosition += stride * length1;
					if(culling != "none") {
						renderer.disable(gl.CULL_FACE);
						renderer.cullFace(gl.BACK);
					}
					renderer.__clearShader();
					break;
				case 13:
					bitmap = null;
					fill = null;
					shaderBuffer = null;
					data.skip(type);
					break;
				case 18:
					var c6 = data.readMoveTo();
					positionX = c6["float"](0);
					positionY = c6["float"](1);
					break;
				default:
					data.skip(type);
				}
			}
			(openfl_geom_Matrix().default).__pool.release(matrix);
		}
		graphics.set___dirty(false);
	}
}
GLGraphics.renderMask = function(graphics,renderer) {
	GLGraphics.maskRender = true;
	GLGraphics.render(graphics,renderer);
	GLGraphics.maskRender = false;
}
GLGraphics.resizeBuffer = function(graphics,length) {
	if(graphics.__bufferData == null) {
		var this1;
		if(length != null) {
			this1 = new Float32Array(length);
		} else {
			this1 = null;
		}
		graphics.__bufferData = this1;
	} else if(length > graphics.__bufferData.length) {
		var this2;
		if(length != null) {
			this2 = new Float32Array(length);
		} else {
			this2 = null;
		}
		var buffer = this2;
		buffer.set(graphics.__bufferData);
		graphics.__bufferData = buffer;
	}
	graphics.__bufferLength = length;
}
GLGraphics.blankBitmapData = new (openfl_display_BitmapData().default)(1,1,false,0)
GLGraphics.tempColorTransform = new (openfl_geom_ColorTransform().default)(0,0,0,1,0,0,0,0)

// Export

exports.default = GLGraphics;