2010-07-02 Zhenyao Mo <zmo@google.com>
authorzmo@google.com <zmo@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Jul 2010 16:35:02 +0000 (16:35 +0000)
committerzmo@google.com <zmo@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Jul 2010 16:35:02 +0000 (16:35 +0000)
        Reviewed by Dimitri Glazkov.

        Implement OpenGL ES 2.0 semantics for vertex attribute 0
        https://bugs.webkit.org/show_bug.cgi?id=41300

        * fast/canvas/webgl/gl-bind-attrib-location-test-expected.txt: Added.
        * fast/canvas/webgl/gl-bind-attrib-location-test.html: Added.
        * fast/canvas/webgl/gl-vertex-attrib-expected.txt: Added.
        * fast/canvas/webgl/gl-vertex-attrib.html: Added.
2010-07-02  Zhenyao Mo  <zmo@google.com>

        Reviewed by Dimitri Glazkov.

        Implement OpenGL ES 2.0 semantics for vertex attribute 0
        https://bugs.webkit.org/show_bug.cgi?id=41300

        Test: fast/canvas/webgl/gl-bind-attrib-location-test.html
              fast/canvas/webgl/gl-vertex-attrib.html

        * html/canvas/WebGLProgram.cpp:
        (WebCore::WebGLProgram::numActiveAttribLocations): const.
        (WebCore::WebGLProgram::getActiveAttribLocation): const.
        (WebCore::WebGLProgram::isUsingVertexAttrib0): Determine whether vertex attrib 0 is used by the program.
        * html/canvas/WebGLProgram.h: Declare isUsingVertexAttrib0.
        * html/canvas/WebGLRenderingContext.cpp:
        (WebCore::WebGLRenderingContext::WebGLRenderingContext): Deal with vertex attrib 0.
        (WebCore::WebGLRenderingContext::disableVertexAttribArray): Ditto.
        (WebCore::WebGLRenderingContext::drawArrays): Ditto.
        (WebCore::WebGLRenderingContext::drawElements): Ditto.
        (WebCore::WebGLRenderingContext::getVertexAttrib): Use cached value instead of calling glGetVertexAtrtrib.
        (WebCore::WebGLRenderingContext::vertexAttrib1f): Validate input, deal with vertex attrib 0.
        (WebCore::WebGLRenderingContext::vertexAttrib1fv): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttrib2f): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttrib2fv): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttrib3f): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttrib3fv): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttrib4f): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttrib4fv): Ditto.
        (WebCore::WebGLRenderingContext::vertexAttribPointer): Ditto.
        (WebCore::WebGLRenderingContext::handleNPOTTextures): Move isGLES2Compliant() to caller.
        (WebCore::WebGLRenderingContext::vertexAttribImpl): Helper for vertexAttribNfv.
        (WebCore::WebGLRenderingContext::initVertexAttrib0): Initialize vertex attrib 0.
        (WebCore::WebGLRenderingContext::simulateVertexAttrib0): Simulate vertex attrib 0.
        (WebCore::WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation): Restore states after simulating vertex attrib 0.
        * html/canvas/WebGLRenderingContext.h:
        (WebCore::WebGLRenderingContext::VertexAttribState::VertexAttribState): Tracking full vertex attrib states.
        (WebCore::WebGLRenderingContext::VertexAttribState::initValue): Init value to [0,0,0,1].

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

LayoutTests/ChangeLog
LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test.html [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/gl-vertex-attrib-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/gl-vertex-attrib.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/html/canvas/WebGLProgram.cpp
WebCore/html/canvas/WebGLProgram.h
WebCore/html/canvas/WebGLRenderingContext.cpp
WebCore/html/canvas/WebGLRenderingContext.h

index c82b96adb62f8c82e26c47a62c378d43944b2a82..c6765d778c849e6ffeaf4dc96d55fcc8833b3895 100644 (file)
@@ -1,3 +1,15 @@
+2010-07-02  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Dimitri Glazkov.
+
+        Implement OpenGL ES 2.0 semantics for vertex attribute 0
+        https://bugs.webkit.org/show_bug.cgi?id=41300
+
+        * fast/canvas/webgl/gl-bind-attrib-location-test-expected.txt: Added.
+        * fast/canvas/webgl/gl-bind-attrib-location-test.html: Added.
+        * fast/canvas/webgl/gl-vertex-attrib-expected.txt: Added.
+        * fast/canvas/webgl/gl-vertex-attrib.html: Added.
+
 2010-07-02  Zhenyao Mo  <zmo@google.com>
 
         Reviewed by Dimitri Glazkov.
diff --git a/LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test-expected.txt b/LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test-expected.txt
new file mode 100644 (file)
index 0000000..3a75ab8
--- /dev/null
@@ -0,0 +1,30 @@
+This test ensures WebGL implementations don't allow names that start with 'gl_' when calling bindAttribLocation.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Canvas.getContext
+PASS [object HTMLCanvasElement] is non-null.
+PASS [object WebGLRenderingContext] is non-null.
+
+Checking gl.bindAttribLocation.
+PASS bindAttribLocation should return INVALID_OPERATION if name starts with 'gl_'
+PASS bindAttribLocation should return INVALID_OPERATION if name starts with 'gl_'
+PASS program linked successfully
+vPosition:3
+vColor   :2
+PASS location of vPositon should be 3
+PASS location of vColor should be 2
+PASS drawing is correct
+PASS program linked successfully
+vPosition:3
+vColor   :0
+PASS location of vPositon should be 3
+PASS location of vColor should be 0
+PASS drawing is correct
+PASS gl.getError() is gl.NO_ERROR
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test.html b/LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test.html
new file mode 100644 (file)
index 0000000..de697f3
--- /dev/null
@@ -0,0 +1,197 @@
+<!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 BindAttribLocation 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 style="border: 1px solid black;" id="canvas" width="50" height="50"></canvas>
+<script id="vshader" type="text/something-not-javascript">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main()
+{
+    gl_Position = vPosition;
+    color = vColor;
+}
+</script>
+<script id="fshader" type="text/something-not-javascript">
+varying vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script>
+description("This test ensures WebGL implementations don't allow names that start with 'gl_' when calling bindAttribLocation.");
+
+debug("");
+debug("Canvas.getContext");
+
+var canvas = document.getElementById("canvas");
+shouldBeNonNull(canvas);
+var gl = canvas.getContext("experimental-webgl");
+shouldBeNonNull(gl);
+
+function fail(x,y, buf, shouldBe)
+{
+    var i = (y*50+x) * 4;
+    var reason = "pixel at ("+x+","+y+") is ("+buf[i]+","+buf[i+1]+","+buf[i+2]+","+buf[i+3]+"), should be "+shouldBe;
+    testFailed(reason);
+}
+
+function pass()
+{
+    testPassed("drawing is correct");
+}
+
+function loadShader(shaderType, shaderId) {
+  // Get the shader source.
+  var shaderSource = document.getElementById(shaderId).text;
+
+  // Create the shader object
+  var shader = gl.createShader(shaderType);
+  if (shader == null) {
+      debug("*** Error: unable to create shader '"+shaderId+"'");
+      return null;
+  }
+
+  // Load the shader source
+  gl.shaderSource(shader, shaderSource);
+
+  // Compile the shader
+  gl.compileShader(shader);
+
+  // Check the compile status
+  var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+  if (!compiled) {
+      // Something went wrong during compilation; get the error
+      var error = gl.getShaderInfoLog(shader);
+      debug("*** Error compiling shader '"+shader+"':"+error);
+      gl.deleteShader(shader);
+      return null;
+  }
+  return shader;
+}
+
+debug("");
+debug("Checking gl.bindAttribLocation.");
+
+var program = gl.createProgram();
+gl.bindAttribLocation(program, 0, "gl_foo");
+assertMsg(gl.getError() == gl.INVALID_OPERATION,
+          "bindAttribLocation should return INVALID_OPERATION if name starts with 'gl_'");
+gl.bindAttribLocation(program, 0, "gl_TexCoord0");
+assertMsg(gl.getError() == gl.INVALID_OPERATION,
+          "bindAttribLocation should return INVALID_OPERATION if name starts with 'gl_'");
+
+var vs = loadShader(gl.VERTEX_SHADER, "vshader");
+var fs = loadShader(gl.FRAGMENT_SHADER, "fshader");
+gl.attachShader(program, vs);
+gl.attachShader(program, fs);
+
+var positions = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positions);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+
+var colors = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colors);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+   0,1,0,1,
+   0,1,0,1,
+   0,1,0,1]), gl.STATIC_DRAW);
+
+function setBindLocations(colorLocation, positionLocation) {
+  gl.bindAttribLocation(program, positionLocation, "vPosition");
+  gl.bindAttribLocation(program, colorLocation, "vColor");
+  gl.linkProgram(program);
+  gl.useProgram(program);
+  var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
+  assertMsg(linked, "program linked successfully");
+
+  debug("vPosition:" + gl.getAttribLocation(program, "vPosition"))
+  debug("vColor   :" + gl.getAttribLocation(program, "vColor"))
+  assertMsg(gl.getAttribLocation(program, "vPosition") == positionLocation,
+            "location of vPositon should be " + positionLocation);
+  assertMsg(gl.getAttribLocation(program, "vColor") == colorLocation,
+            "location of vColor should be " + colorLocation);
+
+  var ploc = gl.getAttribLocation(program, "vPosition");
+  var cloc = gl.getAttribLocation(program, "vColor");
+  gl.bindBuffer(gl.ARRAY_BUFFER, positions);
+  gl.enableVertexAttribArray(positionLocation);
+  gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+  gl.bindBuffer(gl.ARRAY_BUFFER, colors);
+  gl.enableVertexAttribArray(colorLocation);
+  gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
+}
+
+function checkDraw(colorLocation, positionLocation, r, g, b, a) {
+  gl.clearColor(0, 0, 0, 1);
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+  var width = 50;
+  var height = 50;
+  var buf = new Uint8Array(width * height * 4);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+  function checkPixel(x, y, r, g, b, a) {
+    var offset = (y * width + x) * 4;
+    if (buf[offset + 0] != r ||
+        buf[offset + 1] != g ||
+        buf[offset + 2] != b ||
+        buf[offset + 3] != a) {
+        fail(x, y, buf, "(" + r + "," + g + "," + b + "," + a + ")");
+        return false;
+    }
+    return true;
+  }
+
+  // Test several locations
+  // First line should be all black
+  var success = true;
+  for (var i = 0; i < 50; ++i)
+    success = success && checkPixel(i, 0, 0, 0, 0, 255);
+
+  // Line 15 should be red for at least 10 rgba pixels starting 20 pixels in
+  var offset = (15 * 50 + 20) * 4;
+  for (var i = 0; i < 10; ++i)
+    success = success && checkPixel(20 + i, 15, r, g, b, a);
+
+  // Last line should be all black
+  for (var i = 0; i < 50; ++i)
+    success = success && checkPixel(i, 49, 0, 0, 0, 255);
+
+  if (success)
+    pass();
+
+  gl.disableVertexAttribArray(positionLocation);
+  gl.disableVertexAttribArray(colorLocation);
+}
+
+setBindLocations(2, 3);
+checkDraw(2, 3, 0, 255, 0, 255);
+
+setBindLocations(0, 3);
+gl.disableVertexAttribArray(0);
+gl.vertexAttrib4f(0, 1, 0, 0, 1);
+checkDraw(0, 3, 255, 0, 0, 255);
+
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+debug("");
+successfullyParsed = true;
+
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/canvas/webgl/gl-vertex-attrib-expected.txt b/LayoutTests/fast/canvas/webgl/gl-vertex-attrib-expected.txt
new file mode 100644 (file)
index 0000000..55c4c94
--- /dev/null
@@ -0,0 +1,22 @@
+This test ensures WebGL implementations vertexAttrib can be set and read.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Canvas.getContext
+PASS context exists
+
+Checking gl.vertexAttrib.
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[0] is 1
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[1] is 2
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[2] is 3
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[3] is 4
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[0] is 5
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[1] is 0
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[2] is 0
+PASS gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[3] is 1
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/gl-vertex-attrib.html b/LayoutTests/fast/canvas/webgl/gl-vertex-attrib.html
new file mode 100644 (file)
index 0000000..39f94b3
--- /dev/null
@@ -0,0 +1,50 @@
+<!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 vertexAttrib 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="canvas" width="2" height="2"> </canvas>
+<script>
+description("This test ensures WebGL implementations vertexAttrib can be set and read.");
+
+debug("");
+debug("Canvas.getContext");
+
+var gl = create3DContext(document.getElementById("canvas"));
+if (!gl) {
+  testFailed("context does not exist");
+} else {
+  testPassed("context exists");
+
+  debug("");
+  debug("Checking gl.vertexAttrib.");
+
+  gl.vertexAttrib4fv(0, [1, 2, 3, 4]);
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[1]', '2');
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[2]', '3');
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[3]', '4');
+
+  gl.vertexAttrib1f(0, 5);
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[0]', '5');
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+  shouldBe('gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+}
+
+debug("");
+successfullyParsed = true;
+
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+
+</body>
+</html>
index b9accc9eeed5310a8fb26c46aa6cc14e209f9abb..28b4c4e5c8f1bfdf830a2638631badc1073ce5b8 100644 (file)
@@ -1,3 +1,42 @@
+2010-07-02  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Dimitri Glazkov.
+
+        Implement OpenGL ES 2.0 semantics for vertex attribute 0
+        https://bugs.webkit.org/show_bug.cgi?id=41300
+
+        Test: fast/canvas/webgl/gl-bind-attrib-location-test.html
+              fast/canvas/webgl/gl-vertex-attrib.html
+
+        * html/canvas/WebGLProgram.cpp:
+        (WebCore::WebGLProgram::numActiveAttribLocations): const.
+        (WebCore::WebGLProgram::getActiveAttribLocation): const.
+        (WebCore::WebGLProgram::isUsingVertexAttrib0): Determine whether vertex attrib 0 is used by the program.
+        * html/canvas/WebGLProgram.h: Declare isUsingVertexAttrib0.
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::WebGLRenderingContext): Deal with vertex attrib 0.
+        (WebCore::WebGLRenderingContext::disableVertexAttribArray): Ditto.
+        (WebCore::WebGLRenderingContext::drawArrays): Ditto.
+        (WebCore::WebGLRenderingContext::drawElements): Ditto.
+        (WebCore::WebGLRenderingContext::getVertexAttrib): Use cached value instead of calling glGetVertexAtrtrib.
+        (WebCore::WebGLRenderingContext::vertexAttrib1f): Validate input, deal with vertex attrib 0.
+        (WebCore::WebGLRenderingContext::vertexAttrib1fv): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttrib2f): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttrib2fv): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttrib3f): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttrib3fv): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttrib4f): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttrib4fv): Ditto.
+        (WebCore::WebGLRenderingContext::vertexAttribPointer): Ditto.
+        (WebCore::WebGLRenderingContext::handleNPOTTextures): Move isGLES2Compliant() to caller.
+        (WebCore::WebGLRenderingContext::vertexAttribImpl): Helper for vertexAttribNfv.
+        (WebCore::WebGLRenderingContext::initVertexAttrib0): Initialize vertex attrib 0.
+        (WebCore::WebGLRenderingContext::simulateVertexAttrib0): Simulate vertex attrib 0.
+        (WebCore::WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation): Restore states after simulating vertex attrib 0.
+        * html/canvas/WebGLRenderingContext.h:
+        (WebCore::WebGLRenderingContext::VertexAttribState::VertexAttribState): Tracking full vertex attrib states.
+        (WebCore::WebGLRenderingContext::VertexAttribState::initValue): Init value to [0,0,0,1].
+
 2010-07-02  Zhenyao Mo  <zmo@google.com>
 
         Reviewed by Dimitri Glazkov.
