2010-06-25 Zhenyao Mo <zmo@google.com>
authorzmo@google.com <zmo@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 Jun 2010 04:53:24 +0000 (04:53 +0000)
committerzmo@google.com <zmo@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 Jun 2010 04:53:24 +0000 (04:53 +0000)
        Reviewed by Dimitri Glazkov.

        getUniform will not work for fetching uniform array elements
        https://bugs.webkit.org/show_bug.cgi?id=34508

        * fast/canvas/webgl/gl-uniform-arrays-expected.txt: Added.
        * fast/canvas/webgl/gl-uniform-arrays.html: Added.
        * fast/canvas/webgl/incorrect-context-object-behaviour-expected.txt: Change the test so we test the return error explicitly.
        * fast/canvas/webgl/script-tests/incorrect-context-object-behaviour.js: Ditto.
2010-06-25  Zhenyao Mo  <zmo@google.com>

        Reviewed by Dimitri Glazkov.

        getUniform will not work for fetching uniform array elements
        https://bugs.webkit.org/show_bug.cgi?id=34508

        Test: fast/canvas/webgl/gl-uniform-arrays.html

        * html/canvas/WebGLRenderingContext.cpp:
        (WebCore::WebGLRenderingContext::attachShader): Generate correct errors.
        (WebCore::WebGLRenderingContext::getUniform): Dealing with array elements.
        (WebCore::WebGLRenderingContext::useProgram): Deal with program==null.
        (WebCore::WebGLRenderingContext::validateProgram): Generate correct errors.
        * platform/graphics/mac/GraphicsContext3DMac.mm:
        (WebCore::GraphicsContext3D::useProgram): Deal with program==null.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@61939 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/canvas/webgl/gl-uniform-arrays-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/gl-uniform-arrays.html [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour-expected.txt
LayoutTests/fast/canvas/webgl/script-tests/incorrect-context-object-behaviour.js
WebCore/ChangeLog
WebCore/html/canvas/WebGLRenderingContext.cpp
WebCore/platform/graphics/mac/GraphicsContext3DMac.mm

index 4e3b98d..09d6703 100644 (file)
@@ -2,6 +2,18 @@
 
         Reviewed by Dimitri Glazkov.
 
+        getUniform will not work for fetching uniform array elements
+        https://bugs.webkit.org/show_bug.cgi?id=34508
+
+        * fast/canvas/webgl/gl-uniform-arrays-expected.txt: Added.
+        * fast/canvas/webgl/gl-uniform-arrays.html: Added.
+        * fast/canvas/webgl/incorrect-context-object-behaviour-expected.txt: Change the test so we test the return error explicitly.
+        * fast/canvas/webgl/script-tests/incorrect-context-object-behaviour.js: Ditto.
+
+2010-06-25  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Dimitri Glazkov.
+
         Bring set/get state functions to GLES2 conformance
         https://bugs.webkit.org/show_bug.cgi?id=41095
 
diff --git a/LayoutTests/fast/canvas/webgl/gl-uniform-arrays-expected.txt b/LayoutTests/fast/canvas/webgl/gl-uniform-arrays-expected.txt
new file mode 100644 (file)
index 0000000..9c5b7ba
--- /dev/null
@@ -0,0 +1,86 @@
+This test ensures WebGL implementations handle uniform arrays correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+check float
+PASS 1 uniform found
+PASS uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10
+PASS should fail if there is no current program
+PASS can set an array of uniforms with gl.uniform1fv
+PASS can call gl.getUniform
+PASS gl.getUniform returns the correct type.
+PASS can get location of element 0 of array from gl.getUniformLocation
+PASS can get value of element 0 of array from gl.getUniform
+PASS value put in (16) matches value pulled out (16)
+PASS can get location of element 1 of array from gl.getUniformLocation
+PASS can get value of element 1 of array from gl.getUniform
+PASS value put in (15) matches value pulled out (15)
+PASS can get location of element 2 of array from gl.getUniformLocation
+PASS can get value of element 2 of array from gl.getUniform
+PASS value put in (14) matches value pulled out (14)
+PASS using the wrong size of gl.Uniform fails
+PASS can call gl.useProgram(null)
+
+check vec2
+PASS 1 uniform found
+PASS uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10
+PASS should fail if there is no current program
+PASS can set an array of uniforms with gl.uniform2fv
+PASS can call gl.getUniform
+PASS gl.getUniform returns the correct type.
+PASS can get location of element 0 of array from gl.getUniformLocation
+PASS can get value of element 0 of array from gl.getUniform
+PASS value put in ([16, 15]) matches value pulled out ([16, 15])
+PASS can get location of element 1 of array from gl.getUniformLocation
+PASS can get value of element 1 of array from gl.getUniform
+PASS value put in ([14, 13]) matches value pulled out ([14, 13])
+PASS can get location of element 2 of array from gl.getUniformLocation
+PASS can get value of element 2 of array from gl.getUniform
+PASS value put in ([12, 11]) matches value pulled out ([12, 11])
+PASS using the wrong size of gl.Uniform fails
+PASS can call gl.useProgram(null)
+
+check vec3
+PASS 1 uniform found
+PASS uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10
+PASS should fail if there is no current program
+PASS can set an array of uniforms with gl.uniform3fv
+PASS can call gl.getUniform
+PASS gl.getUniform returns the correct type.
+PASS can get location of element 0 of array from gl.getUniformLocation
+PASS can get value of element 0 of array from gl.getUniform
+PASS value put in ([16, 15, 14]) matches value pulled out ([16, 15, 14])
+PASS can get location of element 1 of array from gl.getUniformLocation
+PASS can get value of element 1 of array from gl.getUniform
+PASS value put in ([13, 12, 11]) matches value pulled out ([13, 12, 11])
+PASS can get location of element 2 of array from gl.getUniformLocation
+PASS can get value of element 2 of array from gl.getUniform
+PASS value put in ([10, 11, 9]) matches value pulled out ([10, 11, 9])
+PASS using the wrong size of gl.Uniform fails
+PASS can call gl.useProgram(null)
+
+check vec4
+PASS 1 uniform found
+PASS uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10
+PASS should fail if there is no current program
+PASS can set an array of uniforms with gl.uniform4fv
+PASS can call gl.getUniform
+PASS gl.getUniform returns the correct type.
+PASS can get location of element 0 of array from gl.getUniformLocation
+PASS can get value of element 0 of array from gl.getUniform
+PASS value put in ([16, 15, 14, 13]) matches value pulled out ([16, 15, 14, 13])
+PASS can get location of element 1 of array from gl.getUniformLocation
+PASS can get value of element 1 of array from gl.getUniform
+PASS value put in ([12, 11, 10, 11]) matches value pulled out ([12, 11, 10, 11])
+PASS can get location of element 2 of array from gl.getUniformLocation
+PASS can get value of element 2 of array from gl.getUniform
+PASS value put in ([9, 8, 7, 6]) matches value pulled out ([9, 8, 7, 6])
+PASS using the wrong size of gl.Uniform fails
+PASS can call gl.useProgram(null)
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/gl-uniform-arrays.html b/LayoutTests/fast/canvas/webgl/gl-uniform-arrays.html
new file mode 100644 (file)
index 0000000..2e8ccbe
--- /dev/null
@@ -0,0 +1,261 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL uniform array Conformance Tests</title>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">
+    attribute vec4 vPosition;
+    void main()
+    {
+        gl_Position = vPosition;
+    }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+    uniform $type color[3];
+    void main()
+    {
+        gl_FragColor = vec4(color[0]$elem, color[1]$elem, color[2]$elem, 1);
+    }
+</script>
+<script>
+function loadShader(ctx, shaderType, shaderSource) {
+  // Create the shader object
+  var shader = ctx.createShader(shaderType);
+  if (shader == null) {
+    debug("*** Error: unable to create shader '"+shader+"'");
+    return null;
+  }
+
+  // Load the shader source
+  ctx.shaderSource(shader, shaderSource);
+
+  // Compile the shader
+  ctx.compileShader(shader);
+
+  // Check the compile status
+  var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
+  if (!compiled) {
+    // Something went wrong during compilation; get the error
+    var error = ctx.getShaderInfoLog(shader);
+    debug("*** Error compiling shader '"+shader+"':"+error);
+    ctx.deleteShader(shader);
+    return null;
+  }
+
+  return shader;
+}
+
+function loadProgram(ctx, vertexShaderSrc, fragmentShaderSrc) {
+  var program = ctx.createProgram();
+  var vShader = loadShader(ctx, ctx.VERTEX_SHADER, vertexShaderSrc)
+  var fShader = loadShader(ctx, ctx.FRAGMENT_SHADER, fragmentShaderSrc);
+  ctx.attachShader(program, vShader);
+  ctx.attachShader(program, fShader);
+  ctx.linkProgram(program);
+  var linked = ctx.getProgramParameter(program, ctx.LINK_STATUS);
+  if (!linked) {
+    // something went wrong with the link
+    var error = ctx.getProgramInfoLog (ctx.program);
+    debug("Error in program linking:" + error);
+    ctx.deleteProgram(ctx.program);
+    program = null;
+  }
+//  ctx.deleteShader(fShader);
+//  ctx.deleteShader(vShader);
+  return program;
+}
+
+description("This test ensures WebGL implementations handle uniform arrays correctly.");
+
+debug("");
+
+var gl = create3DContext(document.getElementById("example"));
+
+var vSrc = document.getElementById("vshader").text;
+var fTemplate = document.getElementById("fshader").text;
+
+var typeInfos = [
+  { type: 'float',
+    jsTypeOf: 'number',
+    setter: 'uniform1fv',
+    elem: '',
+    numSrcValues: 3,
+    badSet: function(loc) {
+      gl.uniform2fv(loc, [1, 2]);
+    },
+    srcValueAsString: function(index, srcValues) {
+      return srcValues[index].toString();
+    },
+    returnValueAsString: function(value) {
+      return value === null ? 'null' : value.toString();
+    },
+    checkType: function(value) {
+      return typeof values === 'number';
+    },
+    checkValue: function(typeInfo, index, value) {
+      return typeInfo.srcValues[index] == value;
+    },
+    srcValues: [16, 15, 14]
+  },
+  { type: 'vec2',
+    jsTypeOf: 'Float32Array',
+    setter: 'uniform2fv',
+    elem: '[1]',
+    numSrcValues: 3,
+    badSet: function(loc) {
+      gl.uniform1fv(loc, [2]);
+    },
+    srcValueAsString: function(index, srcValues) {
+      return "[" + srcValues[index * 2 + 0].toString() + ", " +
+                   srcValues[index * 2 + 1].toString() + "]";
+    },
+    returnValueAsString: function(value) {
+      return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
+    },
+    checkType: function(value) {
+      return typeof values.length === 'number' &&
+             values.length == 2;
+    },
+    checkValue: function(typeInfo, index, value) {
+      return value !== null &&
+             typeInfo.srcValues[index * 2 + 0] == value[0] &&
+             typeInfo.srcValues[index * 2 + 1] == value[1];
+    },
+    srcValues: [16, 15, 14, 13, 12, 11],
+  },
+  { type: 'vec3',
+    jsTypeOf: 'Float32Array',
+    setter: 'uniform3fv',
+    elem: '[2]',
+    numSrcValues: 3,
+    badSet: function(loc) {
+      gl.uniform1fv(loc, [2]);
+    },
+    srcValueAsString: function(index, srcValues) {
+      return "[" + srcValues[index * 3 + 0].toString() + ", " +
+                   srcValues[index * 3 + 1].toString() + ", " +
+                   srcValues[index * 3 + 2].toString() + "]";
+    },
+    returnValueAsString: function(value) {
+      return value === null ? 'null' :
+          ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
+    },
+    checkType: function(value) {
+      return typeof values.length === 'number' &&
+             values.length == 3;
+    },
+    checkValue: function(typeInfo, index, value) {
+      return value !== null &&
+             typeInfo.srcValues[index * 3 + 0] == value[0] &&
+             typeInfo.srcValues[index * 3 + 1] == value[1] &&
+             typeInfo.srcValues[index * 3 + 2] == value[2];
+    },
+    srcValues: [16, 15, 14, 13, 12, 11, 10, 11, 9],
+  },
+  { type: 'vec4',
+    jsTypeOf: 'Float32Array',
+    setter: 'uniform4fv',
+    elem: '[3]',
+    numSrcValues: 3,
+    badSet: function(loc) {
+      gl.uniform1fv(loc, [2]);
+    },
+    srcValueAsString: function(index, srcValues) {
+      return "[" + srcValues[index * 4 + 0].toString() + ", " +
+                   srcValues[index * 4 + 1].toString() + ", " +
+                   srcValues[index * 4 + 2].toString() + ", " +
+                   srcValues[index * 4 + 3].toString() + "]";
+    },
+    returnValueAsString: function(value) {
+      return value === null ? 'null' :
+          ("[" + value[0] + ", " + value[1] +
+           ", " + value[2] + ", " + value[3] + "]");
+    },
+    checkType: function(value) {
+      return typeof values.length === 'number' &&
+             values.length == 4;
+    },
+    checkValue: function(typeInfo, index, value) {
+      return value !== null &&
+             typeInfo.srcValues[index * 4 + 0] == value[0] &&
+             typeInfo.srcValues[index * 4 + 1] == value[1] &&
+             typeInfo.srcValues[index * 4 + 2] == value[2] &&
+             typeInfo.srcValues[index * 4 + 3] == value[3];
+    },
+    srcValues: [16, 15, 14, 13, 12, 11, 10, 11, 9, 8, 7, 6, 5],
+  }
+];
+
+for (var tt = 0; tt < typeInfos.length; ++tt) {
+  var typeInfo = typeInfos[tt];
+  debug("");
+  debug("check " + typeInfo.type);
+  var fSrc = fTemplate.replace(/\$type/g, typeInfo.type).
+                       replace(/\$elem/g, typeInfo.elem);
+  //debug("fSrc: " + fSrc);
+  var program = loadProgram(gl, vSrc, fSrc);
+
+  var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+  assertMsg(numUniforms == 1, "1 uniform found");
+  var info = gl.getActiveUniform(program, 0);
+  assertMsg(info.name == "color[0]",
+            "uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10");
+  var loc = gl.getUniformLocation(program, "color");
+  var srcValues = typeInfo.srcValues;
+
+  // Try setting the value before using the program
+  gl[typeInfo.setter](loc, srcValues);
+  assertMsg(gl.getError() == gl.INVALID_OPERATION,
+            "should fail if there is no current program");
+
+  gl.useProgram(program);
+  gl[typeInfo.setter](loc, srcValues);
+  assertMsg(gl.getError() == gl.NO_ERROR,
+            "can set an array of uniforms with gl." + typeInfo.setter);
+  var values = gl.getUniform(program, loc);
+  assertMsg(gl.getError() == gl.NO_ERROR,
+            "can call gl.getUniform");
+  assertMsg(typeInfo.checkType(values),
+            "gl.getUniform returns the correct type.");
+  for (var ii = 0; ii < typeInfo.numSrcValues; ++ii) {
+    var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "can get location of element " + ii +
+              " of array from gl.getUniformLocation");
+    var value = gl.getUniform(program, elemLoc);
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "can get value of element " + ii + " of array from gl.getUniform");
+    assertMsg(typeInfo.checkValue(typeInfo, ii, value),
+              "value put in (" + typeInfo.srcValueAsString(ii, srcValues) +
+              ") matches value pulled out (" +
+              typeInfo.returnValueAsString(value) + ")");
+  }
+  typeInfo.badSet(loc);
+  assertMsg(gl.getError() == gl.INVALID_OPERATION,
+            "using the wrong size of gl.Uniform fails");
+
+  gl.useProgram(null);
+  assertMsg(gl.getError() == gl.NO_ERROR,
+            "can call gl.useProgram(null)");
+}
+debug("");
+successfullyParsed = true;
+
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
index 9356934..bc46373 100644 (file)
@@ -2,28 +2,28 @@ Tests calling WebGL APIs with objects from other contexts
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
-PASS contextA.compileShader(shaderB) threw exception GL error 1282 in compileShader.
-PASS contextA.linkProgram(programB) threw exception GL error 1282 in linkProgram.
-PASS contextA.attachShader(programA, shaderB) threw exception GL error 1281 in attachShader.
-PASS contextA.attachShader(programB, shaderA) threw exception GL error 1281 in attachShader.
-PASS contextA.attachShader(programB, shaderB) threw exception GL error 1281 in attachShader.
-PASS contextA.detachShader(programA, shaderB) threw exception GL error 1282 in detachShader.
-PASS contextA.detachShader(programB, shaderA) threw exception GL error 1282 in detachShader.
-PASS contextA.detachShader(programB, shaderB) threw exception GL error 1282 in detachShader.
-PASS contextA.shaderSource(shaderB, 'foo') threw exception GL error 1282 in shaderSource.
-PASS contextA.bindAttribLocation(programB, 0, 'foo') threw exception GL error 1282 in bindAttribLocation.
-PASS contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferB) threw exception GL error 1282 in bindFramebuffer.
-PASS contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferB) threw exception GL error 1282 in bindRenderbuffer.
-PASS contextA.bindTexture(contextA.TEXTURE_2D, textureB) threw exception GL error 1282 in bindTexture.
-PASS contextA.framebufferRenderbuffer(contextA.FRAMEBUFFER, contextA.DEPTH_ATTACHMENT, contextA.RENDERBUFFER, renderBufferB) threw exception GL error 1282 in framebufferRenderbuffer.
-PASS contextA.framebufferTexture2D(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, contextA.TEXTURE_2D, textureB, 0) threw exception GL error 1282 in framebufferTexture2D.
-PASS contextA.getProgramParameter(programB, 0) threw exception GL error 1282 in getProgramParameter.
-PASS contextA.getProgramInfoLog(programB, 0) threw exception GL error 1282 in getProgramInfoLog.
-PASS contextA.getShaderParameter(shaderB, 0) threw exception GL error 1282 in getShaderParameter.
-PASS contextA.getShaderInfoLog(shaderB, 0) threw exception GL error 1282 in getShaderInfoLog.
-PASS contextA.getShaderSource(shaderB) threw exception GL error 1282 in getShaderSource.
-PASS contextA.getUniform(programB, locationA) threw exception GL error 1282 in getUniform.
-PASS contextA.getUniformLocation(programB, 'u_modelViewProjMatrix') threw exception GL error 1282 in getUniformLocation.
+PASS contextA.compileShader(shaderB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.linkProgram(programB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.attachShader(programA, shaderB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.attachShader(programB, shaderA) generated expected GL error: INVALID_OPERATION.
+PASS contextA.attachShader(programB, shaderB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.detachShader(programA, shaderB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.detachShader(programB, shaderA) generated expected GL error: INVALID_OPERATION.
+PASS contextA.detachShader(programB, shaderB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.shaderSource(shaderB, 'foo') generated expected GL error: INVALID_OPERATION.
+PASS contextA.bindAttribLocation(programB, 0, 'foo') generated expected GL error: INVALID_OPERATION.
+PASS contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.bindTexture(contextA.TEXTURE_2D, textureB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.framebufferRenderbuffer(contextA.FRAMEBUFFER, contextA.DEPTH_ATTACHMENT, contextA.RENDERBUFFER, renderBufferB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.framebufferTexture2D(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, contextA.TEXTURE_2D, textureB, 0) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getProgramParameter(programB, 0) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getProgramInfoLog(programB, 0) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getShaderParameter(shaderB, 0) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getShaderInfoLog(shaderB, 0) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getShaderSource(shaderB) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getUniform(programB, locationA) generated expected GL error: INVALID_OPERATION.
+PASS contextA.getUniformLocation(programB, 'u_modelViewProjMatrix') generated expected GL error: INVALID_OPERATION.
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 9b7e8af..a9d5ee4 100644 (file)
@@ -1,7 +1,7 @@
 description("Tests calling WebGL APIs with objects from other contexts");
 
-var contextA = create3DDebugContext();
-var contextB = create3DDebugContext();
+var contextA = create3DContext();
+var contextB = create3DContext();
 var programA = loadStandardProgram(contextA);
 var programB = loadStandardProgram(contextB);
 var shaderA = loadStandardVertexShader(contextA);
@@ -15,28 +15,27 @@ var renderBufferB = contextB.createRenderbuffer();
 var locationA = contextA.getUniformLocation(programA, 'u_modelViewProjMatrix');
 var locationB = contextB.getUniformLocation(programB, 'u_modelViewProjMatrix');
 
-
-shouldThrow("contextA.compileShader(shaderB)");
-shouldThrow("contextA.linkProgram(programB)");
-shouldThrow("contextA.attachShader(programA, shaderB)");
-shouldThrow("contextA.attachShader(programB, shaderA)");
-shouldThrow("contextA.attachShader(programB, shaderB)");
-shouldThrow("contextA.detachShader(programA, shaderB)");
-shouldThrow("contextA.detachShader(programB, shaderA)");
-shouldThrow("contextA.detachShader(programB, shaderB)");
-shouldThrow("contextA.shaderSource(shaderB, 'foo')");
-shouldThrow("contextA.bindAttribLocation(programB, 0, 'foo')");
-shouldThrow("contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferB)");
-shouldThrow("contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferB)");
-shouldThrow("contextA.bindTexture(contextA.TEXTURE_2D, textureB)");
-shouldThrow("contextA.framebufferRenderbuffer(contextA.FRAMEBUFFER, contextA.DEPTH_ATTACHMENT, contextA.RENDERBUFFER, renderBufferB)");
-shouldThrow("contextA.framebufferTexture2D(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, contextA.TEXTURE_2D, textureB, 0)");
-shouldThrow("contextA.getProgramParameter(programB, 0)");
-shouldThrow("contextA.getProgramInfoLog(programB, 0)");
-shouldThrow("contextA.getShaderParameter(shaderB, 0)");
-shouldThrow("contextA.getShaderInfoLog(shaderB, 0)");
-shouldThrow("contextA.getShaderSource(shaderB)");
-shouldThrow("contextA.getUniform(programB, locationA)");
-shouldThrow("contextA.getUniformLocation(programB, 'u_modelViewProjMatrix')");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.compileShader(shaderB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.linkProgram(programB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programA, shaderB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programB, shaderA)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.attachShader(programB, shaderB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programA, shaderB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderA)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.detachShader(programB, shaderB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.shaderSource(shaderB, 'foo')");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindAttribLocation(programB, 0, 'foo')");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindFramebuffer(contextA.FRAMEBUFFER, frameBufferB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindRenderbuffer(contextA.RENDERBUFFER, renderBufferB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.bindTexture(contextA.TEXTURE_2D, textureB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferRenderbuffer(contextA.FRAMEBUFFER, contextA.DEPTH_ATTACHMENT, contextA.RENDERBUFFER, renderBufferB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.framebufferTexture2D(contextA.FRAMEBUFFER, contextA.COLOR_ATTACHMENT0, contextA.TEXTURE_2D, textureB, 0)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getProgramParameter(programB, 0)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getProgramInfoLog(programB, 0)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderParameter(shaderB, 0)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderInfoLog(shaderB, 0)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderSource(shaderB)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programB, locationA)");
+shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformLocation(programB, 'u_modelViewProjMatrix')");
 
 successfullyParsed = true;
index 65bfb43..510c93e 100644 (file)
@@ -2,6 +2,23 @@
 
         Reviewed by Dimitri Glazkov.
 
+        getUniform will not work for fetching uniform array elements
+        https://bugs.webkit.org/show_bug.cgi?id=34508
+
+        Test: fast/canvas/webgl/gl-uniform-arrays.html
+
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::attachShader): Generate correct errors.
+        (WebCore::WebGLRenderingContext::getUniform): Dealing with array elements.
+        (WebCore::WebGLRenderingContext::useProgram): Deal with program==null.
+        (WebCore::WebGLRenderingContext::validateProgram): Generate correct errors.
+        * platform/graphics/mac/GraphicsContext3DMac.mm:
+        (WebCore::GraphicsContext3D::useProgram): Deal with program==null.
+
+2010-06-25  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Dimitri Glazkov.
+
         Bring set/get state functions to GLES2 conformance
         https://bugs.webkit.org/show_bug.cgi?id=41095
 
index cd74c15..443d204 100644 (file)
@@ -204,10 +204,8 @@ void WebGLRenderingContext::activeTexture(unsigned long texture, ExceptionCode&
 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
 {
     UNUSED_PARAM(ec);
-    if (!program || program->context() != this || !shader || shader->context() != this) {
-        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+    if (!validateWebGLObject(program) || !validateWebGLObject(shader))
         return;
-    }
     m_context->attachShader(program, shader);
     cleanupAfterGraphicsCall(false);
 }
@@ -1491,13 +1489,24 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
         ActiveInfo info;
         if (!m_context->getActiveUniform(program, i, info))
             return WebGLGetInfo();
-        // Now need to look this up by name again to find its location
-        long loc = m_context->getUniformLocation(program, info.name);
-        if (loc == location) {
-            // Found it. Use the type in the ActiveInfo to determine the return type.
-            GraphicsContext3D::WebGLEnumType baseType;
-            unsigned length;
-            switch (info.type) {
+        // Strip "[0]" from the name if it's an array.
+        if (info.size > 1)
+            info.name = info.name.left(info.name.length() - 3);
+        // If it's an array, we need to iterate through each element, appending "[index]" to the name.
+        for (int index = 0; index < info.size; ++index) {
+            String name = info.name;
+            if (info.size > 1 && index >= 1) {
+                name.append('[');
+                name.append(String::number(index));
+                name.append(']');
+            }
+            // Now need to look this up by name again to find its location
+            long loc = m_context->getUniformLocation(program, name);
+            if (loc == location) {
+                // Found it. Use the type in the ActiveInfo to determine the return type.
+                GraphicsContext3D::WebGLEnumType baseType;
+                unsigned length;
+                switch (info.type) {
                 case GraphicsContext3D::BOOL:
                     baseType = GraphicsContext3D::BOOL;
                     length = 1;
@@ -1563,38 +1572,36 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
                     // FIXME: what to do about samplers?
                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
                     return WebGLGetInfo();
-            }
-            switch (baseType) {
-            case GraphicsContext3D::FLOAT: {
-                float value[16] = {0};
-                m_context->getUniformfv(program, location, value);
-                if (length == 1)
-                    return WebGLGetInfo(value[0]);
-                else
+                }
+                switch (baseType) {
+                case GraphicsContext3D::FLOAT: {
+                    float value[16] = {0};
+                    m_context->getUniformfv(program, location, value);
+                    if (length == 1)
+                        return WebGLGetInfo(value[0]);
                     return WebGLGetInfo(Float32Array::create(value, length));
-            }
-            case GraphicsContext3D::INT: {
-                int value[16] = {0};
-                m_context->getUniformiv(program, location, value);
-                if (length == 1)
-                    return WebGLGetInfo(static_cast<long>(value[0]));
-                else
+                }
+                case GraphicsContext3D::INT: {
+                    int value[16] = {0};
+                    m_context->getUniformiv(program, location, value);
+                    if (length == 1)
+                        return WebGLGetInfo(static_cast<long>(value[0]));
                     return WebGLGetInfo(Int32Array::create(value, length));
-            }
-            case GraphicsContext3D::BOOL: {
-                int value[16] = {0};
-                m_context->getUniformiv(program, location, value);
-                if (length == 1)
+                }
+                case GraphicsContext3D::BOOL: {
+                    int value[16] = {0};
+                    m_context->getUniformiv(program, location, value);
+                    if (length > 1) {
+                        unsigned char boolValue[16] = {0};
+                        for (unsigned j = 0; j < length; j++)
+                            boolValue[j] = static_cast<bool>(value[j]);
+                        return WebGLGetInfo(Uint8Array::create(boolValue, length));
+                    }
                     return WebGLGetInfo(static_cast<bool>(value[0]));
-                else {
-                    unsigned char boolValue[16] = {0};
-                    for (unsigned j = 0; j < length; j++)
-                        boolValue[j] = static_cast<bool>(value[j]);
-                    return WebGLGetInfo(Uint8Array::create(boolValue, length));
                 }
-            }
-            default:
-                notImplemented();
+                default:
+                    notImplemented();
+                }
             }
         }
     }
@@ -2958,11 +2965,10 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio
 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
 {
     UNUSED_PARAM(ec);
-    if (!program || program->context() != this) {
-        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+    if (program && program->context() != this) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
         return;
     }
-        
     m_currentProgram = program;
     m_context->useProgram(program);
     cleanupAfterGraphicsCall(false);
@@ -2971,11 +2977,8 @@ void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
 {
     UNUSED_PARAM(ec);
-    if (!program || program->context() != this) {
-        m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+    if (!validateWebGLObject(program))
         return;
-    }
-        
     m_context->validateProgram(program);
     cleanupAfterGraphicsCall(false);
 }
index 6457e4f..2bf3a26 100644 (file)
@@ -1103,10 +1103,8 @@ void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* a
 
 void GraphicsContext3D::useProgram(WebGLProgram* program)
 {
-    ASSERT(program);
-    
     ensureContext(m_contextObj);
-    ::glUseProgram((GLuint) program->object());
+    ::glUseProgram(program ? ((GLuint) program->object()) : 0);
 }
 
 void GraphicsContext3D::validateProgram(WebGLProgram* program)