PDA

View Full Version : QGLWidget doesn't hide



sebc06
8th March 2013, 10:34
Hello,

I built an application for omap3530 device, based on (Qt 4.7 then Qt4.8) + Opengles.
I followed this (http://processors.wiki.ti.com/index.php/Building_Qt_for_OMAP35xx_with_OpenGL_ES_accelerate d_by_SGX) tutorial for SGX + Qt installation.

The application consists in three main widgets: a QGLWidget used to display frames from a webcam, a QTableView used to display some execution events and a vertical QWidget with different QPushButton. One of them is used to switch between QGLWidget and QTableView.

The application is able to switch once from QTableView to QGLWidget but when i get in that view, i can't hide the QGLWidget to display the QTableView. It seems that QGLWidget remains at the top of the screen, catching touch events, and that the main widget doesn't refresh the screen.

I tried different solutions : put the three widget in a QHboxLayout and use hide/show slots, put QTableView and QGLWidget in a QStackedWidget, remove QGLWidget from the layout and set null size to QGLWidget (causes segfault) but none of these solutions works.

Any ideas ?
Thanks

wysota
8th March 2013, 11:09
Show us some code.

Uwe
8th March 2013, 12:33
The application consists in three main widgets: a QGLWidget used to display frames from a webcam, a QTableView used to display some execution events and a vertical QWidget with different QPushButton. One of them is used to switch between QGLWidget and QTableView.

QWS is hopelessly buggy when it comes to mix widgets using a different paint engine in the same top level window. In fact the problem is completely unrelated to OpenGL beside, that an OpenGL widget uses a different paint engine, what introduces a subsurface.

The reason why subsurfaces are always on top is because it is implemented this way. You can find the code in Qt that orders the subsurfaces always on top. You can change this implementation if you want to - but it won't take you far as there are many other issues left.

I had commited a couple of patches for Qt 4.6 so that Qt/QWS is at least not broken when sub surfaces are enabled ( without using them ) - what happens as soon as you enable OpenGL when building Qt - and I have a couple of patches on my disk that I never committed as nobody in the development is interested to fix QWS anymore.

But for your specific problem I recommend to implement an empty dummy widget that controls the position and visibility of the camera picture using the video4linux API. The image itself should be displayed on a higher hardware layer than the one where Qt is.

Uwe

sebc06
8th March 2013, 16:11
Thank you for your answer.
Actually QGLWidget is also used to display some overlay data through QPainter, which can't be achieved through V4L (i think).

Do you think your patches are compliant with Qt4.8 ??

Here is a code sample to reproduce the error.



class GLWidget : public QGLWidget {

Q_OBJECT

public:
GLWidget( );

protected:
void paintGL();
void initializeGL();

private:
void genCross();
QPixmap *crossPixmap;
void drawCross(QPainter *painter);

QGLShaderProgram program;
int matrixUniform;
};

const QPainter::PixmapFragment crossCoord[4] = {
QPainter::PixmapFragment::create(QPointF(300-15-8, 240), QRect(0, 0, 32, 4), 1, 1, 180, 1 ),
QPainter::PixmapFragment::create(QPointF(300+15+8, 240), QRect(0, 0, 32, 4), 1, 1, 0, 1 ),
QPainter::PixmapFragment::create(QPointF(300, 240-15-8), QRect(0, 0, 32, 4), 1, 1, -90, 1 ),
QPainter::PixmapFragment::create(QPointF(300, 240+15+8), QRect(0, 0, 32, 4), 1, 1, 90, 1 )
};
const QPointF pts[5] = {
QPointF(0, 0), QPointF(28, 0), QPointF(32, 2), QPointF(28, 4), QPointF(0, 4)};

GLWidget::GLWidget( )
{
genCross();

this->setAttribute(Qt::WA_AcceptTouchEvents);
this->setAutoBufferSwap(false);
this->setAttribute(Qt::WA_DeleteOnClose);
this->setAutoFillBackground (false);
}


void GLWidget::initializeGL ()
{
QGLShader *vshader = new QGLShader(QGLShader::Vertex);
const char *vsrc =
"attribute highp vec4 vertex;\n"
"attribute highp vec2 texCoord;\n"
"uniform mediump mat4 matrix;\n"
"varying highp vec2 texc;\n"
"void main(void)\n"
"{\n"
" vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n"
" gl_Position = matrix * vertex;\n"
" texc = texCoord;\n"
"}\n";
vshader->compileSourceCode(vsrc);

QGLShader *fshader = new QGLShader(QGLShader::Fragment);
const char *fsrc =
"varying highp vec2 texc;\n"
"uniform sampler2D tex;\n"
"void main(void)\n"
"{\n"
" highp vec3 color = texture2D(tex, texc.st).rgb;\n"
" gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n"
"}\n";
fshader->compileSourceCode(fsrc);

program.addShader(vshader);
program.addShader(fshader);
program.link();

int vertexAttr = program.attributeLocation("vertex");
int texCoordAttr = program.attributeLocation("texCoord");
matrixUniform = program.uniformLocation("matrix");
int textureUniform = program.uniformLocation("tex");

glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
}

void GLWidget::paintGL()
{
QPainter livePainter(this);

livePainter.beginNativePainting();

glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

QMatrix4x4 modelview;
modelview.translate(0, 0, 0);
modelview.scale(1.0,1.0);

program.bind();
program.setUniformValue(matrixUniform, modelview);

//gl stuff
// ...

program.release();

livePainter.endNativePainting();

livePainter.drawPixmapFragments ( crossCoord, 4, *crossPixmap, QPainter::OpaqueHint );

livePainter.end();

swapBuffers();

}

void GLWidget::genCross()
{
crossPixmap = new QPixmap(32, 4);

QPen pen;
pen.setBrush(Qt::black);

QPainter painter(crossPixmap);

painter.setBrush(Qt::yellow);
painter.setPen(pen);
painter.drawPolygon(pts, 5);

painter.end();
}




#include "mainwindow.h"

class MainWindow : public QMainWindow
{
Q_OBJECT
private slots:
void toLog();
void toLive();

public:
MainWindow();

private:
GLWidget *glwidget;
QWidget *iEvent;
};

MainWindow::MainWindow()
{
QWidget *centralWidget = new QWidget();
this->setCentralWidget(centralWidget);

QGridLayout *mainLayout = new QGridLayout();

//Vertical menu
QWidget *verticalMenu = new QWidget(centralWidget);
verticalMenu->setFixedWidth(200);
QVBoxLayout *layout = new QVBoxLayout();
QPushButton *liveButton = new QPushButton("Live", verticalMenu);
layout->addWidget(liveButton);
QPushButton *logButton = new QPushButton("Log", verticalMenu);
layout->addWidget(logButton);
QPushButton *quitButton = new QPushButton("Quit", verticalMenu);
layout->addWidget(quitButton);
verticalMenu->setLayout(layout);
mainLayout->addWidget(verticalMenu, 0, 2);

//Log view
iEvent = new QWidget();
QHBoxLayout *TableLayout = new QHBoxLayout();
QTableView *tableView = new QTableView(this);
QStandardItemModel *model = new QStandardItemModel(0, 4);
model->setHeaderData(0, Qt::Horizontal, QObject::tr("Time"));
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Source"));
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Type"));
model->setHeaderData(3, Qt::Horizontal, QObject::tr("Object"));
tableView->setModel(model);
TableLayout->addWidget(tableView);
mainLayout->addWidget(iEvent, 0, 1);
iEvent->setLayout(TableLayout);

//glWidget
glwidget = new GLWidget();
glwidget->hide();
mainLayout->addWidget(glwidget, 0, 0);

QTimer *mainTimer = new QTimer();
mainTimer->start(5);
QObject::connect(mainTimer, SIGNAL(timeout()), glwidget, SLOT(updateGL()));

centralWidget->setLayout(mainLayout);

// Signals
QObject::connect(logButton, SIGNAL(clicked()), this, SLOT(toLog()));
QObject::connect(liveButton, SIGNAL(clicked()), this, SLOT(toLive()));
QObject::connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
}

void MainWindow::toLog()
{
glwidget->hide();
iEvent->show();
}
void MainWindow::toLive()
{
glwidget->show();
iEvent->hide();
}

wysota
8th March 2013, 19:55
As far as the official line goes, QWS simply doesn't support OpenGL. If you're indeed using QWS then don't use OpenGL. If you need OpenGL, don't use QWS. Best if you just switch to Qt5 with wayland as the compositor. If your hardware supports OpenGLES, it should handle wayland as well.

Uwe
9th March 2013, 09:45
As far as the official line goes, QWS simply doesn't support OpenGL. If you're indeed using QWS then don't use OpenGL. If you need OpenGL, don't use QWS. Best if you just switch to Qt5 with wayland as the compositor. If your hardware supports OpenGLES, it should handle wayland as well.
I'm not sure if this is really the official line - it's more like the current generation of Qt developers doesn't know QWS themself anymore. When I had to deal with these issues ( 4.6, 4.7 days ) the official line was, that QPA is the new thing and QWS won't be touched anymore. But QPA 4.8. was declared as "not worth to be documented yet" - so the situation is quite unsatisfying at the moment. Guess the strategy today is simply waiting for Wayland.

But in fact QWS/OpenGL is not so far from being usable if someone would be interested in fixing it. F.e the wrong stacking order of the subsurfaces is an easy patch. More difficult is the logic that tries to restore parts of the screen from the backing store, that doesn't exits for OpenGL surfaces.

So when you are not willing to patch Qt I would completely agree with Witold: QWS means raster only.

Uwe


As far as the official line goes, QWS simply doesn't support OpenGL. If you're indeed using QWS then don't use OpenGL. If you need OpenGL, don't use QWS. Best if you just switch to Qt5 with wayland as the compositor. If your hardware supports OpenGLES, it should handle wayland as well.
I'm not sure if this is really the official line - it's more like the current generation of Qt developers doesn't know QWS themself anymore. When I had to deal with these issues ( 4.6, 4.7 days ) the official line was, that QPA is the new thing and QWS won't be touched anymore. But QPA 4.8. was declared as "not worth to be documented yet" - so the situation is quite unsatisfying at the moment. Guess the strategy today is simply waiting for Wayland.

But in fact QWS/OpenGL is not so far from being usable if someone would be interested in fixing it. F.e the wrong stacking order of the subsurfaces is an easy patch. More difficult is the logic that tries to restore parts of the screen from the backing store, that doesn't exits for OpenGL surfaces.

So when you are not willing to patch Qt I would completely agree with Witold: QWS means raster only.

Uwe


As far as the official line goes, QWS simply doesn't support OpenGL. If you're indeed using QWS then don't use OpenGL. If you need OpenGL, don't use QWS. Best if you just switch to Qt5 with wayland as the compositor. If your hardware supports OpenGLES, it should handle wayland as well.
I'm not sure if this is really the official line - it's more like the current generation of Qt developers doesn't know QWS themself anymore. When I had to deal with these issues ( 4.6, 4.7 days ) the official line was, that QPA is the new thing and QWS won't be touched anymore. But QPA 4.8. was declared as "not worth to be documented yet" - so the situation is quite unsatisfying at the moment. Guess the strategy today is simply waiting for Wayland.

But in fact QWS/OpenGL is not so far from being usable if someone would be interested in fixing it. F.e the wrong stacking order of the subsurfaces is an easy patch. More difficult is the logic that tries to restore parts of the screen from the backing store, that doesn't exits for OpenGL surfaces.

So when you are not willing to patch Qt I would completely agree with Witold: QWS means raster only.


Actually QGLWidget is also used to display some overlay data through QPainter, which can't be achieved through V4L (i think).
Copying a camera image through QPainter/OpenGL is a complete waste of CPU. This could be done much better by hardware - if it supports stuff like different layers. I strongly recommend to read the specs of your GPU !

Uwe

wysota
9th March 2013, 11:30
I'm not sure if this is really the official line - it's more like the current generation of Qt developers doesn't know QWS themself anymore. When I had to deal with these issues ( 4.6, 4.7 days ) the official line was, that QPA is the new thing and QWS won't be touched anymore. But QPA 4.8. was declared as "not worth to be documented yet" - so the situation is quite unsatisfying at the moment. Guess the strategy today is simply waiting for Wayland.
One of the videos from last DevDays, the one on QPA in Qt5 contains a quote from the developer (AFAIR even with a slide to support that) that QWS doesn't support OpenGL. He also says it is technically possible to combine the two after a lot of struggle but it depends on the hardware and QWS simply isn't prepared for it.