index 750df4502cffbeda36ccb650ef6d032f90272a19..6adbb7a2d419c1162453cb87e0e98ff15c950310 100644 (file)
@@ -71,18 +71,27 @@ bool WebGLProgram::cacheActiveAttribLocations()
     return true;
 }
 
-int WebGLProgram::numActiveAttribLocations()
+int WebGLProgram::numActiveAttribLocations() const
 {
     return static_cast<int>(m_activeAttribLocations.size());
 }
 
-int WebGLProgram::getActiveAttribLocation(int index)
+int WebGLProgram::getActiveAttribLocation(int index) const
 {
     if (index < 0 || index >= numActiveAttribLocations())
         return -1;
     return m_activeAttribLocations[static_cast<size_t>(index)];
 }
 
+bool WebGLProgram::isUsingVertexAttrib0() const
+{
+    for (int ii = 0; ii < numActiveAttribLocations(); ++ii) {
+        if (!getActiveAttribLocation(ii))
+            return true;
+    }
+    return false;
+}
+
 }
 
 #endif // ENABLE(3D_CANVAS)
index b13fc221a2682f7cbc7590b62e72875fc1fc7a80..e18d1b48951748bbca71d31130f266eabb09d7ee 100644 (file)
@@ -43,8 +43,10 @@ namespace WebCore {
         // cacheActiveAttribLocation() is only called once after linkProgram()
         // succeeds.
         bool cacheActiveAttribLocations();
-        int numActiveAttribLocations();
-        int getActiveAttribLocation(int index);
+        int numActiveAttribLocations() const;
+        int getActiveAttribLocation(int index) const;
+
+        bool isUsingVertexAttrib0() const;
 
     protected:
         WebGLProgram(WebGLRenderingContext*);
index 7af65055e64a7ce948cba18cf878f0981c622bb7..c258edc3acf6d2bfec518ede4a2a4cc5a80deebc 100644 (file)
@@ -121,8 +121,10 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
     m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize);
     m_maxCubeMapTextureSize = maxCubeMapTextureSize;
 
