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

        linkProgram should fail when vertex/fragment shaders are not both present
        https://bugs.webkit.org/show_bug.cgi?id=41380

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

        Reviewed by Dimitri Glazkov.

        linkProgram should fail when vertex/fragment shaders are not both present
        https://bugs.webkit.org/show_bug.cgi?id=41380

        Test: fast/canvas/webgl/program-test.html

        * html/canvas/WebGLProgram.cpp: Add flag for link failure due to missing shaders.
        (WebCore::WebGLProgram::WebGLProgram):
        * html/canvas/WebGLProgram.h: Add interface for linkFailure flag.
        (WebCore::WebGLProgram::isLinkFailureFlagSet):
        (WebCore::WebGLProgram::setLinkFailureFlag):
        * html/canvas/WebGLRenderingContext.cpp:
        (WebCore::WebGLRenderingContext::getProgramParameter): Intercept when linkFailureFlag is set.
        (WebCore::WebGLRenderingContext::linkProgram): Check if there are missing shaders and don't link if yes.
        * html/canvas/WebGLShader.cpp: Cache shader type.
        (WebCore::WebGLShader::WebGLShader):
        * html/canvas/WebGLShader.h: Ditto.
        (WebCore::WebGLShader::getType):

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

LayoutTests/ChangeLog
LayoutTests/fast/canvas/webgl/program-test-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/program-test.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/WebGLShader.cpp
WebCore/html/canvas/WebGLShader.h

index 0d96babc02357a75d5fb93d78be7a11b0a59bd61..37d6531cb8e20207a6e75cbc13b77884a088deaf 100644 (file)
@@ -1,3 +1,13 @@
+2010-07-02  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Dimitri Glazkov.
+
+        linkProgram should fail when vertex/fragment shaders are not both present
+        https://bugs.webkit.org/show_bug.cgi?id=41380
+
+        * fast/canvas/webgl/program-test-expected.txt: Added.
+        * fast/canvas/webgl/program-test.html: Added.
+
 2010-07-02  Qi Zhang  <qi.2.zhang@nokia.com>
 
         Reviewed by Laszlo Gombos.
