greggman / twgl.js

A Tiny WebGL helper Library
http://twgljs.org
MIT License
2.67k stars 260 forks source link

Using twgl.js with different context inside iframe #125

Closed shayke closed 2 years ago

shayke commented 5 years ago

Thank you very much for this library, it's a real gem and helps a ton in learning how things work.

I'm having a small issue with your usage of helper.js. It seems like all the is* functions are caching the result which causes errors when using twgl with different gl context inside an iframe: image

image

These errors happen when I'm navigating my app between iframes (each contain it's own canvas context). Is there a reason for this usage of helpers?

greggman commented 5 years ago

Are you sure that's what's causing the errors? I tested it here and doesn't seem like that should be an issue.

The reason it's that way is because of bugs in Chrome's original implementation of WebGL in a worker where they forgot to make those objects public. I can change to something more traditional but it shouldn't be causing the error you're seeing AFAICT

https://jsfiddle.net/greggman/bjy7zt4m/

greggman commented 5 years ago

Pushed 4.9.3 which should not use references. It might break something else though 😭

shayke commented 5 years ago

My use case is quite different from your fiddle. I'm using twgl.js from within an iframe (twgl.js is loaded on the parent, not inside the iframe) That's because I'm using it with mapbox.gl which is also loaded once on the parent window and I don't want to bundle it into each iframe.

Take a look at this: https://jsfiddle.net/eqkjy0oh/12/

It's using as a frame the code I've created here: https://jsfiddle.net/2sufrjv7/11/

That's basically what happens with helper.js cache. I was instantiated once on the parent, then when the iframe child calls is* it returns false.

Anyway, 4.9.4 doesn't really fix this, I'm not sure what else we can use to test the type of the object, there isn't something on the gl context itself?

greggman commented 5 years ago

I can't think of something I can change it to. I'm not willing to change it to gl.isBuffer because that's a full stop synchronization across processes in Chrome. That's way too slow. On top of which gl.isBuffer is not really a check whether something is a buffer or not, it's a check whether or not the given id is a buffer id which is actually a different check. I won't spell out the cases where the check will fail but it it's slow and it's wrong so

It's common in JavaScript to use instanceof. Your example also fails if I change gl.createBuffer() to new Uint8Array(). In other words all of these tests are also going to fail

I don't really have a solution to suggest.

maybe Virtual-WebGL?

shayke commented 5 years ago

I just want to update with the actual use case I'm using just to be clear: Take a look at: https://jsfiddle.net/b702mehc/11/ and the frame at: https://jsfiddle.net/1dr0ckft/11/

So twgl.js is basically sitting at the parent (the createShader function i put on window is like twgl isShader etc..). The child calls the parent with it's GL context

I hope that was clear, you are right saying that every other instanceof check will fail, That's a real problem i suppose not only related to twgl.js. I still prefer your change though if it's applicable, if you think it's dangerous maybe consider rolling back if it's no help anyway?

Thanks for the feedback!

greggman commented 5 years ago

Searching around the net maybe you can fix it

add this function, maybe to helpers.js

 function isType(object, type) {
    const s = Object.prototype.toString.call(object);
    return s.substring(8, s.length - 1) === type;
 }

Then anywhere there is an instanceof test you could change it from

 if (obj instanceof Thing)

to

 if (helper.isType(object, "Thing"))

It's not the same test because derived types won't be handled but I think for the things being checked derived types are unlikely

These tests

could maybe change from

if (typedArrayType === Int8Array)         

to

if (typedArrayType.name !== undefined && typedArrayType.name === Int8Array.name)         

You might try those and see if they fix your issue.