-    if (!isGLES2Compliant())
+    if (!isGLES2Compliant()) {
         createFallbackBlackTextures1x1();
+        initVertexAttrib0();
+    }
     m_context->reshape(canvas()->width(), canvas()->height());
     m_context->viewport(0, 0, canvas()->width(), canvas()->height());
 }
@@ -575,6 +577,20 @@ void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
         return;
     
     buffer->deleteObject();
+
+    if (!isGLES2Compliant()) {
+        VertexAttribState& state = m_vertexAttribState[0];
+        if (buffer == state.bufferBinding) {
+            state.bufferBinding = m_vertexAttrib0Buffer;
+            state.bytesPerElement = 0;
+            state.size = 4;
+            state.type = GraphicsContext3D::FLOAT;
+            state.normalized = false;
+            state.stride = 16;
+            state.originalStride = 0;
+            state.offset = 0;
+        }
+    }
 }
 
 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
@@ -669,9 +685,11 @@ void WebGLRenderingContext::disableVertexAttribArray(unsigned long index, Except
     
     if (index < m_vertexAttribState.size())
         m_vertexAttribState[index].enabled = false;
-    
-    m_context->disableVertexAttribArray(index);
-    cleanupAfterGraphicsCall(false);
+
+    if (index > 0 || isGLES2Compliant()) {
+        m_context->disableVertexAttribArray(index);
+        cleanupAfterGraphicsCall(false);
+    }
 }
 
 bool WebGLRenderingContext::validateElementArraySize(unsigned long count, unsigned long type, long offset)
@@ -853,9 +871,17 @@ void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long coun
         return;
     }
 
