2012-07-16 117 views
-1

我的程序将视频帧显示为OpenGL纹理。错误的OpenGL初始化

我有OpenGL初始化的问题。要看视频,我需要开始渲染线程,停止它并重新开始。我想我在CRenderThread :: InitOpenGL()函数中缺少一些东西。我应该如何做正确的OpenGL初始化?

我的环境:

的Windows 7 64位系统

微软的Visual Studio 2008 x64的

下面是代码:

#include "RenderThread.h" 
#include <QtDebug> 
#include <vm_time.h> 

static Ipp32u UMCToInternalFormat(UMC::ColorFormat format) 
{ 
switch(format) 
{ 
case UMC::BGR24: return GL_BGR; 
case UMC::BGR32: return GL_BGRA; 
case UMC::RGB24: return GL_RGB; 
case UMC::RGB32: return GL_RGBA; 
} 
return 0; 
} 

CRenderThread::CRenderThread(const WId& rnWindowHandle) 
: m_bInitialized(false) 
, m_WindowHandle(rnWindowHandle) 
, m_Texture(0) 
, m_fTextureWidth(0.0f) 
, m_fTextureHeight(0.0f) 
, m_nFrameWidth(0) 
, m_nFrameHeight(0) 
, m_nWindowWidth(0) 
, m_nWindowHeight(0) 
{ 
} 

void CRenderThread::PrepareWork() 
{ 
// Wait until first frame comes 
if(!m_bAbort) 
    Suspend(); 
} 

void CRenderThread::DoOnStop() 
{ 
if(m_WindowGLResourceContext) 
{ 
    wglDeleteContext(m_WindowGLResourceContext); 
    m_WindowGLResourceContext = 0; 
} 
    ReleaseDC(m_WindowHandle, m_WindowDC); 

if(m_Texture) 
{ 
    glDeleteTextures(1, &m_Texture); 
    m_Texture = 0; 
} 
} 

void CRenderThread::InitOpenGL() 
{ 
PIXELFORMATDESCRIPTOR pfd = { 
    sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
    PFD_TYPE_RGBA, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 
}; 

m_WindowDC = GetDC(m_WindowHandle); 
if(!m_WindowDC) 
    return; 

if(!SetPixelFormat(m_WindowDC, ChoosePixelFormat(m_WindowDC, &pfd), &pfd)) 
    return; 

m_WindowGLResourceContext = wglCreateContext(m_WindowDC); // create rendering context 
if(!m_WindowGLResourceContext) 
    return; 

if(!wglMakeCurrent(m_WindowDC, m_WindowGLResourceContext)) // set it as current 
    return; 

// OpenGL context already tied to output window 
// to disable all slow GL components 
// it is not mandatory to disable all if we have accelerated card 
glClearColor(0.0f, 170.0f, 255.0f, 1.0f); 
glClearDepth(1.0); 
glDepthFunc(GL_NEVER); 

// disable slow GL extensions 
glDisable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); 
glDisable(GL_DITHER);  glDisable(GL_FOG);   glDisable(GL_STENCIL_TEST); 
glDisable(GL_LIGHTING); glDisable(GL_LOGIC_OP);  glDisable(GL_TEXTURE_1D); 
glDisable(GL_TEXTURE_2D); 

glPixelTransferi(GL_MAP_COLOR, GL_FALSE); 
glPixelTransferi(GL_RED_SCALE, 1); glPixelTransferi(GL_RED_BIAS, 0); 
glPixelTransferi(GL_GREEN_SCALE, 1); glPixelTransferi(GL_GREEN_BIAS, 0); 
glPixelTransferi(GL_BLUE_SCALE, 1); glPixelTransferi(GL_BLUE_BIAS, 0); 
glPixelTransferi(GL_ALPHA_SCALE, 1); glPixelTransferi(GL_ALPHA_BIAS, 0); 

glEnable(GL_TEXTURE_2D); 
glGenTextures(1, &m_Texture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

glViewport(0, 0, m_nWindowWidth, m_nWindowHeight); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glRasterPos2i(-1, 1);  // move to the upper left corner 
glPixelZoom(1.0, -1.0);  // top to bottom 

SwapBuffers(m_WindowDC); 

m_bInitialized = true; 
} 

void CRenderThread::SetRenderFrame(PVideoData pFrame) 
{ 
Q_ASSERT(pFrame.get()); 
{ 
    //boost::mutex::scoped_lock Lock(m_FrameMutex); 
    m_pFrameToRender = pFrame; 
} 

// Resume thread to render current frame 
Resume(); 
} 

