I tried adding a call to glViewport to initializeGL without improvement. Why would resize fix the problem? What other initialization steps am I missing?
I pasted complete code below. The problem is occasionally the video frames rendered as 2D bitmap textures are display as upside-down mirror images of pieces of my desktop within the OpenGL widget. When this happens, resizing the window (even just 1 pixel) fixes the problem.
Thanks in advance for your time,
-Ed
[b]
/**
@file glwidget.cpp
@brief Widget to handle reception of FES Video API and render as a OpenGl 2-D texture
Disclaimer: This is not an optimized example of using OpenGL.
*/
#include <iostream>
#include <pthread.h>
#include <QBitmap>
#include <QtGui>
#include <QtOpenGL>
#include <math.h>
#include “bitmap.h”
#include “glwidget.h”
#include “mainwindow.h”
using namespace std;
int globalCount = 0;
GLWidget::GLWidget(QWidget parent)
: QGLWidget(parent)
,m_pMainWindow((MainWindow)parent)
,m_stopWatchFramesPerSecond(false)
,m_stopWatchSwitchingLatency(false)
,m_countIntervalFrames(0)
,m_framesPerSecond(0)
,m_showStats(false)
,m_showStatsOnScreen(false)
,m_id(0)
//,m_throwExceptionForTestingPurpose(false)
{
}
GLWidget::~GLWidget()
{
makeCurrent();
glDeleteTextures(1,m_texture);
}
int GLWidget::id() const { return m_id; }
int GLWidget::setId(int value) { return m_id = value; }
QSize GLWidget::minimumSizeHint() const
{
return QSize(50, 50);
}
QSize GLWidget::sizeHint() const
{
return QSize(720, 486);
}
/// \brief Initialze the OpenGL options to use for rendering bitmaps as a 2-D texture using glTexImage2D.
void GLWidget::initializeGL()
{
//glEnable(GL_DEPTH);
//glEnable(GL_DOUBLE);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_RGB);
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
printf("GLWidget::initializeGL(): width=%i, height = %i
", this->width(), this->height());
// I was hoping a call to glViewport here would straighten out upside-down-mirror problem
// This is the problem that fixes itself after the first resize.
glViewport(0, 0, this->width(), this->height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, m_texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
/// Update the averaged frames per second
void GLWidget::updateFramesPerSecond()
{
// Update frames per second
}
/// \brief Renders the video frame as a 2D texture using the OpenGL function glTexImage2D
void GLWidget::onNewVideoFrameHandler(smartPointerEventArgs_t eventArgs)
{
if(NULL == eventArgs.get())
{
// GUI could clear display, show error (or error screen) to user, or display a lost-signal.bmp ?
printf("*** Received NULL EventArgs_t*
");
return;
}
if(CameraVideoSourceType != eventArgs->videoSourceType())
{
return;
}
GLvoid* pBitmapData = NULL;
try
{
if(m_stopWatchSwitchingLatency.running())
{
m_stopWatchSwitchingLatency.stop();
}
CameraVideoEventArgs* cameraVideoEventArgs = dynamic_cast<CameraVideoEventArgs*>(eventArgs.get());
if(NULL == cameraVideoEventArgs->bitmapData())
{
printf("*** Received NULL cameraVideoEventArgs->data()
");
return;
}
/// @todo Insure that width x height can only change when on the first frame received after changing video sources.
pBitmapData = (GLvoid*)cameraVideoEventArgs->bitmapData();
StructBitmapInformationHeader_t bitmapInformationHeader = cameraVideoEventArgs->bitmapInformationHeader();
m_width = bitmapInformationHeader.width;
m_height = bitmapInformationHeader.height;
m_frameIndex = cameraVideoEventArgs->videoStats().frameNumber();
updateFramesPerSecond();
}
catch(…)
{
printf("*** Caught unexpected exception in GLWidget::onNewVideoFrameHandler
");
exit(1);
}
// Multiple instances of QGLWidget would not update until I added call to makeCurrent().
// Not sure if this is optimal or exactly when makeCurrent should be called.
// Makes this widget the current widget for OpenGL operations, i.e. makes the widget’s
// rendering context the current OpenGL rendering context.
makeCurrent();
// After calling glTexImage2D we no longer need a copy of the bitmap data pBitmapData - it can go out of scope.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_width, m_height, 0, GL_BGR, GL_UNSIGNED_BYTE, pBitmapData);
update();
}
/// \brief Renders the bitmap onNewVideoFrameHandler() loaded using call to glTexImage2D.
/// Also displays frames per second and video resolution using renderText
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glPushMatrix();
{
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLE_STRIP);
{
glTexCoord2f(0.0, 0.0);
glVertex2f(-1.0, -1.0);
glTexCoord2f(1.0, 0.0);
glVertex2f(1.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex2f(-1.0, 1.0);
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
}
glEnd();
}
glPopMatrix();
// If enabled, update stats
if(m_showStatsOnScreen && m_showStats)
{
renderText(-0.98,-0.98,0.0,
m_qStringformatter.sprintf(“fps:%4.1f [%i] %i x %i”, m_framesPerSecond, m_frameIndex, m_width, m_height),
QFont(“courier”, 15, 5, false));
}
// The glFlush function forces execution of OpenGL functions in finite time.
swapBuffers();
glFlush();
}
/// \brief Resize window
/// I suspect here might be where you would add code to maintain original aspect ratio?
void GLWidget::resizeGL(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
[/b]