-    handleNPOTTextures(true);
+    bool vertexAttrib0Simulated = false;
+    if (!isGLES2Compliant()) {
+        vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
+        handleNPOTTextures(true);
+    }
     m_context->drawArrays(mode, first, count);
-    handleNPOTTextures(false);
+    if (!isGLES2Compliant()) {
+        handleNPOTTextures(false);
+        if (vertexAttrib0Simulated)
+            restoreStatesAfterVertexAttrib0Simulation();
+    }
     cleanupAfterGraphicsCall(true);
 }
 
@@ -897,9 +923,17 @@ void WebGLRenderingContext::drawElements(unsigned long mode, long count, unsigne
             return;
         }
 
-    handleNPOTTextures(true);
+    bool vertexAttrib0Simulated = false;
+    if (!isGLES2Compliant()) {
+        vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
+        handleNPOTTextures(true);
+    }
     m_context->drawElements(mode, count, type, offset);
-    handleNPOTTextures(false);
+    if (!isGLES2Compliant()) {
+        handleNPOTTextures(false);
+        if (vertexAttrib0Simulated)
+            restoreStatesAfterVertexAttrib0Simulation();
+    }
     cleanupAfterGraphicsCall(true);
 }
 
@@ -1664,39 +1698,48 @@ WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigne
 {
     UNUSED_PARAM(ec);
     WebGLStateRestorer(this, false);
-    switch (pname) {
-    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
-        int name = 0;
-        m_context->getVertexAttribiv(index, pname, &name);
-        return WebGLGetInfo(PassRefPtr<WebGLBuffer>(findBuffer(static_cast<Platform3DObject>(name))));
+    if (index >= m_maxVertexAttribs) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+        return WebGLGetInfo();
     }
+    switch (pname) {
+    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+        if (!isGLES2Compliant() && !index && m_vertexAttribState[0].bufferBinding == m_vertexAttrib0Buffer
+            || index >= m_vertexAttribState.size()
+            || !m_vertexAttribState[index].bufferBinding
+            || !m_vertexAttribState[index].bufferBinding->object())
+            return WebGLGetInfo();
+        return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_vertexAttribState[index].bufferBinding));
     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
-    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED: {
-        int value = 0;
-        m_context->getVertexAttribiv(index, pname, &value);
-        return WebGLGetInfo(static_cast<bool>(value));
-    }
+        if (index >= m_vertexAttribState.size())
+            return WebGLGetInfo(false);
+        return WebGLGetInfo(m_vertexAttribState[index].enabled);
+    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
+        if (index >= m_vertexAttribState.size())
+            return WebGLGetInfo(false);
+        return WebGLGetInfo(m_vertexAttribState[index].normalized);
     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
-    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE: {
-        int value = 0;
-        m_context->getVertexAttribiv(index, pname, &value);
-        return WebGLGetInfo(static_cast<long>(value));
-    }
-    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE: {
-        int value = 0;
-        m_context->getVertexAttribiv(index, pname, &value);
-        return WebGLGetInfo(static_cast<unsigned long>(value));
-    }
-    case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: {
-        float value[4] = {0};
-        m_context->getVertexAttribfv(index, pname, value);
-        return WebGLGetInfo(Float32Array::create(value, 4));
-    }
-    default: {
+        if (index >= m_vertexAttribState.size())
+            return WebGLGetInfo(static_cast<long>(4));
+        return WebGLGetInfo(m_vertexAttribState[index].size);
+    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
+        if (index >= m_vertexAttribState.size())
+            return WebGLGetInfo(static_cast<long>(0));
+        return WebGLGetInfo(m_vertexAttribState[index].originalStride);
+    case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
+        if (index >= m_vertexAttribState.size())
+            return WebGLGetInfo(static_cast<unsigned long>(GraphicsContext3D::FLOAT));
+        return WebGLGetInfo(m_vertexAttribState[index].type);
+    case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
+        if (index >= m_vertexAttribState.size()) {
+            float value[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+            return WebGLGetInfo(Float32Array::create(value, 4));
+        }
+        return WebGLGetInfo(Float32Array::create(m_vertexAttribState[index].value, 4));
+    default:
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
         return WebGLGetInfo();
     }
-    }
 }
 
 long WebGLRenderingContext::getVertexAttribOffset(unsigned long index, unsigned long pname)
@@ -2835,123 +2878,137 @@ void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode
     cleanupAfterGraphicsCall(false);
 }
 
-void WebGLRenderingContext::vertexAttrib1f(unsigned long indx, float v0)
+void WebGLRenderingContext::vertexAttrib1f(unsigned long index, float v0)
 {
-    m_context->vertexAttrib1f(indx, v0);
-    cleanupAfterGraphicsCall(false);
+    // In GL, we skip setting vertexAttrib0 values.
+    if (index || isGLES2Compliant()) {
+        m_context->vertexAttrib1f(index, v0);
+        cleanupAfterGraphicsCall(false);
+    }
+    m_vertexAttribState[index].value[0] = v0;
+    m_vertexAttribState[index].value[1] = 0.0f;
+    m_vertexAttribState[index].value[2] = 0.0f;
+    m_vertexAttribState[index].value[3] = 1.0f;
 }
 
-void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, Float32Array* v)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    m_context->vertexAttrib1fv(indx, v->data());
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, 1);
 }
 
-void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, float* v, int size)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    UNUSED_PARAM(size);
-    
-    m_context->vertexAttrib1fv(indx, v);
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, size, 1);
 }
 
-void WebGLRenderingContext::vertexAttrib2f(unsigned long indx, float v0, float v1)
+void WebGLRenderingContext::vertexAttrib2f(unsigned long index, float v0, float v1)
 {
-    m_context->vertexAttrib2f(indx, v0, v1);
-    cleanupAfterGraphicsCall(false);
+    // In GL, we skip setting vertexAttrib0 values.
+    if (index || isGLES2Compliant()) {
+        m_context->vertexAttrib2f(index, v0, v1);
+        cleanupAfterGraphicsCall(false);
+    }
+    m_vertexAttribState[index].value[0] = v0;
+    m_vertexAttribState[index].value[1] = v1;
+    m_vertexAttribState[index].value[2] = 0.0f;
+    m_vertexAttribState[index].value[3] = 1.0f;
 }
 
-void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, Float32Array* v)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    m_context->vertexAttrib2fv(indx, v->data());
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, 2);
 }
 
-void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, float* v, int size)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    UNUSED_PARAM(size);
-    
-    m_context->vertexAttrib2fv(indx, v);
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, size, 2);
 }
 
-void WebGLRenderingContext::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
+void WebGLRenderingContext::vertexAttrib3f(unsigned long index, float v0, float v1, float v2)
 {
-    m_context->vertexAttrib3f(indx, v0, v1, v2);
-    cleanupAfterGraphicsCall(false);
+    // In GL, we skip setting vertexAttrib0 values.
+    if (index || isGLES2Compliant()) {
+        m_context->vertexAttrib3f(index, v0, v1, v2);
+        cleanupAfterGraphicsCall(false);
+    }
+    m_vertexAttribState[index].value[0] = v0;
+    m_vertexAttribState[index].value[1] = v1;
+    m_vertexAttribState[index].value[2] = v2;
+    m_vertexAttribState[index].value[3] = 1.0f;
 }
 
-void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, Float32Array* v)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    m_context->vertexAttrib3fv(indx, v->data());
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, 3);
 }
 
-void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, float* v, int size)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    UNUSED_PARAM(size);
-    
-    m_context->vertexAttrib3fv(indx, v);
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, size, 3);
 }
 
-void WebGLRenderingContext::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
+void WebGLRenderingContext::vertexAttrib4f(unsigned long index, float v0, float v1, float v2, float v3)
 {
-    m_context->vertexAttrib4f(indx, v0, v1, v2, v3);
-    cleanupAfterGraphicsCall(false);
+    // In GL, we skip setting vertexAttrib0 values.
+    if (index || isGLES2Compliant()) {
+        m_context->vertexAttrib4f(index, v0, v1, v2, v3);
+        cleanupAfterGraphicsCall(false);
+    }
+    m_vertexAttribState[index].value[0] = v0;
+    m_vertexAttribState[index].value[1] = v1;
+    m_vertexAttribState[index].value[2] = v2;
+    m_vertexAttribState[index].value[3] = v3;
 }
 
-void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib4fv(unsigned long index, Float32Array* v)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    m_context->vertexAttrib4fv(indx, v->data());
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, 4);
 }
 
-void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib4fv(unsigned long index, float* v, int size)
 {
-    // FIXME: Need to make sure array is big enough for attribute being set
-    UNUSED_PARAM(size);
-    
-    m_context->vertexAttrib4fv(indx, v);
-    cleanupAfterGraphicsCall(false);
+    vertexAttribImpl(index, v, size, 4);
 }
 
-void WebGLRenderingContext::vertexAttribPointer(unsigned long indx, long size, unsigned long type, bool normalized, unsigned long stride, unsigned long offset, ExceptionCode& ec)
+void WebGLRenderingContext::vertexAttribPointer(unsigned long index, long size, unsigned long type, bool normalized, long stride, long offset, ExceptionCode& ec)
 {
-    UNUSED_PARAM(ec);
-    if (!m_boundArrayBuffer || indx >= m_maxVertexAttribs) {
+    if (index >= m_maxVertexAttribs) {
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
         return;
     }
-    
-    if (indx >= m_vertexAttribState.size())
-        m_vertexAttribState.resize(indx + 1);
-
+    if (size < 1 || size > 4 || stride < 0 || offset < 0) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+        return;
+    }
+    if (!m_boundArrayBuffer) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+        return;
+    }
     // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
     long bytesPerElement = size * sizeInBytes(type, ec);
     if (bytesPerElement <= 0)
         return;
+
+    if (index >= m_vertexAttribState.size())
+        m_vertexAttribState.resize(index + 1);
+
     long validatedStride = bytesPerElement;
     if (stride != 0) {
         if ((long) stride < bytesPerElement) {
             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
             return;
         }
-        
         validatedStride = stride;
     }
