2016-02-28 13 views

risposta

6

A seconda del build GLEW utilizzato, il metodo a tenuta stagna consiste nel chiamare glewInit dopo ogni singolo modifica!

con funzioni X11/GLX puntatori sono invarianti.

Ma in puntatori a funzione di Windows OpenGL sono specifici per ogni contesto. Alcune versioni di GLEW sono multi-context aware, mentre altre no. Quindi, per coprire quel caso, tecnicamente devi chiamarlo, ogni volta che cambia il contesto.

(EDIT: a causa di richiesta di chiarimenti)

per ogni finestra (vale a dire, ogni rendering OpenGL contesto)?

Per prima cosa: i contesti OpenGL non sono legati a Windows. È perfetto avere un'unica finestra ma più contesti di rendering. In Microsoft Windows ciò che conta per OpenGL è il contesto dispositivo (DC) associato a una finestra. Ma funziona anche al contrario: puoi avere un singolo contesto OpenGL, ma più finestre che lo usano (a patto che pixelformat della finestra sia compatibile con il contesto OpenGL).

Quindi questa è legittima:

HWND wnd = create_a window() 
HDC dc = GetDC(wnd) 
PIXELFORMATDESCRIPTOR pf = select_pixelformat(); 
SetPixelFormat(dc, pf); 

HGLRC rc0 = create_opengl_context(dc); 
HGLRC rc1 = create_opengl_context(dc); 

wglMakeCurrent(dc, rc0); 
draw_stuff(); // uses rc0 

wglMakeCurrent(dc, rc1); 
draw_stuff(); // uses rc1 

così è questa

HWND wnd0 = create_a window() 
HDC dc0 = GetDC(wnd) 
HWND wnd1 = create_a window() 
HDC dc1 = GetDC(wnd) 

PIXELFORMATDESCRIPTOR pf = select_pixelformat(); 
SetPixelFormat(dc0, pf); 
SetPixelFormat(dc1, pf); 

HGLRC rc = create_opengl_context(dc0); // works also with dc1 

wglMakeCurrent(dc0, rc); 
draw_stuff(); 
wglMakeCurrent(dc1, rc); 
draw_stuff(); 

Ecco dove estensioni entrano in scena. Una funzione come glActiveTexture non fa parte delle specifiche OpenGL che sono state bloccate in Windows Application Binary Interface (ABI). Quindi è necessario ottenere un puntatore a funzione in fase di esecuzione. Questo è ciò che GLEW fa. Internamente è simile al seguente:

Prima definisce i tipi per i puntatori di funzione, li dichiara come variabili esterne e utilizza un po 'di magia del preprocessore per evitare collisioni nello spazio dei nomi.

typedef void (*PFNGLACTIVETEXTURE)(GLenum); 
extern PFNGLACTIVETEXTURE glew_ActiveTexture; 
#define glActiveTexture glew_ActiveTexture; 

In glewInit variabili puntatore funzione sono impostati ai valori ottenuti usando wglGetProcAddress (per motivi di leggibilità I omettere i getti di tipo).

int glewInit(void) 
{ 
    /* ... */ 

    if(openglsupport >= gl1_2) { 
    /* ... */ 
     glew_ActiveTexture = wglGetProcAddress("glActiveTexture"); 
    /* ... */ 
    } 

    /* ... */ 
} 

Ora la parte importante: wglGetProcAddress lavori con il contesto di rendering OpenGL che è in corso al momento della chiamata. Quindi, qualunque cosa fosse fino all'ultimo, la chiamata effettuata da wglMakeCurrent. Come già spiegato, i puntatori alle funzioni di estensione sono legati al loro contesto OpenGL e diversi contesti OpenGL possono fornire diversi puntatori di funzione per la stessa funzione.

Quindi, se si esegue questa operazione

wglMakeCurrent(…, rc0); 
glewInit(); 
wglMakeCurrent(…, rc1); 
glActiveTexture(…); 

potrebbe non riuscire. Quindi, in generale, con GLEW, ogni chiamata a wglMakeCurrent deve essere immediatamente seguita da un glewInit. Alcune versioni di GLEW sono multi-context aware e lo fanno internamente. Gli altri non lo sono. Tuttavia è perfettamente sicuro chiamare più volte glewInit, quindi il modo sicuro è chiamarlo, per sicurezza.

+0

Ma ancora non capisco completamente. Potresti spiegare un po 'di più sul contesto "cambiare"? –

+0

@ChanggongZhang: vedere il mio aggiornamento. – datenwolf

+0

Ho appena notato che glew fornisce anche [glew32mx.lib, glew32mx.dll]. Questo significa che se voglio creare un'applicazione multi-finestra, dovrei usare glew32mx.dll piuttosto che glew32.dll? E un'altra domanda di follow-up. Potresti @datenwolf fornire una vera e propria applicazione examplex per i multiple-DC-single-RC e single-DC-multiple-RCs? –

Problemi correlati