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"
Forum Updated to NodeBB v4.3 + New Features

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 19 Sept 2022, 01:14 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 10 Oct 2022, 18:53
    0
    • B balping
      19 Sept 2022, 01:14

      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 10 Oct 2022, 18:53 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