-    m_vertexAttribState[indx].bufferBinding = m_boundArrayBuffer;
-    m_vertexAttribState[indx].bytesPerElement = bytesPerElement;
-    m_vertexAttribState[indx].stride = validatedStride;
-    m_vertexAttribState[indx].offset = offset;
-    m_context->vertexAttribPointer(indx, size, type, normalized, stride, offset);
+    m_vertexAttribState[index].bufferBinding = m_boundArrayBuffer;
+    m_vertexAttribState[index].bytesPerElement = bytesPerElement;
+    m_vertexAttribState[index].size = size;
+    m_vertexAttribState[index].type = type;
+    m_vertexAttribState[index].normalized = normalized;
+    m_vertexAttribState[index].stride = validatedStride;
+    m_vertexAttribState[index].originalStride = stride;
+    m_vertexAttribState[index].offset = offset;
+    m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
     cleanupAfterGraphicsCall(false);
 }
 
@@ -3131,8 +3188,6 @@ bool WebGLRenderingContext::isGLES2Compliant()
 
 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
 {
-    if (isGLES2Compliant())
-        return;
     bool resetActiveUnit = false;
     for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
         if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()
@@ -3519,6 +3574,106 @@ bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLo
     return true;
 }
 
+void WebGLRenderingContext::vertexAttribImpl(unsigned long index, Float32Array* v, int expectedSize)
+{
+    if (!v) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+        return;
+    }
+    vertexAttribImpl(index, v->data(), v->length(), expectedSize);
+}
+
+void WebGLRenderingContext::vertexAttribImpl(unsigned long index, float* v, int size, int expectedSize)
+{
+    if (!v) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+        return;
+    }
+    if (size < expectedSize) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+        return;
+    }
+    // In GL, we skip setting vertexAttrib0 values.
+    if (index || isGLES2Compliant()) {
+        switch (expectedSize) {
+        case 1:
+            m_context->vertexAttrib1fv(index, v);
+            break;
+        case 2:
+            m_context->vertexAttrib2fv(index, v);
+            break;
+        case 3:
+            m_context->vertexAttrib3fv(index, v);
+            break;
+        case 4:
+            m_context->vertexAttrib4fv(index, v);
+            break;
+        }
+        cleanupAfterGraphicsCall(false);
+    }
+    m_vertexAttribState[index].initValue();
+    for (int ii = 0; ii < expectedSize; ++ii)
+        m_vertexAttribState[index].value[ii] = v[ii];
+}
+
+void WebGLRenderingContext::initVertexAttrib0()
+{
+    m_vertexAttribState.resize(1);
+    m_vertexAttrib0Buffer = createBuffer();
+    m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer.get());
+    m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
+    m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
+    m_vertexAttribState[0].bufferBinding = m_vertexAttrib0Buffer;
+    m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
+    m_context->enableVertexAttribArray(0);
+    m_vertexAttrib0BufferSize = 0;
+    m_vertexAttrib0BufferValue[0] = 0.0f;
+    m_vertexAttrib0BufferValue[1] = 0.0f;
+    m_vertexAttrib0BufferValue[2] = 0.0f;
+    m_vertexAttrib0BufferValue[3] = 1.0f;
+}
+
+bool WebGLRenderingContext::simulateVertexAttrib0(long numVertex)
+{
+    const VertexAttribState& state = m_vertexAttribState[0];
+    if (state.enabled || !m_currentProgram || !m_currentProgram->object()
+        || !m_currentProgram->isUsingVertexAttrib0())
+        return false;
+    m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer.get());
+    long bufferDataSize = (numVertex + 1) * 4 * sizeof(float);
+    if (bufferDataSize > m_vertexAttrib0BufferSize
+        || state.value[0] != m_vertexAttrib0BufferValue[0]
+        || state.value[1] != m_vertexAttrib0BufferValue[1]
+        || state.value[2] != m_vertexAttrib0BufferValue[2]
+        || state.value[3] != m_vertexAttrib0BufferValue[3]) {
+        RefPtr<Float32Array> bufferData = Float32Array::create((numVertex + 1) * 4);
+        for (long ii = 0; ii < numVertex + 1; ++ii) {
+            bufferData->set(ii * 4, state.value[0]);
+            bufferData->set(ii * 4 + 1, state.value[1]);
+            bufferData->set(ii * 4 + 2, state.value[2]);
+            bufferData->set(ii * 4 + 3, state.value[3]);
+        }
+        m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferData.get(), GraphicsContext3D::DYNAMIC_DRAW);
+        m_vertexAttrib0BufferSize = bufferDataSize;
+        m_vertexAttrib0BufferValue[0] = state.value[0];
+        m_vertexAttrib0BufferValue[1] = state.value[1];
+        m_vertexAttrib0BufferValue[2] = state.value[2];
+        m_vertexAttrib0BufferValue[3] = state.value[3];
+    }
+    m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
+    return true;
+}
+
+void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
+{
+    const VertexAttribState& state = m_vertexAttribState[0];
+    if (state.bufferBinding != m_vertexAttrib0Buffer) {
+        m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, state.bufferBinding.get());
+        m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
+    }
+    m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_boundArrayBuffer.get());
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(3D_CANVAS)
index 93d1b9fbbd3ffd43c59cea963a14168e4462c2d8..b3da05c93bd22d8d4dade89edc81a5f74b3b3367 100644 (file)
@@ -283,20 +283,20 @@ class WebKitCSSMatrix;
         void useProgram(WebGLProgram*, ExceptionCode&);
         void validateProgram(WebGLProgram*, ExceptionCode&);
 
