PDA

View Full Version : About Multi-Thread in Win32 API



Caesirekin
11-12-2013, 02:15 AM
Hi everyone,I has an problem puzzled me up over these day
It's began days ago, Because i try to make an Multi-Thread OpenGL application with Win32 API.
In this program ,i want let WndProc Function process WM_RBUTTONUP message to change OpenGL shading mode
(I got two thread in program, one is redering thread,and one is Win32 main thread)
Code is somewhat lengthly,But in follows:


#include <gl\glew.h>
#include <gl\wglew.h>
#include <gl\glut.h>
#include <Windows.h>

//Just because it's was a test,
//so i declare them global
HWND hWnd;
HDC hdc;
HGLRC hPrimaryRC; //This handle rendering thread
HGLRC hSlaverRC; //This handle WndProc Message
LPDWORD lpThreadId;

//Here is Pixelformat function
void SetRCPixelFormat(HDC hdc)
{
int pfdNum;

PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0,0,0,0,0,0,
0,0,
0,0,0,0,0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};

pfdNum = ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,pfdNum,&pfd);
}

void ActiveGL()
{
GLenum err = glewInit();
}

void Resize(int width,int height)
{
GLdouble aspect = (GLdouble)width/(GLdouble)height;
GLdouble fovy = 90.0;
GLdouble pNear = 1.0;
GLdouble pFar = 32000.0;

glViewport(0,0,width,height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(fovy,aspect,pNear,pFar);
}

void Configure()
{
glClearColor(0.2f,0.2f,0.2f,1.0f);

glShadeModel(GL_SMOOTH);
glFrontFace(GL_CCW);

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);

glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

//Here is rendering thread
void Render(PVOID pParam)
{
//Everything goes well at here
SetRCPixelFormat(hdc);
hPrimaryRC = wglCreateContext(hdc);

wglMakeCurrent(hdc,hPrimaryRC);

RECT rect;
GetClientRect(hWnd,&rect);
Resize(rect.right,rect.bottom);

Configure();

float yRot = 0.0f;

while(1)
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

glPushMatrix();

gluLookAt(0.0,0.0,200.0,0.0,0.0,0.0,0.0,1.0,0.0);

glPushMatrix();
//Draw an rotate cube at origin
glColor4f(1.0f,0.0f,0.0f,0.2f);
glRotatef(yRot,0.0f,1.0f,0.0f);
glutSolidCube(50.0);

glPopMatrix();

glPushMatrix();

//And draw the background behind that cube
glBegin(GL_QUADS);
glColor4f(1.0f,0.0f,0.0f,0.9f);
glVertex3f(-500.0f,500.0f,-100.0f);
glColor4f(0.0f,1.0f,0.0f,0.9f);
glVertex3f(-500.0f,-500.0f,-100.0f);
glColor4f(0.0f,0.0f,1.0f,0.9f);
glVertex3f(500.0f,-500.0f,-100.0f);
glColor4f(1.0f,1.0f,1.0f,1.0f);
glVertex3f(500.0f,500.0f,-100.0f);
glEnd();

glPopMatrix();

glPopMatrix();

glFlush();
SwapBuffers(hdc);

yRot += 0.5f;
}
//When program exit
ReleaseDC(hWnd,hdc);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
//But, yes...something going wrong here
switch(msg)
{
case WM_CREATE:
//I thought following codes is ok
//Cuz‘s Rendering Thread is working well
hdc = GetDC(hWnd);
SetRCPixelFormat(hdc);
hSlaverRC = wglCreateContext(hdc);
wglShareLists(hPrimaryRC,hSlaverRC);
break;
case WM_RBUTTONUP:
//But here comes problem
//I want change OpenGL shading mode
//when i right click the window, but infact...it's doesn't work
//Can someone give me some advise?
wglMakeCurrent(hdc,hSlaverRC);
glShadeModel(GL_FLAT);
glFinish();
break;
case WM_DESTROY:
ReleaseDC(hWnd,hdc);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,msg,wParam,lParam);
}

