VR
Virtual Reality On-line   DirectX
Новости   |     Журнал    |    Хаkер   |     Магазин   |   Проекты
[   Вход    ]
[Kарта сайтa]
[ Download  ]
[  Конкурс  ]
[  Анекдоты ]
[  Ссылки   ]
[  Реклама  ]
[ Почтальон ]
[ О проекте ]






TopList
Delphi+DirectX7,8.
Прямой доступ к памяти
:

Когда я ещё программировал графику под DOS, единственным способом получить большую скорость было использование прямого доступа к видеопамяти. Это было достаточно просто, потому что видеопамять находилась по определённому адресу, а использование прерываний для вывода графики очень сильно тормозило систему. В Windows запрещён прямой доступ, поэтому тут есть проблемы. Но в DirectDraw уже заложили возможность прямого доступа и мы сейчас с ним познакомимся.

В некоторых случаях, прямой доступ к видеопамяти - единственный способ повысить производительность системы. Хотя DirectDraw достаточно быстрая библиотека, она всё же расходует некоторое процессорное время зря. Когда ты обращаешся к видеопамяти напрямую, вывод всегда происходит быстрее.

Для получения прямого доступа к поверхности, нужно вызвать её метод Lock. Этот метод блокирует поверхность и позволяет получить к ней доступ. Во время блокировки поверхности происходить и блокировка системы, поэтому желательно блокировать на небольшые промежутки времени и после использования сразу разблокировывать. У него 4 параметра:

  • Область поверхности, к которой мы хотим получить доступ. Тип параметра - указатель на TRect. Если здесь указать nil , то доступ будет получен ко всей области.
  • Структура типа TDDSURFACEDESC2, куда будет записана инфа о поверхности.
  • Флаги. Можно указывать следующие:
    • DDLOCK_NOSYSLOCK - не блокировать систему (игнорируется при получении доступа к первичной поверхности).
    • DDLOCK_READONLY - заблокировать только для чтения.
    • DDLOCK_SURFACEMEMORYPTR - указывает на то, что надо получить правильный указатель на верхний угал области поверхности.
    • DDLOCK_WAIT - Если сейчас блокировка невозможна, то подождать, пока поверхность не осободится.
    • DDLOCK_WRITEONLY - блокировать только для записи.
  • Последний параметр не используется и должен быть равен 0.
Logo

После использования поверхности, нужно вызвать метод Unlock. У этого метода только один параметр - область поверхности, которая должна быть разблокирована. Желательно разблокировать ту же область, что и блокировалась.

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

Давай напишем процедуру PutPixel, которая будет выводить на экран один пиксел в видеопамять.

procedure TForm1.PutPixel(X, Y: Integer; R, G, B : Byte);
var
 desc : TDDSURFACEDESC2;
 Value:Word;
begin
 ZeroMemory (@desc, SizeOf(desc)); //Обнуляю структуру
 desc.dwSize := SizeOf(desc); //Заполняю размер

 value:=B or (G shl 5) or (R shl 11); //Вычисляю цвет

 FImageSurface.Lock (nil, desc, DDLOCK_WAIT, 0); //Блокировка
 PWord(Integer(desc.lpSurface) + Y * desc.lPitch + X*2)^ := Value;
 FImageSurface.Unlock (nil);//Разблокировка
end;

Первым делом я обнуляю структуру desc и в поле dwSize заношу её размер.

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

Если ты используешь разрешение в 8 бит, то есть максимум можно отобразить 256 цветов и то благодаря палитре, то никаких проблем. У тебя в памяти, каждый байт - это указатель на цвет в палитре, т.е. картинка 8х8 будет выглядеть так:

125 002 015 121 146 166 004 112
225 255 125 125 003 168 112 036
125 082 015 021 146 166 004 112
225 255 125 125 003 168 112 036
225 255 125 125 003 168 112 036
125 082 015 021 146 166 004 112
225 255 125 125 003 168 112 036
125 082 015 021 146 166 004 112

Тут каждое число означает какой-то цвет. Если мы используем режим TrueColor, то в этом режиме каждые три рядом стоящих байта дают цвет. Это значит, что наша табличка должна расширится в ширину в три раза. В этом случае, каждые три байта будут давать цвет (RGB).

Ну а самое интересное происходит при 16-битном цвете, когда в два байта нужно засунуть три цвета. Как это сделать, если два байта - это 16 бит, а 16 на 3 не делится? Очень просто - в этом случае очень часто используется режим 5-6-5, где 5 бит под красный цвет, 6 бит под зелёный и 5 бит под голубой. Можно переключиться на режим 5-5-5, где всем цветам будет отдано одинаковое количество бит, но мы будем рассматривать 5-6-5. Так как 16-битный режим самый сложный, я решил использовать в своём примере именно его.

Чтобы получить результирующий цвет и засунуть его в переменную Value (которая имеет тип WORD или два байта), мне нужно сдвинуть красный цвет на 11 бит влево, зелёный на 5 бит и синий прибавить как есть.

Теперь о том, как записывать в память. Чтобы записать значение цвета в левый верхний угол, ножно присвоить его по адресу указанному в desc.lpSurface, то есть вот сюда - PWord(Integer(desc.lpSurface))^ . Я привожу указатель к типу PWord, потому что записывать буду значение типа Word. Если бы я записывал только байт, то приводил бы к PByte - PByte(Integer(desc.lpSurface))^ .

Чтобы вычеслить строку, в которую надо записать я умножаю значение Y на длинну строки - Y * desc.lPitch. В desc.lPitch как раз и находится длинна строки картинки. Чтобы вычислить Х позицию, я умножаю Х на 2, потому что каждое значение Х позиции состоит из 2 байт.

Ну и наконец в этой процедуре FImageSurface - это поверхность типа IDirectDrawSurface7, в которую я загружу картинку. Именно эту поверхность я блокирую и получаю к ней доступ.

Вот и всё. Чуть позже я напишу пример анимации с использованием прямого доступа к памяти. К этой же статье я прилагаю пример, в котором на экран выводится изображение (я писал этот пример в статье "Delphi+DirectX7,8. Улучшенный вывод на экран") и поверх него случайным образом рисуються точки случайного цвета. Скрин ты можешь видеть где-то выше в этой статье.

 Исходники примера забирай здесь


Copyright©: Horrific aka Флёнов Михаил
Design by FMk group©