Как в GDI с наименьшими затратами сдвинуть изображение на несколько точек по горизонтали? Пробовал BitBlt/SRCCOPY на месте (в пределах одного контекста), но оно двигает полосами. Без CreateCompatibleDC, CreateCompatibleBitmap и BitBlt туда-сюда никак?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В смысле? Я сам его рисую — это графики в реальном времени.
Ты ж не непосредственно на окне рисуешь, а через промежуточный буфер? Ну просто иначе у тебя будет портиться изображение при движении окна за край экрана.
Если ты создал промежуточный буфер через CreateDIBSection, то у тебя есть доступ к его памяти.
ЕМ>После заполнения окна надо двигать нарисованное влево, рисуя новое справа.
Кстати, а почему не ОпенГЛ?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Ты ж не непосредственно на окне рисуешь, а через промежуточный буфер?
Непосредственно в окне.
TB>иначе у тебя будет портиться изображение при движении окна за край экрана.
Ничего не портится, и не должно.
TB>Кстати, а почему не ОпенГЛ?
Я вообще с графикой почти никогда не работал — в GDI более-менее ориентируюсь, а от OpenGL только название знаю. И мне это пока сугубо для отладки, так что нужен самый простой метод. Но быстрый, иначе рисование (даже в отдельном потоке) тормозит работу основного кода.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Ничего не портится, и не должно.
Эээ, но ведь тебе надо полностью обновлять изображение при некоторых действиях. Если ты этого не делаешь, то будет такой эффект:
Задвинь окно частично за экран, а потом верни обратно. Часть, что была за экраном, заполнится либо фоновым цветом окна (это если ты не заблокировал WM_ERASEBKGND), либо заполнится кашей.
То есть мне кажется, что с промежуточным буфером жизнь намного проще. Насчёт перфоманса тоже есть подозрения, что операции, которые делаются в оперативе, будут намного быстрее, чем операции над пикселями окна.
ЕМ>И мне это пока сугубо для отладки, так что нужен самый простой метод.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>тебе надо полностью обновлять изображение при некоторых действиях.
Так это делает винда, присылая мне при этих действиях WM_PAINT. Мое дело — рисовать график в указанном фрагменте окна.
TB>Если ты этого не делаешь, то будет такой эффект
Он будет, если рисовать как придется. Если как положено — из WM_PAINT, WM_DRAWITEM и т.п., то не будет.
TB>Задвинь окно частично за экран, а потом верни обратно. Часть, что была за экраном, заполнится либо фоновым цветом окна (это если ты не заблокировал WM_ERASEBKGND), либо заполнится кашей.
В таких случаях Window Manager пришлет WM_PAINT для нужной области/областей.
TB>есть подозрения, что операции, которые делаются в оперативе, будут намного быстрее, чем операции над пикселями окна.
Так операции те же самые — один раз прочитать каждую точку, один раз записать ее. Меняются только источник/назначение.
Я вроде подобрал параметры, с которыми BitBlt нормально двигает — у него какие-то проблемы, если в операцию попадает граница окна.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Как в GDI с наименьшими затратами сдвинуть изображение на несколько точек по горизонтали? Пробовал BitBlt/SRCCOPY на месте (в пределах одного контекста), но оно двигает полосами. Без CreateCompatibleDC, CreateCompatibleBitmap и BitBlt туда-сюда никак?
А нафига вы его двигаете. Его надо перерисовывать. Если риует долго разбейте на тайлы и кэшируйте их. Но при WM_PAINT перерисовывайте всё что попадает в запрашиваемую область.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В таких случаях Window Manager пришлет WM_PAINT для нужной области/областей.
Но ведь внутри WM_PAINT ты не знаешь, какие области надо перерисовывать. То есть перерисовываешь всё.
ЕМ>Так операции те же самые — один раз прочитать каждую точку, один раз записать ее. Меняются только источник/назначение.
Есть существенная разница, в каком порядке это делать. BitBlt из памяти на экран — это наверное самая быстрая операция, которая затрагивает все пиксели.
То есть я всё равно не вижу смысла отказываться от промежуточного буфера.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, kov_serg, Вы писали:
_>А нафига вы его двигаете.
Чтоб двигался, а не стоял на месте.
_>Его надо перерисовывать.
Когда надо — перерисовываю. Но это медленно.
_>Если риует долго разбейте на тайлы и кэшируйте их.
Не понял, чем это будет отличаться от сдвига, кроме того, что станет значительно сложнее.
_>при WM_PAINT перерисовывайте всё что попадает в запрашиваемую область.
Здравствуйте, T4r4sB, Вы писали:
TB>внутри WM_PAINT ты не знаешь, какие области надо перерисовывать.
Кто вызывает BeginPaint и получает PAINTSTRUCT, те знают. Кто не вызывает — перерисовывают всё.
TB>BitBlt из памяти на экран — это наверное самая быстрая операция, которая затрагивает все пиксели.
Хм, на досуге сравню, но не вижу причин для разницы в скорости. Это ж не какая-нибудь EGA, где все время нужно переключать плоскости.
Здравствуйте, Евгений Музыченко, Вы писали:
_>>А нафига вы его двигаете. ЕМ>Чтоб двигался, а не стоял на месте.
_>>Его надо перерисовывать. ЕМ>Когда надо — перерисовываю. Но это медленно.
Именно поэтому кешируйте если медленно. А двигать можно просто перерисовывая кэшированные фрагменты.
_>>Если риует долго разбейте на тайлы и кэшируйте их. ЕМ>Не понял, чем это будет отличаться от сдвига, кроме того, что станет значительно сложнее.
Ничего не сложнее просто еще промежуточный класс который этим будет заниматься.
_>>при WM_PAINT перерисовывайте всё что попадает в запрашиваемую область. ЕМ>Само собой.
При этом если вы рисуете тайлами оно само всё клипает.
Здравствуйте, kov_serg, Вы писали:
_>Именно поэтому кешируйте если медленно. А двигать можно просто перерисовывая кэшированные фрагменты.
Ничего не понял. Скорость перерисовки в исключительных случаях (например, когда окно было перекрыто) меня не беспокоит — нужно минимизировать лишь время регулярной отрисовки. Пока графики не заполнили все окно, в каждом вызове WM_PAINT дорисовываются только новые точки. Когда уже заполнил, перед дорисовкой новых точек весь график сдвигается влево. Какая разница, будет он сдвигаться копированием из буфера экрана, или из какого-то дополнительного, "кэшированного", буфера?
_>Ничего не сложнее просто еще промежуточный класс который этим будет заниматься.
"Промежуточный класс" — это не "сложнее"?
_>если вы рисуете тайлами оно само всё клипает.
Оно и так "само все клипает". В упор не вижу разницы.
О, спасибо! Очередное подтверждение тому, что виндовая документация убога — функций ScrollDC, ScrollWindow, ScrollWindowEx нет в общем списке функций GDI, только в разделе Scroll Bars, хотя напрямую оно никак не связано.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Ничего не понял. Скорость перерисовки в исключительных случаях (например, когда окно было перекрыто) меня не беспокоит — нужно минимизировать лишь время регулярной отрисовки. Пока графики не заполнили все окно, в каждом вызове WM_PAINT дорисовываются только новые точки. Когда уже заполнил, перед дорисовкой новых точек весь график сдвигается влево. Какая разница, будет он сдвигаться копированием из буфера экрана, или из какого-то дополнительного, "кэшированного", буфера?
Разница огромная.
_>>Ничего не сложнее просто еще промежуточный класс который этим будет заниматься. ЕМ>"Промежуточный класс" — это не "сложнее"?
Нет каждый класс самодостаточен и не связан с остальными. Добавление промежуточного кэширующего слоя не должно влиять на сложность отрисовки, тот кто рисует вообще ого существовании не догадывается.
_>>если вы рисуете тайлами оно само всё клипает. ЕМ>Оно и так "само все клипает". В упор не вижу разницы.
Графики бывают разные сотни точек и миллионы точек. Подходы будут разные для разных уровней детализации.
Если у вас рисует медленно значит точек много и скорей всего рисуете как есть.
Здравствуйте, kov_serg, Вы писали:
_>Разница огромная.
Это все, что Вы можете сказать по сути заданных вопросов?
_>Добавление промежуточного кэширующего слоя не должно влиять на сложность отрисовки
Даже если этот класс где-то существует в готовом виде, уже заточенный под мои потребности, мне придется, как минимум, ознакомиться с его интерфейсом, привязаться к нему, вставить его в текстовом виде или обеспечить линковку. Если же его не существует, мне придется его спроектировать, написать, отладить, а затем сделать с ним все, перечисленное выше. Если, по-Вашему, это не меняет уровень сложности моего кода, то как Вы определяете для себя понятие "сложность"?
_>Если у вас рисует медленно значит точек много
Еще раз, для тех, кому лень вчитаться в уже написанный текст: рисует быстро, перерисовывает медленно, если для сдвига влево использовать полную перерисовку, которая даже идеологически для этой цели некорректна.
Здравствуйте, Евгений Музыченко, Вы писали:
TB>>внутри WM_PAINT ты не знаешь, какие области надо перерисовывать.
ЕМ>Кто вызывает BeginPaint и получает PAINTSTRUCT, те знают. Кто не вызывает — перерисовывают всё.
Те, кто не вызывает, пользуются GetUpdateRect()
TB>>BitBlt из памяти на экран — это наверное самая быстрая операция, которая затрагивает все пиксели.
ЕМ>Хм, на досуге сравню, но не вижу причин для разницы в скорости. Это ж не какая-нибудь EGA, где все время нужно переключать плоскости.
Разницы в скорости нет, но двойной буфер избавляет от мельтешения на экране, когда таскаешь чужое окошко поверх своего или ресайзишь окно.
_____________________
С уважением,
Stanislav V. Zudin