Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Сб апр 20, 2024 05:21

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
 Заголовок сообщения: Wm_paint hell
СообщениеДобавлено: Вс авг 20, 2006 00:24 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
Название темы - перефразировка понятия "dll hell". Это из области .Net, когда обращают внимание на большое количество dll, находящихся в системе, имеющих разные версии, конфликтующих друг с другом и вообще мешающих жить. Разработчики .Net считают, что разобрались с этой проблемой, ну да не о том речь. А речь, собственно, о тех проблемах, которые создает необходимость обработки сообщения wm_paint (прочих тоже, но в гораздо меньшей степени).

Итак, сначала описание проблемы. Допустим, у нас есть окно, и мы хотим там что-то нарисовать. В Форте, разумеется. Надо вводить команды PIXEL CIRCLE LINE RECTANGLE и прочие? Нет, все совсем не так просто. Конечно, нарисовать-то можно, вот только жить этот рисунок будет до первого смещения окна по экрану, перетаскиванию поверх него другого окна и вообще до первой обработки сообщения wm_paint. Это сообщение посылается окну, когда оно должно перерисоваться, и вот тут-то и зарыта собака. Ведь мы никак не модифицировали обработчик wm_paint, и рисунок просто пропал. Кстати, пример с "пропадающим" текстом есть даже в Win32Forth. В справке честно предупреждают, что текст вывести можно, но после перерисовки его в окне уже не будет. Решение проблемы очевидно - надо написать в обработчике порядок действий по рисованию содержимого окна.

Вот тут и начинается собственно hell. Обработчик один, а вариантов содержимого экрана много. Программа вообще развивается, усложняется и живет своей жизнью в процессе разработки. И сидеть программисту в редакторе с открытым обработчиком wm_paint, то есть в самой ответственной части windows-приложения - обработчике сообщений. Там тоже не все просто - надо получить контекст рисования, нарисовать (внутри BeginPaint/EndPaint), освободить контекст. Контекст - это ресурс (а значит, если забудем освободить - имеем утечку ресурсов). Об интерактивной работе тоже не может быть и речи - обработчик нельзя перекомпилировать "на живую". Общий стиль работы соответствует чистому API графической системы Windows - вызов системных функций "вручную". Такой стиль предлагался еще в Borland Pascal 7.0 for Windows и Borland C 3.1 for то же самое. Старый стиль, вобщем. Кстати, в литературе по тем продуктам он рассматривался уже наряду с объектно-ориентированным подходом (OWL). Наконец, на смену пришли визуальные системы, например Delphi. В Delphi программист может ничего не знать о системных сообщениях, потому что в общем и целом надо сделать одно - скопировать некую область с рисунком в окно программы. Существует и специальный компонент - Canvas, представляющий собой массив точек. Программист может поставить на Canvas точку и забыть о ее существовании - обработчик wm_paint возьмет Canvas и скопирует его в окно. Конечно, мелкие рисунки отрисовать вручную было бы гораздо быстрее по сравнению с копированием большой прямоугольной области, зато удобно тем, что можно просто поставить Canvas.Pixels[100,100] = clRed в любой процедуре.

Кстати, вот еще один вариант обработчика wm_paint. :shuffle;

Код:
 
wmpaint:
        invoke  glClear,GL_COLOR_BUFFER_BIT

        mov     eax, 1024
        sub     eax, [ysize]
        shl     eax, 12
        add     eax, screen
        invoke  glDrawPixels, 1024, [ysize], GL_RGBA, GL_UNSIGNED_BYTE, eax

        invoke  SwapBuffers,[hdc]                                             


То есть имеется массив screen, куда можно просто записать что-то в формате RGBA. Отрисовкой занимается само окно, копируя screen на поверхность OpenGL. Собственно, можно было бы и DirectX, и функции GUI, но так уж получилось :)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 01:03 
Хм...

Хищник писал(а):
Итак, сначала описание проблемы. Допустим, у нас есть окно, и мы хотим там что-то нарисовать. В Форте, разумеется. Надо вводить команды PIXEL CIRCLE LINE RECTANGLE и прочие? Нет, все совсем не так просто. Конечно, нарисовать-то можно, вот только жить этот рисунок будет до первого смещения окна по экрану, перетаскиванию поверх него другого окна и вообще до первой обработки сообщения wm_paint.


~profit\prog\browser\layout.f

С самого начала отделил отрисовщик от всех остальных модулей. Самый простой модуль:

Цитата:
Макет — набор команд для окончательной отрисовки на экране для пользователя внешнего вида страницы. Он генерируется во время последнего, окончательного прохода по дереву и является просто массивом блоков. Блок — элементарная команда для рисования страницы, в данной реализации он может быть одного из следующих типов (список можно и надо расширить):
Отрывок. Отрывок текста (как правило, слово), отображаемый на экране.
Иллюстрация. Рисунок, показываемый внутри текущей строки.
Рамка. Этот тип используется на данный момент, в основном, для отладки, хотя его можно доработать, чтобы он отображал фоновый цвет тэгов.
Смена цвета. Блок-команда на изменение текущего цвета рисования. Этот блок не является отображением рисуемого объекта и сам напрямую не рисует, но изменяет состояние просмотрщика и оказывает влияние на блоки, идущие за ним в массиве.
Смена шрифта. Блок-команда на изменение текущего шрифта.

Чтобы показать страницу нужно:
Определить видимые блоки (пока цикл проводится по всем блокам в макете).
Нарисовать каждый видимый блок, сделав необходимые поправки координат с учётом сдвига видимой области относительно начала макета.


Хищник писал(а):
Вот тут и начинается собственно hell. Обработчик один, а вариантов содержимого экрана много. Программа вообще развивается, усложняется и живет своей жизнью в процессе разработки.

Изначально у меня был только блок "Отрезок". Потом добавлял "Рисунок", "Рамка" и остальных.

Были некоторые проблемы с прокруткой, когда макет "мелькал", но кажется проблему заборол (не помно точно, надо свериться с дневником разработки).


Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 01:13 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
profiT писал(а):
С самого начала отделил отрисовщик от всех остальных модулей. Самый простой модуль:


Напоминаю, что речь идет о постоянной работе с графикой. Отрисовка в браузере - это не постоянная работа. Это пишется при разработке самого браузера. А вот попытаться сделать на таких принципах графический редактор уже не получится.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 01:18 
Цитата:
А вот попытаться сделать на таких принципах графический редактор уже не получится.

Если графический редактор -- векторный, то получится. Но да, согласен. Хотя я тут не в теме, по ощущениям говорю...


Последний раз редактировалось profiT Вс авг 20, 2006 01:20, всего редактировалось 1 раз.

Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 01:20 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
profiT писал(а):
Если графический редактор -- векторный, то получится. Но да, согласен.


Да, когда объектов станет много, проще будет просто копировать попиксельно. Что, собственно, и предлагается.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 01:28 
Цитата:
Да, когда объектов станет много, проще будет просто копировать попиксельно.

Смотря какое событие... Насколько я что-то понимаю, кол-во обсчитываемых объектов всегда уменьшается к необходимому минимуму (как и в 3d, есть алгоритмы скрытых фигур).

WM_PAINT передаёт как-то (не помню) ту область которую и надо обновлять, необязательно это всё окно (экран). Можно считать только её.

Но да, без двойной буферизации -- никуда. То есть можно теоретически, но как на практике -- не в курсе...


Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 01:45 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
profiT писал(а):
Смотря какое событие... Насколько я что-то понимаю, кол-во обсчитываемых объектов всегда уменьшается к необходимому минимуму (как и в 3d, есть алгоритмы скрытых фигур).


Вот это и есть hell :) Хорошо, когда мы пишем программу, которая будет выводить что-то при своей работе, тут можно обратить внимание на разные аспекты. А мне вот постоянно надо рисовать графики, причем как в 2D, так и в 3D. И я совершенно не хочу каждый раз лезть в wm_paint и что-то там править, с риском развалить вообще все приложение. Кроме того, интерактивный режим. И это не просто так, это, к примеру, когда после недельного расчета требуется наглядно представить полученные данные и по итогам либо продолжать, либо прекратить. И что, сохранять вообще все данные, выходить, писать программу просмотра графика, запускать, подгружать данные...? По сравнению с ДОСовскими трансляторами - ужасно неудобно.

profiT писал(а):
WM_PAINT передаёт как-то (не помню) ту область которую и надо обновлять, необязательно это всё окно (экран). Можно считать только её.


Очень редко. Восстановление из минимизированного состояния, перемещение по экрану, выход на передний план после того, как окно было полностью закрыто - это все требует полной отрисовки. Оптимизация по частичной отрисовке годится разве что для ситуаций, когда при каждом wm_paint происходит рендеринг всей сцены. А это уже трехмерные пакеты, и вообще непонятно, почему тот же Matlab не рендерит в буфер трехмерные графики. Вобщем, тут экономия копеечная, потому что я даже при постоянных пересылках по 4 Мб в буфер вообще не замечаю никаких тормозов.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 14:22 
Не в сети

Зарегистрирован: Чт май 04, 2006 18:18
Сообщения: 456
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Если работать только с Win32 GDI, то есть ещё один подход. Можно создать Device Context в памяти и при интерактивном рисовании - рисовать в него. А в WM_PAINT просто сделать копирование из memdc в dc на экран. Смотрите например в ~ygrek/prog/ulam/ulam.f слова CreateMemDC, ClearMemDC и заметьте что всё рисование (в частности pixel) делается с хэндлом memdc. А настоящеее рисование происходит в
Код:
PROC: paint
done @ 0= IF EXIT THEN \ если ещё недосчитали то не будем обгрызки выводить
W: srccopy 0 0 memDC maxY maxX 0 0 hDC BitBlt DROP \ из памяти на экран
PROC;

_________________
http://forth.org.ru/~ygrek


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 19:12 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
yGREK писал(а):
Если работать только с Win32 GDI, то есть ещё один подход. Можно создать Device Context в памяти и при интерактивном рисовании - рисовать в него. А в WM_PAINT просто сделать копирование из memdc в dc на экран.


Можно назвать по меньшей мере три подхода, в зависимости от используемой графической библиотеки. Это вывод средствами GDI, через DirectX, или через OpenGL. Промежуточный буфер в памяти присутствует во всех случаях. Вопрос только в том, что GDI довольно медленная вещь, а DirectX (точнее, DirectDraw) - довольно навороченная, сложнее в использовании и ориентирована в основном на игровую графику. С OpenGL работать гораздо приятнее, и качество трехмерной графики будет повыше.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс авг 20, 2006 23:46 
Не в сети

Зарегистрирован: Чт май 04, 2006 18:18
Сообщения: 456
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Хищник писал(а):
Вопрос только в том, что GDI довольно медленная вещь,
...
С OpenGL работать гораздо приятнее, и качество трехмерной графики будет повыше.

Если рисовать OGL по WM_PAINT, то большой скорости всё равно не получить. Вариант - рисовать без WM_PAINT и в отдельном потоке.

_________________
http://forth.org.ru/~ygrek


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн авг 21, 2006 00:03 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
yGREK писал(а):
Если рисовать OGL по WM_PAINT, то большой скорости всё равно не получить. Вариант - рисовать без WM_PAINT и в отдельном потоке.


Стоп-стоп! О чем речь-то? Пока никто в OGL вообще не лезет - есть же массив screen. Это еще одна прослойка по отношению к буферам OGL. Вопрос только в том, что отрисовка поверхности сводится к копированию из обычного массива в память, отвечающую за экранный буфер. Тут уж извините, быстрее просто не получится, точки-то надо проставить так или иначе. Разумеется, в процессе отрисовки никакого обновления экрана не происходит. В OGL скрипт рисования все равно обрамляется вызовами BeginPaint / EndPaint, поэтому лишних операций с экранной памятью тоже нет. Ну и наконец, я сравниваю вывод текста через OpenGL с выводом текста в консоль Win32Forth (средствами GDI, очевидно). "Почувствуйте разницу" - отрисовку экрана у себя я просто не замечаю, а в Win32Forth оно еле-еле ползет (и это на GF6600!).


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 34


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB