diff --git a/test/spec/ol/render/webgl/circlereplay.test.js b/test/spec/ol/render/webgl/circlereplay.test.js index e81058b618..8524928735 100644 --- a/test/spec/ol/render/webgl/circlereplay.test.js +++ b/test/spec/ol/render/webgl/circlereplay.test.js @@ -1,6 +1,9 @@ goog.provide('ol.test.render.webgl.CircleReplay'); +goog.require('ol'); +goog.require('ol.Feature'); goog.require('ol.geom.Circle'); +goog.require('ol.render.webgl.circlereplay.defaultshader'); goog.require('ol.render.webgl.CircleReplay'); goog.require('ol.style.Fill'); goog.require('ol.style.Stroke'); @@ -92,4 +95,149 @@ describe('ol.render.webgl.CircleReplay', function() { expect(replay.indices).to.eql([0, 1, 2]); }); }); + + describe('#setUpProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('returns the locations used by the shaders', function() { + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + expect(locations).to.be.a( + ol.render.webgl.circlereplay.defaultshader.Locations); + }); + + it('gets and compiles the shaders', function() { + sinon.spy(context, 'getProgram'); + sinon.spy(context, 'useProgram'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(context.getProgram.calledWithExactly( + ol.render.webgl.circlereplay.defaultshader.fragment, + ol.render.webgl.circlereplay.defaultshader.vertex)).to.be(true); + expect(context.useProgram.calledOnce).to.be(true); + }); + + it('initializes the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'vertexAttribPointer'); + sinon.spy(gl, 'enableVertexAttribArray'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(gl.vertexAttribPointer.callCount).to.be(gl.getAttribLocation.callCount); + expect(gl.enableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#shutDownProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + disableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('disables the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'disableVertexAttribArray'); + + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + replay.shutDownProgram(gl, locations); + expect(gl.disableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#drawReplay', function() { + var gl, context; + var feature1 = new ol.Feature({ + geometry: new ol.geom.Circle([0, 0], 5000) + }); + var feature2 = new ol.Feature({ + geometry: new ol.geom.Circle([10, 10], 5000) + }); + var feature3 = new ol.Feature({ + geometry: new ol.geom.Circle([20, 20], 5000) + }); + beforeEach(function() { + gl = {}; + context = {}; + replay.setFillStyle_ = function() {}; + replay.setStrokeStyle_ = function() {}; + replay.drawElements = function() {}; + sinon.spy(replay, 'setFillStyle_'); + sinon.spy(replay, 'setStrokeStyle_'); + sinon.spy(replay, 'drawElements'); + }); + + it('draws the elements in a single call if they have the same style', function() { + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + + replay.drawReplay(gl, context, {}, false); + expect(replay.setFillStyle_.calledOnce).to.be(true); + expect(replay.setStrokeStyle_.calledOnce).to.be(true); + expect(replay.drawElements.calledOnce).to.be(true); + }); + + it('draws the elements in batches if there are multiple styles', function() { + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(fillStyle, null); + replay.drawCircle(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(strokeStyle, null); + replay.drawCircle(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + + replay.drawReplay(gl, context, {}, false); + expect(replay.setFillStyle_.calledThrice).to.be(true); + expect(replay.setStrokeStyle_.calledThrice).to.be(true); + expect(replay.drawElements.calledThrice).to.be(true); + }); + + it('can skip elements if needed', function() { + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawCircle(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + var skippedFeatHash = {}; + skippedFeatHash[ol.getUid(feature2).toString()] = true; + + replay.drawReplay(gl, context, skippedFeatHash, false); + expect(replay.setFillStyle_.calledOnce).to.be(true); + expect(replay.setStrokeStyle_.calledOnce).to.be(true); + expect(replay.drawElements.calledTwice).to.be(true); + }); + }); }); diff --git a/test/spec/ol/render/webgl/imagereplay.test.js b/test/spec/ol/render/webgl/imagereplay.test.js index 8ea1997917..7e5b1ce621 100644 --- a/test/spec/ol/render/webgl/imagereplay.test.js +++ b/test/spec/ol/render/webgl/imagereplay.test.js @@ -2,6 +2,7 @@ goog.provide('ol.test.render.webgl.ImageReplay'); goog.require('ol.geom.MultiPoint'); goog.require('ol.geom.Point'); +goog.require('ol.render.webgl.imagereplay.defaultshader'); goog.require('ol.render.webgl.ImageReplay'); goog.require('ol.style.Image'); @@ -166,4 +167,79 @@ describe('ol.render.webgl.ImageReplay', function() { expect(replay.indices[23]).to.be(15); }); }); + + describe('#setUpProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('returns the locations used by the shaders', function() { + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + expect(locations).to.be.a( + ol.render.webgl.imagereplay.defaultshader.Locations); + }); + + it('gets and compiles the shaders', function() { + sinon.spy(context, 'getProgram'); + sinon.spy(context, 'useProgram'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(context.getProgram.calledWithExactly( + ol.render.webgl.imagereplay.defaultshader.fragment, + ol.render.webgl.imagereplay.defaultshader.vertex)).to.be(true); + expect(context.useProgram.calledOnce).to.be(true); + }); + + it('initializes the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'vertexAttribPointer'); + sinon.spy(gl, 'enableVertexAttribArray'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(gl.vertexAttribPointer.callCount).to.be(gl.getAttribLocation.callCount); + expect(gl.enableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#shutDownProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + disableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('disables the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'disableVertexAttribArray'); + + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + replay.shutDownProgram(gl, locations); + expect(gl.disableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); }); diff --git a/test/spec/ol/render/webgl/linestringreplay.test.js b/test/spec/ol/render/webgl/linestringreplay.test.js index 93fff1c28d..219a26a1c9 100644 --- a/test/spec/ol/render/webgl/linestringreplay.test.js +++ b/test/spec/ol/render/webgl/linestringreplay.test.js @@ -1,7 +1,10 @@ goog.provide('ol.test.render.webgl.LineStringReplay'); +goog.require('ol'); +goog.require('ol.Feature'); goog.require('ol.geom.LineString'); goog.require('ol.geom.MultiLineString'); +goog.require('ol.render.webgl.linestringreplay.defaultshader'); goog.require('ol.render.webgl.LineStringReplay'); goog.require('ol.style.Stroke'); @@ -206,4 +209,155 @@ describe('ol.render.webgl.LineStringReplay', function() { replay.vertices.slice(-7)); }); }); + + describe('#setUpProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('returns the locations used by the shaders', function() { + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + expect(locations).to.be.a( + ol.render.webgl.linestringreplay.defaultshader.Locations); + }); + + it('gets and compiles the shaders', function() { + sinon.spy(context, 'getProgram'); + sinon.spy(context, 'useProgram'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(context.getProgram.calledWithExactly( + ol.render.webgl.linestringreplay.defaultshader.fragment, + ol.render.webgl.linestringreplay.defaultshader.vertex)).to.be(true); + expect(context.useProgram.calledOnce).to.be(true); + }); + + it('initializes the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'vertexAttribPointer'); + sinon.spy(gl, 'enableVertexAttribArray'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(gl.vertexAttribPointer.callCount).to.be(gl.getAttribLocation.callCount); + expect(gl.enableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#shutDownProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + disableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('disables the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'disableVertexAttribArray'); + + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + replay.shutDownProgram(gl, locations); + expect(gl.disableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#drawReplay', function() { + var gl, context; + var feature1 = new ol.Feature({ + geometry: new ol.geom.LineString([[0, 0], [500, 500]]) + }); + var feature2 = new ol.Feature({ + geometry: new ol.geom.LineString([[0, 0], [500, 500]]) + }); + var feature3 = new ol.Feature({ + geometry: new ol.geom.LineString([[0, 0], [500, 500]]) + }); + beforeEach(function() { + gl = { + enable: function() {}, + disable: function() {}, + depthMask: function() {}, + depthFunc: function() {}, + clear: function() {}, + getParameter: function() {} + }; + context = {}; + replay.setStrokeStyle_ = function() {}; + replay.drawElements = function() {}; + sinon.spy(replay, 'setStrokeStyle_'); + sinon.spy(replay, 'drawElements'); + sinon.spy(gl, 'clear'); + }); + + it('draws the elements in a single call if they have the same style', function() { + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + + replay.drawReplay(gl, context, {}, false); + expect(replay.setStrokeStyle_.calledOnce).to.be(true); + expect(replay.drawElements.calledOnce).to.be(true); + expect(gl.clear.called).to.be(true); + }); + + it('draws the elements in batches if there are multiple styles', function() { + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(null, strokeStyle2); + replay.drawLineString(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + + replay.drawReplay(gl, context, {}, false); + expect(replay.setStrokeStyle_.calledThrice).to.be(true); + expect(replay.drawElements.calledThrice).to.be(true); + expect(gl.clear.called).to.be(true); + }); + + it('can skip elements if needed', function() { + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(null, strokeStyle1); + replay.drawLineString(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + var skippedFeatHash = {}; + skippedFeatHash[ol.getUid(feature2).toString()] = true; + + replay.drawReplay(gl, context, skippedFeatHash, false); + expect(replay.setStrokeStyle_.calledOnce).to.be(true); + expect(replay.drawElements.calledTwice).to.be(true); + expect(gl.clear.called).to.be(true); + }); + }); }); diff --git a/test/spec/ol/render/webgl/polygonreplay.test.js b/test/spec/ol/render/webgl/polygonreplay.test.js index 449a56ab3f..62f7f8e1cd 100644 --- a/test/spec/ol/render/webgl/polygonreplay.test.js +++ b/test/spec/ol/render/webgl/polygonreplay.test.js @@ -1,7 +1,10 @@ goog.provide('ol.test.render.webgl.PolygonReplay'); +goog.require('ol'); +goog.require('ol.Feature'); goog.require('ol.geom.MultiPolygon'); goog.require('ol.geom.Polygon'); +goog.require('ol.render.webgl.polygonreplay.defaultshader'); goog.require('ol.render.webgl.PolygonReplay'); goog.require('ol.structs.LinkedList'); goog.require('ol.structs.RBush'); @@ -315,4 +318,147 @@ describe('ol.render.webgl.PolygonReplay', function() { }); }); }); + + describe('#setUpProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('returns the locations used by the shaders', function() { + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + expect(locations).to.be.a( + ol.render.webgl.polygonreplay.defaultshader.Locations); + }); + + it('gets and compiles the shaders', function() { + sinon.spy(context, 'getProgram'); + sinon.spy(context, 'useProgram'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(context.getProgram.calledWithExactly( + ol.render.webgl.polygonreplay.defaultshader.fragment, + ol.render.webgl.polygonreplay.defaultshader.vertex)).to.be(true); + expect(context.useProgram.calledOnce).to.be(true); + }); + + it('initializes the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'vertexAttribPointer'); + sinon.spy(gl, 'enableVertexAttribArray'); + + replay.setUpProgram(gl, context, [2, 2], 1); + expect(gl.vertexAttribPointer.callCount).to.be(gl.getAttribLocation.callCount); + expect(gl.enableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#shutDownProgram', function() { + var context, gl; + beforeEach(function() { + context = { + getProgram: function() {}, + useProgram: function() {} + }; + gl = { + enableVertexAttribArray: function() {}, + disableVertexAttribArray: function() {}, + vertexAttribPointer: function() {}, + uniform1f: function() {}, + uniform2fv: function() {}, + getUniformLocation: function() {}, + getAttribLocation: function() {} + }; + }); + + it('disables the attrib pointers', function() { + sinon.spy(gl, 'getAttribLocation'); + sinon.spy(gl, 'disableVertexAttribArray'); + + var locations = replay.setUpProgram(gl, context, [2, 2], 1); + replay.shutDownProgram(gl, locations); + expect(gl.disableVertexAttribArray.callCount).to.be( + gl.getAttribLocation.callCount); + }); + }); + + describe('#drawReplay', function() { + var gl, context; + var feature1 = new ol.Feature({ + geometry: new ol.geom.Polygon([[[0, 0], [500, 500], [500, 0], [0, 0]]]) + }); + var feature2 = new ol.Feature({ + geometry: new ol.geom.Polygon([[[0, 0], [500, 500], [500, 0], [0, 0]]]) + }); + var feature3 = new ol.Feature({ + geometry: new ol.geom.Polygon([[[0, 0], [500, 500], [500, 0], [0, 0]]]) + }); + beforeEach(function() { + gl = {}; + context = {}; + replay.setFillStyle_ = function() {}; + replay.drawElements = function() {}; + sinon.spy(replay, 'setFillStyle_'); + sinon.spy(replay, 'drawElements'); + }); + + it('draws the elements in a single call if they have the same style', function() { + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + + replay.drawReplay(gl, context, {}, false); + expect(replay.setFillStyle_.calledOnce).to.be(true); + expect(replay.drawElements.calledOnce).to.be(true); + }); + + it('draws the elements in batches if there are multiple fill styles', function() { + var fillStyle2 = new ol.style.Fill({ + color: [0, 255, 0, 1] + }); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(fillStyle2, strokeStyle); + replay.drawPolygon(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + + replay.drawReplay(gl, context, {}, false); + expect(replay.setFillStyle_.calledThrice).to.be(true); + expect(replay.drawElements.calledThrice).to.be(true); + }); + + it('can skip elements if needed', function() { + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature1.getGeometry(), feature1); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature2.getGeometry(), feature2); + replay.setFillStrokeStyle(fillStyle, strokeStyle); + replay.drawPolygon(feature3.getGeometry(), feature3); + replay.startIndices.push(replay.indices.length); + var skippedFeatHash = {}; + skippedFeatHash[ol.getUid(feature2).toString()] = true; + + replay.drawReplay(gl, context, skippedFeatHash, false); + expect(replay.setFillStyle_.calledOnce).to.be(true); + expect(replay.drawElements.calledTwice).to.be(true); + }); + }); });