Графика для Windows средствами DirectDraw

       

Создание поверхностей


Остается лишь создать поверхности, используемые в приложении. После вызова SetDisplayMode() функция ActivateDisplayMode() вызывает еще три функции: CreateFlippingSurfaces(), StorePixelFormatData() и CreateCustomSurfaces(). Функция CreateFlippingSurfaces() создает первичную поверхность с возможностью переключения страниц. Функция StorePixelFormatData() используется для чтения и записи сведений о формате пикселей в данном видеорежиме. Эта информация может пригодиться при работе с видеорежимами High и True Color. Функция CreateCustomSurfaces() отвечает за создание и инициализацию вспомогательных поверхностей, специфических для данного приложения. Начнем с функции CreateFlippingSurfaces():


BOOL DirectDrawWin::CreateFlippingSurfaces() { if (primsurf) primsurf->Release(), primsurf=0;

DDSURFACEDESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.dwSize = sizeof( desc ); desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; desc.dwBackBufferCount = 1; HRESULT r=ddraw2->CreateSurface( &desc, &primsurf, 0 ); if (r!=DD_OK) return FALSE; DDSCAPS surfcaps; surfcaps.dwCaps = DDSCAPS_BACKBUFFER; r=primsurf->GetAttachedSurface( &surfcaps, &backsurf ); if (r!=DD_OK) return FALSE;

return TRUE; }


Функция CreateFlippingSurfaces() вызывается при каждой инициализации нового видеорежима, поэтому ее работа начинается с освобождения ранее созданных поверхностей функцией Release(). Затем она объявляет и инициализирует экземпляр структуры DDSURFACEDESC. Эта структура описывает тип создаваемой поверхности. В соответствии с требованиями DirectDraw необходимо установить флаги для всех инициализируемых полей. В нашем случае флаги DDSD_CAPS и DDSD_BACKBUFFERCOUNT говорят о том, что мы задаем возможности поверхности (поле dwCaps) и количество вторичных буферов (поле dwBackCount). В поле dwCaps устанавливаются три флага:

  • DDSCAPS_PRIMARYSURFACE

  • DDSCAPS_FLIP

  • DDSCAPS_COMPLEX

Флаг DDSCAPS_PRIMARYSURFACE означает, что создаваемая поверхность должна находиться в видеопамяти, а ее размеры определяются в соответствии с текущим видеорежимом.
Поскольку размеры первичной поверхности зависят от видеорежима, она должна создаваться после его активизации.

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

Флаг DDSCAPS_COMPLEX используется всегда, когда происходит присоединение поверхностей. В нашем случае первичная поверхность должна быть присоединена к поверхности вторичного буфера. Затем мы присваиваем полю dwBackBufferCount значение 1, показывая, что к создаваемой первичной поверхности должен быть присоединен один вторичный буфер.

Новая поверхность создается вызовом функции CreateSurface() интерфейса DirectDraw. Первым аргументом является указатель на структуру desc, а вторым - указатель на переменную DirectDrawWin::primsurf. Эта переменная объявлена защищенной (protected), поэтому мы можем использовать ее для доступа к первичной поверхности в своих программах. Третий аргумент функции CreateSurface() должен быть равен 0.



Вызов CreateSurface() создает две поверхности: первичную поверхность и вторичный буфер. Позднее указатель на вторичный буфер понадобится нам для подготовки кадров. Чтобы получить этот указатель, следует вызвать функцию GetAttachedSurface() интерфейса DirectDrawSurface и передать ей структуру DDSCAPS с описанием типа интересующей нас присоединенной поверхности. Задавая флаг DDSCAPS_BACKBUFFER, мы вызываем функцию GetAttachedSurface(), которая инициализирует переменную backsurf. Она, как и переменная primsurf, объявлена защищенной, поэтому классы, производные от DirectDrawWin, могут легко обратиться к вторичному буферу.

После того как указатели primsurf и backsurf будут инициализированы, ActivateDisplayMode() вызывает функцию StorePixelFormatData(). Эта функция с помощью функции GetPixelFormat() интерфейса DirectDrawSurface получает информацию о формате хранения цветовых RGB-составляющих для отдельных пикселей.


Формат пикселей зависит от видеокарты, а иногда даже от видеорежима, так что эти сведения оказываются полезными при прямых манипуляциях с поверхностями. Функция StorePixelFormatdata() выглядит так:

BOOL DirectDrawWin::StorePixelFormatData() { DDPIXELFORMAT format; ZeroMemory( &format, sizeof(format) ); format.dwSize=sizeof(format); if (backsurf->GetPixelFormat( &format )!=DD_OK) { return FALSE; }

loREDbit = LowBitPos( format.dwRBitMask ); WORD hiREDbit = HighBitPos( format.dwRBitMask ); numREDbits=(WORD)(hiREDbit-loREDbit+1);

loGREENbit = LowBitPos( format.dwGBitMask ); WORD hiGREENbit = HighBitPos( format.dwGBitMask ); numGREENbits=(WORD)(hiGREENbit-loGREENbit+1); loBLUEbit = LowBitPos( format.dwBBitMask ); WORD hiBLUEbit = HighBitPos( format.dwBBitMask ); numBLUEbits=(WORD)(hiBLUEbit-loBLUEbit+1);

return TRUE; }

Структура DDPIXELFORMAT используется в функции GetPixelFormat() для получения масок, показывающих, какие биты в каждом пикселе заняты красной, зеленой и синей цветовыми составляющими. Маски точно описывают формат пикселя, но на практике работать с ними оказывается не очень удобно. Вместо того чтобы просто сохранить полученные маски, мы на основании каждой из них инициализируем два целых числа. Первое число равно позиции младшего бита цветовой составляющей, а второе — количеству бит, необходимых для ее представления. Для поверхностей True color (24- и 32-битных) цветовые составляющие всегда представляются 8 битами, но для поверхностей High color (16-битных) это число изменяется (обычно 5, но иногда 6 для зеленой составляющей).

Класс DirectDrawWin содержит шесть переменных для описания формата пикселей: loREDbit, numREDbits, loGREENbit, numGREENbits, loBLUEbit и numBLUEbits. Они используются некоторыми функциями DirectDrawWin, однако эти переменные объявлены как защищенные (protected), поэтому к ним можно обращаться и из классов, производных от DirectDrawWin. Эти переменные будут рассмотрены в главе 5.

На этом инициализация приложения подходит к концу.


Функция ActivateDisplayMode() вызывает еще одну функцию, CreateCustomSurfaces(), которая создает вспомогательные поверхности, но к этому моменту инициализация DirectDraw уже завершена. Функция CreateCustomSurfaces() будет рассмотрена в следующем разделе.

Но сначала давайте подведем итоги. Приложение состоит из двух объектов, BounceWin и BounceApp. Объект BounceApp отвечает за создание объекта BounceWin, а BounceWin в свою очередь инициализирует DirectDraw. Сначала он обнаруживает все имеющиеся драйверы DirectDraw, выбирает один из них и использует его для создания экземпляра интерфейса DirectDraw2. Затем он обнаруживает видеорежимы, поддерживаемые инициализированным драйвером, выбирает один из режимов и активизирует его. Далее создается первичная поверхность с возможностью переключения страниц (и вторичным буфером) и, наконец, анализируется формат пикселей для активизированного видеорежима.

Приложение почти готово к работе, но пока у него нет графических данных. Мы подходим к следующему этапу.


Содержание раздела