Trouble with OpenGL + threads...

Started by
3 comments, last by _Silence_ 6 years, 4 months ago

Hi guys, im having a little problem fixing a bug in my program since i multi-threaded it. The app is a little video converter i wrote for fun. To help you understand the problem, ill first explain how the program is made. Im using Delphi to do the GUI/Windows part of the code, then im loading a c++ dll for the video conversion. The problem is not related to the video conversion, but with OpenGL only. The code work like this:


 


DWORD WINAPI JobThread(void *params)
{
    for each files {
      
      ...
      
      _ConvertVideo(input_name, output_name);
    }
}

void EXP_FUNC _ConvertVideo(char *input_fname, char *output_fname)
{
	// Note that im re-initializing and cleaning up OpenGL each time this function is called...
	CGLEngine GLEngine; 
  
	...
  
	// Initialize OpenGL
	GLEngine.Initialize(render_wnd);
	GLEngine.CreateTexture(dst_width, dst_height, 4);
    
	// decode the video and render the frames...
	for each frames {

		...
      
		GLEngine.UpdateTexture(pY, pU, pV);
		GLEngine.Render();   
	}
      
cleanup:
  	GLEngine.DeleteTexture();
	GLEngine.Shutdown();

 	// video cleanup code...
}

 

With a single thread, everything work fine. The problem arise when im starting the thread for a second time, nothing get rendered, but the encoding work fine. For example, if i start the thread with 3 files to process, all of them render fine, but if i start the thread again (with the same batch of files or not...), OpenGL fail to render anything.

Im pretty sure it has something to do with the rendering context (or maybe the window DC?). Here a snippet of my OpenGL class:


bool CGLEngine::Initialize(HWND hWnd)
{
	hDC = GetDC(hWnd);

	if(!SetupPixelFormatDescriptor(hDC)){
		ReleaseDC(hWnd, hDC);
		return false;
	}

	hRC = wglCreateContext(hDC);
	wglMakeCurrent(hDC, hRC);	                        

	// more code ...

	return true;
}

void CGLEngine::Shutdown()
{
	// some code...

	if(hRC){wglDeleteContext(hRC);}
	if(hDC){ReleaseDC(hWnd, hDC);}
	hDC = hRC = NULL;
}

 

The full source code is available here. The most relevant files are:

-OpenGL class (header / source)

-Main code (header / source)

 

Thx in advance if anyone can help me.

Advertisement

I was not deeply into your code, but at first glance I could not see any context sharing.

This is the main piece when doing multithreaded OpenGL programs.

When sharing contexts most of the objects will be shared except containers (you'll have to recreate these containers on both contexts if needed).

For more information see this link and this one.

For creating such shared context, use glXCreateContext or (since you seem to be under Windows) its equivalent one.

33 minutes ago, _Silence_ said:

I was not deeply into your code, but at first glance I could not see any context sharing.

Not sure what you mean by this, since i don't think i need any sharing.

That's what im trying to explain, im only using a secondary thread to do the conversion and rendering, so the main thread is not blocked, but im not lauching more than one (secondary) thread at once. ie:

 

Step 1: User add file(s) he want to convert in a listbox

Step 2: Main thread launch secondary thread and do it's thing until it finish (the main thread is not blocked)

    (User interface is disabled until the thread dies)

    (Secondary thread encode all the files in the list, work well the first time for one or multiple files)

Step 3: Just before the thread exit, it post a message to the main thread so the user interface is re-enabled again

Then you can go to step 1 again (that's where opengl don't work anymore), or close the application, whatever.

 

Hope this clear things a bit.

 

1 hour ago, Vortez said:

Not sure what you mean by this, since i don't think i need any sharing.

That's what im trying to explain, im only using a secondary thread to do the conversion and rendering, so the main thread is not blocked, but im not lauching more than one (secondary) thread at once. ie:

OK. This was not clear to me. And things are still not clear enough:

On which thread do you create your OpenGL window (which thread own the context). The thread were the window and the context was created and first made current, must be the same thread that renders. Note that most of the times APIs that allow to create OpenGL windows will create it in the caller thread, which is usually the main thread.

On which thread do you render (from reading you, it seems to be the second thread) ? If so, this second thread must create the window, the context and makes it current.

Do you create any OpenGL objects on the non-rendering thread ?

 

Hope that could help a bit more :)

This topic is closed to new replies.

Advertisement