PDA

View Full Version : Upside-down 2D texture mirror images until resize?



EdOfTheMountain
06-03-2010, 02:01 PM
I am hoping others may have run into this before.

I made a video player that renders bitmaps of video frames as 2D textures. Occasionally on startup, my app displays upside down mirror images of the desktop or other parts of GUI that get updated periodically when it is supposed to be rendering video frames. Once I resize the window, all is fixed and stable again. I am not sure what to check. Perhaps I am overlooking something in initialization. I am on Linux RHEL 5.3 using QtGlWidget running in a VM.

My resize code:

/// 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);
}

My initialize code:

/// \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 );
//glViewport(0, 0, 200, 100);
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_FILTE R,GL_LINEAR);

}

I have basically cut & paste this OpenGL code from various resources. Except for this problem it works well. Any direction is appreciated.

Thanks in advance,

-Ed

Jan
06-03-2010, 03:06 PM
Is the resize function the only one where you set your viewport? If so, is it called (AFTER initializeGL) at least once? Or only when you manually resize the window ?

Dan Bartlett
06-03-2010, 03:43 PM
void GLWidget::initializeGL()
{
glEnable(GL_DEPTH);
glEnable(GL_DOUBLE);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
glEnable(GL_RGB);
...


It probably won't solve your problem, but I'm fairly sure GL_DEPTH, GL_DOUBLE and GL_RGB aren't valid values for glEnable. GL_DEPTH_TEST is a valid value that enables depth testing , but if you wanted double buffering + using RGB color mode, these are set at the platform level / at context creation time.

also, you have:


glBindTexture(GL_TEXTURE_2D, m_texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_LINEAR);

but you don't generate the texture (unless you've done it somewhere else before?)
It needs glGenTextures called before binding the texture.

EdOfTheMountain
06-04-2010, 07:30 AM
Hi Jan,

Thank you for taking the time to look at my code. Yes, I have a single call to glviewport in my resize routine only:

glViewport(0, 0, width, height)

Should it be called at some point in the initializeGL sequence? If so, where in the sequence does it need to be called?

Thank you for your assistance,

-Ed

EdOfTheMountain
06-04-2010, 08:05 AM
Hi Dan,

Thanks, I think you are right.

After commenting-out, it still works, yet same problem. I do not know if it helped me doing any work in the GPU or not. I guess I can profile it.

void GLWidget::initializeGL()
{
//glEnable(GL_DEPTH);
//glEnable(GL_DOUBLE);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_RGB);

The texture is generated in the callback handler that receives the bitmap from the video decoder. I should have included this code:

/// \brief Renders the video frame as a 2D texture using the OpenGL function glTexImage2D
void GLWidget::onNewVideoFrameHandler(smartPointerEvent Args_t eventArgs)
{
GLvoid* pBitmapData = NULL;
CameraVideoEventArgs* cameraVideoEventArgs = dynamic_cast<CameraVideoEventArgs*>(eventArgs.get());

pBitmapData = (GLvoid*)cameraVideoEventArgs->bitmapData();

StructBitmapInformationHeader_t bitmapInformationHeader = cameraVideoEventArgs->bitmapInformationHeader();
m_width = bitmapInformationHeader.width;
m_height = bitmapInformationHeader.height;

// 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();
}

Thanks again for your time,

-Ed

EdOfTheMountain
06-11-2010, 07:32 AM
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


/**
@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\n", 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_FILTE R,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(smartPointerEvent Args_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*\n");
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()\n");
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\n");
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 &amp;&amp; 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);
}

EdOfTheMountain
06-11-2010, 07:54 AM
I just noticed the upside-down mirror image has a relationship with what desktop screen object I roll the mouse over. This is while it should be drawing video frames at 30 fps. All I see is the upside-down mirror images of other apps and menus from my desktop. Then once I resize, the video frames rendering is fixed and all is good. It's like it is drawing with the wrong layer or something and the resize fixes it?

-Ed