diff --git a/LayoutTests/fast/canvas/webgl/program-test-expected.txt b/LayoutTests/fast/canvas/webgl/program-test-expected.txt
new file mode 100644 (file)
index 0000000..c98d2b2
--- /dev/null
@@ -0,0 +1,58 @@
+Tests that program compiling/linking/using works correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Canvas.getContext
+PASS context exists
+PASS good vertex shader should compile
+PASS good vertex shader #2 should compile
+PASS bad vertex shader should fail to compile
+PASS good fragment shader should compile
+PASS good fragment shader #2 should compile
+PASS bad fragment shader should fail to compile
+PASS should be no errors at this point
+PASS attaching a vertex shader should succeed
+PASS attaching an already attached vertex shader should generate INVALID_OPERATION
+PASS attaching a fragment shader should succeed
+PASS attaching an already attached fragment shader should generate INVALID_OPERATION
+PASS detaching a vertex shader should succeed
+PASS detaching a not already attached vertex shader should generate INVALID_OPERATION
+PASS detaching a fragment shader should succeed
+PASS detaching a not already attached fragment shader should generate INVALID_OPERATION
+PASS getAttachedShaders should return an empty list by default
+PASS attaching a single shader should give the expected list
+PASS attaching some shaders should give the expected list
+PASS attaching a shader and detaching it shoud leave an empty list
+PASS attaching some shaders and detaching them in same order shoud leave an empty list
+PASS attaching some shaders and detaching them in random order shoud leave an empty list
+PASS attaching and detaching some shaders should leave the difference list
+PASS attaching and detaching some shaders should leave the difference list
+PASS attaching a shader that failed to compile should still show it in the list
+PASS attaching shaders, including one that failed to compile, should still show the it in the list
+PASS valid program should link
+PASS using a valid program should succeed
+PASS valid program #2 should link
+PASS using a valid program should succeed
+PASS program with no fragment shader should fail to link
+PASS using an invalid program should generate INVALID_OPERATION
+PASS program with no vertex shader should fail to link
+PASS using an invalid program should generate INVALID_OPERATION
+PASS program with bad vertex shader should fail to link
+PASS using an invalid program should generate INVALID_OPERATION
+PASS program with bad fragment shader should fail to link
+PASS using an invalid program should generate INVALID_OPERATION
+PASS program with bad shaders should fail to link
+PASS using an invalid program should generate INVALID_OPERATION
+PASS using a valid program shouldn't generate a GL error
+PASS should be no errors at this point #2
+PASS drawing with a valid program shouldn't generate a GL error
+PASS using an invalid program should generate INVALID_OPERATION
+PASS drawing with an invalid program should generate some GL error XXX
+PASS linking should fail with in-use formerly good program, with new bad shader attached
+PASS drawing with a valid when last used program shouldn't generate a GL error
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/program-test.html b/LayoutTests/fast/canvas/webgl/program-test.html
new file mode 100644 (file)
index 0000000..e43c995
--- /dev/null
@@ -0,0 +1,235 @@
+<!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 Program Compiling/Linking Conformance Test</title>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
+<script src="../../js/resources/js-test-pre.js" type="text/javascript"></script>
+<script src="resources/webgl-test.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="2" height="2"> </canvas>
+<script type="text/javascript">
+function go() {
+    description("Tests that program compiling/linking/using works correctly.");
+
+    debug("");
+    debug("Canvas.getContext");
+
+    var gl = create3DContext(document.getElementById("canvas"));
+    if (!gl) {
+        testFailed("context does not exist");
+        return;
+    }
+
+    testPassed("context exists");
+
+    gl.clearColor(0.0, 0.0, 0.0, 0.0);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+
+/////// Check compileShader() /////////////////////////////
+
+    var vs = gl.createShader(gl.VERTEX_SHADER);
+    gl.shaderSource(vs, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }");
+    gl.compileShader(vs);
+
+    assertMsg(gl.getShaderParameter(vs, gl.COMPILE_STATUS) == true,
+              "good vertex shader should compile");
+
+    var vs2 = gl.createShader(gl.VERTEX_SHADER);
+    gl.shaderSource(vs2, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex * 0.5; }");
+    gl.compileShader(vs2);
+
+    assertMsg(gl.getShaderParameter(vs2, gl.COMPILE_STATUS) == true,
+              "good vertex shader #2 should compile");
+
+    var vsBad = gl.createShader(gl.VERTEX_SHADER);
+    gl.shaderSource(vsBad, "WILL NOT COMPILE;");
+    gl.compileShader(vsBad);
+
+    assertMsg(gl.getShaderParameter(vsBad, gl.COMPILE_STATUS) == false,
+              "bad vertex shader should fail to compile");
+
+    var fs = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(fs, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varying vec4 vColor; void main() { gl_FragColor = vColor; }");
+    gl.compileShader(fs);
+
+    assertMsg(gl.getShaderParameter(fs, gl.COMPILE_STATUS) == true,
+              "good fragment shader should compile");
+
+    var fs2 = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(fs2, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varying vec4 vColor; void main() { gl_FragColor = vColor * 0.5; }");
+    gl.compileShader(fs2);
+
+    assertMsg(gl.getShaderParameter(fs2, gl.COMPILE_STATUS) == true,
+              "good fragment shader #2 should compile");
+
+    var fsBad = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(fsBad, "WILL NOT COMPILE;");
+    gl.compileShader(fsBad);
+
+    assertMsg(gl.getShaderParameter(fsBad, gl.COMPILE_STATUS) == false,
+              "bad fragment shader should fail to compile");
+
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "should be no errors at this point");
+
+/////// Check attachShader() /////////////////////////////
+
+    function checkAttachShader(already_attached_shaders, shader, expected_error_code, errmsg) {
+        var prog = gl.createProgram();
+        for (var i = 0; i < already_attached_shaders.length; ++i)
+            gl.attachShader(prog, already_attached_shaders[i]);
+        if(gl.getError() != gl.NO_ERROR)
+            assertMsg(false, "unexpected error in attachShader()");
+        gl.attachShader(prog, shader);
+        assertMsg(gl.getError() == expected_error_code, errmsg);
+    }
+
+    checkAttachShader([], vs, gl.NO_ERROR, "attaching a vertex shader should succeed");
+    checkAttachShader([vs], vs, gl.INVALID_OPERATION,
+                      "attaching an already attached vertex shader should generate INVALID_OPERATION");
+    checkAttachShader([], fs, gl.NO_ERROR, "attaching a fragment shader should succeed");
+    checkAttachShader([fs], fs, gl.INVALID_OPERATION,
+                      "attaching an already attached fragment shader should generate INVALID_OPERATION");
+
+/////// Check detachShader() /////////////////////////////
+
+    function checkDetachShader(already_attached_shaders, shader, expected_error_code, errmsg) {
+        var prog = gl.createProgram();
+        for (var i = 0; i < already_attached_shaders.length; ++i)
+            gl.attachShader(prog, already_attached_shaders[i]);
+        if(gl.getError() != gl.NO_ERROR)
+            assertMsg(false, "unexpected error in attachShader()");
+        gl.detachShader(prog, shader);
+        assertMsg(gl.getError() == expected_error_code, errmsg);
+    }
+
+    checkDetachShader([vs], vs, gl.NO_ERROR, "detaching a vertex shader should succeed");
+    checkDetachShader([fs], vs, gl.INVALID_OPERATION,
+                      "detaching a not already attached vertex shader should generate INVALID_OPERATION");
+    checkDetachShader([fs], fs, gl.NO_ERROR, "detaching a fragment shader should succeed");
+    checkDetachShader([vs], fs, gl.INVALID_OPERATION,
+                      "detaching a not already attached fragment shader should generate INVALID_OPERATION");
+
+/////// Check getAttachedShaders() /////////////////////////////
+
+    function checkGetAttachedShaders(shaders_to_attach, shaders_to_detach, expected_shaders, errmsg) {
+        var prog = gl.createProgram();
+        for (var i = 0; i < shaders_to_attach.length; ++i)
+            gl.attachShader(prog, shaders_to_attach[i]);
+        if(gl.getError() != gl.NO_ERROR)
+            assertMsg(false, "unexpected error in attachShader()");
+        for (var i = 0; i < shaders_to_detach.length; ++i)
+            gl.detachShader(prog, shaders_to_detach[i]);
+        if(gl.getError() != gl.NO_ERROR)
+            assertMsg(false, "unexpected error in detachShader()");
+        assertMsg(areArraysEqual(gl.getAttachedShaders(prog), expected_shaders), errmsg);
+    }
+    checkGetAttachedShaders([], [], [], "getAttachedShaders should return an empty list by default");
+    checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should give the expected list");
+    checkGetAttachedShaders([fs, vs, fs2, vs2], [], [fs, vs, fs2, vs2],
+        "attaching some shaders should give the expected list");
+    checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it shoud leave an empty list");
+    checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs, fs2, vs2], [],
+        "attaching some shaders and detaching them in same order shoud leave an empty list");
+    checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs2, vs, fs2], [],
+        "attaching some shaders and detaching them in random order shoud leave an empty list");
+    checkGetAttachedShaders([fs, vs, fs2, vs2], [vs], [fs, fs2, vs2],
+        "attaching and detaching some shaders should leave the difference list");
+    checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs2], [vs, fs2],
+        "attaching and detaching some shaders should leave the difference list");
+    checkGetAttachedShaders([fsBad], [], [fsBad],
+        "attaching a shader that failed to compile should still show it in the list");
+    checkGetAttachedShaders([fs, vsBad, fs2], [], [fs, vsBad, fs2],
+        "attaching shaders, including one that failed to compile, should still show the it in the list");
+
+/////// Check linkProgram() and useProgram /////////////////////////////
+
+    function checkLinkAndUse(shaders, expected_status, errmsg) {
+        var prog = gl.createProgram();
+        for (var i = 0; i < shaders.length; ++i)
+            gl.attachShader(prog, shaders[i]);
+        gl.bindAttribLocation(prog, 0, "aVertex");
+        gl.bindAttribLocation(prog, 1, "aColor");
+        gl.linkProgram(prog);
+        if (gl.getError() != gl.NO_ERROR)
+            assertMsg(false, "unexpected error in linkProgram()");
+        assertMsg(gl.getProgramParameter(prog, gl.LINK_STATUS) == expected_status, errmsg);
+        if (expected_status == true && gl.getProgramParameter(prog, gl.LINK_STATUS) == false)
+            debug(gl.getProgramInfoLog(prog));
+        if (gl.getError() != gl.NO_ERROR)
+            assertMsg(false, "unexpected error in getProgramParameter()");
+        gl.useProgram(prog);
+        if (expected_status == true)
+            assertMsg(gl.getError() == gl.NO_ERROR, "using a valid program should succeed");
+        if (expected_status == false)
+            assertMsg(gl.getError() == gl.INVALID_OPERATION, "using an invalid program should generate INVALID_OPERATION");
+        return prog;
+    }
+
+    var progGood1 = checkLinkAndUse([vs, fs], true, "valid program should link");
+    var progGood2 = checkLinkAndUse([vs, fs2], true, "valid program #2 should link");
+    var progBad1 = checkLinkAndUse([vs], false, "program with no fragment shader should fail to link");
+    var progBad2 = checkLinkAndUse([fs], false, "program with no vertex shader should fail to link");
+    var progBad3 = checkLinkAndUse([vsBad, fs], false, "program with bad vertex shader should fail to link");
+    var progBad4 = checkLinkAndUse([vs, fsBad], false, "program with bad fragment shader should fail to link");
+    var progBad5 = checkLinkAndUse([vsBad, fsBad], false, "program with bad shaders should fail to link");
+
+    gl.useProgram(progGood1);
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "using a valid program shouldn't generate a GL error");
+
+    var vbuf = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
+    gl.bufferData(gl.ARRAY_BUFFER,
+                  new Float32Array([
+                      0.0, 0.0, 0.0, 1.0,
+                      1.0, 0.0, 0.0, 1.0,
+                      1.0, 1.0, 0.0, 1.0,
+                      0.0, 1.0, 0.0, 1.0]),
+                  gl.STATIC_DRAW);
+    gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+    gl.enableVertexAttribArray(0);
+    gl.vertexAttrib3f(1, 1.0, 0.0, 0.0);
+
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "should be no errors at this point #2");
+
+    gl.useProgram(progGood1);
+    gl.drawArrays(gl.TRIANGLES, 0, 3);
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "drawing with a valid program shouldn't generate a GL error");
+
+    gl.useProgram(progBad1);
+    assertMsg(gl.getError() == gl.INVALID_OPERATION,
+              "using an invalid program should generate INVALID_OPERATION");
+    gl.drawArrays(gl.TRIANGLES, 0, 3);
+    assertMsg(gl.getError() != gl.NO_ERROR,
+              "drawing with an invalid program should generate some GL error XXX");
+
+    gl.useProgram(progGood2);
+    gl.attachShader(progGood2, fsBad);
+    gl.linkProgram(progGood2);
+    assertMsg(gl.getProgramParameter(progGood2, gl.LINK_STATUS) == false,
+              "linking should fail with in-use formerly good program, with new bad shader attached");
+
+    gl.useProgram(progGood1);
+    gl.drawArrays(gl.TRIANGLES, 0, 4);
+    assertMsg(gl.getError() == gl.NO_ERROR,
+              "drawing with a valid when last used program shouldn't generate a GL error");
+}
+
+debug("");
+successfullyParsed = true;
+
+go();
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+
+</body>
+</html>
index ae0b6f9e5213d620b5eed60750e9993bd340571a..3777462e1497877c8f6edbc256232eb51419daf4 100644 (file)
@@ -1,3 +1,25 @@
+2010-07-02  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Dimitri Glazkov.
+
+        linkProgram should fail when vertex/fragment shaders are not both present
+        https://bugs.webkit.org/show_bug.cgi?id=41380
+
+        Test: fast/canvas/webgl/program-test.html
+
+        * html/canvas/WebGLProgram.cpp: Add flag for link failure due to missing shaders.
+        (WebCore::WebGLProgram::WebGLProgram):
+        * html/canvas/WebGLProgram.h: Add interface for linkFailure flag.
+        (WebCore::WebGLProgram::isLinkFailureFlagSet):
+        (WebCore::WebGLProgram::setLinkFailureFlag):
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::getProgramParameter): Intercept when linkFailureFlag is set.
+        (WebCore::WebGLRenderingContext::linkProgram): Check if there are missing shaders and don't link if yes.
+        * html/canvas/WebGLShader.cpp: Cache shader type.
+        (WebCore::WebGLShader::WebGLShader):
+        * html/canvas/WebGLShader.h: Ditto.
+        (WebCore::WebGLShader::getType):
+
 2010-07-02  Qi Zhang  <qi.2.zhang@nokia.com>
 
         Reviewed by Laszlo Gombos.
index 6adbb7a2d419c1162453cb87e0e98ff15c950310..000446541a97768f8af766f52e67cf6ec06c517b 100644 (file)
@@ -39,6 +39,7 @@ PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx)
 
 WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
     : CanvasObject(ctx)
+    , m_linkFailure(false)
 {
     setObject(context()->graphicsContext3D()->createProgram());
 }
index e18d1b48951748bbca71d31130f266eabb09d7ee..1049334bef1fd77475f13bc1e405ccc41f85b376 100644 (file)
@@ -48,6 +48,12 @@ namespace WebCore {
 
         bool isUsingVertexAttrib0() const;
 
+        // Return true means getProgramParameter(LINK_STATUS) should return
+        // false; return false means we should actually call
+        // getProgramParameter(LINK_STATUS) to find out.
+        bool isLinkFailureFlagSet() const { return m_linkFailure; }
+        void setLinkFailureFlag(bool failed) { m_linkFailure = failed; }
+
     protected:
         WebGLProgram(WebGLRenderingContext*);
         
@@ -57,6 +63,8 @@ namespace WebCore {
         virtual bool isProgram() const { return true; }
 
         Vector<int> m_activeAttribLocations;
+
+        bool m_linkFailure;
     };
     
 } // namespace WebCore
index c258edc3acf6d2bfec518ede4a2a4cc5a80deebc..94f6de380077701e8926396f05781de7411309ea 100644 (file)
@@ -1410,10 +1410,14 @@ WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, u
     int value = 0;
     switch (pname) {
     case GraphicsContext3D::DELETE_STATUS:
-    case GraphicsContext3D::LINK_STATUS:
     case GraphicsContext3D::VALIDATE_STATUS:
         m_context->getProgramiv(program, pname, &value);
         return WebGLGetInfo(static_cast<bool>(value));
+    case GraphicsContext3D::LINK_STATUS:
+        if (program->isLinkFailureFlagSet())
+            return WebGLGetInfo(false);
+        m_context->getProgramiv(program, pname, &value);
+        return WebGLGetInfo(static_cast<bool>(value));
     case GraphicsContext3D::INFO_LOG_LENGTH:
     case GraphicsContext3D::ATTACHED_SHADERS:
     case GraphicsContext3D::ACTIVE_ATTRIBUTES:
@@ -1829,6 +1833,28 @@ void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec
     UNUSED_PARAM(ec);
     if (!validateWebGLObject(program))
         return;
+    if (!isGLES2Compliant()) {
+        Vector<WebGLShader*> shaders;
+        bool succeed = getAttachedShaders(program, shaders, ec);
+        if (succeed) {
+            bool vShader = false;
+            bool fShader = false;
+            for (size_t ii = 0; ii < shaders.size() && (!vShader || !fShader); ++ii) {
+                if (shaders[ii]->getType() == GraphicsContext3D::VERTEX_SHADER)
+                    vShader = true;
+                else if (shaders[ii]->getType() == GraphicsContext3D::FRAGMENT_SHADER)
+                    fShader = true;
+            }
+            if (!vShader || !fShader)
+                succeed = false;
+        }
+        if (!succeed) {
+            program->setLinkFailureFlag(true);
+            return;
+        }
+        program->setLinkFailureFlag(false);
+    }
+
     m_context->linkProgram(program);
     program->cacheActiveAttribLocations();
     cleanupAfterGraphicsCall(false);
index a353b1594b28e9f8260d2667f378ba41c125dcc9..664d3cbfd17b66c7ad3edec7b37004de5fbaf242 100644 (file)
@@ -39,6 +39,7 @@ PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContext* ctx, Graphics
 
 WebGLShader::WebGLShader(WebGLRenderingContext* ctx, GraphicsContext3D::WebGLEnumType type)
     : CanvasObject(ctx)
+    , m_type(type)
 {
     setObject(context()->graphicsContext3D()->createShader(type));
 }
index d4006aab5f15098cc1fd987b9430fb12728402e2..a0daa5998ef9f07323407a8397836a7e468fa06a 100644 (file)
@@ -39,12 +39,16 @@ namespace WebCore {
         
         static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GraphicsContext3D::WebGLEnumType);
 
+        GraphicsContext3D::WebGLEnumType getType() const { return m_type; }
+
     private:
         WebGLShader(WebGLRenderingContext*, GraphicsContext3D::WebGLEnumType);
 
         virtual void _deleteObject(Platform3DObject);
 
         virtual bool isShader() const { return true; }
+
+        GraphicsContext3D::WebGLEnumType m_type;
     };
     
 } // namespace WebCore