![]() |
|
![]() ![]() ![]() |
|
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
есть такой код.
возможно ли рисовать несколькими потоками в одном CDC? |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Не стоит. MFC-объекты вообще к конкретному потоку относятся.
Кроме того, Draw обычно происходит в результате обработки сообщения OnPaint (и делать иначе редко когда рекомендуется). А WM_PAINT всегда обрабатывается в том потоке которому принадлежит окно. Короче, никакого смысла в многопоточном рисовании нет. -------------------- ... |
|||
|
||||
mrgloom |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
попробовал так.
error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject' видимо все дело в CDC ну а если я хочу рисовать быстрее, то как этого добиться? Это сообщение отредактировал(а) mrgloom - 23.8.2011, 16:53 |
||||
|
|||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
CObject не имеет конструктора копирования. Точнее, имеет, но закрытый - т.е. это концептуально не копируемый объект. Равно как и CDC и почти все MFC-объекты. Однако никто не мешает передавать dc по ссылке, а сейчас у тебя действительно копирование.
И вообще, судя по коду, ты слабо себе представляешь механизм передачи параметров. И с чего ты вообще взял, что в потоках рисование будет быстрее? Если проблема тормозов на рисовании возникает, она наверняка в организации твоего кода - всяких глупостях типа передачи массива в функцию по значению, а также в функции Draw: выделение буфера под 2 точки динамически, да еще в цикле для каждой линии - это просто шедевр. Ты бы азы подучил, прежде чем в буст и потоки лезть... Ты уж не обижайся, но это какой-то кошмар, твой код... -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
так лучше?
вроде бы еще говорили, что лучше рисовать через PolyPolyLine ну тогда надо знать, что из точек собрана связанная последовательная фигура. наблюдая за тем, что загружено только 1 ядро. наверно надо сделать, отдельный поток на рисование, и отдельный на все остальное. |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
хотя нет так как я написал выше не получится.
т.к. получаются лишние связи. а мне надо вывести все независимыми линиями. boost_draw(CDC* dc, vector<Line>& vec) tg.create_thread(boost::bind(&boost_draw, &dc,vec[idx])); так действительно работает, но быстрее (по ощущениям) вроде и не стало. |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Вообще не нужно тут динамическое выделение памяти, под 2-то точки. Можно стековой переменной обойтись. Далее, я не знаю, что за объекты хранятся в temp_lines, но если это просто точки (пара точек), то можно вообще обойтись без копирования, а использовать просто указатель на первую точку (если, конечно, в памяти они образуют массив). Если точек 2, то лучше использовать пару функций MoveTo\LineTo вместо Polyline. PolyPolyline тоже можно использовать, но нужно заранее подготовить данные. Ты же уже знаешь, что точки попарно связаны, этого достаточно. PolyPolyline прекрасно рисует многосвязные фигуры. Кстати, это значительно ускорит рисование (подготовка массива точек и длин + один вызов PolyPolyline) , если линий действительно много. Дело в том, что вызовы функций GDI довольно дорого обходятся.
Но это вовсе не означает, что рисовать нужно в нескольких потоках;рисуй себе в главном (там, где окна живут), а считай в отдельном рабочем. -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
хмм оказалось, что даже автокад как то странно работает с потоками.(т.е. не использует все ядра)
а если все выводить в картинку\текстуру, то это будет как бы "рендеринг", и это уже можно делать в несколько потоков?(или глупая идея) у меня была структура структур(прямоугольников и более сложных примитивов) которую я распарсил в линии и построил quadtree счет идет на милионы линий. вот теперь думаю, что не очень, то это была хорошая идея, лучше было оставить структурами, но в таком случае не очень понятно как создавать quadtree. |
|||
|
||||
Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Ну сам подумай, доступ к растру придется как-то делить - нельзя же позволять нескольким потокам писать в одну область памяти одновременно. А эта синхронизация может сожрать весь выигрыш... А делить пространство, типа первый поток рисует только в первую треть, второй - во вторую и т.д. - тоже неудобно - линии-то где угодно заканчиваются. Миллионы линий - это серьезно, здесь действительно нужно оптимизировать вывод. Навскидку, могу предложить след. варианты. 1) Если линии относительно постоянны, то можно один раз нарисовать их во внеэкранный буфер, а затем быстро бросать на экран по мере надобности (когда WM_PAINT приходят). Внеэкранный буфер обновлять по мере необходимости. Причем, чтобы не тормозило, делать это можно и в отдельном потоке, только организовать так, чтобы блокировка не сразу на весь вывод действовала, а как-то разбить (чтобы можно было частично нарисованные линии вывести на экран). 2) Можно попробовать выводить линии в несколько потоков, но в несколько отдельных растров (разные линии, разумеется), а потом эти растры быстренько объединить подходящей битовой операцией (ИЛИ, например, если фон черный). Но памяти, конечно, отожрется много... Автокад использует какую-то интересную схему кэширования чертежа: обновления, которые время от времени происходят, длятся довольно долго, но зато потом, между ними отрисовка такая быстрая, что больше напоминает выброс растра на экран... но тем не менее это дело масштабируется (так же быстро) в довольно широких пределах... вряд ли растр... Сама бы хотела знать, как они это делают...
Не надо путать структуры индексирования со структурами хранения... Никто ведь не мешает хранить структуры, а дерево строить для линий, используя какую-то ссылочную схему - т.е. линия представляется не как 2 точки, а как ссылка на i-е ребро структуры N. -------------------- ... |
||||
|
|||||
mrgloom |
|
||||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
определить какие линии куда попадают я смогу с помощью quadtree, только вместо выполнения поиска для 1 области, у меня получится несколько таких операций. ну если линии такие большие, что попадают в несколько кусков, то будут рисоваться по несколько раз.(тут только добавляется одна операция отсечения ненужной части.) самый плохой вариант, это когда все линии попадают во все куски, т.е. рисуется такой "забор". только не понятно как это реализовать\рисовать ибо я рисую через Polyline и у нее есть параметр CDC и всё, т.е. непонятно как образно выражаясь взять n кусков памяти под потоки транслировать туда линии, а потом склеить всё в 1 кусок памяти и вывести этот кусок на экран.
что значит линии постоянны? их число постоянное, но вот для того чтобы их например сместить на экране, я к каждой точке прибавляю смещение(возможно это неправильный подход) и делаю это прямо в draw() и чтобы изменить масштаб соответственно тоже самое. т.е. у меня есть init_lines где хранятся неизменяемые линии, которые я считал, а temp_lines это те которые я вывожу при каждом draw()
что такое внеэкранный буфер в терминах GDI? (еще нашел такое http://www.rsdn.ru/forum/winapi/2246791.flat.aspx) что такое растр в терминах GDI?
ну да идея ясна, работаем как с линиями, а когда выводить выводим как структуры по несколько точек,если структура попадает не полностью выводим как линии. я изначально сделал все для линий, чтобы было проще. по идее даже можно у любой структуры описать её BoundingRect и работать с ней целиком. и еще уточнение я вывожу сначала картинки через dc.StretchBlt , а потом накладываю линии через PolyLine, если это важно. и еще я уменьшаю кол-во выводимых линий во-первых отсекая по текущему view по quadtree и если малое увеличение не вывожу маленькие детали, т.е. у меня не просто quadtree, а quadtree+ level of detail. |
||||||||
|
|||||||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Т.е сами линии у тебя не изменяются. Можно поступить, например, так. Завести внеэкранный буфер размером, скажем в 9 текущих экранов (или 4, или... в общем, в зависимости от масштаба - хоть на весь экстент, если размер растра позволит). И нарисовать туда соответствующую часть линий. Выбрасывать на экран соответствующую часть (в зависимости от текущего положения) При скроллинге использовать сдвиг экрана (ScrollDC? это очень быстро) + дорисовывать недостающею часть из буфера. При масштабировании вниз можно тоже не пересчитывать сразу, а использовать StretchBlt/ Пересчитывать буфер начинаем, когда масштаб \ смещение выйдут за пределы Это пара compatible DC + bitmap (обычно compatible, но не обязательно) Растр == битмап, который выбирается в мемори-контекст Отсекать отдельными линиями (ребрами) - очень неэффективно, лучше уж сразу фигуры. Приведу пример из своего приложения. Хранится много графики (в основном полилинии и полигоны, хотя есть и текст и точки и окружности...) В каждой полилинии - до нескольких тысяч точек, полилиний-полигонов иногда сотни тысяч. Т.е., если считать в ребрах, то получаем миллионы линий. Хранится все в даблах, в некоторых логических координатах. Для каждого объекта хранится экстент. Все это добро разделено на слои, как в Автокаде. Есть структура, которая определяет текущее положение и масштаб экрана и, соответственно, преобразование координат. При отрисовке происходит даже не отсечение, а просто проверка на попадание объекта в экран (по экстенту). Затем полилиния пересчитывается в координаты экрана (в целые). Удаляются точки-дубликаты (они возникают при масштабировании-округлении). Рисуем через Polyline или Polygon. Т.е. линейно просматриваются (на предмет экстента) ВСЕ объекты. И притормаживать начинает только при выводе близком к вью-ол, и только если объектов сотни тысяч, и линии длинные (не отсекаются). Внеэкранный буфер имеет размер экрана, без запаса, так проще за ним следить. Т.е. буфер обновляется при любом изменении позиции-масштаба, включении-выключении слоев, изменении объектов и т.д. При рабочем масштабе (т.е. когда на экране можно что-то редактировать) все летает (вместе с подложенным под векторные данные растром). Поэтому никакми дополнительными индексами и потоками не озабачиваюсь. В общем, что хочу сказать... думаю, ты не там ищешь что оптимизировать. Действительно ли тебе нужно квадро-дерево? (Если ты ввел его только для оптимизации вывод, то имхо зря...) Тормоза могут возникать из-за неоптимальных вызово GDI-функций - я уже говорила, они страшно дорогие. Т.е. все эти смены перьев и прочая нужно оптимизировать очень жестко. Толстые линии и линии не солид тоже могут тормозить... -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
про вывод графики понял, его ускорить можно только если использовать что то типа двойного буфера.
у меня получается что перед вывоводом надо из общего кол-ва примитивов выделить те, которые попадают в область+те которые не видны на масштабе, это занимает процессорное время. (если выводить все, то тормозит)
не понял как это? как хранятся примитивы? Это сообщение отредактировал(а) mrgloom - 8.9.2011, 13:56 |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
есть еще идея не строить это квад-дерево(ибо и место занимает и время на построение)
а просто у каждого примитива построить его boundrect (ограничивающий прямоугольник) и проверять пересечение этих прямоугольников с видимым прямоугольником в несколько потоков. Добавлено через 1 минуту и 27 секунд или из этих boundrect примитивов построить R-tree или просто взять сетку с константным шагом. |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Именно их я и называю экстентами. И не надо никакого R-дерева, попробуй сначала быть проще... И несколько потоков тоже не надо... И что ты называешь примитивами? Отдельные отрезки или полные фигуры? Лучше второе - их меньше ![]() На худой конец, используй самый простой пространственный индекс - кластеры постоянного размера (или сетку) - просто поддерживать, просто использовать, а выигрыш дает приличный. Я использую такой индекс в расчетных утилитах, когда нужно искать что-то рядом с чем-то; а для вывода на экран - только проверку экстентов (которые, разумеется, хранятся для каждого объекта). -------------------- ... |
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |