Russian Qt Forum
Октябрь 22, 2019, 18:12 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: (возможная) Заморочка с swapBuffers  (Прочитано 881 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10589


Просмотр профиля
« : Июнь 15, 2019, 17:14 »

Добрый день

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

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

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

Спасибо

Записан
ssoft
Бывалый
*****
Offline Offline

Сообщений: 450


Просмотр профиля
« Ответ #1 : Июнь 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() достаточно.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10589


Просмотр профиля
« Ответ #2 : Июнь 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 обновляет экран
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2068



Просмотр профиля
« Ответ #3 : Июнь 17, 2019, 22:14 »

Что если попробовать поиграть с QSurfaceFormat::SwapBehavior. Задать свой формат через QOpenGLWidget::setFormat.

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

Правда, не знаю, что там будет происходить с буферами под капотом при таком подходе.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10589


Просмотр профиля
« Ответ #4 : Июнь 18, 2019, 07:35 »

Правда, не знаю, что там будет происходить с буферами под капотом при таком подходе.
Да ничего хорошего  Улыбающийся, буфера лучше не трогать

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

Когда же возникает это exposeEvent - не разобрался. Ну ясно при show/hide, но не только. У меня оно приходит когда создается др окно, совершенно постороннее но с translucentBackground
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.089 секунд. Запросов: 22.