-1

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

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

我的环境:

视窗 7 x64

微软视觉工作室 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();
}
4

1 回答 1

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在绑定了您希望它们影响的纹理后,将您的调用移动到。

于 2012-07-16T16:11:47.670 回答