2012-05-16 11 views
23

Ho un'applicazione wxWidgets che ha un numero di finestre opengl figlio. Sto usando la mia classe GL canvas, non quella wx. Le finestre condividono il loro contesto OpenGL. Non penso che il fatto che sia wxwidgets sia davvero rilevante qui.OpenGL sfarfallio/danneggiato con ridimensionamento della finestra e DWM attivo

Le finestre opengl sono figli di finestre che sono fratelli l'una dell'altra, contenute in un controllo a schede. Una specie di interfaccia in stile MDI, ma non è una finestra MDI. Ognuna può essere ridimensionata singolarmente. Tutto funziona bene a meno che Aero non sia abilitato e DWM sia attivo.

Il ridimensionamento di qualsiasi finestra (non di quelle opzionali) fa sfarfallare di tanto in tanto tutte le finestre opengl con una visualizzazione di backing store stantio che contiene tutta la spazzatura sullo schermo in quel punto che non è opengl. Questo accade SOLO con Aero abilitato.

Sono certo che questo è il DWM che non ha effettivamente il contenuto opengl sul suo supporto di superficie di disegno e la finestra non viene ridipinta al momento giusto.

Ho provato così tante cose per aggirare questo, ho una soluzione, ma non è molto bello e coinvolge la lettura del framebuffer con glReadPixels in un DIB e poi copiarlo sul video alla pittura DC nella mia routine OnPaint. Questa soluzione alternativa è abilitata solo se DWM è attivo, ma preferirei non doverlo fare affatto perché danneggia leggermente le prestazioni (ma non troppo male su un sistema capace - le scene sono relativamente semplici grafici 3D). Anche mixare GDI e opengl non è raccomandato, ma questo approccio funziona, sorprendentemente. Per ora posso conviverci, ma preferirei non doverlo fare. Devo ancora farlo in WM_PRINT se voglio comunque catturare uno screenshot della finestra figlio, non riesco a vederlo.

Qualcuno sa di una soluzione migliore a questo?

Prima che qualcuno chiede Io sicuramente fare quanto segue:

  • classe Window ha CS_OWNDC
  • WM_ERASEBACKGROUND non fa nulla e restituisce TRUE.
  • Il doppio buffering è abilitato.
  • Windows ha gli stili di finestra WS_CLIPSIBLINGS e WS_CLIPCHILDREN.
  • Nel gestore di eventi resize, ridisegno immediatamente la finestra.

ho provato:

  • Impostazione PFD_SUPPORT_COMPOSITION nel descrittore formato pixel.
  • Non si utilizza un wxPaintDC nel gestore di vernici e si chiama :: ValidateRect (hwnd, NULL).
  • Handling WM_NCPAINT ed escludendo l'area client
  • Disattivazione vernice NC tramite l'API DWM
  • Escludendo l'area client in caso vernice
  • Calling glFlush e/o glFinish prima e dopo lo swap del buffer.
  • Invalidare la finestra ad ogni evento di disegno (come test!) - ancora sfarfallio !
  • Non si utilizza un contesto GL condiviso.
  • Disabilitare il doppio buffering.
  • Scrivendo a GL_FRONT_AND_BACK

Disattivazione DWM non è un'opzione.

E per quanto ne so, questo è anche un problema se si utilizza Direct3D invece su OpenGL, sebbene non l'abbia provato poiché rappresenta molto lavoro.

+0

mi hanno problemi simili con un app MFC MDI e OpenGL, dove i controlli MFC volte lasciano disegnare artefatti nella finestra GL. Questo si verifica solo quando Aero è abilitato. Allo stesso modo, non ho trovato una soluzione soddisfacente. – mcmcc

+0

Il blitting alla finestra con il contenuto opengl come letto con glReadPixels sembra risolverlo, ma deve esserci un metodo migliore. – Pete

risposta

0

Hmm, forse si è verificato lo stesso problema: se si utilizza "nuovo" MFC verrà creato e l'applicazione con Tab e Window Spliter.

Lo sdoppiatore ha una certa logica (sto indovinando da qualche parte intorno alla finestra trasparente e disegno le linee XOR per la divisione) che causa questo comportamento. Rimuovere lo splitter per confermare che risolve il problema . Se hai bisogno di funzionalità split - inserisci uno splitter diverso.

Anche le schede consentono di ancorare e di dividere nuovamente le finestre con lo stesso problema: rimuovere/sostituire.

Buona fortuna, Igor

+0

Non è un'app wxWidgets o stai rispondendo al commento di mcmcc? Penso che il problema finale sia che il DWM sta componendo in un thread diverso. – Pete

+0

Ho risolto lo stesso problema sostituendo tutte le mie chiamate OpenGL nel metodo Paint. Non ho accesso al mio codice fino a lunedì quindi non posso darti maggiori dettagli ora ... almeno io uso VCL, ma dal momento che è lo stesso problema può essere la stessa soluzione! – Maypeur

2

Questo è un longshot, ma ho appena risolto esattamente lo stesso problema io stesso.

La parte Longshot è disponibile in quanto stiamo facendo proprietario sorteggio del profilo di una casella di gruppo captionless che circonda la nostra finestra OpenGL (vale a dire, per fare un po 'di confine bello), e che non può descrivere il vostro caso.

Quello che abbiamo trovato ha causato il problema era questo:

Stavamo utilizzando una chiamata RoundRect() (con un HOLLOW_BRUSH) per disegnare il contorno della casella di gruppo. Passando a una chiamata MoveToEx() e LineTo() per garantire che JUST le linee vengano disegnate e che nulla venga eseguito all'interno della casella di gruppo, il GDI non tenta di ridisegnare inaspettatamente l'intero contenuto del controllo. È possibile che ci sia una differenza nella logica di invalidazione (o abbiamo avuto un errore in qualche modo nel caricare il pennello vuoto previsto). Stiamo ancora indagando.

-Noel

Problemi correlati