webgl detection problem #724

Closed
JPac1619 opened this Issue Oct 9, 2012 · 6 comments

Comments

Projects
None yet
5 participants
@JPac1619

JPac1619 commented Oct 9, 2012

So I noticed that webgl gets set to true in a webgl capable browser even if webgl is disabled.
Such as in Safari, which is webgl capable but not enabled by default.

I think this is because there is not a test of ctx against null.
This makes me wonder when canvas.getContex("experimental-webgl") actually returns undefined.

Does it only return undefined when the method getContext is not supported?

And does it only return null when getContext is supported (modern browser) but the hardware doesn't support webgl or webgl is disabled?

I don't have a crappy enough graphics card to test this (although I could roll back the drivers I guess).

It would be fairly trivial to add a new flag such as webgl-enabled or add to the webgl object itself.

@JPac1619

This comment has been minimized.

Show comment Hide comment
@JPac1619

JPac1619 Oct 9, 2012

I took a closer look at this at came up with the following conclusion:

AFAIK

Modernizr.webgl = true only signifies that the browser is capable of creating/getting an "experimental-webgl" context. (as intended i guess as it only initially checks for window.WebglRenderingContext).

It doesn't tell you if:

  1. WebGL capable (hardware) OR
  2. WebGL is disabled (browser)

I was referring to the webgl-extensions.js code in my previous post, which does not take into account the possibility that the browser could returns null for a contexts that aren't supported. (Is this as designed?)

As you can see the code checks ctx against undefined exclusively

if (!Modernizr.webgl) return;

    var canvas, ctx, exts;

    try {
        canvas  = document.createElement('canvas');
        ctx     = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
        exts    = ctx.getSupportedExtensions();
    }
    catch (e) {
        return;
    }
    if (ctx === undefined) {

I don't think it is possible to ever get inside this if statement. Shouldn't this be more like
ctx === null or ctx === undefined || ctx === null or ctx == undefined

        Modernizr.webgl = new Boolean(false);
    }
    else {
        Modernizr.webgl = new Boolean(true);
    }


    for (var i = -1, len = exts.length; ++i < len; ){
        Modernizr.webgl[exts[i]] = true;
    }

    // hack for addressing modernizr testsuite failures. sorry.
    if (window.TEST && TEST.audvid){
        TEST.audvid.push('webgl');
    }

    canvas = undefined;

