2016-02-28 14 views

Trả lời

6

Tùy thuộc vào việc xây dựng GLEW đang được sử dụng phương pháp kín nước là gọi glewInit sau mỗi và mọi ngữ cảnh thay đổi!

Với các con trỏ hàm X11/GLX là bất biến.

Nhưng trong con trỏ hàm OpenGL của Windows thì cụ thể cho từng ngữ cảnh. Một số bản xây dựng của GLEW là đa ngữ cảnh, trong khi những người khác thì không. Vì vậy, để bao gồm trường hợp đó, về mặt kỹ thuật bạn phải gọi nó, mọi lúc bối cảnh đã thay đổi.

(EDIT: do yêu cầu làm rõ)

cho mỗi cửa sổ (ví dụ, mỗi OpenGL Rendering Context)?

Điều đầu tiên trước tiên: ngữ cảnh OpenGL không được gắn với cửa sổ. Nó là hoàn toàn tốt để có một cửa sổ duy nhất nhưng nhiều bối cảnh dựng hình. Trong Microsoft Windows, điều quan trọng đối với OpenGL là bối cảnh thiết bị (DC) được liên kết với một cửa sổ. Nhưng nó cũng hoạt động theo cách khác vòng: Bạn có thể có một ngữ cảnh OpenGL duy nhất, nhưng nhiều cửa sổ sử dụng nó (miễn là pixelformat của cửa sổ tương thích với ngữ cảnh OpenGL).

Vì vậy, đây là hợp pháp:

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 

Và như vậy là này

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

Đây là nơi các phần mở rộng nhập hình ảnh. Một hàm như glActiveTexture không phải là một phần của đặc tả OpenGL đã được gắn vào Giao diện nhị phân ứng dụng Windows (ABI). Do đó bạn phải có một con trỏ hàm vào nó khi chạy. Đó là những gì GLEW làm. Bên trong nó trông giống như thế này:

Đầu tiên nó định nghĩa các kiểu cho con trỏ hàm, khai báo chúng dưới dạng biến extern và sử dụng một chút ma thuật tiền xử lý để tránh xung đột không gian tên.

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

Trong glewInit các biến con trỏ hàm được thiết lập để các giá trị thu được sử dụng wglGetProcAddress (vì lợi ích của khả năng đọc tôi bỏ qua đúc loại).

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

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

    /* ... */ 
} 

Bây giờ là phần quan trọng: wglGetProcAddress tác phẩm với bối cảnh render OpenGL đó là hiện tại thời điểm gọi. Vì vậy, bất kỳ điều gì xảy ra với cuộc gọi cuối cùng wglMakeCurrent được thực hiện trước đó. Như đã giải thích, các con trỏ hàm mở rộng được gắn với ngữ cảnh OpenGL của chúng và các bối cảnh OpenGL khác nhau có thể cung cấp các con trỏ hàm khác nhau cho cùng một hàm.

Vì vậy, nếu bạn làm điều này

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

nó có thể thất bại. Vì vậy, nói chung, với GLEW, mọi cuộc gọi tới wglMakeCurrent phải được theo sau bởi glewInit. Một số bản xây dựng của GLEW là đa ngữ cảnh giác và làm điều này trong nội bộ. Những người khác thì không. Tuy nhiên, hoàn toàn an toàn khi gọi số glewInit nhiều lần, vì vậy, cách an toàn là gọi nó, chỉ để chắc chắn.

+0

Nhưng tôi vẫn chưa hiểu đầy đủ. Bạn có thể giải thích thêm một chút về ngữ cảnh "thay đổi" không? –

+0

@ChanggongZhang: xem cập nhật của tôi. – datenwolf

+0

Tôi chỉ nhận thấy rằng glew cũng cung cấp [glew32mx.lib, glew32mx.dll]. Điều này có nghĩa là Nếu tôi muốn tạo một ứng dụng nhiều cửa sổ, tôi nên sử dụng glew32mx.dll thay vì glew32.dll? Và một câu hỏi tiếp theo khác. Bạn có thể @datenwolf cung cấp ví dụ ứng dụng thực sự cho nhiều DC-single-RC & single-DC-nhiều-RC không? –

Các vấn đề liên quan