summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js72
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js583
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js54
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js190
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js323
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js1274
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js123
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js113
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js115
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js641
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js101
11 files changed, 3589 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js
new file mode 100644
index 0000000000..c0400465e4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrDefs.js
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrDefs');
+
+goog.scope(function() {
+
+var rrDefs = framework.referencerenderer.rrDefs;
+
+/**
+ * @enum
+ */
+rrDefs.FaceType = {
+ FACETYPE_FRONT: 0,
+ FACETYPE_BACK: 1
+};
+
+/**
+ * @enum
+ */
+rrDefs.IndexType = {
+ INDEXTYPE_UINT8: 0,
+ INDEXTYPE_UINT16: 1,
+ INDEXTYPE_UINT32: 2
+};
+
+/**
+ * @enum
+ */
+rrDefs.ProvokingVertex = {
+ PROVOKINGVERTEX_FIRST: 1,
+ PROVOKINGVERTEX_LAST: 2 // \note valid value, "last vertex", not last of enum
+};
+
+/**
+ * @interface
+ */
+rrDefs.Sampler = function() {};
+
+/**
+ * @param {Array<number>} pos
+ * @param {number=} lod
+ * @return {Array<number>}
+ */
+rrDefs.Sampler.prototype.sample = function(pos, lod) {};
+
+/**
+ * @param {Array<Array<number>>} packetTexcoords 4 coordinates
+ * @param {number} lodBias
+ * @return {Array<Array<number>>} 4 vec4 samples
+ */
+rrDefs.Sampler.prototype.sample4 = function(packetTexcoords, lodBias) {};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js
new file mode 100644
index 0000000000..a9c2a1f464
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js
@@ -0,0 +1,583 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrRenderState');
+
+goog.scope(function() {
+
+var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+var deMath = framework.delibs.debase.deMath;
+var rrRenderState = framework.referencerenderer.rrRenderState;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+
+/** Return oldValue with the bits indicated by mask replaced by corresponding bits of newValue.
+ * @param {number} oldValue
+ * @param {number} newValue
+ * @param {number} mask
+ * @return {number}
+ */
+rrFragmentOperations.maskedBitReplace = function(oldValue, newValue, mask) {
+ return (oldValue & ~mask) | (newValue & mask);
+};
+
+/**
+ * @param {Array<number>} point
+ * @param {?} rect
+ * @return {boolean}
+ */
+rrFragmentOperations.isInsideRect = function(point, rect) {
+ return deMath.deInBounds32(point[0], rect.left, rect.left + rect.width) &&
+ deMath.deInBounds32(point[1], rect.bottom, rect.bottom + rect.height);
+};
+
+/**
+ * @constructor
+ * @param {Array<number>} coefficents
+ * @param {Array<number>} coords
+ * @param {number} depth
+ */
+rrFragmentOperations.Fragment = function(coefficents, coords, depth) {
+ /** @type {Array<number>} */ this.barycentric = coefficents;
+ /** @type {Array<number>} */ this.pixelCoord = coords;
+ /** @type {boolean} */ this.isAlive = true;
+ /** @type {boolean} */ this.stencilPassed = true;
+ /** @type {boolean} */ this.depthPassed = true;
+ /** @type {Array<number>} */ this.sampleDepths = [depth];
+ /** @type {Array<number>} */ this.clampedBlendSrcColor = [];
+ /** @type {Array<number>} */ this.clampedBlendSrc1Color = [];
+ /** @type {Array<number>} */ this.clampedBlendDstColor = [];
+ /** @type {Array<number>} */ this.blendSrcFactorRGB = [];
+ /** @type {number} */ this.blendSrcFactorA = NaN;
+ /** @type {Array<number>} */ this.blendDstFactorRGB = [];
+ /** @type {number} */ this.blendDstFactorA = NaN;
+ /** @type {Array<number>} */ this.blendedRGB = [];
+ /** @type {number} */ this.blendedA = NaN;
+ /** @type {Array<number>} */ this.signedValue = []; //!< integer targets
+ /** @type {Array<number>} */ this.unsignedValue = []; //!< unsigned integer targets
+ /** @type {Array<number>} */ this.value = []; /*TODO: what type should it be? */
+ /** @type {Array<number>} */ this.value1 = []; /*TODO: what type should it be? */
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {rrRenderState.WindowRectangle} scissorRect
+ */
+rrFragmentOperations.executeScissorTest = function(inputFragments, scissorRect) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ if (!rrFragmentOperations.isInsideRect(frag.pixelCoord, scissorRect))
+ frag.isAlive = false;
+ }
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {rrRenderState.StencilState} stencilState
+ * @param {number} numStencilBits
+ * @param {tcuTexture.PixelBufferAccess} stencilBuffer
+ */
+rrFragmentOperations.executeStencilCompare = function(inputFragments, stencilState, numStencilBits, stencilBuffer) {
+ var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1);
+
+ /**
+ * @param {function(number=,number=):boolean} expression
+ */
+ var sample_register_stencil_compare = function(expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var fragSampleNdx = 0;
+ var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ var maskedRef = stencilState.compMask & clampedStencilRef;
+ var maskedBuf = stencilState.compMask & stencilBufferValue;
+ frag.stencilPassed = expression(maskedRef, maskedBuf);
+ }
+ }
+ };
+
+ switch (stencilState.func) {
+ case rrRenderState.TestFunc.NEVER: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return false;}); break;
+ case rrRenderState.TestFunc.ALWAYS: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return true;}); break;
+ case rrRenderState.TestFunc.LESS: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef < maskedBuf;}); break;
+ case rrRenderState.TestFunc.LEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef <= maskedBuf;}); break;
+ case rrRenderState.TestFunc.GREATER: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef > maskedBuf;}); break;
+ case rrRenderState.TestFunc.GEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef >= maskedBuf;}); break;
+ case rrRenderState.TestFunc.EQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef == maskedBuf;}); break;
+ case rrRenderState.TestFunc.NOTEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef != maskedBuf;}); break;
+ default:
+ throw new Error('Unrecognized stencil test function:' + stencilState.func);
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {rrRenderState.StencilState} stencilState
+ * @param {number} numStencilBits
+ * @param {tcuTexture.PixelBufferAccess} stencilBuffer
+ */
+rrFragmentOperations.executeStencilSFail = function(inputFragments, stencilState, numStencilBits, stencilBuffer) {
+ var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1);
+ /**
+ * @param {function(number,number):number} expression
+ */
+ var sample_register_sfail = function(expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive && !frag.stencilPassed) {
+ var fragSampleNdx = 0;
+ var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ stencilBuffer.setPixStencil(rrFragmentOperations.maskedBitReplace(stencilBufferValue, expression(stencilBufferValue, numStencilBits), stencilState.writeMask), fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ frag.isAlive = false;
+ }
+ }
+ };
+
+ switch (stencilState.sFail) {
+ case rrRenderState.StencilOp.KEEP:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return stencilBufferValue;}); break;
+ case rrRenderState.StencilOp.ZERO:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return 0;}); break;
+ case rrRenderState.StencilOp.REPLACE:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return clampedStencilRef;}); break;
+ case rrRenderState.StencilOp.INCR:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.DECR:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.INCR_WRAP:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (stencilBufferValue + 1) & ((1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.DECR_WRAP:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (stencilBufferValue - 1) & ((1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.INVERT:
+ sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (~stencilBufferValue) & ((1 << numStencilBits) - 1);}); break;
+ default:
+ throw new Error('Unrecognized stencil op:' + stencilState.sFail);
+ }
+
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {rrRenderState.TestFunc} depthFunc
+ * @param {tcuTexture.PixelBufferAccess} depthBuffer
+ */
+rrFragmentOperations.executeDepthCompare = function(inputFragments, depthFunc, depthBuffer) {
+ /**
+ * @param {function(number=,number=):boolean} expression
+ */
+ var convertToDepthBuffer = false;
+
+ var access;
+ if (depthBuffer.getFormat().type != tcuTexture.ChannelType.FLOAT &&
+ depthBuffer.getFormat().type != tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV) {
+ access = new tcuTexture.PixelBufferAccess({
+ format: depthBuffer.getFormat(),
+ width: 1,
+ height: 1,
+ depth: 1,
+ data: new ArrayBuffer(8)
+ });
+ convertToDepthBuffer = true;
+ }
+
+ var sample_register_depth_compare = function(expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var fragSampleNdx = 0;
+ var depthBufferValue = depthBuffer.getPixDepth(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ var sampleDepthFloat = frag.sampleDepths[fragSampleNdx];
+
+ var sampleDepth;
+ if (convertToDepthBuffer) {
+ /* convert input float to target buffer format for comparison */
+ access.setPixDepth(sampleDepthFloat, 0, 0, 0);
+ sampleDepth = access.getPixDepth(0, 0, 0);
+ } else {
+ sampleDepth = deMath.clamp(sampleDepthFloat, 0.0, 1.0);
+ }
+
+ frag.depthPassed = expression(sampleDepth, depthBufferValue);
+ }
+ }
+ };
+
+ switch (depthFunc) {
+ case rrRenderState.TestFunc.NEVER: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return false;}); break;
+ case rrRenderState.TestFunc.ALWAYS: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return true;}); break;
+ case rrRenderState.TestFunc.LESS: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth < depthBufferValue;}); break;
+ case rrRenderState.TestFunc.LEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth <= depthBufferValue;}); break;
+ case rrRenderState.TestFunc.GREATER: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth > depthBufferValue;}); break;
+ case rrRenderState.TestFunc.GEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth >= depthBufferValue;}); break;
+ case rrRenderState.TestFunc.EQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth == depthBufferValue;}); break;
+ case rrRenderState.TestFunc.NOTEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth != depthBufferValue;}); break;
+ default:
+ throw new Error('Unrecognized depth function:' + depthFunc);
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {tcuTexture.PixelBufferAccess} depthBuffer
+ */
+rrFragmentOperations.executeDepthWrite = function(inputFragments, depthBuffer) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive && frag.depthPassed) {
+ var fragSampleNdx = 0;
+ var clampedDepth = deMath.clamp(frag.sampleDepths[fragSampleNdx], 0.0, 1.0);
+ depthBuffer.setPixDepth(clampedDepth, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ }
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {rrRenderState.StencilState} stencilState
+ * @param {number} numStencilBits
+ * @param {tcuTexture.PixelBufferAccess} stencilBuffer
+ */
+rrFragmentOperations.executeStencilDpFailAndPass = function(inputFragments, stencilState, numStencilBits, stencilBuffer) {
+ var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1);
+
+ /**
+ * @param {function(boolean):boolean} condition
+ * @param {function(number,number):number} expression
+ */
+ var sample_register_dpfail_or_dppass = function(condition, expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive && condition(frag.depthPassed)) {
+ var fragSampleNdx = 0;
+ var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ stencilBuffer.setPixStencil(rrFragmentOperations.maskedBitReplace(stencilBufferValue, expression(stencilBufferValue, numStencilBits), stencilState.writeMask), fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ }
+ }
+ };
+
+ var switch_dpfail_or_dppass = function(op_name, condition) {
+ switch (stencilState[op_name]) {
+ case rrRenderState.StencilOp.KEEP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return stencilBufferValue;}); break;
+ case rrRenderState.StencilOp.ZERO: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return 0;}); break;
+ case rrRenderState.StencilOp.REPLACE: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return clampedStencilRef;}); break;
+ case rrRenderState.StencilOp.INCR: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.DECR: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.INCR_WRAP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (stencilBufferValue + 1) & ((1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.DECR_WRAP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (stencilBufferValue - 1) & ((1 << numStencilBits) - 1);}); break;
+ case rrRenderState.StencilOp.INVERT: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (~stencilBufferValue) & ((1 << numStencilBits) - 1);}); break;
+ default:
+ throw new Error('Unrecognized stencil operation:' + op_name);
+ }
+ };
+
+ var passed = function(depthPassed) { return depthPassed;};
+ var failed = function(depthPassed) { return !depthPassed;};
+
+ switch_dpfail_or_dppass('dpFail', failed);
+ switch_dpfail_or_dppass('dpPass', passed);
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {Array<number>} blendColor
+ * @param {rrRenderState.BlendState} blendRGBState
+ */
+rrFragmentOperations.executeBlendFactorComputeRGB = function(inputFragments, blendColor, blendRGBState) {
+ /**
+ * @param {string} factor_name
+ * @param {function(Array<number>, Array<number>, Array<number>):Array<number>} expression
+ */
+ var sample_register_blend_factor = function(factor_name, expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var src = frag.clampedBlendSrcColor;
+ var src1 = frag.clampedBlendSrc1Color;
+ var dst = frag.clampedBlendDstColor;
+ frag[factor_name] = deMath.clampVector(expression(src, src1, dst), 0, 1);
+ }
+ }
+ };
+
+ var switch_src_or_dst_factor_rgb = function(func_name, factor_name) {
+ switch (blendRGBState[func_name]) {
+ case rrRenderState.BlendFunc.ZERO:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [0, 0, 0];}); break;
+ case rrRenderState.BlendFunc.ONE:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1, 1, 1];}); break;
+ case rrRenderState.BlendFunc.SRC_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(src, [0, 1, 2]);}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(src, [0, 1, 2]));}); break;
+ case rrRenderState.BlendFunc.DST_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(dst, [0, 1, 2]);}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(dst, [0, 1, 2]));}); break;
+ case rrRenderState.BlendFunc.SRC_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [src[3], src[3], src[3]];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - src[3], 1.0 - src[3], 1.0 - src[3]];}); break;
+ case rrRenderState.BlendFunc.DST_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [dst[3], dst[3], dst[3]];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - dst[3], 1.0 - dst[3], 1.0 - dst[3]];}); break;
+ case rrRenderState.BlendFunc.CONSTANT_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(blendColor, [0, 1, 2]);}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(blendColor, [0, 1, 2]));}); break;
+ case rrRenderState.BlendFunc.CONSTANT_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [blendColor[3], blendColor[3], blendColor[3]];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - blendColor[3], 1.0 - blendColor[3], 1.0 - blendColor[3]];}); break;
+ case rrRenderState.BlendFunc.SRC_ALPHA_SATURATE:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [Math.min(src[3], 1.0 - dst[3]), Math.min(src[3], 1.0 - dst[3]), Math.min(src[3], 1.0 - dst[3])];}); break;
+ case rrRenderState.BlendFunc.SRC1_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(src1, [0, 1, 2]);}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(src1, [0, 1, 2]));}); break;
+ case rrRenderState.BlendFunc.SRC1_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [src1[3], src1[3], src1[3]];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - src1[3], 1.0 - src1[3], 1.0 - src1[3]];}); break;
+ default:
+ throw new Error('Unrecognized blend function:' + func_name);
+ }
+ };
+
+ switch_src_or_dst_factor_rgb('srcFunc', 'blendSrcFactorRGB');
+ switch_src_or_dst_factor_rgb('dstFunc', 'blendDstFactorRGB');
+
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {Array<number>} blendColor
+ * @param {rrRenderState.BlendState} blendAState
+ */
+rrFragmentOperations.executeBlendFactorComputeA = function(inputFragments, blendColor, blendAState) {
+ /**
+ * @param {string} factor_name
+ * @param {function(Array<number>, Array<number>, Array<number>):number} expression
+ */
+ var sample_register_blend_factor = function(factor_name, expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var src = frag.clampedBlendSrcColor;
+ var src1 = frag.clampedBlendSrc1Color;
+ var dst = frag.clampedBlendDstColor;
+ frag[factor_name] = deMath.clamp(expression(src, src1, dst), 0, 1);
+ }
+ }
+ };
+
+ var swictch_src_or_dst_factor_a = function(func_name, factor_name) {
+ switch (blendAState[func_name]) {
+ case rrRenderState.BlendFunc.ZERO:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 0.0;}); break;
+ case rrRenderState.BlendFunc.ONE:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0;}); break;
+ case rrRenderState.BlendFunc.SRC_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return src[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src[3];}); break;
+ case rrRenderState.BlendFunc.DST_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return dst[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - dst[3];}); break;
+ case rrRenderState.BlendFunc.SRC_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return src[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src[3];}); break;
+ case rrRenderState.BlendFunc.DST_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return dst[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - dst[3];}); break;
+ case rrRenderState.BlendFunc.CONSTANT_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return blendColor[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - blendColor[3];}); break;
+ case rrRenderState.BlendFunc.CONSTANT_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return blendColor[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - blendColor[3];}); break;
+ case rrRenderState.BlendFunc.SRC_ALPHA_SATURATE:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0;}); break;
+ case rrRenderState.BlendFunc.SRC1_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return src1[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src1[3];}); break;
+ case rrRenderState.BlendFunc.SRC1_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return src1[3];}); break;
+ case rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA:
+ sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src1[3];}); break;
+ default:
+ throw new Error('Unrecognized blend function:' + func_name);
+ }
+ };
+
+ swictch_src_or_dst_factor_a('srcFunc', 'blendSrcFactorA');
+ swictch_src_or_dst_factor_a('dstFunc', 'blendDstFactorA');
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
+ * @param {rrRenderState.BlendState} blendRGBState
+ * @param {rrRenderState.BlendState} blendAState
+ */
+rrFragmentOperations.executeBlend = function(inputFragments, blendRGBState, blendAState) {
+ var sample_register_blended_color = function(color_name, expression) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var src = frag.clampedBlendSrcColor;
+ var dst = frag.clampedBlendDstColor;
+ frag[color_name] = expression(src, dst, frag);
+ }
+ }
+ };
+
+ switch (blendRGBState.equation) {
+ case rrRenderState.BlendEquation.ADD:
+ sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.add(deMath.multiply(deMath.swizzle(src, [0, 1, 2]), frag.blendSrcFactorRGB), deMath.multiply(deMath.swizzle(dst, [0, 1, 2]), frag.blendDstFactorRGB));}); break;
+ case rrRenderState.BlendEquation.SUBTRACT:
+ sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.subtract(deMath.multiply(deMath.swizzle(src, [0, 1, 2]), frag.blendSrcFactorRGB), deMath.multiply(deMath.swizzle(dst, [0, 1, 2]), frag.blendDstFactorRGB));}); break;
+ case rrRenderState.BlendEquation.REVERSE_SUBTRACT:
+ sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.subtract(deMath.multiply(deMath.swizzle(dst, [0, 1, 2]), frag.blendDstFactorRGB), deMath.multiply(deMath.swizzle(src, [0, 1, 2]), frag.blendSrcFactorRGB));}); break;
+ case rrRenderState.BlendEquation.MIN:
+ sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.min(deMath.swizzle(src, [0, 1, 2]), deMath.swizzle(dst, [0, 1, 2]));}); break;
+ case rrRenderState.BlendEquation.MAX:
+ sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.max(deMath.swizzle(src, [0, 1, 2]), deMath.swizzle(dst, [0, 1, 2]));}); break;
+ default:
+ throw new Error('Unrecognized blend equation:' + blendRGBState.equation);
+ }
+
+ switch (blendAState.equation) {
+ case rrRenderState.BlendEquation.ADD:
+ sample_register_blended_color('blendedA', function(src, dst, frag) { return src[3] * frag.blendSrcFactorA + dst[3] * frag.blendDstFactorA;}); break;
+ case rrRenderState.BlendEquation.SUBTRACT:
+ sample_register_blended_color('blendedA', function(src, dst, frag) { return src[3] * frag.blendSrcFactorA - dst[3] * frag.blendDstFactorA;}); break;
+ case rrRenderState.BlendEquation.REVERSE_SUBTRACT:
+ sample_register_blended_color('blendedA', function(src, dst, frag) { return dst[3] * frag.blendDstFactorA - src[3] * frag.blendSrcFactorA;}); break;
+ case rrRenderState.BlendEquation.MIN:
+ sample_register_blended_color('blendedA', function(src, dst, frag) { return Math.min(src[3], dst[3]);}); break;
+ case rrRenderState.BlendEquation.MAX:
+ sample_register_blended_color('blendedA', function(src, dst, frag) { return Math.max(src[3], dst[3]);}); break;
+ default:
+ throw new Error('Unrecognized blend equation:' + blendAState.equation);
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments
+ * @param {boolean} isSRGB
+ * @param {tcuTexture.PixelBufferAccess} colorBuffer
+ */
+rrFragmentOperations.executeColorWrite = function(inputFragments, isSRGB, colorBuffer) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var combinedColor = frag.blendedRGB.slice();
+ combinedColor[3] = frag.blendedA;
+ if (isSRGB)
+ combinedColor = tcuTextureUtil.linearToSRGB(combinedColor);
+
+ colorBuffer.setPixel(combinedColor, 0, frag.pixelCoord[0], frag.pixelCoord[1]);
+ }
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments
+ * @param {Array<boolean>} colorMaskFactor
+ * @param {Array<boolean>} colorMaskNegationFactor
+ * @param {boolean} isSRGB
+ * @param {tcuTexture.PixelBufferAccess} colorBuffer
+ */
+rrFragmentOperations.executeMaskedColorWrite = function(inputFragments, colorMaskFactor, colorMaskNegationFactor, isSRGB, colorBuffer) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var fragSampleNdx = 0;
+ var originalColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ var newColor = frag.blendedRGB.slice();
+ newColor[3] = frag.blendedA;
+
+ if (isSRGB)
+ newColor = tcuTextureUtil.linearToSRGB(newColor);
+
+ newColor = deMath.add(deMath.multiply(colorMaskFactor, newColor), deMath.multiply(colorMaskNegationFactor, originalColor));
+
+ colorBuffer.setPixel(newColor, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ }
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments
+ * @param {Array<boolean>} colorMask
+ * @param {tcuTexture.PixelBufferAccess} colorBuffer
+ */
+rrFragmentOperations.executeSignedValueWrite = function(inputFragments, colorMask, colorBuffer) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var fragSampleNdx = 0;
+ var originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ var newValue = tcuTextureUtil.select(frag.signedValue, originalValue, colorMask);
+
+ colorBuffer.setPixelInt(newValue, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ }
+ }
+};
+
+/**
+ * @param {Array<rrFragmentOperations.Fragment>} inputFragments
+ * @param {Array<boolean>} colorMask
+ * @param {tcuTexture.PixelBufferAccess} colorBuffer
+ */
+rrFragmentOperations.executeUnsignedValueWrite = function(inputFragments, colorMask, colorBuffer) {
+ for (var i = 0; i < inputFragments.length; i++) {
+ var frag = inputFragments[i];
+ if (frag.isAlive) {
+ var fragSampleNdx = 0;
+ var originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ var newValue = tcuTextureUtil.select(frag.unsignedValue, originalValue, colorMask);
+
+ colorBuffer.setPixelInt(newValue, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]);
+ }
+ }
+};
+
+/**
+ * @constructor
+ */
+rrFragmentOperations.FragmentProcessor = function() {
+ /* TODO: implement */
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js
new file mode 100644
index 0000000000..62a92a4227
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrGenericVector.js
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrGenericVector');
+
+goog.scope(function() {
+
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * rrGenericVector.GenericVecType
+ * @enum
+ */
+ rrGenericVector.GenericVecType = {
+ FLOAT: 0,
+ UINT32: 1,
+ INT32: 2
+ };
+
+ /**
+ * @constructor
+ * @param {number=} a
+ * @param {number=} b
+ * @param {number=} c
+ * @param {number=} d
+ */
+ rrGenericVector.GenericVec4 = function(a, b, c, d) {
+ this.data = [a || 0, b || 0, c || 0, d || 0];
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js
new file mode 100644
index 0000000000..6de1ca2701
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrMultisamplePixelBufferAccess.js
@@ -0,0 +1,190 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+
+var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+};
+
+/**
+ * \brief Read-write pixel data access to multisampled buffers.
+ *
+ * Multisampled data access follows the multisampled indexing convention.
+ *
+ * Prevents accidental usage of non-multisampled buffer as multisampled
+ * with PixelBufferAccess.
+ * @constructor
+ * @param {tcuTexture.PixelBufferAccess=} rawAccess
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess = function(rawAccess) {
+ this.m_access = rawAccess || new tcuTexture.PixelBufferAccess({
+ width: 0,
+ height: 0});
+};
+
+/**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.raw = function() { return this.m_access; };
+
+/**
+ * @return {boolean}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.isEmpty = function() { return this.m_access.isEmpty(); };
+
+/**
+ * @return {number}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.getNumSamples = function() { return this.raw().getWidth(); };
+
+/**
+ * @return {tcuTexture.PixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.toSinglesampleAccess = function() {
+ DE_ASSERT(this.getNumSamples() == 1);
+
+ return new tcuTexture.PixelBufferAccess({
+ format: this.m_access.getFormat(),
+ width: this.m_access.getHeight(),
+ height: this.m_access.getDepth(),
+ depth: 1,
+ rowPitch: this.m_access.getSlicePitch(),
+ slicePitch: this.m_access.getSlicePitch() * this.m_access.getDepth(),
+ data: this.m_access.m_data,
+ offset: this.m_access.m_offset});
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} original
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess = function(original) {
+ return new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess(
+ new tcuTexture.PixelBufferAccess({
+ format: original.getFormat(),
+ width: 1,
+ height: original.getWidth(),
+ depth: original.getHeight(),
+ rowPitch: original.getFormat().getPixelSize(),
+ slicePitch: original.getRowPitch(),
+ data: original.m_data,
+ offset: original.m_offset}));
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} multisampledAccess
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess = function(multisampledAccess) {
+ return new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess(multisampledAccess);
+};
+
+/**
+ * @param {Array<number>} region
+ * @return {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.getSubregion = function(region) {
+ var x = region[0];
+ var y = region[1];
+ var width = region[2];
+ var height = region[3];
+
+ return rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromMultisampleAccess(tcuTextureUtil.getSubregion(this.raw(), 0, x, y, this.getNumSamples(), width, height));
+};
+
+/**
+ * @return {Array<number>} [x, y, width, height]
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.getBufferSize = function() {
+ return [0, 0, this.raw().getHeight(), this.raw().getDepth()];
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} dst
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.resolveMultisampleColorBuffer = function(dst) {
+ var src = this;
+ DE_ASSERT(dst.getWidth() == src.raw().getHeight());
+ DE_ASSERT(dst.getHeight() == src.raw().getDepth());
+
+ var numSamples = src.getNumSamples();
+ var sum = [0, 0, 0, 0];
+ for (var y = 0; y < dst.getHeight(); y++) {
+ for (var x = 0; x < dst.getWidth(); x++) {
+ sum[0] = 0;
+ sum[1] = 0;
+ sum[2] = 0;
+ sum[3] = 0;
+
+ for (var s = 0; s < src.raw().getWidth(); s++) {
+ var pixel = src.raw().getPixel(s, x, y);
+ sum[0] += pixel[0];
+ sum[1] += pixel[1];
+ sum[2] += pixel[2];
+ sum[3] += pixel[3];
+ }
+
+ sum[0] /= numSamples;
+ sum[1] /= numSamples;
+ sum[2] /= numSamples;
+ sum[3] /= numSamples;
+
+ dst.setPixel(sum, x, y);
+ }
+ }
+};
+
+/**
+ * @param {number} x
+ * @param {number} y
+ * @return {Array<number>}
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.resolveMultisamplePixel = function(x, y) {
+ var sum = [0, 0, 0, 0];
+ for (var s = 0; s < this.getNumSamples(); s++)
+ sum = deMath.add(sum, this.raw().getPixel(s, x, y));
+
+ for (var i = 0; i < sum.length; i++)
+ sum[i] = sum[i] / this.getNumSamples();
+
+ return sum;
+};
+
+/**
+ * @param {Array<number>} color
+ */
+rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.prototype.clear = function(color) {
+ this.raw().clear(color);
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js
new file mode 100644
index 0000000000..cac4dc56a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderState.js
@@ -0,0 +1,323 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Reference Renderer
+ * -----------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Reference renderer render state.
+ *//*--------------------------------------------------------------------*/
+'use strict';
+goog.provide('framework.referencerenderer.rrRenderState');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+
+goog.scope(function() {
+
+var rrRenderState = framework.referencerenderer.rrRenderState;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var rrDefs = framework.referencerenderer.rrDefs;
+
+/**
+ * Enum for rrRenderState.HorizontalFill values.
+ * @enum {number}
+ */
+rrRenderState.HorizontalFill = {
+ LEFT: 0,
+ RIGHT: 1
+};
+
+/**
+ * Enum for rrRenderState.VerticalFill values.
+ * @enum {number}
+ */
+rrRenderState.VerticalFill = {
+ TOP: 0,
+ BOTTOM: 1
+};
+
+/**
+ * Enum for rrRenderState.Winding values.
+ * @enum {number}
+ */
+rrRenderState.Winding = {
+ CCW: 0,
+ CC: 1
+};
+
+/**
+ * Enum for rrRenderState.CullMode values.
+ * @enum {number}
+ */
+rrRenderState.CullMode = {
+ NONE: 0,
+ BACK: 1,
+ FRONT: 2
+};
+
+/**rrRenderState.Winding : rrRenderState.Winding,
+
+ * @constructor
+ */
+rrRenderState.RasterizationState = function() {
+ /** @type {number} */ this.winding = rrRenderState.Winding.CCW;
+ /** @type {number} */ this.horizontalFill = rrRenderState.HorizontalFill.LEFT;
+ /** @type {number} */ this.verticalFill = rrRenderState.VerticalFill.BOTTOM;
+};
+
+/**
+ * Enum for rrRenderState.TestFunc values.
+ * @enum {number}
+ */
+rrRenderState.TestFunc = {
+ NEVER: 0,
+ ALWAYS: 1,
+ LESS: 2,
+ LEQUAL: 3,
+ GREATER: 4,
+ GEQUAL: 5,
+ EQUAL: 6,
+ NOTEQUAL: 7
+};
+
+/**
+ * Enum for rrRenderState.StencilOp values.
+ * @enum {number}
+ */
+rrRenderState.StencilOp = {
+ KEEP: 0,
+ ZERO: 1,
+ REPLACE: 2,
+ INCR: 3, //!< Increment with saturation.
+ DECR: 4, //!< Decrement with saturation.
+ INCR_WRAP: 5,
+ DECR_WRAP: 6,
+ INVERT: 7
+};
+
+/**
+ * Enum for rrRenderState.BlendMode values.
+ * @enum {number}
+ */
+rrRenderState.BlendMode = {
+ NONE: 0, //!< No blending.
+ STANDARD: 1 //!< Standard blending.
+// Advanced blending is not supported
+// ADVANCED : 2 //!< Advanced blending mode, as defined in gl.KHR_blend_equation_advanced.
+};
+
+/**
+ * Enum for rrRenderState.BlendEquation values.
+ * @enum {number}
+ */
+rrRenderState.BlendEquation = {
+ ADD: 0,
+ SUBTRACT: 1,
+ REVERSE_SUBTRACT: 2,
+ MIN: 3,
+ MAX: 4
+};
+
+// /**
+// * Enum for rrRenderState.BlendEquationAdvanced values.
+// * @enum {number}
+// */
+// rrRenderState.BlendEquationAdvanced = {
+// MULTIPLY : 0,
+// SCREEN : 1,
+// OVERLAY : 2,
+// DARKEN : 3,
+// LIGHTEN : 4,
+// COLORDODGE : 5,
+// COLORBURN : 6,
+// HARDLIGHT : 7,
+// SOFTLIGHT : 8,
+// DIFFERENCE : 9,
+// EXCLUSION : 10,
+// HSL_HUE : 11,
+// HSL_SATURATION : 12,
+// HSL_COLOR : 13,
+// HSL_LUMINOSITY : 14
+// };
+
+/**
+ * Enum for rrRenderState.BlendFunc values.
+ * @enum {number}
+ */
+rrRenderState.BlendFunc = {
+ ZERO: 0,
+ ONE: 1,
+ SRC_COLOR: 2,
+ ONE_MINUS_SRC_COLOR: 3,
+ DST_COLOR: 4,
+ ONE_MINUS_DST_COLOR: 5,
+ SRC_ALPHA: 6,
+ ONE_MINUS_SRC_ALPHA: 7,
+ DST_ALPHA: 8,
+ ONE_MINUS_DST_ALPHA: 9,
+ CONSTANT_COLOR: 10,
+ ONE_MINUS_CONSTANT_COLOR: 11,
+ CONSTANT_ALPHA: 12,
+ ONE_MINUS_CONSTANT_ALPHA: 13,
+ SRC_ALPHA_SATURATE: 14,
+ SRC1_COLOR: 15,
+ ONE_MINUS_SRC1_COLOR: 16,
+ SRC1_ALPHA: 17,
+ ONE_MINUS_SRC1_ALPHA: 18
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.StencilState = function() {
+ /** @type {number} */ this.func = rrRenderState.TestFunc.ALWAYS;
+ /** @type {number} */ this.ref = 0;
+ /** @type {number} */ this.compMask = ~0;
+ /** @type {number} */ this.sFail = rrRenderState.StencilOp.KEEP;
+ /** @type {number} */ this.dpFail = rrRenderState.StencilOp.KEEP;
+ /** @type {number} */ this.dpPass = rrRenderState.StencilOp.KEEP;
+ /** @type {number} */ this.writeMask = ~0;
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.BlendState = function() {
+ /** @type {number} */ this.equation = rrRenderState.BlendEquation.ADD;
+ /** @type {number} */ this.srcFunc = rrRenderState.BlendFunc.ONE;
+ /** @type {number} */ this.dstFunc = rrRenderState.BlendFunc.ZERO;
+};
+
+/**
+ * @param {(Array<number>|number)} left_
+ * @param {number=} bottom_
+ * @param {number=} width_
+ * @param {number=} height_
+ * @constructor
+ */
+rrRenderState.WindowRectangle = function(left_, bottom_, width_, height_) {
+ // Is first parameter an array? Use it
+ if (left_.length && left_.length == 4) {
+ this.left = left_[0];
+ this.bottom = left_[1];
+ this.width = left_[2];
+ this.height = left_[3];
+ } else {
+ this.left = left_;
+ this.bottom = bottom_;
+ this.width = width_;
+ this.height = height_;
+ }
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.FragmentOperationState = function() {
+ /** @type {boolean} */ this.scissorTestEnabled = false;
+ /** @type {rrRenderState.WindowRectangle} */ this.scissorRectangle = new rrRenderState.WindowRectangle(0, 0, 1, 1);
+
+ /** @type {boolean} */ this.stencilTestEnabled = false;
+
+ /** @type {Array<rrRenderState.StencilState>} */ this.stencilStates = [];
+ for (var type in rrDefs.FaceType)
+ this.stencilStates[rrDefs.FaceType[type]] = new rrRenderState.StencilState();
+
+ /** @type {boolean} */ this.depthTestEnabled = false;
+ /** @type {rrRenderState.TestFunc} */ this.depthFunc = rrRenderState.TestFunc.LESS;
+ /** @type {boolean} */ this.depthMask = true;
+
+ /** @type {rrRenderState.BlendMode} */ this.blendMode = rrRenderState.BlendMode.NONE;
+ /** @type {rrRenderState.BlendState} */ this.blendRGBState = new rrRenderState.BlendState();
+ /** @type {rrRenderState.BlendState} */ this.blendAState = new rrRenderState.BlendState();
+ /** @type {Array<number>} */ this.blendColor = [0.0, 0.0, 0.0, 0.0];
+// /** @type {rrRenderState.BlendEquationAdvanced} */ this.blendEquationAdvanced = null;
+
+ /** @type {boolean} */ this.sRGBEnabled = true;
+
+ /** @type {boolean} */ this.depthClampEnabled = false;
+
+ /** @type {boolean} */ this.polygonOffsetEnabled = false;
+ /** @type {number} */ this.polygonOffsetFactor = 0.0;
+ /** @type {number} */ this.polygonOffsetUnits = 0.0;
+
+ /** @type {Array<boolean>} */ this.colorMask = [true, true, true, true];
+
+ /** @type {number} */ this.numStencilBits = 8;
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.PointState = function() {
+ /** @type {number} */ this.pointSize = 1.0;
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.LineState = function() {
+ /** @type {number} */ this.lineWidth = 1.0;
+};
+
+/**
+ * Constructor checks if the parameter has a "raw" member to detect if the instance is
+ * of type rrRenderState.WindowRectangle or MultisamplePixelBufferAccess.
+ * @param {rrRenderState.WindowRectangle|rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} rect_
+ * @constructor
+ */
+rrRenderState.ViewportState = function(rect_) {
+ /** @type {number} */ this.zn = 0.0;
+ /** @type {number} */ this.zf = 1.0;
+ /** @type {rrRenderState.WindowRectangle} */ this.rect;
+
+ if (rect_.raw) {
+ this.rect = new rrRenderState.WindowRectangle(0, 0, rect_.raw().getHeight(),
+ rect_.raw().getDepth());
+ } else {
+ this.rect = /** @type {rrRenderState.WindowRectangle} */ (rect_);
+ }
+};
+
+/**
+ * @constructor
+ */
+rrRenderState.RestartState = function() {
+ /** @type {boolean} */ this.enabled = false;
+ /** @type {number} */ this.restartIndex = 0xFFFFFFFF;
+};
+
+/**
+ * @constructor
+ * @param {rrRenderState.ViewportState} viewport_
+ */
+rrRenderState.RenderState = function(viewport_) {
+ /** @type {rrRenderState.CullMode} */ this.cullMode = rrRenderState.CullMode.NONE;
+ /** @type {number} */ this.provokingVertexConvention;
+ /** @type {rrRenderState.ViewportState} */ this.viewport = viewport_;
+
+ /** @type {rrRenderState.RasterizationState} */ this.rasterization = new rrRenderState.RasterizationState();
+ /** @type {rrRenderState.FragmentOperationState} */ this.fragOps = new rrRenderState.FragmentOperationState();
+ /** @type {rrRenderState.PointState} */ this.point = new rrRenderState.PointState();
+ /** @type {rrRenderState.LineState} */ this.line = new rrRenderState.LineState();
+ /** @type {rrRenderState.RestartState} */ this.restart = new rrRenderState.RestartState();
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js
new file mode 100644
index 0000000000..4d5752b2c4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrRenderer.js
@@ -0,0 +1,1274 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrRenderer');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.delibs.debase.deUtil');
+goog.require('framework.opengl.simplereference.sglrShaderProgram');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
+goog.require('framework.referencerenderer.rrRenderState');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+var rrRenderer = framework.referencerenderer.rrRenderer;
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+var rrDefs = framework.referencerenderer.rrDefs;
+var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+var deMath = framework.delibs.debase.deMath;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuTexture = framework.common.tcuTexture;
+var rrRenderState = framework.referencerenderer.rrRenderState;
+var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
+var rrShadingContext = framework.referencerenderer.rrShadingContext;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var deString = framework.delibs.debase.deString;
+var deUtil = framework.delibs.debase.deUtil;
+
+/**
+ * @enum
+ */
+rrRenderer.PrimitiveType = {
+ TRIANGLES: 0, //!< Separate rrRenderer.triangles
+ TRIANGLE_STRIP: 1, //!< rrRenderer.Triangle strip
+ TRIANGLE_FAN: 2, //!< rrRenderer.Triangle fan
+
+ LINES: 3, //!< Separate lines
+ LINE_STRIP: 4, //!< Line strip
+ LINE_LOOP: 5, //!< Line loop
+
+ POINTS: 6 //!< Points
+};
+
+// /**
+// * @constructor
+// * @param {boolean} depthEnabled Is depth buffer enabled
+// */
+// rrRenderer.RasterizationInternalBuffers = function(depthEnabled) {
+// /*std::vector<rrFragmentOperations.Fragment>*/ this.fragmentPackets = [];
+// /*std::vector<GenericVec4>*/ this.shaderOutputs = [];
+// /*std::vector<Fragment>*/ this.shadedFragments = [];
+// /*float**/ this.fragmentDepthBuffer = depthEnabled ? [] : null;
+// };
+
+/**
+ * @constructor
+ * @param {number=} id
+ */
+rrRenderer.DrawContext = function(id) {
+ this.primitiveID = id || 0;
+
+};
+
+/**
+ * Transform [x, y] to window (pixel) coordinates.
+ * z and w are unchanged
+ * @param {rrRenderState.RenderState} state
+ * @param {rrVertexPacket.VertexPacket} packet
+ * Wreturn {Array<number>}
+ */
+rrRenderer.transformGLToWindowCoords = function(state, packet) {
+ var transformed = [packet.position[0] / packet.position[3],
+ packet.position[1] / packet.position[3],
+ packet.position[2],
+ packet.position[3]];
+ var viewport = state.viewport.rect;
+ var halfW = viewport.width / 2;
+ var halfH = viewport.height / 2;
+ var oX = viewport.left + halfW;
+ var oY = viewport.bottom + halfH;
+
+ return [
+ transformed[0] * halfW + oX,
+ transformed[1] * halfH + oY,
+ transformed[2],
+ transformed[3]
+ ];
+};
+
+/**
+ * @constructor
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess} colorMultisampleBuffer
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess=} depthMultisampleBuffer
+ * @param {rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess=} stencilMultisampleBuffer
+ */
+rrRenderer.RenderTarget = function(colorMultisampleBuffer, depthMultisampleBuffer, stencilMultisampleBuffer) {
+ this.MAX_COLOR_BUFFERS = 4;
+ this.colorBuffers = [];
+ this.colorBuffers[0] = colorMultisampleBuffer;
+ this.depthBuffer = depthMultisampleBuffer || new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess();
+ this.stencilBuffer = stencilMultisampleBuffer || new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess();
+ this.numColorBuffers = 1;
+};
+
+// NOTE: Program object is useless. Let's just use the sglrShaderProgram
+// /**
+// * @constructor
+// * @param {rrShaders.VertexShader} vertexShader_
+// * @param {rrShaders.FragmentShader} fragmentShader_
+// */
+// var Program = function(vertexShader_, fragmentShader_) {
+// this.vertexShader = vertexShader_;
+// this.fragmentShader = fragmentShader_;
+// };
+
+/**
+ * @constructor
+ * @param {ArrayBuffer} data
+ * @param {rrDefs.IndexType} type
+ * @param {number} offset
+ * @param {number=} baseVertex_
+ */
+rrRenderer.DrawIndices = function(data, type, offset, baseVertex_) {
+ /** @type {ArrayBuffer} */ this.data = data;
+ /** @type {number} */ this.baseVertex = baseVertex_ || 0;
+ /** @type {rrDefs.IndexType} */ this.indexType = type;
+ /** @type {goog.NumberArray} */ this.access = null;
+ switch (type) {
+ case rrDefs.IndexType.INDEXTYPE_UINT8: this.access = new Uint8Array(data).subarray(offset); break;
+ case rrDefs.IndexType.INDEXTYPE_UINT16: this.access = new Uint16Array(data).subarray(offset / 2); break;
+ case rrDefs.IndexType.INDEXTYPE_UINT32: this.access = new Uint32Array(data).subarray(offset / 4); break;
+ default: throw new Error('Invalid type: ' + type);
+ }
+};
+
+/**
+ * @return {number}
+ */
+rrRenderer.DrawIndices.prototype.readIndexArray = function(index) { return this.access[index]; };
+
+/**
+ * @constructor
+ * @param {rrRenderer.PrimitiveType} primitiveType
+ * @param {number} numElements
+ * @param {(number|rrRenderer.DrawIndices)} indices
+ */
+rrRenderer.PrimitiveList = function(primitiveType, numElements, indices) {
+ /** @type {rrRenderer.PrimitiveType} */ this.m_primitiveType = primitiveType;
+ /** @type {number} */ this.m_numElements = numElements;
+ if (typeof indices == 'number') {
+ // !< primitive list for drawArrays-like call
+ this.m_indices = null;
+ this.m_indexType = null;
+ this.m_baseVertex = indices;
+ } else {
+ // !< primitive list for drawElements-like call
+ this.m_indices = indices;
+ this.m_indexType = indices.indexType;
+ this.m_baseVertex = indices.baseVertex;
+ }
+ this.m_iterator = 0;
+};
+
+/**
+ * @param {number} elementNdx
+ * @return {number}
+ */
+rrRenderer.PrimitiveList.prototype.getIndex = function(elementNdx) {
+ if (this.m_indices) {
+ var index = this.m_baseVertex + this.m_indices.readIndexArray(elementNdx);
+ if (index < 0)
+ throw new Error('Index must not be negative');
+
+ return index;
+ } else
+ return this.m_baseVertex + elementNdx;
+};
+
+/**
+ * @param {number} elementNdx
+ * @param {number} restartIndex
+ * @return {boolean}
+ */
+rrRenderer.PrimitiveList.prototype.isRestartIndex = function(elementNdx, restartIndex) {
+ // implicit index or explicit index (without base vertex) equals restart
+ if (this.m_indices)
+ return this.m_indices.readIndexArray(elementNdx) == restartIndex;
+ else
+ return elementNdx == restartIndex;
+};
+
+/**
+ * @return {number}
+ */
+rrRenderer.PrimitiveList.prototype.getNumElements = function() {return this.m_numElements;};
+
+/**
+ * @return {rrRenderer.PrimitiveType}
+ */
+rrRenderer.PrimitiveList.prototype.getPrimitiveType = function() {return this.m_primitiveType;};
+
+/**
+ * @return {?rrDefs.IndexType}
+ */
+rrRenderer.PrimitiveList.prototype.getIndexType = function() {return this.m_indexType;};
+
+/**
+ * Generate a primitive from indices
+ * @param {boolean=} reset Restart generating primitives. Default false
+ * @return {Array<number>}
+ */
+rrRenderer.PrimitiveList.prototype.getNextPrimitive = function(reset) {
+ if (reset)
+ this.m_iterator = 0;
+ var result = [];
+ var i = this.m_iterator;
+ switch (this.m_primitiveType) {
+ case rrRenderer.PrimitiveType.TRIANGLES:
+ if (this.m_iterator + 3 <= this.m_numElements) {
+ result = [i, i + 1, i + 2];
+ this.m_iterator += 3;
+ }
+ break;
+ case rrRenderer.PrimitiveType.TRIANGLE_STRIP:
+ if (this.m_iterator + 3 <= this.m_numElements) {
+ result = [i, i + 1, i + 2];
+ this.m_iterator += 1;
+ }
+ break;
+ case rrRenderer.PrimitiveType.TRIANGLE_FAN:
+ if (this.m_iterator + 3 <= this.m_numElements) {
+ result = [0, i + 1, i + 2];
+ this.m_iterator += 1;
+ }
+ break;
+ case rrRenderer.PrimitiveType.LINES:
+ if (this.m_iterator + 2 <= this.m_numElements) {
+ result = [i, i + 1];
+ this.m_iterator += 2;
+ }
+ break;
+ case rrRenderer.PrimitiveType.LINE_STRIP:
+ if (this.m_iterator + 2 <= this.m_numElements) {
+ result = [i, i + 1];
+ this.m_iterator += 1;
+ }
+ break;
+ case rrRenderer.PrimitiveType.LINE_LOOP:
+ if (this.m_iterator == this.m_numElements)
+ break;
+ if (this.m_iterator + 2 <= this.m_numElements)
+ result = [i, i + 1];
+ else
+ result = [i, 0];
+ this.m_iterator += 1;
+ break;
+ case rrRenderer.PrimitiveType.POINTS:
+ if (this.m_iterator == this.m_numElements)
+ break;
+ else
+ result = [i];
+ this.m_iterator += 1;
+ break;
+ default:
+ throw new Error('Unsupported primitive type: ' + deString.enumToString(rrRenderer.PrimitiveType, this.m_primitiveType));
+ }
+
+ return result;
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {Array<rrFragmentOperations.Fragment>} fragments Fragments to write
+*/
+rrRenderer.writeFragments = function(state, renderTarget, fragments) {
+ /* TODO: Add blending, depth, stencil ... */
+ var colorbuffer = renderTarget.colorBuffers[0].raw();
+ for (var i = 0; i < fragments.length; i++) {
+ var fragment = fragments[i];
+ colorbuffer.setPixel(fragment.value, 0, fragment.pixelCoord[0], fragment.pixelCoord[1]);
+ }
+
+};
+
+/**
+ * @param {rrRenderState.RenderState} renderState
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {Array<rrFragmentOperations.Fragment>} fragments Fragments to write
+*/
+rrRenderer.writeFragments2 = function(renderState, renderTarget, fragments) {
+ /*
+void FragmentProcessor::render (const rr::MultisamplePixelBufferAccess& msColorBuffer,
+ const rr::MultisamplePixelBufferAccess& msDepthBuffer,
+ const rr::MultisamplePixelBufferAccess& msStencilBuffer,
+ const Fragment* fragments,
+ int numFragments,
+ FaceType fragmentFacing,
+ const FragmentOperationState& state)
+*/
+
+ /** @const */ var fragmentFacing = rrDefs.FaceType.FACETYPE_FRONT;
+ var colorBuffer = renderTarget.colorBuffers[0].raw();
+ var depthBuffer = renderTarget.depthBuffer.raw();
+ var stencilBuffer = renderTarget.stencilBuffer.raw();
+ var state = renderState.fragOps;
+
+ var hasDepth = depthBuffer.getWidth() > 0 && depthBuffer.getHeight() > 0 && depthBuffer.getDepth() > 0;
+ var hasStencil = stencilBuffer.getWidth() > 0 && stencilBuffer.getHeight() > 0 && stencilBuffer.getDepth() > 0;
+ var doDepthTest = hasDepth && state.depthTestEnabled;
+ var doStencilTest = hasStencil && state.stencilTestEnabled;
+
+ var colorbufferClass = tcuTexture.getTextureChannelClass(colorBuffer.getFormat().type);
+ var fragmentDataType = rrGenericVector.GenericVecType.FLOAT;
+ switch (colorbufferClass) {
+ case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
+ fragmentDataType = rrGenericVector.GenericVecType.INT32;
+ break;
+ case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
+ fragmentDataType = rrGenericVector.GenericVecType.UINT32;
+ break;
+ }
+
+ if (!((!hasDepth || colorBuffer.getWidth() == depthBuffer.getWidth()) && (!hasStencil || colorBuffer.getWidth() == stencilBuffer.getWidth())))
+ throw new Error('Attachment must have the same width');
+ if (!((!hasDepth || colorBuffer.getHeight() == depthBuffer.getHeight()) && (!hasStencil || colorBuffer.getHeight() == stencilBuffer.getHeight())))
+ throw new Error('Attachment must have the same height');
+ if (!((!hasDepth || colorBuffer.getDepth() == depthBuffer.getDepth()) && (!hasStencil || colorBuffer.getDepth() == stencilBuffer.getDepth())))
+ throw new Error('Attachment must have the same depth');
+
+ var stencilState = state.stencilStates[fragmentFacing];
+ var colorMaskFactor = [state.colorMask[0] ? 1 : 0, state.colorMask[1] ? 1 : 0, state.colorMask[2] ? 1 : 0, state.colorMask[3] ? 1 : 0];
+ var colorMaskNegationFactor = [state.colorMask[0] ? false : true, state.colorMask[1] ? false : true, state.colorMask[2] ? false : true, state.colorMask[3] ? false : true];
+ var sRGBTarget = state.sRGBEnabled && colorBuffer.getFormat().isSRGB();
+
+ // Scissor test.
+
+ if (state.scissorTestEnabled)
+ rrFragmentOperations.executeScissorTest(fragments, state.scissorRectangle);
+
+ // Stencil test.
+
+ if (doStencilTest) {
+ rrFragmentOperations.executeStencilCompare(fragments, stencilState, state.numStencilBits, stencilBuffer);
+ rrFragmentOperations.executeStencilSFail(fragments, stencilState, state.numStencilBits, stencilBuffer);
+ }
+
+ // Depth test.
+ // \note Current value of isAlive is needed for dpPass and dpFail, so it's only updated after them and not right after depth test.
+
+ if (doDepthTest) {
+ rrFragmentOperations.executeDepthCompare(fragments, state.depthFunc, depthBuffer);
+
+ if (state.depthMask)
+ rrFragmentOperations.executeDepthWrite(fragments, depthBuffer);
+ }
+
+ // Do dpFail and dpPass stencil writes.
+
+ if (doStencilTest)
+ rrFragmentOperations.executeStencilDpFailAndPass(fragments, stencilState, state.numStencilBits, stencilBuffer);
+
+ // Kill the samples that failed depth test.
+
+ if (doDepthTest) {
+ for (var i = 0; i < fragments.length; i++)
+ fragments[i].isAlive = fragments[i].isAlive && fragments[i].depthPassed;
+ }
+
+ // Paint fragments to target
+
+ switch (fragmentDataType) {
+ case rrGenericVector.GenericVecType.FLOAT:
+ // Blend calculation - only if using blend.
+ if (state.blendMode == rrRenderState.BlendMode.STANDARD) {
+ // Put dst color to register, doing srgb-to-linear conversion if needed.
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ var dstColor = colorBuffer.getPixel(0, frag.pixelCoord[0], frag.pixelCoord[1]);
+
+ /* TODO: Check frag.value and frag.value1 types */
+ frag.clampedBlendSrcColor = deMath.clampVector(frag.value, 0, 1);
+ frag.clampedBlendSrc1Color = deMath.clampVector(frag.value1, 0, 1);
+ frag.clampedBlendDstColor = deMath.clampVector(sRGBTarget ? tcuTexture.sRGBToLinear(dstColor) : dstColor, 0, 1);
+ }
+ }
+
+ // Calculate blend factors to register.
+ rrFragmentOperations.executeBlendFactorComputeRGB(fragments, state.blendColor, state.blendRGBState);
+ rrFragmentOperations.executeBlendFactorComputeA(fragments, state.blendColor, state.blendAState);
+
+ // Compute blended color.
+ rrFragmentOperations.executeBlend(fragments, state.blendRGBState, state.blendAState);
+ } else {
+ // Not using blend - just put values to register as-is.
+
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ frag.blendedRGB = deMath.swizzle(frag.value, [0, 1, 2]);
+ frag.blendedA = frag.value[3];
+ }
+ }
+ }
+
+ // Finally, write the colors to the color buffer.
+
+ if (state.colorMask[0] && state.colorMask[1] && state.colorMask[2] && state.colorMask[3]) {
+ /* TODO: Add quick path */
+ // if (colorBuffer.getFormat().isEqual(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)))
+ // executeRGBA8ColorWrite(fragments, colorBuffer);
+ // else
+ rrFragmentOperations.executeColorWrite(fragments, sRGBTarget, colorBuffer);
+ } else if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
+ rrFragmentOperations.executeMaskedColorWrite(fragments, colorMaskFactor, colorMaskNegationFactor, sRGBTarget, colorBuffer);
+ break;
+
+ case rrGenericVector.GenericVecType.INT32:
+ // Write fragments
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ frag.signedValue = frag.value;
+ }
+ }
+
+ if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
+ rrFragmentOperations.executeSignedValueWrite(fragments, state.colorMask, colorBuffer);
+ break;
+
+ case rrGenericVector.GenericVecType.UINT32:
+ // Write fragments
+ for (var i = 0; i < fragments.length; i++) {
+ var frag = fragments[i];
+ if (frag.isAlive) {
+ frag.unsignedValue = frag.value;
+ }
+ }
+
+ if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
+ rrFragmentOperations.executeUnsignedValueWrite(fragments, state.colorMask, colorBuffer);
+ break;
+
+ default:
+ throw new Error('Unrecognized fragment data type:' + fragmentDataType);
+ }
+};
+
+/**
+ * Determines the index of the corresponding vertex according to top/right conditions.
+ * @param {boolean} isTop
+ * @param {boolean} isRight
+ * @return {number}
+ */
+rrRenderer.getIndexOfCorner = function(isTop, isRight, vertexPackets) {
+ var x = null;
+ var y = null;
+
+ var xcriteria = isRight ? Math.max : Math.min;
+ var ycriteria = isTop ? Math.max : Math.min;
+
+ // Determine corner values
+ for (var i = 0; i < vertexPackets.length; i++) {
+ x = x != null ? xcriteria(vertexPackets[i].position[0], x) : vertexPackets[i].position[0];
+ y = y != null ? ycriteria(vertexPackets[i].position[1], y) : vertexPackets[i].position[1];
+ }
+
+ // Search for matching vertex
+ for (var v = 0; v < vertexPackets.length; v++)
+ if (vertexPackets[v].position[0] == x &&
+ vertexPackets[v].position[1] == y)
+ return v;
+
+ throw new Error('Corner not found');
+};
+
+/**
+ * Check that point is in the clipping volume
+ * @param {number} x
+ * @param {number} y
+ * @param {number} z
+ * @param {rrRenderState.WindowRectangle} rect
+ * @return {boolean}
+ */
+rrRenderer.clipTest = function(x, y, z, rect) {
+ x = Math.round(x);
+ y = Math.round(y);
+ if (!deMath.deInBounds32(x, rect.left, rect.left + rect.width))
+ return false;
+ if (!deMath.deInBounds32(y, rect.bottom, rect.bottom + rect.height))
+ return false;
+ if (z < 0 || z > 1)
+ return false;
+ return true;
+};
+
+// Rasterizer configuration
+rrRenderer.RASTERIZER_SUBPIXEL_BITS = 8;
+rrRenderer.RASTERIZER_MAX_SAMPLES_PER_FRAGMENT = 16;
+
+// Referenced from rrRasterizer.hpp
+
+/**
+ * Get coverage bit value
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @param {number} sampleNdx
+ * @return {number}
+ */
+rrRenderer.getCoverageBit = function(numSamples, x, y, sampleNdx) {
+ var maxSamples = 16;
+ assertMsgOptions(maxSamples >= rrRenderer.RASTERIZER_MAX_SAMPLES_PER_FRAGMENT, 'maxSamples should not greater than ' + rrRenderer.RASTERIZER_MAX_SAMPLES_PER_FRAGMENT, false, true);
+ assertMsgOptions(deMath.deInRange32(numSamples, 1, maxSamples) && deMath.deInBounds32(x, 0, 2) && deMath.deInBounds32(y, 0, 2), 'numSamples, x or y not in bound', false, true);
+ return 1 << ((x * 2 + y) * numSamples + sampleNdx);
+};
+
+/**
+ * Get all sample bits for fragment
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+rrRenderer.getCoverageFragmentSampleBits = function(numSamples, x, y) {
+ assertMsgOptions(deMath.deInBounds32(x, 0, 2) && deMath.deInBounds32(y, 0, 2), 'x or y is not in bound 0 to 2', false, true);
+ var fragMask = (1 << numSamples) - 1;
+ return fragMask << (x * 2 + y) * numSamples;
+};
+
+/**
+ * Set coverage bit in coverage mask
+ * @param {number} mask
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @param {number} sampleNdx
+ * @param {number} val
+ * @return {number}
+ */
+rrRenderer.setCoverageValue = function(mask, numSamples, x, y, sampleNdx, val) {
+ var bit = rrRenderer.getCoverageBit(numSamples, x, y, sampleNdx);
+ return val ? (mask | bit) : (mask & ~bit);
+};
+
+/**
+ * Test if any sample for fragment is live
+ * @param {number} mask
+ * @param {number} numSamples
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+rrRenderer.getCoverageAnyFragmentSampleLive = function(mask, numSamples, x, y) {
+ return (mask & rrRenderer.getCoverageFragmentSampleBits(numSamples, x, y)) != 0;
+};
+
+// Referenced from rrRasterizer.cpp
+
+/**
+ * Pixel coord to sub pixel coord
+ * @param {number} v
+ * @return {number}
+ */
+rrRenderer.toSubpixelCoord = function(v) {
+ return Math.trunc(v * (1 << rrRenderer.RASTERIZER_SUBPIXEL_BITS) + (v < 0 ? -0.5 : 0.5));
+};
+
+/**
+ * Floor sub pixel coord to pixel coord
+ * @param {number} coord
+ * @param {boolean} fillEdge
+ * @return {number}
+ */
+rrRenderer.floorSubpixelToPixelCoord = function(coord, fillEdge) {
+ if (coord >= 0)
+ return Math.trunc((coord - (fillEdge ? 1 : 0)) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+ else
+ return Math.trunc((coord - ((1 << rrRenderer.RASTERIZER_SUBPIXEL_BITS) - (fillEdge ? 0 : 1))) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+};
+
+/**
+ * Ceil sub pixel coord to pixel coord
+ * @param {number} coord
+ * @param {boolean} fillEdge
+ * @return {number}
+ */
+rrRenderer.ceilSubpixelToPixelCoord = function(coord, fillEdge) {
+ if (coord >= 0)
+ return Math.trunc((coord + (1 << rrRenderer.RASTERIZER_SUBPIXEL_BITS) - (fillEdge ? 0 : 1)) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+ else
+ return Math.trunc((coord + (fillEdge ? 1 : 0)) >> rrRenderer.RASTERIZER_SUBPIXEL_BITS);
+};
+
+/**
+ * \brief Edge function - referenced from struct EdgeFunction in rrRasterizer.hpp
+ *
+ * Edge function can be evaluated for point P (in a fixed-point coordinates
+ * with RASTERIZER_SUBPIXEL_BITS fractional part) by computing
+ * D = a * Px + b * Py + c
+ *
+ * D will be fixed-point value where lower (RASTERIZER_SUBPIXEL_BITS * 2) bits
+ * will be fractional part.
+ *
+ * Member function evaluateEdge, reverseEdge and isInsideCCW are referenced from rrRasterizer.cpp.
+ *
+ * @param {number} a
+ * @param {number} b
+ * @param {number} c
+ * @param {boolean} inclusive
+ */
+rrRenderer.edgeFunction = function(a, b, c, inclusive) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.inclusive = inclusive; // True if edge is inclusive according to fill rules
+};
+
+/**
+ * Evaluate point (x,y)
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ */
+rrRenderer.edgeFunction.prototype.evaluateEdge = function(x, y) {
+ return this.a * x + this.b * y + this.c;
+};
+
+/**
+ * Reverse edge (e.g. from CCW to CW)
+ */
+rrRenderer.edgeFunction.prototype.reverseEdge = function () {
+ this.a = -this.a;
+ this.b = -this.b;
+ this.c = -this.c;
+ this.inclusive = !this.inclusive;
+};
+
+/**
+ * Determine if a point with value edgeVal is inside the CCW region of the edge
+ * @param {number} edgeVal
+ * @return {boolean}
+ */
+rrRenderer.edgeFunction.prototype.isInsideCCW = function(edgeVal) {
+ return this.inclusive ? edgeVal >= 0 : edgeVal > 0;
+};
+
+/**
+ * Init an edge function in counter-clockwise (CCW) orientation
+ * @param {number} horizontalFill
+ * @param {number} verticalFill
+ * @param {number} x0
+ * @param {number} y0
+ * @param {number} x1
+ * @param {number} y1
+ * @return {rrRenderer.edgeFunction}
+ */
+rrRenderer.initEdgeCCW = function(horizontalFill, verticalFill, x0, y0, x1, y1) {
+ var xd = x1 - x0;
+ var yd = y1 - y0;
+ var inclusive = false;
+
+ if (yd == 0)
+ inclusive = verticalFill == rrRenderState.VerticalFill.BOTTOM ? xd >= 0 : xd <= 0;
+ else
+ inclusive = horizontalFill == rrRenderState.HorizontalFill.LEFT ? yd <= 0 : yd >=0;
+
+ return new rrRenderer.edgeFunction(y0 - y1, x1 - x0, x0 * y1 - y0 * x1, inclusive);
+};
+
+/**
+ * \brief Triangle rasterizer - referenced from class TriangleRasterizer in rrRasterizer.hpp
+ *
+ * Triangle rasterizer implements following features:
+ * - Rasterization using fixed-point coordinates
+ * - 1-sample rasterization (the value of numSamples always equals 1 in sglrReferenceContext)
+ * - Depth interpolation
+ * - Perspective-correct barycentric computation for interpolation
+ * - Visible face determination
+ * - Clipping - native dEQP does clipping before rasterization; see function drawBasicPrimitives
+ * in rrRenderer.cpp for more details
+ *
+ * It does not (and will not) implement following:
+ * - Triangle setup
+ * - Degenerate elimination
+ * - Coordinate transformation (inputs are in screen-space)
+ * - Culling - logic can be implemented outside by querying visible face
+ * - Scissoring - (this can be done by controlling viewport rectangle)
+ * - Any per-fragment operations
+ *
+ * @param {rrRenderState.RenderState} state
+ */
+rrRenderer.triangleRasterizer = function(state) {
+ this.m_viewport = state.viewport;
+ this.m_winding = state.rasterization.winding;
+ this.m_horizontalFill = state.rasterization.horizontalFill;
+ this.m_verticalFill = state.rasterization.verticalFill;
+};
+
+/**
+ * Initialize triangle rasterization
+ * @param {vec} v0 Screen-space coordinates (x, y, z) and 1/w for vertex 0
+ * @param {vec} v1 Screen-space coordinates (x, y, z) and 1/w for vertex 1
+ * @param {vec} v2 Screen-space coordinates (x, y, z) and 1/w for vertex 2
+ */
+rrRenderer.triangleRasterizer.prototype.init = function(v0, v1, v2) {
+ this.m_v0 = v0;
+ this.m_v1 = v1;
+ this.m_v2 = v2;
+
+ // Positions in fixed-point coordinates
+ var x0 = rrRenderer.toSubpixelCoord(v0[0]);
+ var y0 = rrRenderer.toSubpixelCoord(v0[1]);
+ var x1 = rrRenderer.toSubpixelCoord(v1[0]);
+ var y1 = rrRenderer.toSubpixelCoord(v1[1]);
+ var x2 = rrRenderer.toSubpixelCoord(v2[0]);
+ var y2 = rrRenderer.toSubpixelCoord(v2[1]);
+
+ // Initialize edge functions
+ if (this.m_winding == rrRenderState.Winding.CCW) {
+ this.m_edge01 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x0, y0, x1, y1);
+ this.m_edge12 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x1, y1, x2, y2);
+ this.m_edge20 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x2, y2, x0, y0);
+ } else {
+ // Reverse edges
+ this.m_edge01 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x1, y1, x0, y0);
+ this.m_edge12 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x2, y2, x1, y1);
+ this.m_edge20 = rrRenderer.initEdgeCCW(this.m_horizontalFill, this.m_verticalFill, x0, y0, x2, y2);
+ }
+
+ // Determine face
+ var s = this.m_edge01.evaluateEdge(x2, y2);
+ var positiveArea = (this.m_winding == rrRenderState.Winding.CCW ) ? s > 0 : s < 0;
+ this.m_face = positiveArea ? rrDefs.FaceType.FACETYPE_FRONT : rrDefs.FaceType.FACETYPE_BACK;
+ if (!positiveArea) {
+ // Reverse edges so that we can use CCW area tests & interpolation
+ this.m_edge01.reverseEdge();
+ this.m_edge12.reverseEdge();
+ this.m_edge20.reverseEdge();
+ }
+
+ // Bounding box
+ var minX = Math.min(x0, x1, x2);
+ var maxX = Math.max(x0, x1, x2);
+ var minY = Math.min(y0, y1, y2);
+ var maxY = Math.max(y0, y1, y2);
+
+ this.m_bboxMin = [];
+ this.m_bboxMax = [];
+ this.m_bboxMin[0] = rrRenderer.floorSubpixelToPixelCoord(minX, this.m_horizontalFill == rrRenderState.HorizontalFill.LEFT);
+ this.m_bboxMin[1] = rrRenderer.floorSubpixelToPixelCoord(minY, this.m_verticalFill == rrRenderState.VerticalFill.BOTTOM);
+ this.m_bboxMax[0] = rrRenderer.ceilSubpixelToPixelCoord(maxX, this.m_horizontalFill == rrRenderState.HorizontalFill.RIGHT);
+ this.m_bboxMax[1] = rrRenderer.ceilSubpixelToPixelCoord(maxY, this.m_verticalFill == rrRenderState.VerticalFill.TOP);
+
+ // Clamp to viewport
+ var wX0 = this.m_viewport.rect.left;
+ var wY0 = this.m_viewport.rect.bottom;
+ var wX1 = wX0 + this.m_viewport.rect.width - 1;
+ var wY1 = wY0 + this.m_viewport.rect.height - 1;
+
+ this.m_bboxMin[0] = deMath.clamp(this.m_bboxMin[0], wX0, wX1);
+ this.m_bboxMin[1] = deMath.clamp(this.m_bboxMin[1], wY0, wY1);
+ this.m_bboxMax[0] = deMath.clamp(this.m_bboxMax[0], wX0, wX1);
+ this.m_bboxMax[1] = deMath.clamp(this.m_bboxMax[1], wY0, wY1);
+
+ this.m_curPos = [this.m_bboxMin[0], this.m_bboxMin[1]];
+};
+
+rrRenderer.triangleRasterizer.prototype.rasterize = function() {
+ var fragmentPackets = [];
+ var halfPixel = 1 << (rrRenderer.RASTERIZER_SUBPIXEL_BITS - 1);
+
+ // For depth interpolation; given barycentrics A, B, C = (1 - A -B)
+ // We can reformulate the usual z = z0 * A + z1 * B + z2 * C into more
+ // stable equation z = A * (z0 - z2) + B * (z1 - z2) + z2
+ var za = this.m_v0[2] - this.m_v2[2];
+ var zb = this.m_v1[2] - this.m_v2[2];
+ var zc = this.m_v2[2];
+
+ var zn = this.m_viewport.zn;
+ var zf = this.m_viewport.zf;
+ var depthScale = (zf - zn) / 2;
+ var depthBias = (zf + zn) / 2;
+
+ while (this.m_curPos[1] <= this.m_bboxMax[1]) {
+ var x0 = this.m_curPos[0];
+ var y0 = this.m_curPos[1];
+
+ // Subpixel coords of (x0, y0), (x0 + 1, y0), (x0, y0 + 1), (x0 + 1, y0 + 1)
+ var sx0 = rrRenderer.toSubpixelCoord(x0) + halfPixel;
+ var sx1 = rrRenderer.toSubpixelCoord(x0 + 1) + halfPixel;
+ var sy0 = rrRenderer.toSubpixelCoord(y0) + halfPixel;
+ var sy1 = rrRenderer.toSubpixelCoord(y0 + 1) + halfPixel;
+
+ var sx = [sx0, sx1, sx0, sx1];
+ var sy = [sy0, sy0, sy1, sy1];
+
+ // Viewport test
+ var outX1 = x0 + 1 == this.m_viewport.rect.left + this.m_viewport.rect.width;
+ var outY1 = y0 + 1 == this.m_viewport.rect.bottom + this.m_viewport.rect.height;
+
+ // Coverage
+ var coverage = 0;
+
+ // Evaluate edge values
+ var e01 = [];
+ var e12 = [];
+ var e20 = [];
+ for (var i = 0; i < 4; i++) {
+ e01.push(this.m_edge01.evaluateEdge(sx[i], sy[i]));
+ e12.push(this.m_edge12.evaluateEdge(sx[i], sy[i]));
+ e20.push(this.m_edge20.evaluateEdge(sx[i], sy[i]));
+ }
+
+ // Compute coverage mask
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 0, 0, 0, this.m_edge01.isInsideCCW(e01[0]) && this.m_edge12.isInsideCCW(e12[0]) && this.m_edge20.isInsideCCW(e20[0]));
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 1, 0, 0, !outX1 && this.m_edge01.isInsideCCW(e01[1]) && this.m_edge12.isInsideCCW(e12[1]) && this.m_edge20.isInsideCCW(e20[1]));
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 0, 1, 0, !outY1 && this.m_edge01.isInsideCCW(e01[2]) && this.m_edge12.isInsideCCW(e12[2]) && this.m_edge20.isInsideCCW(e20[2]));
+ coverage = rrRenderer.setCoverageValue(coverage, 1, 1, 1, 0, !outX1 && !outY1 && this.m_edge01.isInsideCCW(e01[3]) && this.m_edge12.isInsideCCW(e12[3]) && this.m_edge20.isInsideCCW(e20[3]));
+
+ // Advance to next location
+ this.m_curPos[0] += 2;
+ if (this.m_curPos[0] > this.m_bboxMax[0]) {
+ this.m_curPos[0] = this.m_bboxMin[0];
+ this.m_curPos[1] += 2;
+ }
+
+ if (coverage == 0)
+ continue; // Discard
+
+ // Compute depth and barycentric coordinates
+ var edgeSum = deMath.add(deMath.add(e01, e12), e20);
+ var z0 = deMath.divide(e12, edgeSum);
+ var z1 = deMath.divide(e20, edgeSum);
+
+ var b0 = deMath.multiply(e12, [this.m_v0[3], this.m_v0[3], this.m_v0[3], this.m_v0[3]]);
+ var b1 = deMath.multiply(e20, [this.m_v1[3], this.m_v1[3], this.m_v1[3], this.m_v1[3]]);
+ var b2 = deMath.multiply(e01, [this.m_v2[3], this.m_v2[3], this.m_v2[3], this.m_v2[3]]);
+ var bSum = deMath.add(deMath.add(b0, b1), b2);
+ var barycentric0 = deMath.divide(b0, bSum);
+ var barycentric1 = deMath.divide(b1, bSum);
+ var barycentric2 = deMath.subtract(deMath.subtract([1, 1, 1, 1], barycentric0), barycentric1);
+
+ // In native dEQP, after rasterization, the pixel (x0, y0) actually represents four pixels:
+ // (x0, y0), (x0 + 1, y0), (x0, y0 + 1) and (x0 + 1, y0 + 1).
+ // The barycentrics and depths of these four pixels are to be computed after rasterization:
+ // barycentrics are computed in function shadeFragments in es3fFboTestUtil.cpp;
+ // depths are computed in function writeFragmentPackets in rrRenderer.cpp.
+
+ // In js, pixels are processed one after another, so their depths and barycentrics should be computed immediately.
+
+ // Determine if (x0, y0), (x0 + 1, y0), (x0, y0 + 1), (x0 + 1, y0 + 1) can be rendered
+ for (var fragNdx = 0; fragNdx < 4; fragNdx++) {
+ var xo = fragNdx % 2;
+ var yo = Math.trunc(fragNdx / 2);
+ var x = x0 + xo;
+ var y = y0 + yo;
+
+ // The value of numSamples always equals 1 in sglrReferenceContext.
+ if(rrRenderer.getCoverageAnyFragmentSampleLive(coverage, 1, xo, yo)) {
+ // Barycentric coordinates - referenced from function readTriangleVarying in rrShadingContext.hpp
+ var b = [barycentric0[fragNdx], barycentric1[fragNdx], barycentric2[fragNdx]];
+
+ // Depth - referenced from writeFragmentPackets in rrRenderer.cpp
+ var depth = z0[fragNdx] * za + z1[fragNdx] * zb + zc;
+ depth = depth * depthScale + depthBias;
+
+ // Clip test
+ // Native dEQP does clipping test before rasterization.
+ if (!rrRenderer.clipTest(x, y, depth, this.m_viewport.rect))
+ continue;
+
+ fragmentPackets.push(new rrFragmentOperations.Fragment(b, [x, y], depth));
+ }
+ }
+ }
+ return fragmentPackets;
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {Array<rrVertexAttrib.VertexAttrib>} vertexAttribs
+ * @param {rrRenderer.PrimitiveType} primitive
+ * @param {(number|rrRenderer.DrawIndices)} first Index of first quad vertex
+ * @param {number} count Number of indices
+ * @param {number} instanceID
+ */
+rrRenderer.drawTriangles = function(state, renderTarget, program, vertexAttribs, primitive, first, count, instanceID) {
+
+ /**
+ * @param {Array<rrVertexPacket.VertexPacket>} vertices
+ * @param {Array<number>} indices
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ var selectVertices = function(vertices, indices) {
+ var result = [];
+ for (var i = 0; i < indices.length; i++)
+ result.push(vertices[indices[i]]);
+ return result;
+ };
+
+ // Referenced from native dEQP Renderer::drawInstanced() in rrRenderer.cpp
+
+ var primitives = new rrRenderer.PrimitiveList(primitive, count, first);
+ // Do not draw if nothing to draw
+ if (primitives.getNumElements() == 0)
+ return;
+
+ // Prepare transformation
+ var numVaryings = program.vertexShader.getOutputs().length;
+ var vpalloc = new rrVertexPacket.VertexPacketAllocator(numVaryings);
+ var vertexPackets = vpalloc.allocArray(primitives.getNumElements());
+ var drawContext = new rrRenderer.DrawContext();
+ drawContext.primitiveID = 0;
+
+ var numberOfVertices = primitives.getNumElements();
+ var numVertexPackets = 0;
+ for (var elementNdx = 0; elementNdx < numberOfVertices; ++elementNdx) {
+
+ // input
+ vertexPackets[numVertexPackets].instanceNdx = instanceID;
+ vertexPackets[numVertexPackets].vertexNdx = primitives.getIndex(elementNdx);
+
+ // output
+ vertexPackets[numVertexPackets].pointSize = state.point.pointSize; // default value from the current state
+ vertexPackets[numVertexPackets].position = [0, 0, 0, 0]; // no undefined values
+
+ ++numVertexPackets;
+
+ }
+ program.shadeVertices(vertexAttribs, vertexPackets, numVertexPackets);
+
+ // Referenced from native dEQP Renderer::rasterizePrimitive() for triangle rasterization in rrRenderer.cpp
+
+ // In native dEQP, only maxFragmentPackets packets are processed per rasterize-shade-write loop;
+ // in js all packets are processed in one loop.
+
+ var rasterizer = new rrRenderer.triangleRasterizer(state);
+
+ for (var prim = primitives.getNextPrimitive(true); prim.length > 0; prim = primitives.getNextPrimitive()) {
+ var vertices = selectVertices(vertexPackets, prim);
+
+ var v0 = rrRenderer.transformGLToWindowCoords(state, vertices[0]);
+ var v1 = rrRenderer.transformGLToWindowCoords(state, vertices[1]);
+ var v2 = rrRenderer.transformGLToWindowCoords(state, vertices[2]);
+
+ rasterizer.init(v0, v1, v2);
+
+ // Culling
+ if ((state.cullMode == rrRenderState.CullMode.FRONT && rasterizer.m_face == rrDefs.FaceType.FACETYPE_FRONT) ||
+ (state.cullMode == rrRenderState.CullMode.BACK && rasterizer.m_face == rrDefs.FaceType.FACETYPE_BACK))
+ return;
+
+ /* TODO: Add Polygon Offset and Depth Clamp */
+
+ // Compute a conservative integer bounding box for the triangle
+ var minX = Math.floor(Math.min(v0[0], v1[0], v2[0]));
+ var maxX = Math.ceil(Math.max(v0[0], v1[0], v2[0]));
+ var minY = Math.floor(Math.min(v0[1], v1[1], v2[1]));
+ var maxY = Math.ceil(Math.max(v0[1], v1[1], v2[1]));
+
+ // Shading context
+ var shadingContext = new rrShadingContext.FragmentShadingContext(
+ vertices[0].outputs,
+ vertices[1].outputs,
+ vertices[2].outputs
+ );
+ shadingContext.setSize(maxX - minX, maxY - minY);
+
+ // Rasterize
+ var fragmentPackets = rasterizer.rasterize();
+
+ // Shade
+ program.shadeFragments(fragmentPackets, shadingContext);
+
+ // Handle fragment shader outputs
+ rrRenderer.writeFragments2(state, renderTarget, fragmentPackets);
+ }
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {Array<rrVertexAttrib.VertexAttrib>} vertexAttribs
+ * @param {rrRenderer.PrimitiveType} primitive
+ * @param {(number|rrRenderer.DrawIndices)} first Index of first quad vertex
+ * @param {number} count Number of indices
+ * @param {number} instanceID
+ */
+rrRenderer.drawLines = function(state, renderTarget, program, vertexAttribs, primitive, first, count, instanceID) {
+
+ /**
+ * @param {Array<rrVertexPacket.VertexPacket>} vertices
+ * @param {Array<number>} indices
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ var selectVertices = function(vertices, indices) {
+ var result = [];
+ for (var i = 0; i < indices.length; i++)
+ result.push(vertices[indices[i]]);
+ return result;
+ };
+
+ var lengthSquared = function(a) {
+ var sqSum = 0;
+ for (var i = 0; i < a.length; i++)
+ sqSum += a[i] * a[i];
+ return sqSum;
+ };
+
+ var dot = function(a, b) {
+ var res = 0;
+ for (var i = 0; i < a.length; i++)
+ res += a[i] * b[i];
+ return res;
+ };
+
+ var rasterizeLine = function(v0, v1) {
+ var d = [
+ Math.abs(v1[0] - v0[0]),
+ Math.abs(v1[1] - v0[1])];
+ var xstep = v0[0] < v1[0] ? 1 : -1;
+ var ystep = v0[1] < v1[1] ? 1 : -1;
+ var x = v0[0];
+ var y = v0[1];
+ var offset = d[0] - d[1];
+ var lenV = [v1[0] - v0[0], v1[1] - v0[1]];
+ var lenSq = lengthSquared(lenV);
+
+ var packets = [];
+
+ while (true) {
+ var t = dot([x - v0[0], y - v0[1]], lenV) / lenSq;
+ var depth = (1 - t) * v0[2] + t * v1[2];
+ var b = [0, 0, 0];
+ b[0] = 1 - t;
+ b[1] = t;
+
+ if (x == v1[0] && y == v1[1])
+ break;
+
+ depth = depth * depthScale + depthBias;
+ packets.push(new rrFragmentOperations.Fragment(b, [x, y], depth));
+
+ var offset2 = 2 * offset;
+ if (offset2 > -1 * d[1]) {
+ x += xstep;
+ offset -= d[1];
+ }
+
+ if (offset2 < d[0]) {
+ y += ystep;
+ offset += d[0];
+ }
+ }
+ return packets;
+ };
+
+ var primitives = new rrRenderer.PrimitiveList(primitive, count, first);
+ // Do not draw if nothing to draw
+ if (primitives.getNumElements() == 0)
+ return;
+
+ // Prepare transformation
+ var numVaryings = program.vertexShader.getOutputs().length;
+ var vpalloc = new rrVertexPacket.VertexPacketAllocator(numVaryings);
+ var vertexPackets = vpalloc.allocArray(primitives.getNumElements());
+ var drawContext = new rrRenderer.DrawContext();
+ drawContext.primitiveID = 0;
+
+ var numberOfVertices = primitives.getNumElements();
+ var numVertexPackets = 0;
+ for (var elementNdx = 0; elementNdx < numberOfVertices; ++elementNdx) {
+
+ // input
+ vertexPackets[numVertexPackets].instanceNdx = instanceID;
+ vertexPackets[numVertexPackets].vertexNdx = primitives.getIndex(elementNdx);
+
+ // output
+ vertexPackets[numVertexPackets].pointSize = state.point.pointSize; // default value from the current state
+ vertexPackets[numVertexPackets].position = [0, 0, 0, 0]; // no undefined values
+
+ ++numVertexPackets;
+
+ }
+ program.shadeVertices(vertexAttribs, vertexPackets, numVertexPackets);
+
+ var zn = state.viewport.zn;
+ var zf = state.viewport.zf;
+ var depthScale = (zf - zn) / 2;
+ var depthBias = (zf + zn) / 2;
+
+ // For each quad, we get a group of six vertex packets
+ for (var prim = primitives.getNextPrimitive(true); prim.length > 0; prim = primitives.getNextPrimitive()) {
+ var linePackets = selectVertices(vertexPackets, prim);
+
+ var v0 = rrRenderer.transformGLToWindowCoords(state, linePackets[0]);
+ var v1 = rrRenderer.transformGLToWindowCoords(state, linePackets[1]);
+ v0[2] = linePackets[0].position[2];
+ v1[2] = linePackets[1].position[2];
+
+ v0[0] = Math.floor(v0[0]);
+ v0[1] = Math.floor(v0[1]);
+ v1[0] = Math.floor(v1[0]);
+ v1[1] = Math.floor(v1[1]);
+
+ var lineWidth = state.line.lineWidth;
+
+ var shadingContext = new rrShadingContext.FragmentShadingContext(
+ linePackets[0].outputs,
+ linePackets[1].outputs,
+ null
+ );
+ var isXmajor = Math.abs(v1[0] - v0[0]) >= Math.abs(v1[1] - v0[1]);
+ var packets = [];
+ if (isXmajor)
+ packets = rasterizeLine([v0[0], v0[1] - (lineWidth - 1) / 2, v0[2]],
+ [v1[0], v1[1] - (lineWidth - 1) / 2, v1[2]]);
+ else
+ packets = rasterizeLine([v0[0] - (lineWidth - 1) / 2, v0[1], v0[2]],
+ [v1[0] - (lineWidth - 1) / 2, v1[1], v1[2]]);
+ var numPackets = packets.length;
+ if (lineWidth > 1)
+ for (var i = 0; i < numPackets; i++) {
+ var p = packets[i];
+ for (var j = 1; j < lineWidth; j++) {
+ var p2 = deUtil.clone(p);
+ if (isXmajor)
+ p2.pixelCoord[1] += j;
+ else
+ p2.pixelCoord[0] += j;
+ packets.push(p2);
+ }
+ }
+
+ var clipped = [];
+ for (var i = 0; i < packets.length; i++) {
+ var p = packets[i];
+ if (rrRenderer.clipTest(p.pixelCoord[0], p.pixelCoord[1], p.sampleDepths[0], state.viewport.rect))
+ clipped.push(p);
+ }
+ program.shadeFragments(clipped, shadingContext);
+
+ rrRenderer.writeFragments2(state, renderTarget, clipped);
+ }
+};
+
+/**
+ * @param {rrRenderState.RenderState} state
+ * @param {rrRenderer.RenderTarget} renderTarget
+ * @param {sglrShaderProgram.ShaderProgram} program
+ * @param {Array<rrVertexAttrib.VertexAttrib>} vertexAttribs
+ * @param {rrRenderer.PrimitiveType} primitive
+ * @param {(number|rrRenderer.DrawIndices)} first Index of first quad vertex
+ * @param {number} count Number of indices
+ * @param {number} instanceID
+ */
+rrRenderer.drawPoints = function(state, renderTarget, program, vertexAttribs, primitive, first, count, instanceID) {
+ /**
+ * @param {Array<rrVertexPacket.VertexPacket>} vertices
+ * @param {Array<number>} indices
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ var selectVertices = function(vertices, indices) {
+ var result = [];
+ for (var i = 0; i < indices.length; i++)
+ result.push(vertices[indices[i]]);
+ return result;
+ };
+
+ var primitives = new rrRenderer.PrimitiveList(primitive, count, first);
+ // Do not draw if nothing to draw
+ if (primitives.getNumElements() == 0)
+ return;
+
+ // Prepare transformation
+ var numVaryings = program.vertexShader.getOutputs().length;
+ var vpalloc = new rrVertexPacket.VertexPacketAllocator(numVaryings);
+ var vertexPackets = vpalloc.allocArray(primitives.getNumElements());
+ var drawContext = new rrRenderer.DrawContext();
+ drawContext.primitiveID = 0;
+
+ var numberOfVertices = primitives.getNumElements();
+ var numVertexPackets = 0;
+ for (var elementNdx = 0; elementNdx < numberOfVertices; ++elementNdx) {
+
+ // input
+ vertexPackets[numVertexPackets].instanceNdx = instanceID;
+ vertexPackets[numVertexPackets].vertexNdx = primitives.getIndex(elementNdx);
+
+ // output
+ vertexPackets[numVertexPackets].pointSize = state.point.pointSize; // default value from the current state
+ vertexPackets[numVertexPackets].position = [0, 0, 0, 0]; // no undefined values
+
+ ++numVertexPackets;
+
+ }
+ program.shadeVertices(vertexAttribs, vertexPackets, numVertexPackets);
+
+ var zn = state.viewport.zn;
+ var zf = state.viewport.zf;
+ var depthScale = (zf - zn) / 2;
+ var depthBias = (zf + zn) / 2;
+
+ // For each primitive, we draw a point.
+ for (var prim = primitives.getNextPrimitive(true); prim.length > 0; prim = primitives.getNextPrimitive()) {
+ var pointPackets = selectVertices(vertexPackets, prim);
+
+ var v0 = rrRenderer.transformGLToWindowCoords(state, pointPackets[0]);
+ v0[2] = pointPackets[0].position[2];
+ var pointSize = pointPackets[0].pointSize;
+
+ var shadingContext = new rrShadingContext.FragmentShadingContext(
+ pointPackets[0].outputs,
+ null,
+ null
+ );
+ var packets = [];
+
+ var x = v0[0];
+ var y = v0[1];
+ var depth = v0[2];
+ var b = [1, 0, 0];
+ depth = depth * depthScale + depthBias;
+
+ for (var i = Math.floor(x - pointSize / 2); i < x + pointSize / 2; i++) {
+ for (var j = Math.floor(y - pointSize / 2); j < y + pointSize / 2; j++) {
+ var centerX = i + 0.5;
+ var centerY = j + 0.5;
+ if (Math.abs(centerX - x) <= pointSize / 2 &&
+ Math.abs(centerY - y) <= pointSize / 2 &&
+ rrRenderer.clipTest(i, j, depth, state.viewport.rect))
+ packets.push(new rrFragmentOperations.Fragment(b, [i, j], depth));
+ }
+ }
+
+ program.shadeFragments(packets, shadingContext);
+
+ rrRenderer.writeFragments2(state, renderTarget, packets);
+ }
+};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js
new file mode 100644
index 0000000000..143d9b7289
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShaders.js
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrShaders');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrGenericVector');
+goog.require('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.referencerenderer.rrVertexPacket');
+
+goog.scope(function() {
+
+var rrShaders = framework.referencerenderer.rrShaders;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+var rrShadingContext = framework.referencerenderer.rrShadingContext;
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+
+ /**
+ * Vertex shader input information
+ * @constructor
+ */
+ rrShaders.VertexInputInfo = function() {
+ /** @type {rrGenericVector.GenericVecType} */ this.type;
+ };
+
+ /**
+ * Shader varying information
+ * @constructor
+ */
+ rrShaders.VertexVaryingInfo = function() {
+ /** @type {rrGenericVector.GenericVecType} */ this.type;
+ /** @type {boolean} */ var flatshade = false;
+ };
+
+ /**
+ * Fragment shader output information
+ * @constructor
+ */
+ rrShaders.FragmentOutputInfo = function() {
+ //Sensible defaults
+ /** @type {rrGenericVector.GenericVecType} */ this.type;
+ };
+
+ /**
+ * Vertex shader interface
+ *
+ * Vertex shaders execute shading for set of vertex packets. See VertexPacket
+ * documentation for more details on shading API.
+ * @constructor
+ * @param {number} numInputs
+ * @param {number} numOutputs
+ */
+ rrShaders.VertexShader = function(numInputs, numOutputs) {
+ /** @type {Array<rrShaders.VertexInputInfo>} */ this.m_inputs = [];
+ for (var ndx = 0; ndx < numInputs; ndx++) this.m_inputs[ndx] = new rrShaders.VertexInputInfo();
+ /** @type {Array<rrShaders.VertexVaryingInfo>} */ this.m_outputs = [];
+ for (var ndx = 0; ndx < numOutputs; ndx++) this.m_outputs[ndx] = new rrShaders.VertexVaryingInfo();
+ };
+
+ /**
+ * getInputs
+ * @return {Array<rrShaders.VertexInputInfo>}
+ */
+ rrShaders.VertexShader.prototype.getInputs = function() {return this.m_inputs;};
+
+ /**
+ * getOutputs
+ * @return {Array<rrShaders.VertexVaryingInfo>}
+ */
+ rrShaders.VertexShader.prototype.getOutputs = function() {return this.m_outputs;};
+
+ /**
+ * Fragment shader interface
+ *
+ * Fragment shader executes shading for list of fragment packets. See
+ * FragmentPacket documentation for more details on shading API.
+ * @constructor
+ * @param {number} numInputs
+ * @param {number} numOutputs
+ */
+ rrShaders.FragmentShader = function(numInputs, numOutputs) {
+ /** @type {Array<rrShaders.VertexVaryingInfo>} */ this.m_inputs = [];
+ for (var ndx = 0; ndx < numInputs; ndx++) this.m_inputs[ndx] = new rrShaders.VertexVaryingInfo();
+ /** @type {Array<rrShaders.FragmentOutputInfo>} */ this.m_outputs = [];
+ for (var ndx = 0; ndx < numOutputs; ndx++) this.m_outputs[ndx] = new rrShaders.FragmentOutputInfo();
+ /** @type {*} */ this.m_container; // owner object
+ };
+
+ /**
+ * getInputs
+ * @return {Array<rrShaders.VertexVaryingInfo>}
+ */
+ rrShaders.FragmentShader.prototype.getInputs = function() {return this.m_inputs;};
+
+ /**
+ * getOutputs
+ * @return {Array<rrShaders.FragmentOutputInfo>}
+ */
+ rrShaders.FragmentShader.prototype.getOutputs = function() {return this.m_outputs;};
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js
new file mode 100644
index 0000000000..38b9d201f9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrShadingContext.js
@@ -0,0 +1,113 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrShadingContext');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrDefs');
+goog.require('framework.referencerenderer.rrFragmentOperations');
+goog.require('framework.referencerenderer.rrGenericVector');
+
+goog.scope(function() {
+
+ var rrShadingContext = framework.referencerenderer.rrShadingContext;
+ var deMath = framework.delibs.debase.deMath;
+ var rrDefs = framework.referencerenderer.rrDefs;
+ var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
+ var rrGenericVector = framework.referencerenderer.rrGenericVector;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * Fragment shading context
+ *
+ * Contains per-primitive information used in fragment shading
+ * @constructor
+ * @param {Array<Array<number>>} varying0 (GenericVec4*)
+ * @param {Array<Array<number>>} varying1 (GenericVec4*)
+ * @param {Array<Array<number>>} varying2 (GenericVec4*)
+ */
+ rrShadingContext.FragmentShadingContext = function(varying0, varying1, varying2) {
+ /** @type {Array<Array<Array<number>>>} */ this.varyings = [varying0, varying1, varying2]; //!< Vertex shader outputs. Pointer will be NULL if there is no such vertex.
+ this.m_width = 0xFFFFFFFF;
+ this.m_height = 0xFFFFFFFF;
+ };
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ */
+ rrShadingContext.FragmentShadingContext.prototype.setSize = function(width, height) {
+ this.m_width = width;
+ this.m_height = height;
+ };
+
+ rrShadingContext.FragmentShadingContext.prototype.getWidth = function() {
+ return this.m_width;
+ };
+
+ rrShadingContext.FragmentShadingContext.prototype.getHeight = function() {
+ return this.m_height;
+ };
+
+ // Read Varying
+
+ /**
+ * @param {rrFragmentOperations.Fragment} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ * @param {number} varyingLoc
+ * @return {Array<number>} (Vector<T, 4>)
+ */
+ rrShadingContext.readTriangleVarying = function(packet, context, varyingLoc) {
+ var result = deMath.scale(
+ context.varyings[0][varyingLoc],
+ packet.barycentric[0]
+ );
+
+ if (context.varyings[1])
+ result = deMath.add(result, deMath.scale(
+ context.varyings[1][varyingLoc],
+ packet.barycentric[1]
+ ));
+
+ if (context.varyings[2])
+ result = deMath.add(result, deMath.scale(
+ context.varyings[2][varyingLoc],
+ packet.barycentric[2]
+ ));
+
+ return result;
+ };
+
+ /**
+ * @param {rrFragmentOperations.Fragment} packet
+ * @param {rrShadingContext.FragmentShadingContext} context
+ * @param {number} varyingLoc
+ * @return {Array<number>} (Vector<T, 4>)
+ */
+ rrShadingContext.readVarying = function(packet, context, varyingLoc) {
+ return rrShadingContext.readTriangleVarying(packet, context, varyingLoc);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js
new file mode 100644
index 0000000000..03a58168fc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrUtil.js
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrUtil');
+goog.require('framework.opengl.simplereference.sglrGLContext');
+goog.require('framework.opengl.simplereference.sglrReferenceContext');
+
+goog.scope(function() {
+
+ var rrUtil = framework.referencerenderer.rrUtil;
+ var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
+ var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
+
+ /**
+ * @param {sglrGLContext.GLContext | WebGL2RenderingContext | sglrReferenceContext.ReferenceContext} ctx
+ * @param {number|Object} program
+ * @param {Array<number>} p0
+ * @param {Array<number>} p1
+ */
+ rrUtil.drawQuad = function(ctx, program, p0, p1) {
+ // Vertex data.
+ var hz = (p0[2] + p1[2]) * 0.5;
+ /** @type {Array<number>} */ var position = [
+ p0[0], p0[1], p0[2], 1.0,
+ p0[0], p1[1], hz, 1.0,
+ p1[0], p0[1], hz, 1.0,
+ p1[0], p1[1], p1[2], 1.0
+ ];
+ /** @type {Array<number>} */ var coord = [
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 0.0,
+ 1.0, 1.0
+ ];
+ /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
+
+ var posLoc = ctx.getAttribLocation(program, 'a_position');
+ if (posLoc == -1)
+ throw new Error('a_position attribute is not defined.');
+
+ var coordLoc = ctx.getAttribLocation(program, 'a_coord');
+ var vaoID;
+ var bufIDs = [];
+
+ vaoID = ctx.createVertexArray();
+ ctx.bindVertexArray(vaoID);
+
+ bufIDs[0] = ctx.createBuffer();
+ bufIDs[1] = ctx.createBuffer();
+
+ ctx.useProgram(program);
+
+ if (posLoc >= 0) {
+ ctx.bindBuffer(gl.ARRAY_BUFFER, bufIDs[0]);
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(position), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(posLoc);
+ ctx.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, null);
+ }
+
+ if (coordLoc >= 0) {
+ ctx.bindBuffer(gl.ARRAY_BUFFER, bufIDs[1]);
+ ctx.bufferData(gl.ARRAY_BUFFER, new Float32Array(coord), gl.STATIC_DRAW);
+
+ ctx.enableVertexAttribArray(coordLoc);
+ ctx.vertexAttribPointer(coordLoc, 2, gl.FLOAT, false, 0, 0);
+
+ ctx.bindBuffer(gl.ARRAY_BUFFER, null);
+ }
+
+ {
+ var ndxID = ctx.createBuffer();
+
+ ctx.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ndxID);
+ ctx.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
+
+ ctx.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+
+ ctx.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ ctx.deleteBuffer(ndxID);
+ }
+
+ ctx.bindVertexArray(null);
+ ctx.deleteBuffer(bufIDs[0]);
+ ctx.deleteBuffer(bufIDs[1]);
+ ctx.deleteVertexArray(vaoID);
+
+ if (posLoc >= 0)
+ ctx.disableVertexAttribArray(posLoc);
+
+ if (coordLoc >= 0)
+ ctx.disableVertexAttribArray(coordLoc);
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js
new file mode 100644
index 0000000000..f6095e2cc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexAttrib.js
@@ -0,0 +1,641 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrVertexAttrib');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.referencerenderer.rrGenericVector');
+
+goog.scope(function() {
+
+var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
+var deMath = framework.delibs.debase.deMath;
+var tcuFloat = framework.common.tcuFloat;
+var rrGenericVector = framework.referencerenderer.rrGenericVector;
+
+ var DE_ASSERT = function(x) {
+ if (!x)
+ throw new Error('Assert failed');
+ };
+
+ /**
+ * rrVertexAttrib.NormalOrder
+ * @enum
+ */
+ rrVertexAttrib.NormalOrder = {
+ T0: 0,
+ T1: 1,
+ T2: 2,
+ T3: 3
+ };
+
+ /**
+ * rrVertexAttrib.BGRAOrder
+ * @enum
+ */
+ rrVertexAttrib.BGRAOrder = {
+ T0: 2,
+ T1: 1,
+ T2: 0,
+ T3: 3
+ };
+
+ /**
+ * rrVertexAttrib.VertexAttribType enum
+ * @enum
+ */
+ rrVertexAttrib.VertexAttribType = {
+ // Can only be rrVertexAttrib.read as floats
+ FLOAT: 0,
+ HALF: 1,
+ FIXED: 2,
+ DOUBLE: 3,
+
+ // Can only be rrVertexAttrib.read as floats, will be normalized
+ NONPURE_UNORM8: 4,
+ NONPURE_UNORM16: 5,
+ NONPURE_UNORM32: 6,
+ NONPURE_UNORM_2_10_10_10_REV: 7, //!< Packed format, only size = 4 is allowed
+
+ // Clamped formats, GLES3-style conversion: max{c / (2^(b-1) - 1), -1 }
+ NONPURE_SNORM8_CLAMP: 8,
+ NONPURE_SNORM16_CLAMP: 9,
+ NONPURE_SNORM32_CLAMP: 10,
+ NONPURE_SNORM_2_10_10_10_REV_CLAMP: 11, //!< Packed format, only size = 4 is allowed
+
+ // Scaled formats, GLES2-style conversion: (2c + 1) / (2^b - 1)
+ NONPURE_SNORM8_SCALE: 12,
+ NONPURE_SNORM16_SCALE: 13,
+ NONPURE_SNORM32_SCALE: 14,
+ NONPURE_SNORM_2_10_10_10_REV_SCALE: 15, //!< Packed format, only size = 4 is allowed
+
+ // can only be rrVertexAttrib.read as float, will not be normalized
+ NONPURE_UINT8: 16,
+ NONPURE_UINT16: 17,
+ NONPURE_UINT32: 18,
+
+ NONPURE_INT8: 19,
+ NONPURE_INT16: 20,
+ NONPURE_INT32: 21,
+
+ NONPURE_UINT_2_10_10_10_REV: 22, //!< Packed format, only size = 4 is allowed
+ NONPURE_INT_2_10_10_10_REV: 23, //!< Packed format, only size = 4 is allowed
+
+ // can only be rrVertexAttrib.read as integers
+ PURE_UINT8: 24,
+ PURE_UINT16: 25,
+ PURE_UINT32: 26,
+
+ PURE_INT8: 27,
+ PURE_INT16: 28,
+ PURE_INT32: 29,
+
+ // reordered formats of gl.ARB_vertex_array_bgra
+ NONPURE_UNORM8_BGRA: 30,
+ NONPURE_UNORM_2_10_10_10_REV_BGRA: 31,
+ NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA: 32,
+ NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA: 33,
+
+ // can be rrVertexAttrib.read as anything
+ DONT_CARE: 34 //!< Do not enforce type checking when reading GENERIC attribute. Used for current client side attributes.
+ };
+
+ /**
+ * rrVertexAttrib.VertexAttrib class
+ * @constructor
+ */
+ rrVertexAttrib.VertexAttrib = function() {
+ /** @type {rrVertexAttrib.VertexAttribType} */ this.type = rrVertexAttrib.VertexAttribType.FLOAT;
+ /** @type {number} */ this.size = 0;
+ /** @type {number} */ this.stride = 0;
+ /** @type {number} */ this.instanceDivisor = 0;
+ /** @type {number} */ this.offset = 0; //Added this property to compensate functionality (not in original dEQP).
+ /** @type {ArrayBuffer} */ this.pointer = null;
+ /** @type {Array<number>|rrGenericVector.GenericVec4} */ this.generic; //!< Generic attribute, used if pointer is null.
+ };
+
+ /**
+ * @param {rrVertexAttrib.VertexAttribType} type
+ * @return {number}
+ */
+ rrVertexAttrib.getComponentSize = function(type) {
+ switch (type) {
+ case rrVertexAttrib.VertexAttribType.FLOAT: return 4;
+ case rrVertexAttrib.VertexAttribType.HALF: return 2;
+ case rrVertexAttrib.VertexAttribType.FIXED: return 4;
+ case rrVertexAttrib.VertexAttribType.DOUBLE: return 8; //sizeof(double);
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM16: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_CLAMP: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_CLAMP: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_CLAMP: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_SCALE: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_SCALE: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_SCALE: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT8: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT16: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT8: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT16: return 2;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT8: return 1;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT16: return 2;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT32: return 4;
+ case rrVertexAttrib.VertexAttribType.PURE_INT8: return 1;
+ case rrVertexAttrib.VertexAttribType.PURE_INT16: return 2;
+ case rrVertexAttrib.VertexAttribType.PURE_INT32: return 4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8_BGRA: return 1;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV_BGRA: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA: return 1; //sizeof(deUint32)/4;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA: return 1; //sizeof(deUint32)/4;
+ default:
+ throw new Error('rrVertexAttrib.getComponentSize - Invalid type');
+ }
+ };
+
+ /**
+ * rrVertexAttrib.isValidVertexAttrib function
+ * @param {rrVertexAttrib.VertexAttrib} vertexAttrib
+ * @return {boolean}
+ */
+ rrVertexAttrib.isValidVertexAttrib = function(vertexAttrib) {
+ // Trivial range checks.
+ if (!deMath.deInBounds32(vertexAttrib.type, 0, Object.keys(rrVertexAttrib.VertexAttribType).length) ||
+ !deMath.deInRange32(vertexAttrib.size, 0, 4) ||
+ vertexAttrib.instanceDivisor < 0)
+ return false;
+
+ // Generic attributes
+ if (!vertexAttrib.pointer && vertexAttrib.type != rrVertexAttrib.VertexAttribType.DONT_CARE)
+ return false;
+
+ // Packed formats
+ if ((vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV_BGRA ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA ||
+ vertexAttrib.type == rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA) &&
+ vertexAttrib.size != 4)
+ return false;
+
+ return true;
+ };
+
+ /**
+ * rrVertexAttrib.readVertexAttrib function
+ * @param {rrVertexAttrib.VertexAttrib} vertexAttrib
+ * @param {number} instanceNdx
+ * @param {number} vertexNdx
+ * @param {rrGenericVector.GenericVecType} genericType
+ * @return {goog.NumberArray}
+ */
+ rrVertexAttrib.readVertexAttrib = function(vertexAttrib, instanceNdx, vertexNdx, genericType) {
+ DE_ASSERT(rrVertexAttrib.isValidVertexAttrib(vertexAttrib));
+ /** @type {goog.NumberArray} */ var dst;
+
+ var arrayType = null;
+ switch (genericType) {
+ case rrGenericVector.GenericVecType.INT32:
+ arrayType = Int32Array;
+ break;
+ case rrGenericVector.GenericVecType.UINT32:
+ arrayType = Uint32Array;
+ break;
+ case rrGenericVector.GenericVecType.FLOAT:
+ arrayType = Float32Array;
+ break;
+ }
+
+ if (vertexAttrib.pointer) {
+ /** @type {number} */ var elementNdx = (vertexAttrib.instanceDivisor != 0) ? (instanceNdx / vertexAttrib.instanceDivisor) : vertexNdx;
+ /** @type {number} */ var compSize = rrVertexAttrib.getComponentSize(vertexAttrib.type);
+ /** @type {number} */ var stride = (vertexAttrib.stride != 0) ? (vertexAttrib.stride) : (vertexAttrib.size * compSize);
+ /** @type {number} */ var byteOffset = vertexAttrib.offset + (elementNdx * stride);
+
+ dst = [0, 0, 0, 1]; // defaults
+
+ if (arrayType != null) {
+ dst = new arrayType(dst);
+ }
+
+ rrVertexAttrib.read(dst, vertexAttrib.type, vertexAttrib.size, new Uint8Array(vertexAttrib.pointer, byteOffset));
+ } else {
+ dst = new arrayType(/** @type {Array<number>} */ vertexAttrib.generic.data);
+ }
+
+ return dst;
+ };
+
+ /**
+ * rrVertexAttrib.readHalf
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.readHalf = function(dst, size, ptr) {
+ var arraysize16 = 2; //2 bytes
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize16)); //Small buffer copy (max. 8 bytes)
+ var aligned = new Uint16Array(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = tcuFloat.newFloat32From16(aligned[0]).getValue();
+ if (size >= 2) dst[1] = tcuFloat.newFloat32From16(aligned[1]).getValue();
+ if (size >= 3) dst[2] = tcuFloat.newFloat32From16(aligned[2]).getValue();
+ if (size >= 4) dst[3] = tcuFloat.newFloat32From16(aligned[3]).getValue();
+ };
+
+ /**
+ * rrVertexAttrib.readFixed
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ /*rrVertexAttrib.readFixed = function(dst, size, ptr) {
+ var arraysize32 = 4; //4 bytes
+
+ //Reinterpret ptr as a uint16 array,
+ //assuming original ptr is 8-bits per element
+ var aligned = new Int32Array(ptr.buffer).subarray(
+ ptr.byteOffset / arraysize32,
+ (ptr.byteOffset + ptr.byteLength) / arraysize32);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = aligned[0] / (1 << 16);
+ if (size >= 2) dst[1] = aligned[1] / (1 << 16);
+ if (size >= 3) dst[2] = aligned[2] / (1 << 16);
+ if (size >= 4) dst[3] = aligned[3] / (1 << 16);
+ };*/
+
+ /**
+ * TODO: Check 64 bit numbers are handled ok
+ * rrVertexAttrib.readDouble
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ /*rrVertexAttrib.readDouble = function(dst, size, ptr) {
+ var arraysize64 = 8; //8 bytes
+
+ //Reinterpret 'ptr' into 'aligned' as a float64 array,
+ //assuming original ptr is 8-bits per element.
+ var aligned = new Float64Array(ptr.buffer).subarray(
+ ptr.byteOffset / arraysize64,
+ (ptr.byteOffset + ptr.byteLength) / arraysize64);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = aligned[0];
+ if (size >= 2) dst[1] = aligned[1];
+ if (size >= 3) dst[2] = aligned[2];
+ if (size >= 4) dst[3] = aligned[3];
+ };*/
+
+ /**
+ * extendSign
+ * @param {number} integerLen
+ * @param {number} integer_ (deUint32)
+ * @return {number} (deInt32)
+ */
+ rrVertexAttrib.extendSign = function(integerLen, integer_) {
+ return new Int32Array([
+ deMath.binaryOp(
+ 0 -
+ deMath.shiftLeft(
+ deMath.binaryOp(
+ integer_,
+ deMath.shiftLeft(
+ 1,
+ (integerLen - 1)
+ ),
+ deMath.BinaryOp.AND
+ ),
+ 1
+ ) ,
+
+integer_,
+ deMath.BinaryOp.OR
+ )
+ ])[0];
+ };
+
+ /**
+ * rrVertexAttrib.readUint2101010Rev
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.readUint2101010Rev = function(dst, size, ptr) {
+ var arraysize32 = 4; //4 bytes
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[0] = deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND);
+ if (size >= 2) dst[1] = deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND);
+ if (size >= 3) dst[2] = deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND);
+ if (size >= 4) dst[3] = deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND);
+ };
+
+ /**
+ * rrVertexAttrib.readInt2101010Rev
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.readInt2101010Rev = function(dst, size, ptr) {
+ var arraysize32 = 4; //4 bytes
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[0] = rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND));
+ if (size >= 2) dst[1] = rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND));
+ if (size >= 3) dst[2] = rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND));
+ if (size >= 4) dst[3] = rrVertexAttrib.extendSign(2, deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND));
+ };
+
+ /**
+ * rrVertexAttrib.readUnorm2101010RevOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ */
+ rrVertexAttrib.readUnorm2101010RevOrder = function(dst, size, ptr, order) {
+ var arraysize32 = 4; //4 bytes
+
+ //Left shift within 32-bit range as 32-bit int.
+ var range10 = new Uint32Array([deMath.shiftLeft(1, 10) - 1])[0];
+ var range2 = new Uint32Array([deMath.shiftLeft(1, 2) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[order.T0] = deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND) / range10;
+ if (size >= 2) dst[order.T1] = deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND) / range10;
+ if (size >= 3) dst[order.T2] = deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND) / range10;
+ if (size >= 4) dst[order.T3] = deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND) / range2;
+ };
+
+ /**
+ * rrVertexAttrib.readSnorm2101010RevClampOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ */
+ rrVertexAttrib.readSnorm2101010RevClampOrder = function(dst, size, ptr, order) {
+ var arraysize32 = 4; //4 bytes
+
+ //Left shift within 32-bit range as 32-bit int.
+ var range10 = new Uint32Array([deMath.shiftLeft(1, 10 - 1) - 1])[0];
+ var range2 = new Uint32Array([deMath.shiftLeft(1, 2 - 1) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[order.T0] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND))])[0] / range10);
+ if (size >= 2) dst[order.T1] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND))])[0] / range10);
+ if (size >= 3) dst[order.T2] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND))])[0] / range10);
+ if (size >= 4) dst[order.T3] = Math.max(-1.0, new Float32Array([rrVertexAttrib.extendSign(2, deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND))])[0] / range2);
+ };
+
+ /**
+ * rrVertexAttrib.readSnorm2101010RevScaleOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ */
+ rrVertexAttrib.readSnorm2101010RevScaleOrder = function(dst, size, ptr, order) {
+ var arraysize32 = 4; //4 bytes
+
+ //Left shift within 32-bit range as 32-bit int.
+ var range10 = new Uint32Array([deMath.shiftLeft(1, 10) - 1])[0];
+ var range2 = new Uint32Array([deMath.shiftLeft(1, 2) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arraysize32)); //Small buffer copy (max. 16 bytes)
+ var aligned = new Uint32Array(ptrclone.buffer)[0];
+
+ dst[order.T0] = new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 0), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range10;
+ if (size >= 2) dst[order.T1] = new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 10), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range10;
+ if (size >= 3) dst[order.T2] = new Float32Array([rrVertexAttrib.extendSign(10, deMath.binaryOp(deMath.shiftRight(aligned, 20), deMath.shiftLeft(1, 10) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range10;
+ if (size >= 4) dst[order.T3] = new Float32Array([rrVertexAttrib.extendSign(2, deMath.binaryOp(deMath.shiftRight(aligned, 30), deMath.shiftLeft(1, 2) - 1, deMath.BinaryOp.AND)) * 2.0 + 1.0])[0] / range2;
+ };
+
+ /**
+ * rrVertexAttrib.readUnormOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order
+ * @param readAsTypeArray
+ */
+ rrVertexAttrib.readUnormOrder = function(dst, size, ptr, order, readAsTypeArray) {
+ var arrayelementsize = readAsTypeArray.BYTES_PER_ELEMENT;
+
+ //Left shift within 32-bit range as 32-bit float.
+ var range = new Float32Array([deMath.shiftLeft(1, arrayelementsize * 8) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arrayelementsize)); //Small buffer copy (max. 16 bytes)
+ var aligned = new readAsTypeArray(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[order.T0] = aligned[0] / range;
+ if (size >= 2) dst[order.T1] = aligned[1] / range;
+ if (size >= 3) dst[order.T2] = aligned[2] / range;
+ if (size >= 4) dst[order.T3] = aligned[3] / range;
+ };
+
+ /**
+ * rrVertexAttrib.readSnormClamp
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {function(new:ArrayBufferView,(Array<number>|ArrayBuffer|ArrayBufferView|null|number), number=, number=)} readAsTypeArray
+ */
+ rrVertexAttrib.readSnormClamp = function(dst, size, ptr, readAsTypeArray) {
+ var arrayelementsize = readAsTypeArray.BYTES_PER_ELEMENT;
+
+ //Left shift within 32-bit range as 32-bit float.
+ var range = new Float32Array([deMath.shiftLeft(1, arrayelementsize * 8 - 1) - 1])[0];
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arrayelementsize)); //Small buffer copy (max. 16 bytes)
+ var aligned = new readAsTypeArray(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ dst[0] = Math.max(-1, aligned[0] / range);
+ if (size >= 2) dst[1] = Math.max(-1, aligned[1] / range);
+ if (size >= 3) dst[2] = Math.max(-1, aligned[2] / range);
+ if (size >= 4) dst[3] = Math.max(-1, aligned[3] / range);
+ };
+
+ /**
+ * rrVertexAttrib.readOrder
+ * @param {goog.NumberArray} dst
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ * @param {Object<rrVertexAttrib.NormalOrder|rrVertexAttrib.BGRAOrder>} order NormalOrder or BGRAOrder
+ * @param readAsTypeArray Typed Array type
+ */
+ rrVertexAttrib.readOrder = function(dst, size, ptr, order, readAsTypeArray) {
+ var arrayelementsize = readAsTypeArray.BYTES_PER_ELEMENT;
+
+ var ptrclone = new Uint8Array(ptr.subarray(0, size * arrayelementsize)); //Small buffer copy (max. 16 bytes)
+ var aligned = new readAsTypeArray(ptrclone.buffer);
+
+ //Reinterpret aligned's values into the dst vector.
+ //(automatic in JS typed arrays).
+ dst[order.T0] = aligned[0];
+ if (size >= 2) dst[order.T1] = aligned[1];
+ if (size >= 3) dst[order.T2] = aligned[2];
+ if (size >= 4) dst[order.T3] = aligned[3];
+ };
+
+ /**
+ * TODO: Implement readSNormScale.
+ * @param {goog.NumberArray} dst
+ * @param {rrVertexAttrib.VertexAttribType} type
+ * @param {number} size
+ * @param {Uint8Array} ptr
+ */
+ rrVertexAttrib.read = function(dst, type, size, ptr) {
+ var order;
+
+ switch (type) {
+ case rrVertexAttrib.VertexAttribType.FLOAT:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Float32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.HALF:
+ rrVertexAttrib.readHalf(dst, size, ptr);
+ break;
+ /*case rrVertexAttrib.VertexAttribType.FIXED:
+ rrVertexAttrib.readFixed(dst, size, ptr);
+ break;
+ case rrVertexAttrib.VertexAttribType.DOUBLE:
+ rrVertexAttrib.readDouble(dst, size, ptr);
+ break;*/
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM16:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM32:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV:
+ rrVertexAttrib.readUnorm2101010RevOrder(dst, size, ptr, rrVertexAttrib.NormalOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_CLAMP: //Int8
+ rrVertexAttrib.readSnormClamp(dst, size, ptr, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_CLAMP: //Int16
+ rrVertexAttrib.readSnormClamp(dst, size, ptr, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_CLAMP: //Int32
+ rrVertexAttrib.readSnormClamp(dst, size, ptr, Int32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP:
+ rrVertexAttrib.readSnorm2101010RevClampOrder(dst, size, ptr, rrVertexAttrib.NormalOrder);
+ break;
+ /*case rrVertexAttrib.VertexAttribType.NONPURE_SNORM8_SCALE: //Int8
+ rrVertexAttrib.readSnormScale(dst, size, ptr, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM16_SCALE: //Int16
+ rrVertexAttrib.readSnormScale(dst, size, ptr, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM32_SCALE: //Int32
+ rrVertexAttrib.readSnormScale(dst, size, ptr, Int32Array);
+ break;*/
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE:
+ rrVertexAttrib.readSnorm2101010RevScaleOrder(dst, size, ptr, rrVertexAttrib.NormalOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT_2_10_10_10_REV:
+ rrVertexAttrib.readUint2101010Rev(dst, size, ptr);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT_2_10_10_10_REV:
+ rrVertexAttrib.readInt2101010Rev(dst, size, ptr);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM8_BGRA:
+ rrVertexAttrib.readUnormOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UNORM_2_10_10_10_REV_BGRA:
+ rrVertexAttrib.readUnorm2101010RevOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_CLAMP_BGRA:
+ rrVertexAttrib.readSnorm2101010RevClampOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_SNORM_2_10_10_10_REV_SCALE_BGRA:
+ rrVertexAttrib.readSnorm2101010RevScaleOrder(dst, size, ptr, rrVertexAttrib.BGRAOrder);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_UINT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.NONPURE_INT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_UINT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Uint32Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_INT8:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int8Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_INT16:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int16Array);
+ break;
+ case rrVertexAttrib.VertexAttribType.PURE_INT32:
+ rrVertexAttrib.readOrder(dst, size, ptr, rrVertexAttrib.NormalOrder, Int32Array);
+ break;
+
+ default:
+ throw new Error('rrVertexAttrib.read - Invalid type');
+ }
+ };
+
+});
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js
new file mode 100644
index 0000000000..ec00e17d19
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrVertexPacket.js
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('framework.referencerenderer.rrVertexPacket');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
+var tcuTexture = framework.common.tcuTexture;
+var deMath = framework.delibs.debase.deMath;
+
+ /**
+ * rrVertexPacket.VertexPacket class. (Should only be created by rrVertexPacket.VertexPacketAllocator)
+ * @constructor
+ */
+ rrVertexPacket.VertexPacket = function() {
+ /** @type {number} */ this.instanceNdx;
+ /** @type {number} */ this.vertexNdx;
+ /** @type {goog.NumberArray} */ this.position; //!< Transformed position - must be written always.
+ /** @type {number} */ this.pointSize; //!< Point size, required when rendering points.
+ // /** @type {number} */ this.primitiveID; //!< Geometry shader output (Not used in webGL)
+ /** @type {Array<goog.NumberArray>} */ this.outputs = [[0, 0, 0, 0]];
+ };
+
+ /**
+ * rrVertexPacket.VertexPacketAllocator class
+ * @constructor
+ * @param {number} numberOfVertexOutputs
+ */
+ rrVertexPacket.VertexPacketAllocator = function(numberOfVertexOutputs) {
+ /** @type {number} */ this.m_numberOfVertexOutputs = numberOfVertexOutputs;
+ /** @type {Uint8Array} */ this.m_allocations;
+ /** @type {Array<rrVertexPacket.VertexPacket>} */ this.m_singleAllocPool = [];
+ };
+
+ /**
+ * @return {number}
+ */
+ rrVertexPacket.VertexPacketAllocator.prototype.getNumVertexOutputs = function() {
+ return this.m_numberOfVertexOutputs;
+ };
+
+ /**
+ * allocArray
+ * @param {number} count
+ * @return {Array<rrVertexPacket.VertexPacket>}
+ */
+ rrVertexPacket.VertexPacketAllocator.prototype.allocArray = function(count) {
+ if (!count)
+ return [];
+
+ /** @type {number} */ var extraVaryings = (this.m_numberOfVertexOutputs == 0) ? (0) : (this.m_numberOfVertexOutputs - 1);
+ // /** @type {number} TODO: Check what this size is used for */ var packetSize = sizeof(rrVertexPacket.VertexPacket) + extraVaryings * sizeof(GenericVec4);
+
+ /** @type {Array<rrVertexPacket.VertexPacket>} */ var retVal = [];
+ // /** @type {Uint8Array} TODO: same as above */ var ptr = new deInt8[packetSize * count]; // throws bad_alloc => ok
+
+ //run ctors
+ for (var i = 0; i < count; ++i)
+ retVal.push(new rrVertexPacket.VertexPacket());
+
+ /** TODO: same as previous - this.m_allocations.push_back(ptr); */
+
+ return retVal;
+ };
+
+ /**
+ * @return {rrVertexPacket.VertexPacket}
+ */
+ rrVertexPacket.VertexPacketAllocator.prototype.alloc = function() {
+ /** @type {number} */ var poolSize = 8;
+
+ if (this.m_singleAllocPool.length == 0)
+ this.m_singleAllocPool = this.allocArray(poolSize);
+
+ /** @type {rrVertexPacket.VertexPacket} */ var packet = this.m_singleAllocPool.pop();
+
+ return packet;
+ };
+
+});