GUI-Thread mit OpenGL/DirectX - überhaupt möglich?



  • Ehm, nur mal so, ein ganz anderes Problem, das mir gerade aufgefallen ist, als ich nur mal den Message-Loop vom Rest trennen wollte: Die HDCs und HGLRCs scheinen nicht Thread-Safe zu sein. Heißt für mich, dass man unter Windows nur im Window-Thread rendern kann. Was relativ bescheuert ist, aber da lässt sich wohl kaum etwas gegen unternehmen. Und mir scheint auch, dass es da einige Fallstricke gibt. Man kann z.B. nicht einfach mal einen memory-mapped Pointer an glTexImage2D geben, weil das dann blocken könnte. Vielleicht hat hier ja jemand eine Idee, wie man das lösen könnte. 😞



  • Was genau meinst du mit "nicht threadsafe", wie äußert sich das und woher kommen die betreffenden HDCs und HGRCs?



  • Na ja, dass man Get/Peek-Message nur in dem Thread benutzen kann, für den auch das Fenster erstellt wurde, sollte ja klar sein. Und das HWND kann man scheinbar auch nur in dem Thread benutzen, wenn man GetDC aufruft. Diesen DC braucht man ja wieder für wglCreateContext - dessen Rückgabewert man auch nicht einfach in einem anderen Thread benutzen darf. (Und so zieht sich das auch weiter wenn man einen modernen Kontext erstellt.) - Oder gibt es da irgendwo ein "Schlupfloch"?



  • cooky451 schrieb:

    Und das HWND kann man scheinbar auch nur in dem Thread benutzen, wenn man GetDC aufruft.

    Das wär mir neu.

    cooky451 schrieb:

    [...] dessen Rückgabewert man auch nicht einfach in einem anderen Thread benutzen darf.

    Das wär mir ebenfalls neu.

    Du kannst ein HDC nur in einem Thread gleichzeitig benutzen und ein GL Context kann auch zu jedem Zeitpunkt nur in einem Thread aktiv sein. Aber ansonsten...



  • Ah, sehr schön. Gerade probiert, und es funktioniert perfekt, das HWND kann man also auch in einem anderen Thread benutzen. Danke! 🙂

    Eine kleine Frage noch am Rande*: Vorher hat das Rendern einfach gestoppt, sobald ich das Fenster vergrößert/kleinert habe. Das ist jetzt nicht mehr so, was grundsätzlich positiv ist. Aber dafür flackert es, weil das beim verkleinern scheinbar von Windows einmal komplett mit weiß überschrieben wird. Kann man das irgendwie verhindern indem man WM_PAINT abfängt oder sowas?

    * Sollte wohl eher in's WinAPI-Forum, aber wo wir schon mal hier sind..



  • Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen und in WM_PAINT ValidateRect() aufrufen, sofern du das Fenster schon an anderer Stelle periodisch neu bemalst.



  • dot schrieb:

    Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen

    This.
    Hier noch was interessantes dazu:
    http://stackoverflow.com/a/1750301/1743172



  • Scorcher24 schrieb:

    dot schrieb:

    Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen

    This.
    Hier noch was interessantes dazu:
    http://stackoverflow.com/a/1750301/1743172

    Das mit CS_OWNDC ist afaik allerdings nicht korrekt. Ist aber auch schon ein ganzes Weilchen her, dass ich mich damit mal beschäftigt hab...



  • dot schrieb:

    Scorcher24 schrieb:

    dot schrieb:

    Evtl. einfach mal den Background Brush auf 0 setzen? Ansonten evtl. WM_ERASEBKGND abfangen

    This.
    Hier noch was interessantes dazu:
    http://stackoverflow.com/a/1750301/1743172

    Das mit CS_OWNDC ist afaik allerdings nicht korrekt. Ist aber auch schon ein ganzes Weilchen her, dass ich mich damit mal beschäftigt hab...

    Soweit ich weiss schon und im OpenGL Wiki ist es auch noch so drin:
    http://www.opengl.org/wiki/Platform_specifics:_Windows#What_should_I_do_before_the_window_is_created.3F

    Wikis sind nicht das Ende alles Wissens, aber ich vertraue einfach mal auf dieses.



  • CS_OWNDC sollte afaik generell schon seit langem nichtmehr benutzt werden. Es tut afaik nichts anderes, als sicherzustellen, dass das System dir für ein entsprechendes Fenster immer den selben DC liefert. Die saubere Lösung wäre imo, den DC einfach nicht zu Releasen, so lange man ihn noch braucht, anstatt jedesmal einen neuen DC anzufordern und diesen Hack im Betriebssystem zu nutzen, um immer den gleichen DC zu bekommen...



  • Mit

    case WM_ERASEBKGND:
      return TRUE;
    case WM_PAINT:
      ValidateRect(hwnd, 0);
      break;
    

    sieht es schon deutlich besser aus, aber noch nicht fehlerfrei. Wenn man das Fenster verkleinert scheinen zumindest die einzelnen "Objekte" darauf immer noch zu flackern, bzw. einen Frame lang nicht gezeichnet zu werden. Ich fürchte da kann man wohl nicht mehr so viel dran ändern?



  • Was genau für "Objekte drauf"?



  • Den Kram den ich halt mit OpenGL zeichne. Texte, Sprites, ... - Der Unterschied zu vorher ist, dass die Farbe mit der in clear()e jetzt stimmt. (Vorher wurde beim verkleinern ja mit weiß gecleared, was ziemlich schlimm aussah.)


Anmelden zum Antworten