Національний університет «Львівська Політехніка»
Лабораторна робота №4
Робота з методами DirectDraw.
Львів 2011
Тема ( Робота з методами DirectDraw.
Мета ( Зрозуміти принципи та навчитись використовувати методи DirectDraw.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Для роботи з графікою існує обширний набір функцій GDI (Graphics Device Interface) – інтерфейс графічного пристрою. Ці функції універсальні як для малювання як на екрані, так і на принтері, але платою за універсальність є швидкодія. Створити більш-менш динамічну графічну програму з використанням лише GDI-функцій (наприклад, SetPixel) практично неможливо. На допомогу приходять методи прямого запису даних у відео-пам’ять, які дають максимальну швидкодію.
Методи DirectDraw включаються в концепцію DirextX, який включає в себе також методи DirectSound та Direct3D, які постійно поновлюються. Саме тому компанія Microsoft вирішила, що зручніше поновлювати таблицю віртуальних методів, ніж кожний раз створювати нові API-функції для нових версій методів, і реалізувала їх як звичайні методи абстрактних COM-об’єктів.
Для створення екземпляру об’єкту DirectDraw можна використовувати звичайний механізм створення COM-об’єктів за допомогою API-функції CoCreateInstance, яку ви використовували в лабораторній роботі №1. Після створення його необхідно ініциалізувати методом ініціалізації (див. таблицю 5), але цього можна не робити, якщо використовувати спеціалізовану API-функцію DirectDrawCreate. Параметрами цієї функції є ідентифікатор версії (або 0 ( для поточної версії), адреса змінної, яка буде містити вказівник на об’єкт після виконання функції, а також зарезервований параметр (що дорівнює 0).
Особливістю використання об’єкту DirectDraw є те, що він вимагає наявність вікна. Вікно можна створити з довільними параметрами, навіть не видимим. Виконання функції DirectDrawCreate необхідно робити тоді, коли вікно вже створене, тобто у віконній процедурі при обробці повідомлення WM_CREATE. Одразу ж після створення об’єкту DirectDraw необхідно викликати його 20-й метод “SetCooperativeLevel” (таблиця 5), який встановить ексклюзивні права на область відео-пам’яті, яку ви використовуєте та зарезервує повноекранний відео-буфер, який електронними засобами відео-карти буде відображатись на екрані монітору. Після цього необхідно переключити відео-карту у потрібний відео-режим за допомогою 21-го методу “SetDisplayMode”. В параметрах цього метода необхідно вказати ширину та висоту екрану в пікселях, а також кількість біт на один піксель.
Таблиця 5
№
Адр.
Назва методу
параметри
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
18
19
20
21
22
00
04
08
0c
10
14
18
1c
20
24
28
2c
30
34
38
3c
40
44
48
4c
50
54
58
QueryInterface
AddRef
Release
Compact
CreateClipper
CreatePalette
CreateSurface
DuplicateSurface
EnumDisplayModes
EnumSurfaces
FlipToGDISurface
GetCaps
GetDisplayMode
GetFourCCCodes
GetGDISurface
GetMonitorFrequency
GetScanLine
GetVerticalBlankStatus
Initialize
RestoreDisplayMode
SetCooperativeLevel
SetDisplayMode
WaitForVerticalBlank
riid, LPVOID ppvObj
LPDIRECTDRAWCLIPPER FAR*, Iunknown
LPPALET, LPDIRECTDRAWPAL, IUnknown
LPDDSURF, LPDIRECTDRAWSURF, IUnknown
LPDIRECTDRAWSURF, LPDIRECTDRAWSURF
LPDDSURF, LPVOID, LPDDENUMMODCALLBACK
LPDDSURF,LPVOID,LPDDENUMSURFACESCALLB
LPDDCAPS;
LPDWORD
*
*
*
LPBOOL
GUID
HWND, DWORD
DWORD, DWORD,DWORD
DWORD, HANDLE
Після того, як відео-карта переключена у відповідний режим, можна створити об’єкт Surface, методи якого показані в таблиці 6. Для створення цього об’єкту використовуємо 7-й метод DirectDraw: “CreateSurface” (таблиця 5). Результатом цього методу буде вказівник LPS на новий об’єкт Surface, який представляє видиму відео-сторінку, і методи якого представлені в таблиці 6 (див. програму далі). Одним з параметрів цього метода є вказівник на структуру DDSURFACEDESC2, в якій буде записана адреса відео-сторінки (lpSurface), в яку можна буде записати відео-дані.
Для роботи з іншою відео-сторінкою, яка в даний момент не видима необхідно отримати іншу таблицю віртуальних методів за допомогою метода “GetAttachedSurface” об’єкта LPS (таблиця 6, див. програму далі). В результаті виконання цього методу отримуємо вказівник DDBACK на таблицю віртуальних методів для роботи з невидимою відео-сторінкою. Тепер утворені всі необхідні компоненти DirectDraw і можна приступати до малювання.
Таблиця 6
№
Адр.
Назва методу
параметри
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
00
04
08
0c
10
14
18
1c
20
24
28
2c
30
34
38
3c
40
44
48
4c
50
54
58
5c
60
64
68
6c
70
74
78
7c
80
84
88
8c
QueryInterface
AddRef
Release
AddAttachedSurface
AddOverlayDirtyRect
Blt
BltBatch
BltFast
DeleteAttachedSurface
EnumAttachedSurfaces
EnumOverlayZOrders
Flip
GetAttachedSurface
GetBltStatus
GetCaps
GetClipper
GetColorKey
GetDC
GetFlipStatus
GetOverlayPosition
GetPalette
GetPixelFormat
GetSurfaceDesc
Initialize
IsLost
Lock
ReleaseDC
Restore
SetClipper
SetColorKey
SetOverlayPosition
SetPalette
Unlock
UpdateOverlay
UpdateOverlayDisplay
UpdateOverlayZOrder
REFIID riid, LPVOID ppvObj
LPDIRECTDRAWSURFACE
LPRECT
LPRECT,LPDIRECT, LPRECT,DWRD, LPDDBLT
LPDDBLTBATCH, DWORD, DWORD
DWORD,DWORD,LPDIRECT, LPRECT,DWORD
DWORD,LPDIRECTDRAWSURFACE) PURE
LPVOID,LPDDENUMSURFACESCALLBACK
DWORD,LPVOID,LPDDENUMSCALLBACK
LPDIRECTDRAWSURFACE, DWORD
LPDDSCAPS, LPDIRECTDRAWSURFACE
DWORD
LPDDSCAPS
PURE,LPDIRECTDRAWCLIPPER FAR
DWORD, LPDDCOLORKEY
HDC
DWORD
LPLONG, LPLONG
LPDIRECTDRAWPALETTE FAR
LPDDPIXELFORMAT
LPDDSURFACEDESC
LPDIRECTDRAW, LPDDSURFACEDESC
LPRECT,LPDDSURFACEDESC,DWORD,HANDLE
HDC
LPDIRECTDRAWCLIPPER
DWORD, LPDDCOLORKEY
LONG, LONG
LPDIRECTDRAWPALETTE
LPVOID
LPRECT, LPDIR,LPRECT,DWD, LPDDOVERLAX
DWORD
DWORD, LPDIRECTDRAWSURFACE
Для малювання в програмі необхідно створити таймер, і при надходженні у віконну процедуру повідомлення WM_TIMER необхідно переключити відео-сторінки. Таким чином можна досягти плавності малювання об’єктів, які рухаються, тому що коли на екрані зображена одна відео-сторінка, процес виводу змінює відео-дані іншої сторінки, яка в даний момент не видима.
Для запису у відео-сторінку необхідно, щоб вона була фізично присутня в пам’яті, тому перед записом необхідно застосувати метод Lock з таблиці віртуальних методів об’єкту DDBACK невидимої відео-сторінки. Ця таблиця має таку ж саму структуру, як і таблиця 6, але всі методи відносяться до невидимої відео-сторінки.
В результаті виконання 26-го метода “Lock” змінна lpSurface буде містити початок невидимої відео-сторінки, яку використовує процедура малювання. Після закінчення малювання використовується 12-й метод “Flip” з таблиці віртуальних методів для видимої відео-сторінки LPS. Метод “Flip” фактично міняє місцями відео-сторінки на екрані монітору, але вказівники LPS і DDBACK як і раніше містять адреси методів для роботи з видимою і невидимою відео-сторінками. Після малювання бажано розблокувати відео-сторінку методом “Unlock” (№33 у таблиці 6).
.486
.model flat, stdcall
extrn CreateWindowExA:Proc, RegisterClassA:Proc, GetMessageA:Proc
extrn DispatchMessageA:Proc, DefWindowProcA:Proc, MessageBoxA:Proc
extrn DirectDrawCreate:Proc, SetTimer:Proc, ShowCursor:Proc, TextOutA:Proc
extrn lstrlen:Proc, SetBkMode:Proc, ExitProcess:Proc
INCLUDELIB DDraw.LIB
SetCooperativeLevel equ 50h
SetDisplayMode equ 54h
CreateSurface equ 18h
Surface_Lock equ 64h
Surface_Unlock equ 80h
Surface_Restore equ 6Ch
Surface_GetDC equ 44h
Surface_ReleaseDC equ 68h
GetAttachedSurface equ 30h
Surface_Flip equ 2Ch
WM_CREATE equ 1h
WM_KEYDOWN equ 100h
WM_TIMER equ 113h
WS_POPUP equ 80000000h
DDSD_CAPS equ 000001h
DDSD_PITCH equ 000008h
DDSD_BACKBUFFERCOUNT equ 000020h
DDSCAPS_PRIMARYSURFACE equ 200h
DDSCAPS_FRONTBUFFER equ 20h
DDSCAPS_BACKBUFFER equ 04h
DDSCAPS_FLIP equ 10h
DDSCAPS_COMPLEX equ 08h
DDLOCK_WAIT equ 1
DDFLIP_WAIT equ 1
DDSCL_FULLSCREEN equ 1h
DDSCL_EXCLUSIVE equ 10h
;=======================================================
.data
wc: dd 0, offset WndProc, 7 dup(0), offset WndClassName
msg:
msHWND dd 0
msMESSAGE dd 0
msWPARAM dd 0
msLPARAM dd 0
msTIME dd 0
ptX dd 0
ptY dd 0
NewHWnd dd 0
WndClassName db "DeepPurple",0
TEXT1 db " Приклад DirectDraw ",0
SCREEN_WIDTH dd 800
SCREEN_HEIGHT dd 600
SCREEN_BPP dd 16
LPDD dd 0 ; ddraw interface pointer
LPS dd 0
DDBACK dd 0
DDSURFACEDESC2:
dd 108,DDSD_CAPS or DDSD_BACKBUFFERCOUNT,0,0
lPitch dd 0
dwBackBufferCount dd 1,0,0,0
lpSurface dd 0,16 dup(0) ; вказівник на відео-сторінку
ddsCaps dd DDSCAPS_PRIMARYSURFACE or DDSCAPS_COMPLEX or DDSCAPS_FLIP
dwTextureStage dd 0
BEGIN_COLOR dd 00
HDC dd 0
X dd 0
Y dd 0
HV dd 1
VV DD 1
R db 0
G db 0
B db 0
;======================================================
.code
Start: call RegisterClassA,offset wc
call CreateWindowExA,0,eax,0,WS_POPUP,1,1,1,1,0,0,0,0
mov NewHWnd,eax
call ShowCursor,0
call SetTimer,NewHWnd,0,20,offset WndProc
;===================================================
msg_loop: call GetMessageA,offset msg,NewHWnd,0,0
cmp eax,-1
jz STOP
cmp msMESSAGE,WM_KEYDOWN
jnz CONTINUE_LOOP
cmp msWPARAM,1bh
jz STOP
CONTINUE_LOOP:
call DispatchMessageA,offset msg
jmp msg_loop
STOP: call ExitProcess,0
;=====================================================
WndProc proc hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
cmp wmsg,WM_CREATE ; Створення об’єктів DirectDraw та Surface
jnz TIMER
call DirectDrawCreate, 0, offset LPDD, 0
mov eax,LPDD
mov eax, [eax]
call [eax+SetCooperativeLevel],LPDD, hwnd, DDSCL_EXCLUSIVE OR DDSCL_FULLSCREEN
mov eax,LPDD
mov eax, [eax]
call [eax+SetDisplayMode],LPDD, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP
mov eax, LPDD
mov eax, [eax]
call dword ptr [eax+CreateSurface],LPDD, offset DDSURFACEDESC2, offset LPS,0
or eax,eax
jnz STOP
mov ddsCaps,DDSCAPS_BACKBUFFER
mov eax,LPS
mov eax, [eax]
call dword ptr [eax+GetAttachedSurface],LPS, offset ddsCaps, offset DDBACK
or eax,eax
jnz STOP
;---------------------------------------------------------------------------------------------------
TIMER: cmp wmsg,WM_TIMER
jnz EXIT1 ; Обробка подій від таймеру
mov eax,DDBACK
mov eax, [eax]
call dword ptr [eax+Surface_Lock], DDBACK, 0, offset DDSURFACEDESC2, DDLOCK_WAIT, 0
or eax,eax
jnz NO_PAINT
call PAINT ; Ваша процедура малювання
mov eax,LPS
mov eax, [eax]
call [eax+Surface_Flip],LPS,0,0
NO_PAINT:
EXIT1: call DefWindowProcA, hwnd, wmsg, wparam, lparam
ret
WndProc endp
;=====================================================
PAINT: pushad
cld
mov eax,BEGIN_COLOR
and eax,0ffffffh
mov edx,SCREEN_HEIGHT
mov ebx,lpSurface ; початок відео-сторінки
L_BLT: mov edi,ebx
mov ecx,SCREEN_WIDTH
add eax,10001h
push eax
call CONVERT_to_RGB16
not ax
repnz stosw ; Прямий запис у відео-пам’ять
pop eax
add ebx,lPitch ; Перехід на новий рядок
dec edx
jnz L_BLT
popad
mov eax,DDBACK
mov eax, [eax]
call [eax+Surface_Unlock],DDBACK,0
mov eax,DDBACK
mov eax, [eax]
call [eax+Surface_GetDC],DDBACK,offset HDC
call SetBkMode,HDC,1
call lstrlen,offset TEXT1
call TextOutA,HDC,X,Y,offset TEXT1,eax
mov eax,DDBACK
mov eax, [eax]
call [eax+Surface_ReleaseDC],DDBACK,HDC
mov eax,HV
add X,eax
mov eax,VV
add Y,eax
cmp X,700
jb M1
neg HV
M1: cmp Y,590
jb M2
neg VV
M2:
add BEGIN_COLOR,010305h
ret
;---------------------------------- Процедура для перетворення EAX у 16-бітний колір
CONVERT_to_RGB16:
mov B,al
mov G,ah
shr eax,16
mov R,al
shr R,3 ; 5 біт = 8-3 на червону компоненту
shr G,2 ; 6 біт = 8-2 на зелену компоненту
shr B,3 ; 5 біт = 8-3 на синю компоненту
xor eax,eax
mov al,R
shl ax,6
or al,G
shl ax,5
or al,B
ret
end Start
Для застосування до відео-сторінки функцій GDI (наприклад, вивід тексту) необхідно застосувати 18-й метод “GetDC” з таблиці віртуальних методів відповідної відео-сторінки. Після закінчення використання функцій GDI в даній відео-сторінці необхідно викликати 27-й метод “ReleaseDC”.
ПОРЯДОК ВИКОНАННЯ РОБОТИ
Створити файл DDraw.LIB з файлу DDraw.DLL за допомогою програми H:\tasm\bin\implib.exe. Для цього треба скопіювати вказані файли в свій каталог і запустити команду: IMPLIB.EXE DDraw.LIB DDraw.DLL
Запустити програму та проглянути послідовність методів, що викликаються.
Змінити текст, який виводиться в програмі на своє прізвище.
Змінити шрифт вказаного надпису так, як було описано у файлі SYS_DD3.doc.
Намалювати на екрані прямокутник шляхом прямого запису в пам’ять.
Приклад Реалізації програми
Висновок:
Для створення цьго малюнка, я використав методи Direct Draw. Рух здійснюється за допомогою збільшення координат позиції фігури.