🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

OpenGL & Threads

Started by
3 comments, last by taby 3 years, 6 months ago

I was creating a game engine, but I couldn't get to understand how thread works, I tried to look for an answer on the internet, with no answer. I had created a thread to render and the main thread is in the UI (GetMessages Windows Win32). But it doesn't show anyone that I created a sprite. (without thread I can show)

I ask that you can help me how to solve and help me understand about it.

Thanks!

WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));

m_hinstance = GetModuleHandle(NULL);

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.hInstance = m_hinstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.lpszClassName = L"Engine";

wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;

if (!RegisterClassEx(&wc)) {
	const wchar_t *info = L"Failed to register the window class.";
	MessageBox(NULL, info, L"Error", MB_OK | MB_ICONERROR);
	return false;
}
		
if (m_borderless == Borderless::FULLSCREEN) {
			
}		
else if (m_borderless == Borderless::WINDOWED) {
	m_hwnd = CreateWindowEx(
		NULL,
		wc.lpszClassName,
		m_title.c_str(),
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
		//WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
		0, 0,
		m_size.width, m_size.height,
		NULL, NULL, m_hinstance, NULL
	);

	if (!m_hwnd) {
		const wchar_t *info = L"Failed to create window.";
		MessageBox(NULL, info, L"Error", MB_OK | MB_ICONERROR);
		return false;
	}

	RECT rect;
	if (GetClientRect(m_hwnd, &rect)) {
		m_border.width = m_size.width - rect.right;
		m_border.height = m_size.height - rect.bottom;
		SetWindowPos(m_hwnd, HWND_TOPMOST, 0, 0, m_size.width + m_border.width, m_size.height + m_border.height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
	}
}
else if (m_borderless == Borderless::BORDERLESS) {
	int width = GetSystemMetrics(SM_CXSCREEN);
	int height = GetSystemMetrics(SM_CYSCREEN);

	m_hwnd = CreateWindowEx(
		NULL,
		wc.lpszClassName,
		m_title.c_str(),
		WS_POPUP | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION,
		0, 0,
		width,
		height,
		NULL, NULL, m_hinstance, NULL
	);

	if (!m_hwnd) {
		const wchar_t *info = L"Failed to create window.";
		MessageBox(NULL, info, L"Error", MB_OK | MB_ICONERROR);
		return false;
	}
}

static 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,
	24,
	8,
	0,
	PFD_MAIN_PLANE,
	0,
	0, 0, 0
};

int nMyPixelFormatID;
HDC hDC;
HGLRC hRC;
HGLRC hRC2;

if (!(hDC = GetDC(m_hwnd))) {
	return false;
}

if (!(nMyPixelFormatID = ChoosePixelFormat(hDC, &pfd))) {
	return false;
}

if (!SetPixelFormat(hDC, nMyPixelFormatID, &pfd)) {
	return false;
}

if (!(hRC = wglCreateContext(hDC))) {
	return false;
}

if(!(hRC2 = wglCreateContext(hDC))) {
	return false;
}

if(!wglShareLists(hRC, hRC2))
{
	return false;
}

if (!wglMakeCurrent(hDC, hRC)) {
	return false;
}

ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
m_hdc = hDC;
m_hrc = hRC;
m_hrc2 = hRC2;

if (GLEXT::GetInstance()->Initialize()) {
	LOG_SUCCESS(L"Initialize Window has been successfully.");
	if (m_borderless == Borderless::FULLSCREEN) {
				
	}
	else if (m_borderless == Borderless::WINDOWED) {
		glViewport(0, 0, m_size.width, m_size.height);
	}
	else if (m_borderless == Borderless::BORDERLESS) {
		int width = GetSystemMetrics(SM_CXSCREEN);
		int height = GetSystemMetrics(SM_CYSCREEN);
		glViewport(0, 0, width, height);
	}
	m_created = true;

	// vsync
	SetVSync(m_vsync);

	// callback
	if (m_initialize_callback != NULL)
		m_initialize_callback();

	if (m_loadcontent_callback != NULL)
		m_loadcontent_callback();

	return true;
} else {
	// failed load gxt
}

Main Thread:

void threadGame(bool &alive){
	Engine::GLEXT::GetInstance()->Delete();
	wglMakeCurrent(Window::GetInstance()->GetHDC(), Window::GetInstance()->GetHRC2());
	Engine::GLEXT::GetInstance()->Initialize();
	Render::GetInstance()->Initialize();
	Timer time;

	bool fpslimit = false;

	float timer = 0.0f;
	float updateTimer = time.ElapsedMillis();
	float updateTick = 1000.0f / 60.0f;

	UINT updates = 0;
	UINT frames = 0;

	float delta = 0;
	float last = time.ElapsedMillis();

	while(alive)
	{
		float now = time.ElapsedMillis();
		if(fpslimit) {
			if(now - updateTimer > updateTick) {

				delta = now - last;
				last = now;

				onUpdate(delta);
				updates++;

				updateTimer += updateTick;
			}
		}
		else {
			delta = now - last;
			last = now;

			onUpdate(delta);
			updates++;
		}

		onRender();
		frames++;

		if(time.Elapsed() - timer > 1.0f) {
			timer += 1.0f;

			// set title
			std::wostringstream ws;
			ws << L"Delta: ";
			ws << delta;
			ws << L" - FPS: ";
			ws << updates;
			ws << L" - Frames: ";
			ws << frames;

			std::wstring s(ws.str());
			Window::GetInstance()->SetTitle(s);

			updates = 0;
			frames = 0;
		}
	}
}
bool alive = true;
std::thread thread(threadGame, std::ref(alive));

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

alive = false;
thread.join();
Advertisement

You are missing important information from your code, for example what is the code you pasted first that seems to create the render window, where is it called, so I can just guess and my guess is that

wglMakeCurrent(Window::GetInstance()->GetHDC(), Window::GetInstance()->GetHRC2());

fails in the thread function und you don't catch the return value to handle that failure. And if I'm correct, you are creating the rendering window in the main thread but try to access it in the render thread which will not work. You have first to tell the main thread to release ownership of the context by calling

wglMakeCurrent(0, 0);

and after that, it should be possible for the render thread to get ownership of the render context on that window

Carlos Oliveira said:
if(!wglShareLists(hRC, hRC2)) { return false; }

This is old and deprecated, and won't work if you're not displaying with display lists only. You need to use wglCreateContextAttribsARB. Read carefully this for more information.

EDIT: I'm just realizing I'm late here…

If it's possible, switch to using C++ threads. It's part of the standard now.

Likewise, with all of the Windows code. Try SDL instead.

This topic is closed to new replies.

Advertisement