void CRenderThread::DoWork() 
{ 
IppiSize CurWinSize; 
UMC::Status nStatus = UMC::UMC_OK; 

::RECT rect; 
GetClientRect(m_WindowHandle, &rect); 
CurWinSize.height = rect.bottom; 
CurWinSize.width = rect.right; 

if(!m_bInitialized) 
    InitOpenGL(); 

if(CurWinSize.width > IPP_MAX_16S || CurWinSize.height > IPP_MAX_16S) // window seems to be destroyed 
    return; 

// reinit buffers if window size has been changed 
if(CurWinSize.height != m_nWindowHeight || CurWinSize.width != m_nWindowWidth) 
{ 
    m_nWindowWidth = CurWinSize.width; 
    m_nWindowHeight = CurWinSize.height; 

    glViewport(0, 0, m_nWindowWidth, m_nWindowHeight); 
} 

// Render frame 
{ 
    //boost::mutex::scoped_lock Lock(m_FrameMutex); 
    if(m_pFrameToRender.get()) 
    { 
     if(m_nWindowWidth && m_nWindowHeight) 
     { 
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

      m_nFrameWidth = m_pFrameToRender->GetWidth(); 
      m_nFrameHeight = m_pFrameToRender->GetHeight(); 
      m_nRenderFormat = UMCToInternalFormat(m_pFrameToRender->GetColorFormat()); 

      glTexImage2D(GL_TEXTURE_2D, 0, 3, m_nFrameWidth, m_nFrameHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pFrameToRender->GetBufferPointer()); 
      //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_nFrameWidth, m_nFrameHeight, m_nRenderFormat, GL_UNSIGNED_BYTE, m_pFrameToRender->GetBufferPointer()); 

      glBegin(GL_POLYGON); 
      glTexCoord2i(0, 0); glVertex2f(-1.0, 1.0); 
      glTexCoord2i(1, 0); glVertex2f(1.0, 1.0); 
      glTexCoord2i(1, 1); glVertex2f(1.0, -1.0); 
      glTexCoord2i(0, 1); glVertex2f(-1.0, -1.0); 
      glEnd(); 

      glFlush(); 

      SwapBuffers(m_WindowDC); // to draw on physical screen 
     } 
    } 
} 

// Wait for next frame to render 
if(!m_bAbort) 
    Suspend(); 
} 
+1

它看起来好像你试图从多个线程访问单个GL上下文。是这样吗? – genpfault 2012-07-16 16:15:10

+0

不,从函数体中调用创建OpenGL上下文的函数CRenderThread :: InitOpenGL()。 – Thomas13 2012-07-17 04:36:21

回答

2

夫妇的想法,不一定都是相关的到您的问题:

glClearColor(0.0f, 170.0f, 255.0f, 1.0f);

清除颜色被钳位到的[0,1]的范围内,不[0,255]。


// disable slow GL extensions 
glDisable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); 
glDisable(GL_DITHER);  glDisable(GL_FOG);   glDisable(GL_STENCIL_TEST); 
glDisable(GL_LIGHTING); glDisable(GL_LOGIC_OP);  glDisable(GL_TEXTURE_1D); 
glDisable(GL_TEXTURE_2D); 

这些(和最重要OpenGL设置)默认情况下禁用。这些都无所作为。虽然没有伤害任何东西。


glPixelTransferi(GL_MAP_COLOR, GL_FALSE); 
glPixelTransferi(GL_RED_SCALE, 1); glPixelTransferi(GL_RED_BIAS, 0); 
glPixelTransferi(GL_GREEN_SCALE, 1); glPixelTransferi(GL_GREEN_BIAS, 0); 
glPixelTransferi(GL_BLUE_SCALE, 1); glPixelTransferi(GL_BLUE_BIAS, 0); 
glPixelTransferi(GL_ALPHA_SCALE, 1); glPixelTransferi(GL_ALPHA_BIAS, 0); 

再次,这些所有的默认值。


glEnable(GL_TEXTURE_2D); 
glGenTextures(1, &m_Texture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

这实际上可能是一个真正的问题。 glTexParameter只会影响当前绑定的纹理,但您在此处调用它们时不会绑定纹理。所以这些什么都不做。当你实际上稍后使用纹理时,它将在最小过滤器上设置mipmapping,这可能会导致它不显示。将您的glTexParameter调用移到您希望它们生效的纹理上之后。

+0

蒂姆,不幸的是这并没有帮助。我在CRenderThread :: DoWork()中的glTexImage2D之前移动了纹理gereration和绑定,但行为保持不变 - 我需要重新启动线程才能看到视频。 – Thomas13 2012-07-17 04:39:49