-
Notifications
You must be signed in to change notification settings - Fork 494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sokol_app custom canvas name not working #407
Comments
Ok, Reading further the documentation. The return type of
In my defense I will say that the docs contradict themselves since it also says that the function returns a strict positive (the handle itself) or a negative on failure, and forgets to mention that 0 is algo a failure. Anyway, my problem persist and this only confirms that |
This could be a bug in sokol_app.h, or something weird in the emscripten SDK's emscripten_webgl_create_context() function, I need to look into this. But in general, if you have a canvas element in the HTML file like this: <canvas id="aaaa" ...> ...then the sokol_main() function should look like this: sapp_desc sokol_main(...) {
return (sapp_desc){
.html5_canvas_name = "aaaa",
...
};
} If this doesn't work then it's either a bug in sokol_app.h or in emscripten_webgl_create_context(). As far as I'm aware, I'm only using a hardwired canvas name in the (still experimental) WebGPU setup code here: Line 4381 in 345fa62
But for WebGL, it should always use the canvas name from the sapp_desc struct (and if this isn't set, the default "canvas"). There are some special "meta-names" for HTML elements in the emscripten APIs (e.g. "#canvas" vs "canvas", but I can't currently find the documentation for those, they might be deprecated (but for this specific use case they would be irrelevant anyway). |
Ok, I can reproduce the error, if both the canvas name in the HTML and the name passed to emscripten_webgl_create_context() match, but are different than "canvas", then the function returns a 0 context handle (which is a problem, it should return a context handle > 0). If the canvas name doesn't match, than sokol_app.h already errors out earlier before the WebGL context is created (that's where the "sokol_app.h: invalid target" message is coming from. I'll look into this. |
What you are saying sounds exactly like my issue. I tried to dig around and tried updating to latest versions of both emsdk and sokol but it wouldn't work (on my first tries I was using like 3 to 4 months old repos). I even tried hardcoding in the generated .js file my own canvas element but also would fail, so it kind of seemed an issue in emsdk and sokol seemed to have the correct name all the time. I'll try to look more into the emsdk side of it or even how sdl2 does it (if at all). Anyway, thanks! |
I think I found the issue, emscripten_create_webgl_canvas() expects the canvas id in the form "#canvas_name" (the leading # is important). I will add a fix to sokol_app.h, so that this leading '#' is added internally (just using Before that I'll try to find documentation why this is the case or maybe ask around on the emscripten discussion group... PS: ah, probably that's why: https://www.w3schools.com/cssref/css_selectors.asp '#id' is the CSS convention for identifying an element by its id. This also explains why 'canvas' picks "any" canvas, because this is the convention to select by the HTML element's tag name. I clearly understood this part wrong... |
I have committed a fix here: No changes should be required from your side. The Please let me know if it works so I can close the ticket :) |
...I wonder if you will run into followup problems when running multiple sokol_app.h instances and WebGL canvases on the same page because of things like this: Line 3774 in 030e901
...I'm not sure if Let me know how it goes :) |
Aah, I should have looked more into it, I did see some examples of emscripten using the '#' in the names but didn't find anything talking about it so didn't look into it. It's working great now! As you said I also expected there to be issues with the Module but emscripten has a pretty good explanation of how to work with it here and more specifically the solution I'm using is explained here, using the MODULARIZE build option, but I'll copy it here for reference: Another option is to use the createMyModule(/* optional default settings */).then(function(Module) {
// this is reached when everything is ready, and you can call methods on Module
}); In my case for example, I want to have a page with multiple examples for a project of mine, so I have a folder structure that looks like this:
Each numbered folder will have the Here is my first demo...
<canvas class="game" id="demo1" height="100" width="700"/>
And another demo here!
<canvas class="game" id="demo2" height="100" width="700"/>
<script>
// Load the numbered demo by creating a script element with the source
// being the one generated by emscripten. When the script is loaded, start
// the "execution" of the demo itself.
var loaddemo = function (number) {
const demo = document.createElement('script');
demo.src = 'demos/' + number + '/' + 'app.js';
demo.type = 'text/javascript';
demo.onload = function(url) {
// This is "DemoModule" because that's how I have defined it when building with emscripten:
// ... -s MODULARIZE=1 -s 'EXPORT_NAME="DemoModule"'
DemoModule({
// Here it's possible to overwrite part of Modules if needed before execution.
// Since the wasm and data files are not in the same location as my .html file,
// I change the Module.locateFile function to return the proper folder it should use.
'locateFile' : function(url) {
console.log("file located: " + url + '\n' + 'demos/' + number + '/' + url);
return 'demos/' + number + '/' + url;
}
}).then(function(Module) {
// This is called after the Module has been loaded if I understand correctly
console.log('Loaded demo ' + number);
});
};
document.head.appendChild(demo);
}
// When the page loads, just load the demos...
window.onload = function () {
console.log("Page loaded");
loaddemo(1);
loaddemo(2);
}
</script> Ofcourse, in the .c source code of the first demo I've set the sokol canvas name to I don't have a public showcase of it now but I might soon, I'll let you know :) |
Just an extra detail in case someone might want to try this. I'm not sure why, or if it's an issue or a bug, but if I set the In that image, the first application's This is my <canvas class="game" id="demo1" height="100" width="700"/> And this is my .game {
border: black solid 2px;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
} There is other stuff but not sure what it could be causing this. |
Aparently it was the |
Trying to have multiple canvases and sokol applications running on one same page I started trying some things.
One thing I would need is to change the name of the canvas of each application, which in sokol, defaults to "canvas".
We can change on creation with html5_canvas_name, correct, and if we set a name for a canvas that is not present in the HTML it even warns you that it's not a valid name, that's great too.
However, I haven't been able to successfully set a canvas name and use it. If the canvas is not called canvas, I can't in any way use it, even if my names match.
Setting the name as "aaaa" in my constructor and a canvas like this:
sokol_app won't complain that it cant find the canvas (I tested changing the name in my c code and it does indeed complain, so just to make it clear) and it tries to create the context and other initializations, and in function
_sapp_emsc_webgl_init
it crashes giving me the following on the Chrome debugger:Looking into what sokol_app is doing:
The crash happens at the end, on the call to
emscripten_webgl_enable_extension(ctx, "WEBKIT_WEBGL_compressed_texture_pvrtc");
however I suspect the issue comes from before that, inemscripten_webgl_create_context
.After some testing, when I don't set any canvas name and go with defaults, rendering properly, the value of
ctx
is1
, which according to the documentation means:The docs also say that the return type of
emscripten_webgl_create_context
is:That means that when everything is good it returns 1 in my machine and will do some initializations later on, since it's deferred, that's all good. When trying to use a custom canvas name however, the return I get is 0.
According to the docs, that's not even possible? It's supposed to get an
strict positive on success
ora negative on failure
? Well I get a 0, which also, according to the docs is a success. It's confusing. However if the only change is the canvas name, and it really succeeded I would expect to get a 1, since that's what a success returns when using a default canvas.Anyway my point is, that it's al weird and that I believe the context creation is failing, but the only difference is that name of the canvas, so I have no clue how to debug this. Hopefully it's just a silly thing I'm doing wrong... Is there any examples of the canvas name being different and working?
Not sure if related but as a side note... If I set the name as default in my .c source, and create 2 canvas like this in my html.
Even though by default it should take the 2nd one, it actually takes the first one... I'm really confused.
The text was updated successfully, but these errors were encountered: