• 0

WPF rendering with OpenGL in another thread


Question

I'm trying to make a video player in WPF, using libavcodec for decoding and OpenGL for rendering.

I host my own C++/CLI control derived from Windows.Forms.UserControl inside a WindowsFormsHost. I use its Handle to initialize an OpenGL context.

Here is the code for my override of OnPaint:

wglMakeCurrent(m_hDC, m_hRC);
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(m_hDC);

This works fine. When OnPaint is called, the control, which covers the whole window, is cleared to red.

Now, WPF controls when OnPaint is called, not me. When I'll be rendering video, I need to be able to draw to the screen when I decide to. So I've put the above code in an infinite loop and made it execute on a BackgroundWorker thread. Now, the problem is that wglMakeCurrent fails in this situation with"error 170: the requested resource is in use". Consequently, the call to glClear() (and any further rendering) does nothing.

I don't understand exactly which resource is in use and why, and I'd like to know what's wrong with my approach.

Thanks!

P.S. here is the initialization code in case this could be useful. It is hooked to the "Load" event of the control. And yes this is essentially copy-pasted from a tutorial on the net.

m_hWnd	= (HWND) this->Handle.ToPointer();

			if(m_hWnd)
			{
				m_hDC = GetDC(m_hWnd);
				if(!m_hDC)
				{
					Helper::ErrorExit(L"BuildWindowCore");
				}
				uint PixelFormat;

				BYTE iAlphaBits = 0;
				BYTE iColorBits = 32;
				BYTE iDepthBits = 16;
				BYTE iAccumBits = 0;
				BYTE iStencilBits = 0;

				static PIXELFORMATDESCRIPTOR pfd = 
				{
					sizeof(PIXELFORMATDESCRIPTOR),	//size
					1,								//version
					PFD_DRAW_TO_WINDOW|				//flags
					PFD_SUPPORT_OPENGL|
					PFD_DOUBLEBUFFER,
					PFD_TYPE_RGBA,					//pixeltype
					iColorBits,
					0, 0, 0, 0, 0, 0,				//color bits ignored
					iAlphaBits,						
					0,								//alpha shift ignored
					iAccumBits,						//accum. buffer
					0, 0, 0, 0,						//accum bits ignored
					iDepthBits,						//depth buffer
					iStencilBits,					//stencil buffer
					0,								//aux buffer
					PFD_MAIN_PLANE,					//layer type
					0,								//reserved
					0, 0, 0							//masks ignored
				};

				PixelFormat = ChoosePixelFormat(m_hDC, &pfd);
				if(!PixelFormat)
				{
					Helper::ErrorExit(L"BuildWindowCore");
				}

				if(!SetPixelFormat(m_hDC, PixelFormat, &pfd))
				{
					Helper::ErrorExit(L"BuildWindowCore");
				}

				m_hRC = wglCreateContext(m_hDC);
				if(!m_hRC)
				{
					Helper::ErrorExit(L"BuildWindowCore");
				}

				if(!wglMakeCurrent(m_hDC, m_hRC))
				{
					Helper::ErrorExit(L"BuildWindowCore");
				}

1 answer to this question

Recommended Posts

  • 0

I'm guessing I am not allowed to update it on a thread other than the UI thread, since it is part of the UI. But I don't want playing video to block the UI. So, I need to implement a scheme where I render one frame at a time, using something like a DispatcherTimer. Am I on the right track?

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.