Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for WebAssembly
  4. WebAssembly multi canvas "Failed to make context current"
QtWS25 Last Chance

WebAssembly multi canvas "Failed to make context current"

Scheduled Pinned Locked Moved Unsolved Qt for WebAssembly
webassemblymulti-screengles2
2 Posts 1 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    balping
    wrote on last edited by balping
    #1

    I'm trying to use multiple canvases / screens to render multiple QQuickView windows in wasm. I'm using Qt 6.3.2

    // main.cpp
    #include <QGuiApplication>
    #include <QQuickView>
    
    int main(int argc, char *argv[]){
    	QGuiApplication app(argc, argv);
    
    	const auto screens = app.screens();
    	if(screens.size() < 2){
    		qDebug() << "Expected at least 2 screens";
    		return 1;
    	}
    
    	for(auto & screen : screens){
    		qDebug() << screen;
    	}
    
    	QQuickView mainViewer;
    	mainViewer.setScreen(screens[0]);
    	mainViewer.setSource(QUrl(u"qrc:/wasm-multiwindow/main.qml"_qs));
    	mainViewer.setResizeMode(QQuickView::SizeRootObjectToView);
    
    
    	QQuickView secondViewer;
    	secondViewer.setScreen(screens[1]);
    	secondViewer.setSource(QUrl(u"qrc:/wasm-multiwindow/second.qml"_qs));
    	secondViewer.setResizeMode(QQuickView::SizeRootObjectToView);
    
    	mainViewer.show();
    	secondViewer.show();
    
    
    	return app.exec();
    }
    

    In the browser's console I get the following error:

    QRhiGles2: Failed to make context current. Expect bad things to happen.
    Failed to start frame
    

    If I set the same screen for both QQuickView objects, there's no error, but only one of them is visible of course. I have no issue running this code on x64 Linux target with two physical displays.

    So is this a bug

    1. in the browser?
    2. in Qt?
    3. in my code?

    If it's option 3, maybe I could try to add manual locking around the opengl context?

    Also, I have no problem creating 2 widgets on 2 canvases:

    // this works
    #include <QApplication>
    #include <QWidget>
    
    
    int main(int argc, char *argv[]){
    	QApplication app(argc, argv);
    
    	const auto screens = app.screens();
    	if(screens.size() < 2){
    		qDebug() << "Expected at least 2 screens";
    		return 1;
    	}
    
    	QWidget w1;
    	w1.setScreen(screens[0]);
    	w1.show();
    
    	QWidget w2;
    	w2.setScreen(screens[1]);
    	w2.show();
    
    	return app.exec();
    }
    

    For completeness here's rest of my code:

    # wasm-multiwindow.pro
    QT += quick
    
    SOURCES += \
            main.cpp
    
    resources.files = main.qml second.qml
    resources.prefix = /$${TARGET}
    RESOURCES += resources
    
    # Additional import path used to resolve QML modules in Qt Creator's code model
    QML_IMPORT_PATH =
    
    # Additional import path used to resolve QML modules just for Qt Quick Designer
    QML_DESIGNER_IMPORT_PATH =
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
    // main.qml
    import QtQuick
    
    Rectangle {
        width: 640
        height: 480
        visible: true
        color: "#ff0000"
    
        Text {
            text: "hello"
        }
    }
    
    // second.qml
    import QtQuick
    
    Rectangle {
        width: 640
        height: 480
        visible: true
        color: "#00ff00"
    
        Text {
            text: "hi"
        }
    }
    

    This is the default autogenerated HTML, with an extra canvas inserted.

    <!doctype html>
    <html lang="en-us">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
        <!--Set visual viewport size for mobile devices to the device size,
            witch results in a scale of 1 and a 1:1 mapping between CSS pixels
            and Qt device independent pixels. -->
        <meta name="viewport" content="width=device-width, height=device-height, user-scalable=0"/>
    
        <title>wasm-multiwindow</title>
        <style>
          /* Make the html body cover the entire (visual) viewport with no scroll bars. */
          html, body { padding: 0; margin: 0; overflow:hidden; height: 100% }
          /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
          canvas { border: 0px none; background-color: white; height:50%; width:100%;  }
          /* The contenteditable property is set to true for the canvas in order to support
             clipboard events. Hide the resulting focus frame and set the cursor back to
             the default cursor. */
          canvas { outline: 0px solid transparent; caret-color: transparent; cursor:default }
        </style>
      </head>
      <body onload="init()">
        <figure style="overflow:visible;" id="qtspinner">
          <center style="margin-top:1.5em; line-height:150%">
            <img src="qtlogo.svg" width="320" height="200" style="display:block"></img>
            <strong>Qt for WebAssembly: wasm-multiwindow</strong>
            <div id="qtstatus"></div>
            <noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
          </center>
        </figure>
        <canvas id="qtcanvas" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
        <canvas id="qtcanvas2" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
    
        <script type='text/javascript'>
            function init() {
              var spinner = document.querySelector('#qtspinner');
              var canvas = document.querySelector('#qtcanvas');
              var canvas2 = document.querySelector('#qtcanvas2');
              var status = document.querySelector('#qtstatus')
    
              var qtLoader = QtLoader({
                  canvasElements : [canvas, canvas2],
                  showLoader: function(loaderStatus) {
                      spinner.style.display = 'block';
                      canvas.style.display = 'none';
                      status.innerHTML = loaderStatus + "...";
                  },
                  showError: function(errorText) {
                      status.innerHTML = errorText;
                      spinner.style.display = 'block';
                      canvas.style.display = 'none';
                  },
                  showExit: function() {
                      status.innerHTML = "Application exit";
                      if (qtLoader.exitCode !== undefined)
                          status.innerHTML += " with code " + qtLoader.exitCode;
                      if (qtLoader.exitText !== undefined)
                          status.innerHTML += " (" + qtLoader.exitText + ")";
                      spinner.style.display = 'block';
                      canvas.style.display = 'none';
                  },
                  showCanvas: function() {
                      spinner.style.display = 'none';
                      canvas.style.display = 'block';
                  },
              });
              qtLoader.loadEmscriptenModule("wasm-multiwindow");
          }
        </script>
        <script type="text/javascript" src="qtloader.js"></script>
      </body>
    </html>
    

    And here's the full console output:

    writeStackCookie: 432bd0 qtloader.js:396:25
    checkStackCookie: 432bd0 2 qtloader.js:396:25
    QML debugging is enabled. Only use this in a safe environment. qtloader.js:396:25
    checkStackCookie: 432bd0 qtloader.js:396:25
    InstallTrigger is deprecated and will be removed in the future. qtloader.js line 467 > eval:7386:6
    QScreen(0x93dba8, name="qtcanvas") qtloader.js:396:25
    QScreen(0x93e410, name="qtcanvas2") qtloader.js:396:25
    Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread qtloader.js:396:25
    writeStackCookie: 980340 da626f5d-f10d-4e17-8d04-6b0ecadc878f:842:6
    writeStackCookie: 1c82f20 6ecfa28e-e258-4b5e-9554-21200ff1c8f1:842:6
    checkStackCookie: 432bd0 qtloader.js:396:25
    QRhiGles2: Failed to make context current. Expect bad things to happen. qtloader.js:396:25
    Failed to start frame qtloader.js:396:25
    checkStackCookie: 432bd0 qtloader.js:396:25
    main loop exiting.. qtloader.js:396:25
    QRhiGles2: Failed to make context current. Expect bad things to happen. qtloader.js:396:25
    Failed to start frame qtloader.js:396:25
    
    B 1 Reply Last reply
    0
    • B balping

      I'm trying to use multiple canvases / screens to render multiple QQuickView windows in wasm. I'm using Qt 6.3.2

      // main.cpp
      #include <QGuiApplication>
      #include <QQuickView>
      
      int main(int argc, char *argv[]){
      	QGuiApplication app(argc, argv);
      
      	const auto screens = app.screens();
      	if(screens.size() < 2){
      		qDebug() << "Expected at least 2 screens";
      		return 1;
      	}
      
      	for(auto & screen : screens){
      		qDebug() << screen;
      	}
      
      	QQuickView mainViewer;
      	mainViewer.setScreen(screens[0]);
      	mainViewer.setSource(QUrl(u"qrc:/wasm-multiwindow/main.qml"_qs));
      	mainViewer.setResizeMode(QQuickView::SizeRootObjectToView);
      
      
      	QQuickView secondViewer;
      	secondViewer.setScreen(screens[1]);
      	secondViewer.setSource(QUrl(u"qrc:/wasm-multiwindow/second.qml"_qs));
      	secondViewer.setResizeMode(QQuickView::SizeRootObjectToView);
      
      	mainViewer.show();
      	secondViewer.show();
      
      
      	return app.exec();
      }
      

      In the browser's console I get the following error:

      QRhiGles2: Failed to make context current. Expect bad things to happen.
      Failed to start frame
      

      If I set the same screen for both QQuickView objects, there's no error, but only one of them is visible of course. I have no issue running this code on x64 Linux target with two physical displays.

      So is this a bug

      1. in the browser?
      2. in Qt?
      3. in my code?

      If it's option 3, maybe I could try to add manual locking around the opengl context?

      Also, I have no problem creating 2 widgets on 2 canvases:

      // this works
      #include <QApplication>
      #include <QWidget>
      
      
      int main(int argc, char *argv[]){
      	QApplication app(argc, argv);
      
      	const auto screens = app.screens();
      	if(screens.size() < 2){
      		qDebug() << "Expected at least 2 screens";
      		return 1;
      	}
      
      	QWidget w1;
      	w1.setScreen(screens[0]);
      	w1.show();
      
      	QWidget w2;
      	w2.setScreen(screens[1]);
      	w2.show();
      
      	return app.exec();
      }
      

      For completeness here's rest of my code:

      # wasm-multiwindow.pro
      QT += quick
      
      SOURCES += \
              main.cpp
      
      resources.files = main.qml second.qml
      resources.prefix = /$${TARGET}
      RESOURCES += resources
      
      # Additional import path used to resolve QML modules in Qt Creator's code model
      QML_IMPORT_PATH =
      
      # Additional import path used to resolve QML modules just for Qt Quick Designer
      QML_DESIGNER_IMPORT_PATH =
      
      # Default rules for deployment.
      qnx: target.path = /tmp/$${TARGET}/bin
      else: unix:!android: target.path = /opt/$${TARGET}/bin
      !isEmpty(target.path): INSTALLS += target
      
      // main.qml
      import QtQuick
      
      Rectangle {
          width: 640
          height: 480
          visible: true
          color: "#ff0000"
      
          Text {
              text: "hello"
          }
      }
      
      // second.qml
      import QtQuick
      
      Rectangle {
          width: 640
          height: 480
          visible: true
          color: "#00ff00"
      
          Text {
              text: "hi"
          }
      }
      

      This is the default autogenerated HTML, with an extra canvas inserted.

      <!doctype html>
      <html lang="en-us">
        <head>
          <meta charset="utf-8">
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      
          <!--Set visual viewport size for mobile devices to the device size,
              witch results in a scale of 1 and a 1:1 mapping between CSS pixels
              and Qt device independent pixels. -->
          <meta name="viewport" content="width=device-width, height=device-height, user-scalable=0"/>
      
          <title>wasm-multiwindow</title>
          <style>
            /* Make the html body cover the entire (visual) viewport with no scroll bars. */
            html, body { padding: 0; margin: 0; overflow:hidden; height: 100% }
            /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
            canvas { border: 0px none; background-color: white; height:50%; width:100%;  }
            /* The contenteditable property is set to true for the canvas in order to support
               clipboard events. Hide the resulting focus frame and set the cursor back to
               the default cursor. */
            canvas { outline: 0px solid transparent; caret-color: transparent; cursor:default }
          </style>
        </head>
        <body onload="init()">
          <figure style="overflow:visible;" id="qtspinner">
            <center style="margin-top:1.5em; line-height:150%">
              <img src="qtlogo.svg" width="320" height="200" style="display:block"></img>
              <strong>Qt for WebAssembly: wasm-multiwindow</strong>
              <div id="qtstatus"></div>
              <noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
            </center>
          </figure>
          <canvas id="qtcanvas" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
          <canvas id="qtcanvas2" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
      
          <script type='text/javascript'>
              function init() {
                var spinner = document.querySelector('#qtspinner');
                var canvas = document.querySelector('#qtcanvas');
                var canvas2 = document.querySelector('#qtcanvas2');
                var status = document.querySelector('#qtstatus')
      
                var qtLoader = QtLoader({
                    canvasElements : [canvas, canvas2],
                    showLoader: function(loaderStatus) {
                        spinner.style.display = 'block';
                        canvas.style.display = 'none';
                        status.innerHTML = loaderStatus + "...";
                    },
                    showError: function(errorText) {
                        status.innerHTML = errorText;
                        spinner.style.display = 'block';
                        canvas.style.display = 'none';
                    },
                    showExit: function() {
                        status.innerHTML = "Application exit";
                        if (qtLoader.exitCode !== undefined)
                            status.innerHTML += " with code " + qtLoader.exitCode;
                        if (qtLoader.exitText !== undefined)
                            status.innerHTML += " (" + qtLoader.exitText + ")";
                        spinner.style.display = 'block';
                        canvas.style.display = 'none';
                    },
                    showCanvas: function() {
                        spinner.style.display = 'none';
                        canvas.style.display = 'block';
                    },
                });
                qtLoader.loadEmscriptenModule("wasm-multiwindow");
            }
          </script>
          <script type="text/javascript" src="qtloader.js"></script>
        </body>
      </html>
      

      And here's the full console output:

      writeStackCookie: 432bd0 qtloader.js:396:25
      checkStackCookie: 432bd0 2 qtloader.js:396:25
      QML debugging is enabled. Only use this in a safe environment. qtloader.js:396:25
      checkStackCookie: 432bd0 qtloader.js:396:25
      InstallTrigger is deprecated and will be removed in the future. qtloader.js line 467 > eval:7386:6
      QScreen(0x93dba8, name="qtcanvas") qtloader.js:396:25
      QScreen(0x93e410, name="qtcanvas2") qtloader.js:396:25
      Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread qtloader.js:396:25
      writeStackCookie: 980340 da626f5d-f10d-4e17-8d04-6b0ecadc878f:842:6
      writeStackCookie: 1c82f20 6ecfa28e-e258-4b5e-9554-21200ff1c8f1:842:6
      checkStackCookie: 432bd0 qtloader.js:396:25
      QRhiGles2: Failed to make context current. Expect bad things to happen. qtloader.js:396:25
      Failed to start frame qtloader.js:396:25
      checkStackCookie: 432bd0 qtloader.js:396:25
      main loop exiting.. qtloader.js:396:25
      QRhiGles2: Failed to make context current. Expect bad things to happen. qtloader.js:396:25
      Failed to start frame qtloader.js:396:25
      
      B Offline
      B Offline
      balping
      wrote on last edited by
      #2

      It is indeed a bug, see: https://bugreports.qt.io/browse/QTBUG-106707

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved