Изначально проблема возникла при попытке в реальном режиме времени параллельно с проигрыванием звука из *.wav файла прокручивать по экрану соответствующий ему график. При этом есть два момента. Во-первых, для выигрыша в скорости при прокрутке уже построенный график просто смещался на канве простым копированием (например функцией CopyRect), а достраивались только новые точки. Во-вторых, операции непосредственного копирования на экран синхронизировались с разверткой монитора средствами DirectX. Для обкатки на практике такого способа быстрого вывода графики был создан дополнительный проект, который условно можно назвать «Осцилографом». С помощью генератора псевдослучайных чисел генерируется новые точки, которые в реальном режиме времени выводятся на экран. Таким образом, график все время смещается вправо. Основная идея, как уже упоминалось выше – уже построенный график просто копируется вправо на канве, а на новое место слева достраивается новая точка. И т.д. Если такую операцию выполнять без синхронизации с разверткой монитора, то изображение будет дергаться, смыкаться и т.д. Основная причина – если обновление графика при копировании происходит, когда «луч» монитора находится на нем, то часть графика выше луча еще не будет сдвинута, а часть ниже луча – будет. Возникает эффект смещения, который визуально выливается в нехорошие вещи. В моем вспомогательном проекте синхронизация с разверткой монитора выполнена на DirectX. При этом должен отметить, что стандартная для таких целей функция WaitForVerticalBlank не использовалась, так как забирает практически 100 процентов времени процессора (не известно на что!). Синхронизация выполнена с помощью функции GetScanLine – более подробно можете посмотреть внизу, я выложу код. Основная идея такая. Есть две буферные поверхности (как я их назвал – активная и пассивная) и одна первичная. Есть два потока. Один поток осуществляет блиттинг с активной поверхности на первичную, а также блиттинг со смещением с активной поверхности на пассивную. Второй поток просто достраивает на пассивную поверхность новую точку. Эти операции длятся на протяжении одного кадра. Потом активная поверхность меняется местами с пассивной и т.д. Блиттинг осуществляется не всей поверхности сразу, а отслеживает в цикле положение луча и блиттится полосками над лучем. Это сложно объяснить словами, кому интересно – лучше в коде посмотрите. Приведенный ниже код является полностью рабочим и удовлетворяет всем требованиям, которые выдвигались вначале разработки. НО С ОДНИМ НО (в котором, собственно, и заключается проблема и из-за которого я и пишу данный пост). График движется абсолютно нормально, без дерганий и мерцаний, четко виден и т.п. на трубчатых мониторах. При этом желательно конечно, чтобы компьютер был довольно мощным (процессор от 2 ГГц), либо же не раскрывайте окно на весь экран. Проблема возникает на жидко-кристаллических мониторах. График как и раньше не дергается, но при этом линии графика при смещении выглядят размытыми. При чем чем больше смещение на одну точку, тем более размытыми выглядят линии графика. В этом Вы сможете убедиться самостоятельно, так как в программе предусмотрена опция изменения величины смещения. Я акцентирую внимание: при прочих равных условиях (тот же самый компьютер, та же самая программа, то же разрешение монитора и частота обновления) на трубчатом мониторе все класно, а на TFT график выглядит размытым. В чем может быть причина такого эффекта? На сколько я понимаю, ТФТ монитор иначе, чем трубчатый, обновляет свой экран. Я, конечно же, понимаю, что такое понятие, как «луч» в случае жидко кристаллических мониторов вырождается, но тем не менее в документации к DirectX я не встречал упоминаний, что данная функция относится лишь к какому то виду мониторов или что этот код надо писать так-то для таких мониторов, и так-то для таких. У меня возникает куча вопросов по тому, как именно ТФТ монитор обновляет свой экран. Я искал какую-нибудь литературу на эту тему как в книжках, так и в Инете, но ничего не нашел. Может кто-нибудь что-нибудь встречал, киньте пожалуйста линк или отошлите мне на почту volkovych(собака)gmail.com. Например, ТФТ обновляет экран строчка за строчкой сверху вниз или же по мере поступления данных и необходимости обновить ту или иную часть экрана? Он обновляет экран со стабильной частотой и весь, или же по мере поступления данных и только те части, которые изменились? Он изменяет в данный момент лишь какой-то один кусок данных, или же может обновлять сразу две области? Ответы на эти вопросы дали бы пищу для дальнейших рассуждений. И еще. Мерцание на ТФТ-мониторах, про которое я писал, наблюдается как при DVI, так и при VGA-подключении. Кстати, я слышал, что вроде бы DVI имеет свою собственную синхронизацию, кто-нибудь встречал инфу на эту тему? Исполняемый файл можно закачать здесь (489 кБ): http://rapidshare.de/files/28504278/Project1.exe.html Вот код: Заголовочный файл Файл реализации Буду благодарен за любую помощь! ПС. В случае необходимости могу выложить и весь билдеровский проект.
Если тебе нужно оптимизировать только прокрутку - DirectDraw имхо бессмысленно использовать (по крайней мере до 10 версии), уж слишком большие издержки на COM вызовы. Используй функции ScrollDC, GdiSetBatchLimit (10), и GdiFlush по таймеру 20мс - у тебя все должно гладко прокручиваться, даже на первом пне (при относительно небольших размерах растра).
alpet При использовании ScrollDC присутсвует эффект смещения - копирование канвы просто не успевает осуществиться за время одного кадра. Про другие функции, которые ты назвал, я ничего не слышал, буду благодарен за коментарии. Речь идет о прокрутке на весь экран.
WishMaster Кстати у меня прокрутка с использованием ScrollDC - никаких тобой описанных эффектов, при нормальных драйверах видеокартах не вызывала. Разве что на слабых компьютерах достичь 5 FPS для полноэкранного разрешения было уже здорово, впрочем и на современных - 25 особо достичь не удастся, все-таки GDI. Видимо кадр (1/100-1/60 сек), полноэкранное изменение блиттингом не провести (если карта недорогая) - нужно переключение (Flip) поверхностей (в этих случаях синхронизация имеет смысл). Описанные функции используются для накопления вызовов GDI в "юзермодном" буфере, как правило более примитивных (Line/Poly*/Rect*), и выполненния их за раз, по вызову GdiFlush. Если у тебя используются хотя бы две функции блиттинга - использование пакетирования может быть оправданно - лишние вызовы ядра не будут выполняться. На использование в DirectX они по идее влиять не должны. Процессор у тебя грузится на 100%, из-за того что пауза между двумя кадрами, обычно меньше кванта выделяемого потоку в среднем. По этому поток планируется постоянно - система считает что ты хочешь рисовать анимацию со скоростью 60 кадров сек (вернее с частотой обновления дисплея). Так-что актуально оставить и Sleep, а синхронизацию вызывать непосредственно перед переключением поверхностей. Не имеет смысла особого указывать паузу < 20 мс, для анимации нормальная пауза между вызовами составляет 35ms, за вычетом время требуемого на отрисовку (обычно 2-14мс). При этом частота выделения квантов потоку может составить 20-30 раз/сек (в WinXP во всяком случае), вобщем тут можно в принципе поэксперементировать (см. прогу в аттаче).
alpet Ну программу специально ж для вас переводил на русский, а это упустил Интерфейс же на родном пишу Спасибо, я подумаю над написаным.
Как 25 FPS? Речь идет о выводе нового кадра для каждого нового кадра монитора, то есть FPS должно быть равно частоте монитора. Во всех других случая наблюдается либо мерцание (если через кадр выводить), либо упомянутый эффект смещения. Относительно переключения поверхностей, то у меня оконное приложение с объектом отсечения. Flip в таких случаях не работает. Спасибо за функции, почитаю, я про них не слышал до этого, но действительно в других случаях могут оказаться полезными. Что же касается блиттинга, то он у меня весь на DirectX. Что ты имеешь ввиду, что они не повлияют на Директ? У меня процессор не грузится на 100%, я писал, что в случае использования функции WaitForVerticalBlank она так грузится. У меня же все норм. Эту фразу не уловил. Как это система может что-то так считать? У меня Слип есть, без него никак, а вот относительно "вызывать синхронизацию", то я ничего не вызываю, а сам отслеживаю, когда луч доходит до конца экрана. Не в этом проблема. Синхронизация как раз у меня работает зашибись. Проблема в том, что на ТФТ мониторах линии графика выглядят размыто. Я уже начал понимать в чем дело. Дело в банальной вещи, про которую я сначала забыл - времени отклика. Сейчас ковыряюсь в этом направлении... посмотрим! Гм, ну тогда ни про какое рисование каждого кадра не может быть и разговора. А что прога делает? Я запустил, она что-то выводит, а что - не пойму
У TFT экранов время закрывания ячейки (гашения пиксела) значительно (в 2-3 раза) больше времени открывания. Соответственно когда рядом светятся уже зажёгшийся новый и недопогасший старый, то эффект размазывания и програмно он не лечится. ИМХО чем древнее (или левее ) экран, тем дольше гаснут пиксели. На первых поколениях был вообще кошмар! Хотя интересно попробовать программно выровнять задержку включения и гашения, т.е. сначала гасить, а рисовать новые с паузой, тогда по идее будет эффект плавного перетекания и размазывание должно уменьшиться, но скорее всего придётся привязывать задержку к конкретному экрану, да и многозадачность внесёт свои глюки.