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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Оптимизации рендеринга QGraphicsView на разных платформах  (Прочитано 6145 раз)
Pritcher
Гость
« : Май 05, 2015, 18:46 »

Привет!
Я разрабатываю пиксельный графический редактор. Все реализуется с помощью QGraphicsScene & QGraphicsView с вьюпортом QOpenGLWidget. Есть необходимость выделять текущий пиксель (находящийся под курсором). Для этого я в методе QGraphicsView::drawForeground отрисовываю точку методом QPainter::drwaPoint. Помимо этого есть док, в котором отображаются координаты текущего положение курсора. Итого в методе QGraphicsScene::mouseMoveEvent происходит emit сигнала для сообщения о смене положения курсора.
На Linux такое решение поставленной задачи не приносит хлопот, всё отрисовывается так, как и задумывалось. На Windows 7 же без принудительного вызова update() по рабочей области в методе mouseMoveEvent вызов drawForeground не происходит, а => нет отрисовки пикселя. У меня на стационарном ПК стоит старенький Athlon 5000+ 2х2.6 Гц, Win7 и все эти операции занимают у моего проца около 70%. Товарищи смеются, а у меня никаких идей, как можно было бы сократить нагрузку. Может, кто-нибудь предложит что-нибудь конструктивное?
На моём ноуте Linux, i5 4x2.6, жрёт максимум 5%.
У товарища на ноутбуке Win8 i3 4х2.5 — 13,5%.

P.S. Пробовал ставить фиксированный фпс (50-60 апдейтов в секунду), вызывая QGraphicsView::setViewportUpdateMode( QGraphicsView::NoViewportUpdate ), особых изменений не было.
Крутой нагрузки в методе drawForeground нет, лишь проверка на попадание курсора в рабочую область и отрисовка около 100 различных примитивов с помощью QPainter (пиксельная сетка, тайловая сетка, тайловые номера).
При этом опытным путем выяснено, что основная нагрузка именно на update(), вызываемом в mouseMoveEvent.

P.S.S. Изначально курсор был отдельным элементом QGraphicsItem, но от этой идеи пришлось отказаться, т.к. при масштабировании квадратик курсора размером в 1 пиксель имел сторону несколько бОльшую, чем квадратик, отображаемый как пиксель QImage. Таким способом можно было бы отказаться от постоянной перерисовки всей сцены, но проблему с одинаковыми сторонами не решил.
« Последнее редактирование: Май 06, 2015, 20:31 от Pritcher » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #1 : Май 06, 2015, 01:11 »

Пикселы на QGraphicsScene это печально Грустный Надо свою отрисовку через QPainter делать.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Май 06, 2015, 09:29 »

Создать окно (а не просто виджет) наверху и двигать его, тогда этим займется ОС, сцена перерисовываться не будет. Правда это немалые хлопоты с фокусом, но все лучше чем перерисовка (потенциально огромной) сцены (у меня с OpenGL)
Записан
Pritcher
Гость
« Ответ #3 : Май 06, 2015, 10:17 »

Создать окно (а не просто виджет) наверху и двигать его, тогда этим займется ОС, сцена перерисовываться не будет. Правда это немалые хлопоты с фокусом, но все лучше чем перерисовка (потенциально огромной) сцены (у меня с OpenGL)

Идея интересная!
Но вот сама реализация редактора на QGraphicsScene имеет место быть? Или же стоит реализовывать всё на QWidget, с рисованием на QImage (как это сделано, например,  в редакторе EasyPaint)?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Май 06, 2015, 10:33 »

Но вот сама реализация редактора на QGraphicsScene имеет место быть?
Перечитал первый пост. Если юзаете QOpenGLWidget - то можно просто создать обычный виджет (не окно) наверху. Собственно в этом и достоинство QOpenGLWidget - его можно совмещать, комбинировать с другими и/или обычными как угодно, это не вызывает перерисовок всей сцены (в отличие от QGLWidget или QOpenGLWindow). Точнее: рисование будет вызвано, но его можно пропустить, останется старый буфер.

С точки зрения пиксельного редактора - ну хз, я не вижу зачем здесь вообще OpenGL если операции растровые. Ну может как-то "на перспективу"
Записан
Pritcher
Гость
« Ответ #5 : Май 06, 2015, 15:40 »

Перечитал первый пост. Если юзаете QOpenGLWidget - то можно просто создать обычный виджет (не окно) наверху. Собственно в этом и достоинство QOpenGLWidget - его можно совмещать, комбинировать с другими и/или обычными как угодно, это не вызывает перерисовок всей сцены (в отличие от QGLWidget или QOpenGLWindow). Точнее: рисование будет вызвано, но его можно пропустить, останется старый буфер.

С точки зрения пиксельного редактора - ну хз, я не вижу зачем здесь вообще OpenGL если операции растровые. Ну может как-то "на перспективу"

Хм, дельное замечание по поводу QOpenGLWidget. Я его применял по причине того, что рендеринг был быстрее, без него текущий пиксель не всегда успевал за курсором. Но это было на ранней стадии разработки, когда не было никаких оптимизаций и было немалое количество неверных решений. Сейчас же убрал этот вьюпорт, собрал с -O3 и загруженность процессора упала. Хоть и грузит всё ядро на моём проце, но уже одно и довольно терпимо в целом. Пиксель под курсором раньше был больше размером потому, что QRectF размером 1х1 в Qt почему-то больше, чем точка, рисуемая QPainter::drawPoint.

Спасибо за совет.
Записан
Pritcher
Гость
« Ответ #6 : Май 06, 2015, 19:25 »

Ну что ж, вроде, смог снизить нагрузку на моём проце до 25% в самых "тяжелых" моментах.
Создал таймер с интервалом в 16 мсек, добавил в mousePressEvent:

Код
C
if ( _mouseTimer.remainingTime() )
   return;
_mouseTimer.start();
« Последнее редактирование: Май 06, 2015, 19:26 от Pritcher » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Май 07, 2015, 07:02 »

Ну что ж, вроде, смог снизить нагрузку на моём проце до 25% в самых "тяжелых" моментах.
Что-то "не то", все равно слишком много. Неясно Вы используете QOpenGLWidget или уже от него отказались. Если используете - поставьте печать на каждое его paintGL, увидите много интересного
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #8 : Май 07, 2015, 09:10 »

какая версия Qt у вас? Если 5я, то нет смысла заморачиваться с QGLWidget. Если 4я то тут я не помощник, хотя у меня сложные сцены рисовались побыстрее чем у вас в любом случае.
Попробуйте поиграться с параметрами кеширования сцены.
Записан
Pritcher
Гость
« Ответ #9 : Май 09, 2015, 09:15 »

]Что-то "не то", все равно слишком много. Неясно Вы используете QOpenGLWidget или уже от него отказались. Если используете - поставьте печать на каждое его paintGL, увидите много интересного

Что вы имеете в виду под "печатью"?

Отказался.
Дело в том, что у меня процессор в аналогичном редакторе выдаёт ровно такие же цифры в нагрузке, поэтому меня устраивает такая производительность. Протестировал на более современных системах, более 8% не выдаёт.

Когда делаю вьюпорт QOpenGLWidget, то нагрузка в любой момент, когда активно окно приложения, 70%.

Вот собственно мои действия, что привели к уменьшению нагрузки:
1) Оставил родной вьюпорт для QGraphicsView
2) Добавил таймер


какая версия Qt у вас? Если 5я, то нет смысла заморачиваться с QGLWidget. Если 4я то тут я не помощник, хотя у меня сложные сцены рисовались побыстрее чем у вас в любом случае.
Попробуйте поиграться с параметрами кеширования сцены.
У меня Qt 5-ой версии, иначе я не смог бы использовать QOpenGLWidget.
Спасибо за совет, попробую на досуге.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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