错误的OpenGL初始化

时间:2012-07-16 14:29:52

标签: opengl

我的程序将视频帧显示为OpenGL纹理。

我遇到OpenGL初始化问题。要观看视频,我需要开始渲染线程,停止并重新开始。我想我在CRenderThread :: InitOpenGL()函数中遗漏了一些东西。我该怎么做才能正确初始化OpenGL?

我的环境:

  

Windows 7 x64

     

Microsoft 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 个答案:

答案 0 :(得分: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仅影响当前绑定的纹理,但您在此处调用它们时没有纹理绑定。所以这些都无所作为。当您实际上稍后使用纹理时,它将在min过滤器上设置mipmapping,这可能导致它不被显示。在绑定要使其生效的纹理后,将glTexParameter调用移动到其中。