Во время выполнения программы, приходится вызывать функцию StretchBlt. В среднем, около 100-120 раз в секунду. Задача алгоритма — пропорциональный scaling некоторых изображений с выводом результата на экран (в данном случае — в окно).
Оцените, pls, код. И подскажите, какие есть альтернативы. В StretchBlt не устраивает скорость и "ступенчатость" (по-моему, это называется "ближайший цвет" — отсутствие сглаживания)
HWND iHwnd;
int mCount;
int mCountOfScale;
RECT[] mDestRect;
HDC[] mSrcBitmapDC;
int[] mSrcBitmapWidth;
int[] mSrcBitmapHeight;
float mScale;
case WM_PAINT:
int lWidth = 1024;
int lHeight = 738;
PAINTSTRUCT lPS;
HDC lWindowDC = ::BeginPaint(iHwnd, &lPS);
HDC lBitmapDC = ::CreateCompatibleDC(lWindowDC);
HBITMAP lBitmap = ::CreateCompatibleBitmap(lWindowDC, lWidth, lHeight);
HGDIOBJ lNullBitmap = ::SelectObject(lBitmapDC, lBitmap);
for (int j = 0; j < mCount; j++)
{
::StretchBlt(
lBitmapDC, // dest DC - tempory image
mDestRect[j].left, mDestRect[j].top, // position for drawing
mSrcBitmapWidth[j] * ьScale, // needed width of image
mSrcBitmapHeight[j] * mScale, // needed height of image
mSrcBitmapDC[j], // src DC - image
0, 0, mSrcBitmapWidth[j], mSrcBitmapHeight[j], // size of source image
SRCCOPY);
}
::BitBlt(lWindowDC, 0, 0, lWidth, lHeight, lBitmapDC, 0, 0, SRCCOPY);
::SelectObject(lBitmapDC, lNullBitmap);
::DeleteDC(lBitmapDC);
::DeleteObject(lBitmap);
::EndPaint(iHwnd, &lPS);
break;
Примечания:
все исходные структуры для примера упрощены до массивов
копирование во временный bitmap задумано, как избавление от мерцания. Или я чего-то неправильно делаю?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
07.11.06 13:45: Перенесено модератором из 'WIN API' — Odi$$ey
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
A>Оцените, pls, код. И подскажите, какие есть альтернативы. В StretchBlt не устраивает скорость и "ступенчатость" (по-моему, это называется "ближайший цвет" — отсутствие сглаживания)
SetStretchBltMode — есть такая функция. переключает режим масштабирования, сглаживание в этом списке присутствует под именем HALFTONE (только в линейке NT). тормозит еще сильнее, естественно
в данном случае StretchBlt выполняется в памяти, GDI тут поступает чисто софтово, отсюда тормоза. видеокарта убыстряет растровые операции при переносе видеопамять-видеопамять, и, МОЖЕТ БЫТЬ, оперативка-видеопамять.
а нельзя картинку отрендерить один раз, а потом показывать по WM_PAINT обычным BitBlt?
Все вопросы на nightblade@inbox.ru
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
От:
Аноним
Дата:
07.11.06 10:58
Оценка:
Здравствуйте, spbAngel, Вы писали:
A>Во время выполнения программы, приходится вызывать функцию StretchBlt. В среднем, около 100-120 раз в секунду. Задача алгоритма — пропорциональный scaling некоторых изображений с выводом результата на экран (в данном случае — в окно).
SetStretchBltMode
A зачем 100-120 раз в секунду, если даже для фильма 30 раз вполне достаточно? И каждый раз именно Stretch?
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
Судя по моему предыдущему опыту, подобные критические функции я просто переписывал вручную, что всегда давало серьезный прирост производительности.
Просто для стандартных RGBA использовать свою отрисовку, а для всяких "нестандартных" — _стандартную_.
Учитывая, что отрисовка чисто софтварная, то можно реализовать софтварный мип-маппинг иль еще чего наворотить, но это никому ненужный изврат, зато не будет ступенчатости .
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
Здравствуйте, NightBlade, Вы писали:
A>>Оцените, pls, код. И подскажите, какие есть альтернативы. В StretchBlt не устраивает скорость и "ступенчатость" (по-моему, это называется "ближайший цвет" — отсутствие сглаживания)
NB>SetStretchBltMode — есть такая функция. переключает режим масштабирования, сглаживание в этом списке присутствует под именем HALFTONE (только в линейке NT). тормозит еще сильнее, естественно
Спасибо. Попробую.
NB>в данном случае StretchBlt выполняется в памяти, GDI тут поступает чисто софтово, отсюда тормоза. видеокарта убыстряет растровые операции при переносе видеопамять-видеопамять, и, МОЖЕТ БЫТЬ, оперативка-видеопамять.
Не подскажите, как с этим можно использовать? Как загружать рисунки в видеопамять?
NB>а нельзя картинку отрендерить один раз, а потом показывать по WM_PAINT обычным BitBlt?
К сожалению, нет. Исходные рисунки и конечные положения на рисунке постоянно меняются.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, spbAngel, Вы писали:
A>>Во время выполнения программы, приходится вызывать функцию StretchBlt. В среднем, около 100-120 раз в секунду. Задача алгоритма — пропорциональный scaling некоторых изображений с выводом результата на экран (в данном случае — в окно). А>SetStretchBltMode
А>A зачем 100-120 раз в секунду, если даже для фильма 30 раз вполне достаточно? И каждый раз именно Stretch?
Именно Stretch. Около 20-25 раз в секунду, около 5-10 (до 20) рисунков за раз.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [GDI] Узкое место - StretchBlt. Возможна ли альтернатива
NB>>в данном случае StretchBlt выполняется в памяти, GDI тут поступает чисто софтово, отсюда тормоза. видеокарта убыстряет растровые операции при переносе видеопамять-видеопамять, и, МОЖЕТ БЫТЬ, оперативка-видеопамять.
A>Не подскажите, как с этим можно использовать? Как загружать рисунки в видеопамять?
под видеопамятью в данном случае я подразумевал видеобуфер, т.е. экран, т.е. самая быстрая отрисовка — из одного видимого окна в другое видимое окно (или из одной части окна в другое)
в данном случае это не поможет
для загрузки изображений в память видеокарты (текстур, например) требуется использование DirectX
как более быструю альтернативу могу предложить использовать DirectDraw или группу функций DrawDib
Все вопросы на nightblade@inbox.ru
Re[2]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
. Хотя, по этому поводу, критически высказывались некоторые люди. Имеет ли смысл проверять? И заменить StretchBlt на DrawDibDraw?
Не имеет. Видимый прирост производительности _в_некоторых_ ситуациях обеспечивает только ручное написание блиттера. А обычно gdi даже быстрее.
Теперь, что надо делать вам.
1. Вынести создание совместимого контекста и битмапа за пределы paint — пусть живет всегда (соответственно, пересоздавать при изменении режимов, для чего обрабатывать соотв. сообщение). Попробовать — если производительнсть устроит — отлично. В большинстве нормальных драйверов тут используется аппаратный блиттер, поэтому даже написав функции стретча вручную, сравнимой производительности не достигнуть.
2. Попробовать использовать dib секции вместо совместимого битмапа, либо обычные DIB.
А вообще — 100 фпс при помощи или без gdi — довольно нетривиально. Учитывая, что один экран это по меньшей мере 4 мб данных + затраты на скалинг.. Имхо, без аппаратной поддержки тут не обойтись.
Может, direct3d посмотреть?
Здравствуйте, Andrew S, Вы писали:
AS>Может, direct3d посмотреть?
Спасибо. На днях понял, что это вполне подходящий вариант (Direct3D для отрисовки 2D — не мог привыкнуть) и дописываю уже прототип. За одно и DirectX изучу...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
Здравствуйте, NightBlade, Вы писали:
NB>для загрузки изображений в память видеокарты (текстур, например) требуется использование DirectX
NB>как более быструю альтернативу могу предложить использовать DirectDraw или группу функций DrawDib
Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
Здравствуйте, spbAngel, Вы писали:
A>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.
Direct3D для 2D задачи — вполне нормальное явление. Ибо так можно задействовать мощь аппаратного ускорения современных видеокарт.
Re[5]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
A>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.
DirectX любой версии тащит за собой все предыдущие, для совместимости
Все вопросы на nightblade@inbox.ru
Re[6]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
Здравствуйте, NightBlade, Вы писали:
A>>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.
NB>DirectX любой версии тащит за собой все предыдущие, для совместимости
Думаете, стОит использовать именно DirectDraw? Понимаю, что логичней, но... Не могу сформулировать в вопрос чувства. Как-никак 7-ая версия...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
A>>>Насколько я помню, DirectDraw отсутствует уже в 8-ой версии DirectX. Сейчас пишу прототип на Direct3D. Или я неправ? Просто Direct3D для решения 2D-задачи... Просто непривычно.
NB>>DirectX любой версии тащит за собой все предыдущие, для совместимости
A>Думаете, стОит использовать именно DirectDraw? Понимаю, что логичней, но... Не могу сформулировать в вопрос чувства. Как-никак 7-ая версия...
Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
Здравствуйте, Andrew S, Вы писали:
A>>Думаете, стОит использовать именно DirectDraw? Понимаю, что логичней, но... Не могу сформулировать в вопрос чувства. Как-никак 7-ая версия...
AS>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
Благодарю. Выполненные тесты и мнение опытного разработчика — то что было надо. Буду копать в сторону Direct3D
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: [GDI] Узкое место - StretchBlt. Возможна ли альтернат
Здравствуйте, spbAngel, Вы писали:
A>Здравствуйте, Andrew S, Вы писали:
A>>>Думаете, стОит использовать именно DirectDraw? AS>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio
AFAIK, DirectDraw умеет делать stretch с фильтрацией на большинстве современных и не очень видеокарт (начиная где-то с TNT).
Хотя у некоторых карт есть специфические особенности, например, у Radeon'ов (по крайней мере 9000'ой серии) размер поверхности, с которой можно делать stretch, ограничен максимальным размером текстуры (видимо, ATI'шники реализовали stretch через наложение текстуры; у NVidia всё "по-честному", размер поверхности ограничен только объёмом видеопамяти). Похожие проблемы у интегрированного видео на i915 — там при превышении макс. размера текстуры всё начинает сильно тормозить. На старом интегрированном видео (i810, i815 и вроде i845) аппаратный stretch через DirectDraw не работает, хотя текстуры накладывать они могут.
В D3D ограничение на размер текстуры официальное, т.е. больше — однозначно нельзя. Обычный макс. размер для карты "средней устарелости" (ранние GeForce, Radeon) — 2048 * 2048.
А игрушки используют D3D главным образом для спецэффектов вроде полупрозрачности, поворота картинки и т.п. Этого в DirectDraw действительно нет.
Re[10]: [GDI] Узкое место - StretchBlt. Возможна ли альтерна
A>>>>Думаете, стОит использовать именно DirectDraw? AS>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
S>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio
Видимо. Взгляните на интерфейсы DDI и DDDI — посмотрите, что мешает делать аппаратный стретч и в ddraw и в gdi одновременно? Поэтому, собственно, разницу между стретчем в ddraw и gdi найти будет трудно, если у разработчиков драйверов голова и руки были на месте.
А тестировалось это дело все на MX400. Я не претендую на полную объективность, отнюдь. Если у вас есть другие данные и они подтверждаются практикой — велкам, вам только спасибо скажут.
Здравствуйте, Sapersky, Вы писали:
S>Здравствуйте, spbAngel, Вы писали:
A>>Здравствуйте, Andrew S, Вы писали:
A>>>>Думаете, стОит использовать именно DirectDraw? AS>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
S>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio S>AFAIK, DirectDraw умеет делать stretch с фильтрацией на большинстве современных и не очень видеокарт (начиная где-то с TNT). S>Хотя у некоторых карт есть специфические особенности, например, у Radeon'ов (по крайней мере 9000'ой серии) размер поверхности, с которой можно делать stretch, ограничен максимальным размером текстуры (видимо, ATI'шники реализовали stretch через наложение текстуры; у NVidia всё "по-честному", размер поверхности ограничен только объёмом видеопамяти). Похожие проблемы у интегрированного видео на i915 — там при превышении макс. размера текстуры всё начинает сильно тормозить. На старом интегрированном видео (i810, i815 и вроде i845) аппаратный stretch через DirectDraw не работает, хотя текстуры накладывать они могут.
S>В D3D ограничение на размер текстуры официальное, т.е. больше — однозначно нельзя. Обычный макс. размер для карты "средней устарелости" (ранние GeForce, Radeon) — 2048 * 2048.
Respect. Когда-нибудь, и я буду такими данными делиться. А пока, вот сам узнаю. Глубоко копаешь.
S>А игрушки используют D3D главным образом для спецэффектов вроде полупрозрачности, поворота картинки и т.п. Этого в DirectDraw действительно нет.
Спасибо за инфу. Думается, что это может пригодится в будущем. Посему, всё таки остановим выбор на D3D.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[11]: [GDI] Узкое место - StretchBlt. Возможна ли альтерна
От:
Аноним
Дата:
10.11.06 17:44
Оценка:
Здравствуйте, Andrew S, Вы писали:
A>>>>>Думаете, стОит использовать именно DirectDraw? AS>>>>Нет, не стОит. Там практически не поддерживается аппаратное ускорение, даже для блиттера (по-крайней мере, я для себя в свое время такие выводы сделал, потестировав производительность блиттинга директдрава и gdi). Почти все современные 2d игрушки используют direct3d.
S>>Видимо во времена ваших тестов самыми распространёнными картами были S3 Trio
AS>Видимо. Взгляните на интерфейсы DDI и DDDI — посмотрите, что мешает делать аппаратный стретч и в ddraw и в gdi одновременно? Поэтому, собственно, разницу между стретчем в ddraw и gdi найти будет трудно, если у разработчиков драйверов голова и руки были на месте.
Уточню: под аппаратным stretch я подразумеваю полностью аппаратный, с перемещением видеопамять->видеопамять. В случае системная->видео скорость, действительно, мало отличается от GDI. Похоже что DirectDraw в этом случае переключается на обычный StretchBlt.
В варианте видео->видео DirectDraw, по моим тестам, быстрее GDI в десятки-сотни раз. Stretch на весь экран занимает, как правило, меньше миллисекунды даже на старых картах. К тому же он делается с фильтрацией независимо от версии Windows (StretchBlt может фильтровать только в NT).
Фактически скорость получается примерно такая же, как и в D3D, да и по некоторым косвенным признакам (см. в предыдущем сообщении про Radeon) можно судить, что аппаратный stretch DirectDraw ближе к D3D, чем к GDI.