return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow)
{
MSG msg;
WNDCLASSEX wndex;

wndex.cbSize = sizeof(WNDCLASSEX);
wndex.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
wndex.cbClsExtra = 0;
wndex.cbWndExtra = 0;
wndex.lpfnWndProc = WndProc;
wndex.hInstance = hInstance;
wndex.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
wndex.hCursor = LoadCursor(NULL,IDC_ARROW);
wndex.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndex.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
wndex.lpszClassName = TEXT("MainWindow");
wndex.lpszMenuName = NULL;

if(!RegisterClassEx(&wndex))
{
MessageBox(NULL,TEXT("程序初始化失败"),TEXT("启动失败"),MB_OK);
return 0;
}

hWnd = CreateWindow(TEXT("MainWindow"),TEXT("MultGL"),
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,72 0,480,NULL,NULL,hInstance,NULL);

ShowWindow(hWnd,SW_MAXIMIZE);
UpdateWindow(hWnd);

//Just called glewInit
ActiveGL();

CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)Ren der,NULL,NULL,lpThreadId);

while(GetMessage(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

wglMakeCurrent(NULL,NULL);
wglDeleteContext(hPrimaryRC);
wglDeleteContext(hSlaverRC);

return msg.wParam;
}

Question are following up in those description
I Search a lot of bbs ,but in the end, i still can't solve that problem.
Please help T^T, and forgive my english not well... it's teach by my math teacher

Caesirekin
11-12-2013, 11:16 PM
If nobody could hlep me slove this problem,
May some one give me some references document what may helpful for me?
I'm really interesting about multi-thread opengl,and i don't want use others libraries
It's not good for a beginner to understanding those thinking, i thought
Thanks everyone

Aleksandar
11-13-2013, 08:33 AM
Your problem is not OpenGL related. You have to learn how to use events to send "commands" to rendering thread.
What you've done is making two contexts that share resources using "an old way" through wglShareLists(), and then you changed state of non-rendering context hoping it would change state of the rendering context too. Well, it is totally wrong assumption.

Advice: Use a single GL context in the rendering thread and whenever something have to be changed send a message to that thread. Use events to signal addition of a message to a command queue.

Dan Bartlett
11-13-2013, 09:18 AM
You are setting glShadeModel(GL_FLAT) in one context, but rendering with the other context. Since this state is per-context it never affects rendering. Only certain objects are shared between contexts - see the OpenGL spec. appendices.

Caesirekin
11-13-2013, 09:13 PM
Your problem is not OpenGL related. You have to learn how to use events to send "commands" to rendering thread.
What you've done is making two contexts that share resources using "an old way" through wglShareLists(), and then you changed state of non-rendering context hoping it would change state of the rendering context too. Well, it is totally wrong assumption.

Advice: Use a single GL context in the rendering thread and whenever something have to be changed send a message to that thread. Use events to signal addition of a message to a command queue.

Thanks very much
And yes,I was using and old tutorial to learning those thing, really
My Win32 API tutorial was published may has ten years ago(those book was diffcult to find in china),
And my OpenGL tutorial is SuperBible (Fourth Edition),I buy the fifth edition too, but haven't read yet.
I'll keep learning,Anyway,As you've said, i think i should learning more about Win32 API and OpenGL more deeply
Thanks again.

Caesirekin
11-13-2013, 09:24 PM
You are setting glShadeModel(GL_FLAT) in one context, but rendering with the other context. Since this state is per-context it never affects rendering. Only certain objects are shared between contexts - see the OpenGL spec. appendices.

Thanks for your hlep,someone told me that wglMakeCurrent can changing the current redering context to another thread, so i try these code
Whatever, i will try that book(is it a book?),a book is very useful help for me

Caesirekin
11-13-2013, 09:36 PM
You are setting glShadeModel(GL_FLAT) in one context, but rendering with the other context. Since this state is per-context it never affects rendering. Only certain objects are shared between contexts - see the OpenGL spec. appendices.

Well ... I thought i misunderstanding your means, i'll see the OpenGL specification right now...= =!