-        void vertexAttrib1f(unsigned long indx, float x);
-        void vertexAttrib1fv(unsigned long indx, Float32Array* values);
-        void vertexAttrib1fv(unsigned long indx, float* values, int size);
-        void vertexAttrib2f(unsigned long indx, float x, float y);
-        void vertexAttrib2fv(unsigned long indx, Float32Array* values);
-        void vertexAttrib2fv(unsigned long indx, float* values, int size);
-        void vertexAttrib3f(unsigned long indx, float x, float y, float z);
-        void vertexAttrib3fv(unsigned long indx, Float32Array* values);
-        void vertexAttrib3fv(unsigned long indx, float* values, int size);
-        void vertexAttrib4f(unsigned long indx, float x, float y, float z, float w);
-        void vertexAttrib4fv(unsigned long indx, Float32Array* values);
-        void vertexAttrib4fv(unsigned long indx, float* values, int size);
-        void vertexAttribPointer(unsigned long indx, long size, unsigned long type, bool normalized,
-                                 unsigned long stride, unsigned long offset, ExceptionCode&);
+        void vertexAttrib1f(unsigned long index, float x);
+        void vertexAttrib1fv(unsigned long index, Float32Array* values);
+        void vertexAttrib1fv(unsigned long index, float* values, int size);
+        void vertexAttrib2f(unsigned long index, float x, float y);
+        void vertexAttrib2fv(unsigned long index, Float32Array* values);
+        void vertexAttrib2fv(unsigned long index, float* values, int size);
+        void vertexAttrib3f(unsigned long index, float x, float y, float z);
+        void vertexAttrib3fv(unsigned long index, Float32Array* values);
+        void vertexAttrib3fv(unsigned long index, float* values, int size);
+        void vertexAttrib4f(unsigned long index, float x, float y, float z, float w);
+        void vertexAttrib4fv(unsigned long index, Float32Array* values);
+        void vertexAttrib4fv(unsigned long index, float* values, int size);
+        void vertexAttribPointer(unsigned long index, long size, unsigned long type, bool normalized,
+                                 long stride, long offset, ExceptionCode&);
 
         void viewport(long x, long y, unsigned long width, unsigned long height);
 
@@ -357,16 +357,44 @@ class WebKitCSSMatrix;
         // Cached values for vertex attrib range checks
         class VertexAttribState {
         public:
-            VertexAttribState() : enabled(false), bytesPerElement(0), stride(0), offset(0) { }
+            VertexAttribState()
+                : enabled(false)
+                , bytesPerElement(0)
+                , size(4)
+                , type(GraphicsContext3D::FLOAT)
+                , normalized(false)
+                , stride(16)
+                , originalStride(0)
+                , offset(0)
+            {
+                initValue();
+            }
+
+            void initValue()
+            {
+                value[0] = 0.0f;
+                value[1] = 0.0f;
+                value[2] = 0.0f;
+                value[3] = 1.0f;
+            }
+
             bool enabled;
             RefPtr<WebGLBuffer> bufferBinding;
             long bytesPerElement;
-            unsigned long stride;
-            unsigned long offset;
+            long size;
+            unsigned long type;
+            bool normalized;
+            long stride;
+            long originalStride;
+            long offset;
+            float value[4];
         };
         
         Vector<VertexAttribState> m_vertexAttribState;
         unsigned m_maxVertexAttribs;
+        RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
+        long m_vertexAttrib0BufferSize;
+        float m_vertexAttrib0BufferValue[4];
 
         RefPtr<WebGLProgram> m_currentProgram;
         RefPtr<WebGLFramebuffer> m_framebufferBinding;
@@ -473,6 +501,15 @@ class WebKitCSSMatrix;
         bool validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, Float32Array* v, int mod);
         bool validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, void* v, int size, int mod);
 
+        // Helper functions for vertexAttribNfv.
+        void vertexAttribImpl(unsigned long index, Float32Array* v, int expectedSize);
+        void vertexAttribImpl(unsigned long index, float* v, int size, int expectedSize);
+
+        // Helpers for simulating vertexAttrib0
+        void initVertexAttrib0();
+        bool simulateVertexAttrib0(long numVertex);
+        void restoreStatesAfterVertexAttrib0Simulation();
+
         friend class WebGLStateRestorer;
     };