http://seprize.narod.ru

Блитинг

< Часть 1 | Часть 2 | Часть 3 >

Вспомогательная поверхность создана и заполнена растром размером 256x256 пикселов. Среди аргументов операции блиттинга присутствуют структуры типа trect, задающие местоположение в принимающей поверх­ности и копируемую область. Поэтому код обработчика перерисовки окна дополнился переменными dstRect и srcRect типа trect. Заполняем их поля с помощью API-функции SetRect:

 

SetRect (dstRect, 100, 100, 356, 356);     // Для принимающей поверхности

SetRect (srcRect, 0, 0, 256, 256);         // Для источника

Теоретически эта операция также может привести к провалу. Для важных приложений рекомендую здесь анализировать возвращаемое булево значе­ние. К тому же соглашусь, что в данном примере оптимальным решением было бы использование глобальных переменных, заполняемых один раз, а не при каждой перерисовке окна. Просто код в таком виде удобнее читать, а перерисовка не станет производиться интенсивно.

Канву для вывода растра не используем, делаем теперь все традиционным для DirectDraw способом:

while True do begin  // Возможно, придется производить неоднократно hRet := FDDSPrimary.Blt (@dstRect, FDDSImage, @srcRect, DDBLT_WAIT,

nil); // Собственно блиттинг

if hRet = DDERR_SURFACELOST then begin    // Поверхность потеряна

if Failed (RestoreAll) then Exit;       // Пытаемся восстановить end else Break;

 // Или все прошло успешно, или неустранимая ошибка

end;

Потеря любой поверхности является верным признаком того, что надо вос­станавливать все поверхности. Поэтому каждый раз в случае ошибки обра­щаемся к пользовательской функции RestoreAll:

function TfrmDD.RestoreAll : HRESULT; begin

Result := DD_FALSE;     // Определяемся с результатом

// Пытаемся восстановить первичную поверхность

if Succeeded (FDDSPrimary._Restore) then begin

// Пытаемся восстановить вторичную поверхность if Failed (FDDSImage._Restore) then Exit; Result := DD_OK;      // Все прошло успешно end; end;

Нажав комбинацию клавиш <Alt>+<Tab>, переключитесь с этого приложе­ния, а затем верните ему фокус. Если восстановление поверхностей прошло успешно, вы увидите картинку с пейзажем. Но если это получилось с вашей картой, совсем не обязательно, что это произойдет и с другими. На иных компьютерах пользователи в такой ситуации могут получить бессмысленный узор. Согласно рекомендациям разработчиков, поверхности, содержащие растр, при восстановлении должны заново заполняться.

Если это окно из рассматриваемого примера у вас восстанавливается без потерь, можете двигаться дальше. Если же у вас картинка при восстановле­нии портится, функцию восстановления исправьте следующим образом:

function TfrmDD.RestoreAll : HRESULT; var

hRet : HRESULT; begin

hRet := FDDSPrimary._Restore; if Succeeded (hRet) then begin hRet := FDDSImage._Restore; if Failed (hRet) then begin Result := hRet; Exit; end;

// Перезагружаем на поверхность содержимое растра Result := DDReLoadBitmap(FDDSImage, imageBMP); end else Result := hRet; end;

Теперь мы можем узнать смысл первых трех аргументов метода Blt поверх­ности. Первый из них — указатель на структуру типа trect, задающую ме­стоположение и размер области, в которую происходит копирование. Вто­рой параметр — поверхность источника. Третий аргумент — указатель на структуру типа trect, задающую местоположение и размер области, из ко­торой происходит копирование.

Флагом задаем константу ddblt_wait, не комбинацию значений. Дополни­тельные параметры пока не указываем, поэтому последний аргумент метода устанавливаем в nil.

Пример простой, но очень важный. Осмыслим изученное. Естественным для DirectDraw способом воспроизведения является блиттинг. На вспомога­тельных поверхностях размещаем нужные нам образы, а в определенный момент времени копируем требуемые области с одной поверхности на другую, в простейшем случае — со вспомогательных поверхностей на первич­ную, связанную с экраном.

Вторичных поверхностей создают столько, сколько требуется приложению. Разработчик сам решает, что и где ему располагать, но здесь надо учесть не­большую тонкость: если видеокарта имеет малый размер памяти, то вторич­ную поверхность не получится создать размером больше первичной. Может быть, это происходит только с конкретными картами, но я действительно встречался с такой ситуацией.

Поверхностей вы можете создавать сколько угодно, но чем их меньше, тем быстрее будет осуществляться блиттинг. Поэтому лучше не плодить множе­ство поверхностей, а, в идеальном случае, располагать все образы на одной большой поверхности.

В общем случае операция копирования блоков из системной памяти в ви­деопамять осуществляется медленнее, чем из видеопамяти в видеопамять. Поэтому образы, выводимые наиболее часто, старайтесь размещать в видео­памяти, а при ее нехватке те из образов, которые редко будут появляться, например заставки или меню, следует размещать в системной памяти. Поддержка AGP если и стирает разницу в скоростях обмена, то незначи­тельно. Если бы скорости работы с видеопамятью и системной памятью сосовпадали или были близки друг к другу, не было бы нужды производите­лям карт выпускать модели, различающиеся размером видеопамяти, а поль­зователям оставалось лишь наращивать размер системной памяти. Для поверхности, создаваемой в видеопамяти, надо использовать комбина­цию   флагов   DDSCAPS_OFFSCREENPLAIN    or    DDSCAPS_VIDEOMEMORY.    И    Наоборот,

флаг ddscaps_systemmemory указывает, что поверхность должна располагаться в системной памяти.

Метод GetAvailablevidMem главного объекта DirectDraw позволяет выяснить, сколько видеопамяти осталось в распоряжении приложения. При нехватке видеопамяти операция создания поверхности завершится про­валом, код соответствующей ошибки — dderr_outofvideomemory. В этом слу­чае необходимо поменять флаг и заново попытаться создать поверхность. Теперь обсудим вопросы масштабирования растров. Вспомогательная функ­ция копирования растра поддерживает масштабирование.  Задайте размер. вторичной поверхности больше, чем размер используемого растра, напри­мер, так:

ddsd.dwWidth  := wrkBitmap.Width * 2;

Теперь при воспроизведении мы увидим картинку, растянутую вдоль экра­на, но не всю, а только ее половину. Для того чтобы вывести ее целиком, надо изменить значение поля Right структуры dstRect:

SetRect   (dstRect,   100,   100,   100  +  256  *   2,   356);

 

P.S. Данная статья будет подправлена, обогащена примерами, но пока я считаю что многих она заинтересует

< Часть 1 | Часть 2 | Часть 3 >

 

. : навигация : .

главная
DirectX
уроки
словарь
гостевая книга
о проекте
 
.: DirectX :.
введение
уроки
файлы
 

статистика

RAMBLER'S TOP100

Если вы используете материалы с данного сайта, то сообщите владельцу по почте
и вставьте ссылку на этот сайт "seprize.narod.ru"
seprize@narod.ru

© Сайт открылся 04.09.2002     Дата последнего обновления 09.10.2002

Сайт управляется системой uCoz