Russian Qt Forum

Qt => OpenGL => Тема начата: Igors от Июнь 15, 2019, 17:14



Название: (возможная) Заморочка с swapBuffers
Отправлено: Igors от Июнь 15, 2019, 17:14
Добрый день

Мерзкий баг, возникает на машине заказчика (но не на моей). Поэтому возможно изложенное ниже - лишь мои домыслы. Ну как есть

Есть QOpenGLWindow которое рисуется стандартнo (paintGL и.т.п). Но есть необходимость "пропустить" (дорогостоящее) рисование. Ну ладно, проверяю "есть ли данные для перерисовки", и, если нет, то просто выхожу из paintGL return'ом. И вот похоже так делать нельзя, т.к. после paintGL автоматом Qt вызывает swapBuffers. При этом на экран выводится содержимое того буфера что я (гордо) отказался рисовать. А оно, в общем случае "не определено". Собсно на стороне заказчика так и происходит - то покажет предыдущий кадр, то вообще зальет окно красным.

Пока не могу придумать как этого избежать. paintGL (в конечном итоге) вмонтировано в exposeEvent, это событие фильтровать никак нельзя. Поизучал исходники по стеку вызовов, как-то пресечь нежелательный вызов swapBuffers - такой возможности не видно. Откуда берется exposeEvent - хз, по крайней мере в одном случае когда я создаю совсем др окно. Как-то искуственно создать данные для перерисовки - как минимум сложно, скорее нереально. Что посоветуете?

Спасибо



Название: Re: (возможная) Заморочка с swapBuffers
Отправлено: ssoft от Июнь 17, 2019, 07:55
Может можно переопределить базовый метод?

virtual void paintEvent(QPaintEvent *event) override

Метод базового класса, который ни о каком OpenGL ничего не знает.

Я когда-то тоже прореживал рисование кадров, но делал это по-другому.
Методы paint вызываются по событию QPaintEvent, которое генерируется по update(), repaint().
Чтобы рисовать не чаще чем 1 кадр/N миллисекунд использовал таймер.

Код
C++ (Qt)
void updateGL ()
{
   if ( !redraw_timer.isActive() )
       redraw_timer.start();
}
void updateByTimer ()
{
   update();
}
 

Сейчас уже не заморачиваюсь. Встроенного прореживания в update() достаточно.


Название: Re: (возможная) Заморочка с swapBuffers
Отправлено: Igors от Июнь 17, 2019, 10:04
Может можно переопределить базовый метод?

virtual void paintEvent(QPaintEvent *event) override

Метод базового класса, который ни о каком OpenGL ничего не знает.
Проверял, не конает. Вот метод doFlush который вызывается как из exposeEvent так и из UpdateRequest
Код
C++ (Qt)
// qpaintdevivewindow_p.h
 
bool paint(const QRegion &region)
{
Q_Q(QPaintDeviceWindow);
QRegion toPaint = region & dirtyRegion;
if (toPaint.isEmpty())
return false;
 
// Clear the region now. The overridden functions may call update().
dirtyRegion -= toPaint;
 
beginPaint(toPaint);
 
QPaintEvent paintEvent(toPaint);
q->paintEvent(&paintEvent);
 
endPaint();
 
return true;
}
 
void doFlush(const QRegion &region)
{
QRegion toFlush = region;
if (paint(toFlush))
flush(toFlush);
}
 
paint упорно возвращает true и flush обновляет экран


Название: Re: (возможная) Заморочка с swapBuffers
Отправлено: __Heaven__ от Июнь 17, 2019, 22:14
Что если попробовать поиграть с QSurfaceFormat::SwapBehavior. Задать свой формат через QOpenGLWidget::setFormat.

Возможно проявляется из-за:
QSurfaceFormat::DefaultSwapBehavior The default, unspecified swap behaviour of the platform

Правда, не знаю, что там будет происходить с буферами под капотом при таком подходе.


Название: Re: (возможная) Заморочка с swapBuffers
Отправлено: Igors от Июнь 18, 2019, 07:35
Правда, не знаю, что там будет происходить с буферами под капотом при таком подходе.
Да ничего хорошего  :), буфера лучше не трогать

В общем порешал перекрыв exposeEvent для моего класса порожденного от QOpenGLWindow (игнорировать это событие если нет данных рисования). Не уверен что это правильно, но другого не видно. По ходу дела еще одна мелкая проблемка вылезла - show показывает окно сразу, только потом я заряжаю свои данные и вызываю update. Поэтому сначала видно "старое" изображение (что было до закрытия окна). Решается в том же exposeEvent.

Когда же возникает это exposeEvent - не разобрался. Ну ясно при show/hide, но не только. У меня оно приходит когда создается др окно, совершенно постороннее но с translucentBackground