Is it even possible for canvas.getContext(...) to return undefined? (Isn't spec to return null?)

I understand that Modernizr wants to save time/be more efficient by not creating a context unless necessary.
My question is how much time in loading is actually saved. (Yes I know I can just run some tests (and probably will) to see for myself but was just wondering what the current consensus is).

JPac1619 commented Oct 9, 2012

I took a closer look at this at came up with the following conclusion:

AFAIK

Modernizr.webgl = true only signifies that the browser is capable of creating/getting an "experimental-webgl" context. (as intended i guess as it only initially checks for window.WebglRenderingContext).

It doesn't tell you if:

  1. WebGL capable (hardware) OR
  2. WebGL is disabled (browser)

I was referring to the webgl-extensions.js code in my previous post, which does not take into account the possibility that the browser could returns null for a contexts that aren't supported. (Is this as designed?)

As you can see the code checks ctx against undefined exclusively

if (!Modernizr.webgl) return;

    var canvas, ctx, exts;

    try {
        canvas  = document.createElement('canvas');
        ctx     = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
        exts    = ctx.getSupportedExtensions();
    }
    catch (e) {
        return;
    }
    if (ctx === undefined) {

I don't think it is possible to ever get inside this if statement. Shouldn't this be more like
ctx === null or ctx === undefined || ctx === null or ctx == undefined

        Modernizr.webgl = new Boolean(false);
    }
    else {
        Modernizr.webgl = new Boolean(true);
    }


    for (var i = -1, len = exts.length; ++i < len; ){
        Modernizr.webgl[exts[i]] = true;
    }

    // hack for addressing modernizr testsuite failures. sorry.
    if (window.TEST && TEST.audvid){
        TEST.audvid.push('webgl');
    }

    canvas = undefined;

Is it even possible for canvas.getContext(...) to return undefined? (Isn't spec to return null?)

I understand that Modernizr wants to save time/be more efficient by not creating a context unless necessary.
My question is how much time in loading is actually saved. (Yes I know I can just run some tests (and probably will) to see for myself but was just wondering what the current consensus is).

@robwalch

This comment has been minimized.

Show comment Hide comment
@robwalch

robwalch Nov 17, 2012

This is the WebGL detection test recommended for three.js
https://github.com/mrdoob/three.js/wiki/Detecting-WebGL-and-browser-compatibility-with-three.js

function() {
    try {
        return !!window.WebGLRenderingContext && !!document.createElement('canvas').getContext('experimental-webgl');
    } catch(e) {
        return false;
    }
}

I suppose it's missing the 'webgl' context check JPac1619 included in above. The WebGL test that only checks window.WebGLRenderingContext is incomplete, and causing confusion. I'm glad it's not slow, but hope there's a way to improve the test as it stands or rename it to indicate it that webgl canvas contexts may still not be available even when the test passes.

This is the WebGL detection test recommended for three.js
https://github.com/mrdoob/three.js/wiki/Detecting-WebGL-and-browser-compatibility-with-three.js

function() {
    try {
        return !!window.WebGLRenderingContext && !!document.createElement('canvas').getContext('experimental-webgl');
    } catch(e) {
        return false;
    }
}

I suppose it's missing the 'webgl' context check JPac1619 included in above. The WebGL test that only checks window.WebGLRenderingContext is incomplete, and causing confusion. I'm glad it's not slow, but hope there's a way to improve the test as it stands or rename it to indicate it that webgl canvas contexts may still not be available even when the test passes.

@haeric

This comment has been minimized.

Show comment Hide comment
@haeric

haeric Apr 15, 2013

Contributor

I just stumbled on this as well. According to #511, the webgl check was made 'soft' (meaning: not actually making a context) for performance reasons. Context creation has gotten pretty snappy lately (Chrome, Macbook pro 13", non-retina: ~15ms), but maybe not fast enough.

The soft check would work if the browser would remove WebGLRenderingContext if webgl isn't supported, but the bug hasn't gotten any attention, it seems.. https://bugzilla.mozilla.org/show_bug.cgi?id=736232

There's no support for lazy evalution in Modernizr, right? So we can't defer the context-creation to when the .webgl is actually used?

Contributor

haeric commented Apr 15, 2013

I just stumbled on this as well. According to #511, the webgl check was made 'soft' (meaning: not actually making a context) for performance reasons. Context creation has gotten pretty snappy lately (Chrome, Macbook pro 13", non-retina: ~15ms), but maybe not fast enough.

The soft check would work if the browser would remove WebGLRenderingContext if webgl isn't supported, but the bug hasn't gotten any attention, it seems.. https://bugzilla.mozilla.org/show_bug.cgi?id=736232

There's no support for lazy evalution in Modernizr, right? So we can't defer the context-creation to when the .webgl is actually used?

@patrickkettner

This comment has been minimized.

Show comment Hide comment
@patrickkettner

patrickkettner Jul 13, 2013

Owner

@haeric The plumbing required for a real check (canvas.supportsContext) was added to webkit recently - so hopefully a real check will be coming in the not too distant future.

Modernizr has asyncTest internally, but it gets stripped out for the distributed copy. You can add a custom test for lazy eval if you were willing to build locally.

Check out the webp check for a easy to follow example.

Owner

patrickkettner commented Jul 13, 2013

@haeric The plumbing required for a real check (canvas.supportsContext) was added to webkit recently - so hopefully a real check will be coming in the not too distant future.

Modernizr has asyncTest internally, but it gets stripped out for the distributed copy. You can add a custom test for lazy eval if you were willing to build locally.

Check out the webp check for a easy to follow example.

@haeric

This comment has been minimized.

Show comment Hide comment
@haeric

haeric Jul 13, 2013

Contributor

@patrickkettner Thanks, I might try that :)

Looking forward to the real check, it's a bit dodgy that Safari gives a false positive at the moment.

Contributor

haeric commented Jul 13, 2013

@patrickkettner Thanks, I might try that :)

Looking forward to the real check, it's a bit dodgy that Safari gives a false positive at the moment.

@AshCoolman

This comment has been minimized.

Show comment Hide comment
@AshCoolman

AshCoolman Oct 30, 2013

Also lending my support for a "hard reality" check for Safari.

Also lending my support for a "hard reality" check for Safari.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment