2016-02-28 10 views

Antwort

6

Je nach verwendetem GLEW-Build lautet die wasserdichte Methode glewInit nach jedem Kontext Änderung!

Mit X11/GLX-Funktionen sind Zeiger invariant.

Aber in Windows OpenGL Funktionszeiger sind spezifisch für jeden Kontext. Einige Builds von GLEW sind multikontextbewusst, andere nicht. Um diesen Fall zu erfassen, müssen Sie ihn technisch benennen, immer wenn sich der Kontext ändert.

(EDIT: aufgrund Anfrage zur Klärung)

für jedes Fenster (das heißt, jeder OpenGL Rendering-Kontext)?

Das Wichtigste zuerst: OpenGL-Kontexte sind nicht an Windows gebunden. Es ist vollkommen in Ordnung, ein einzelnes Fenster, aber mehrere Renderkontexte zu haben. In Microsoft Windows, was OpenGL betrifft, ist der Gerätekontext (DC) mit einem Fenster verbunden. Es funktioniert aber auch anders herum: Sie können einen einzelnen OpenGL-Kontext haben, aber mehrere Fenster, die ihn verwenden (solange das Pixelformat des Fensters mit dem OpenGL-Kontext kompatibel ist).

Das ist also legitim:

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 

Und so ist diese

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(); 

Hier, wo Erweiterungen das Bild eingeben. Eine Funktion wie glActiveTexture ist nicht Teil der OpenGL-Spezifikation, die in der Windows Application Binary Interface (ABI) festgelegt wurde. Daher müssen Sie zur Laufzeit einen Funktionszeiger darauf bekommen. Das macht GLEW. Intern sieht es folgendermaßen aus:

Zuerst definiert es Typen für die Funktionszeiger, deklariert sie als externe Variablen und verwendet ein wenig Präprozessor-Magie, um Namespace-Kollisionen zu vermeiden.

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

glewInit In den Funktionszeiger-Variablen werden auf die Werte gesetzt, erhalten unter Verwendung wglGetProcAddress (aus Gründen der Lesbarkeit ich die Art Gußteile wegzulassen). Jetzt

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

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

    /* ... */ 
} 

der wichtige Teil: wglGetProcAddress Arbeiten mit dem OpenGL Rendering Kontext, der zum Zeitpunkt des Aufrufs aktuell ist. Also was immer bis zuletzt wglMakeCurrent Anruf davor gemacht wurde. Wie bereits erläutert, sind Erweiterungsfunktionszeiger an ihren OpenGL-Kontext gebunden und verschiedene OpenGL-Kontexte können verschiedene Funktionszeiger für dieselbe Funktion ergeben.

Also, wenn Sie dies tun

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

es fehlschlagen. Im Allgemeinen muss also bei GLEW jedem Aufruf an wglMakeCurrent sofort eine glewInit folgen. Einige Builds von GLEW sind multikontextbewusst und tun dies intern. Andere sind nicht. Es ist jedoch absolut sicher, glewInit mehrere Male zu rufen, also ist der sichere Weg, es zu nennen, nur um sicher zu sein.

+0

Aber ich verstehe immer noch nicht vollständig. Könntest du ein bisschen mehr über Kontext "change" erklären? –

+0

@ChanggongZhang: siehe mein Update. – datenwolf

+0

Ich habe gerade bemerkt, dass glew auch [glew32mx.lib, glew32mx.dll] bereitstellt. Bedeutet das, wenn ich eine Multi-Fenster-App erstellen möchte, sollte ich glew32mx.dll statt glew32.dll verwenden? Und noch eine weitere Frage. Könnten Sie @datenwolf ein echtes Anwendungsbeispiel für die Multi-DCs-Single-RC und Single-DC-Multiple-RCs bieten? –

Verwandte Themen