НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
Лабораторна робота №1
з дисципліни “ Операційні системи ”
“Робота з методами DirectDraw ”
Bиконав:
студент групи КН – 20
Лектор:ЗербіноД. Д.
Керівник лабораторних занять:ЗербіноД. Д.
Львів – 2012
Мета ( Зрозуміти принципи та навчитись використовувати методи DirectDraw.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Для роботи з графікою існує обширний набір функцій GDI (GraphicsDeviceInterface) – інтерфейс графічного пристрою. Ці функції універсальні як для малювання як на екрані, так і на принтері, але платою за універсальність є швидкодія. Створити більш-менш динамічну графічну програму з використанням лише 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).
Програмна реалізація:
Вміст файлаDATA.txt:
wc: dd 0, offsetWndProc, 7 dup(0), offsetWndClassName
msg:
msHWND dd 0
msMESSAGE dd 0
msWPARAM dd 0
msLPARAM dd 0
msTIME dd 0
ptX dd 0
ptY dd 0
NewHWnddd 0
WndClassNamedb "DeepPurple",0
TEXT1 db "by Nykytenko",0
SCREEN_WIDTH dd 1024
SCREEN_HEIGHT dd 768
SCREEN_BPP dd 16
LPDD dd 0 ; ddrawinterfacepointer
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
LOGFONTA:
lfHeight DD 50 ; Висота
lfWidth DD 20 ; Ширина
lfEscapement DD 3600 ; Кут нахилу * 10
lfOrientation DD 0 ;
lfWeight DD 1000 ; Жирнiсть (1000-Bold)
lfItalic DB 1 ; Курсив
lfUnderline DB 1 ; Пiдкреслення
lfStrikeOut DB 0
lfCharSet DB 1 ; 255 – шрифти DOS
lfOutPrecision DB 0
lfClipPrecision DB 0
lfQuality DB 1
lfPitchAndFamily DB 0
lfFaceName DB 'Algerian' ; Назва фонту
Reserv DB 32-6 dup(0)
HRedPen dd 0
OldPos dd 0,0
HGreenPen dd 0
HYELLPen dd 0
HBRUSHRED dd 0
HBRUSHGRAY dd 0
HBRUSHBLACK dd 0
HBRUSHYELL dd 0
HBLACKPen dd 0
HBRUSHGreen dd 0
HGOLDPen dd 0
HFont dd 0
Вміст файлаMyPic.txt:
;сонце
callSelectObject,HDC,HYELLPen
callSelectObject,HDC, HBRUSHYELL
CallEllipse,HDC,-20,-20,100,100
;===============================================================
callSelectObject,HDC,HBLACKPen
CallRectangle,HDC,0,455,1040,485
callSelectObject,HDC,HBRUSHBLACK
CallRectangle,HDC,330,440,350,460
;дяпчик-тьола
CallMoveToEx,HDC,500,420,offsetOldPos
CallLineTo,HDC,520,440
CallMoveToEx,HDC,500,420,offsetOldPos
CallLineTo,HDC,480,440
CallMoveToEx,HDC,480,440,offsetOldPos
CallLineTo,HDC,520,440
CallMoveToEx,HDC,500,420,offsetOldPos
CallLineTo,HDC,500,400
CallMoveToEx,HDC,500,410,offsetOldPos
CallLineTo,HDC,525,420
CallMoveToEx,HDC,500,410,offsetOldPos
CallLineTo,HDC,475,390
CallMoveToEx,HDC,495,440,offsetOldPos
CallLineTo,HDC,495,465
CallMoveToEx,HDC,505,440,offsetOldPos
CallLineTo,HDC,505,465
CallEllipse,HDC,495,380,505,400
;дяпчик-тіп
CallMoveToEx,HDC,550,420,offsetOldPos
CallLineTo,HDC,550,400
CallMoveToEx,HDC,550,410,offsetOldPos
CallLineTo,HDC,575,420
CallMoveToEx,HDC,550,410,offsetOldPos
CallLineTo,HDC,525,420
CallMoveToEx,HDC,545,440,offsetOldPos
CallLineTo,HDC,545,465
CallMoveToEx,HDC,555,440,offsetOldPos
CallLineTo,HDC,555,465
CallMoveToEx,HDC,545,440,offsetOldPos
CallLineTo,HDC,550,420
CallMoveToEx,HDC,555,440,offsetOldPos
CallLineTo,HDC,550,420
CallEllipse,HDC,545,380,555,400
;===thebaloon
callSelectObject,HDC,HRedPen
CallMoveToEx,HDC,475,390,offsetOldPos
CallLineTo,HDC,475,350
callSelectObject,HDC,HGreenPen
callSelectObject,HDC, HBRUSHYELL
CallEllipse,HDC,460,320,490,360
;===========thetree==========
callSelectObject,HDC,HGreenPen
CallMoveToEx,HDC,260,440,offsetOldPos
CallLineTo,HDC,340,380
CallMoveToEx,HDC,340,380,offsetOldPos
CallLineTo,HDC,425,440
CallMoveToEx,HDC,425,440,offsetOldPos
CallLineTo,HDC,260,440
CallMoveToEx,HDC,260,380,offsetOldPos
CallLineTo,HDC,340,320
CallMoveToEx,HDC,340,320,offsetOldPos
CallLineTo,HDC,425,380
CallMoveToEx,HDC,425,380,offsetOldPos
CallLineTo,HDC,260,380
CallMoveToEx,HDC,260,320,offsetOldPos
CallLineTo,HDC,340,260
CallMoveToEx,HDC,340,260,offsetOldPos
CallLineTo,HDC,425,320
CallMoveToEx,HDC,425,320,offsetOldPos
CallLineTo,HDC,260,320
Вміст файлаMAIN.txt:
.486
.modelflat, stdcall
extrnCreateWindowExA:Proc, RegisterClassA:Proc, GetMessageA:Proc
extrnDispatchMessageA:Proc, DefWindowProcA:Proc, MessageBoxA:Proc
extrnDirectDrawCreate:Proc, SetTimer:Proc, ShowCursor:Proc, TextOutA:Proc
extrnlstrlen:Proc, SetBkMode:Proc, ExitProcess:Proc, SetTextColor:proc, CreateFontIndirectA:proc, SelectObject:proc
extrnCreatePen: Proc, MoveToEx: proc, LineTo: proc, Ellipse: proc, Rectangle: proc, CreateSolidBrush: 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
;******************************************************
include DATA.txt
;*******************************************************
.code
Start:
call CreatePen,0, 2, 0000ffh
movHRedPen, eax
call CreatePen,0, 2, 00ff00h
movHGreenPen, eax
call CreatePen,0, 2, 06fff0h
movHYELLPen, eax
call CreatePen,0, 3, 465945h
movHBLACKPen, eax
call CreatePen,0, 2, 4F7942h
movHGOLDPen, eax
CallCreateSolidBrush, 00FF00h
movHBRUSHGreen, eax
CallCreateSolidBrush, 0000ffh
mov HBRUSHRED, eax
CallCreateSolidBrush, 3D2B1Fh
mov HBRUSHBLACK, eax
CallCreateSolidBrush, 06fff0h
mov HBRUSHYELL, eax
callCreateFontIndirectA, offset LOGFONTA
movHFont, eax
callRegisterClassA,offsetwc
callCreateWindowExA,0,eax,0,WS_POPUP,1,1,1,1,0,0,0,0
movNewHWnd,eax
call ShowCursor,0
call SetTimer,NewHWnd,0,20,offsetWndProc
;===================================================
msg_loop: callGetMessageA,offsetmsg,NewHWnd,0,0
cmpeax,-1
jz STOP
cmpmsMESSAGE,WM_KEYDOWN
jnz CONTINUE_LOOP
cmp msWPARAM,1bh
jz STOP
CONTINUE_LOOP:
callDispatchMessageA,offsetmsg
jmpmsg_loop
STOP: callExitProcess,0
;=====================================================
WndProcprochwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
cmpwmsg,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
moveax, LPDD
moveax, [eax]
calldwordptr [eax+CreateSurface],LPDD, offset DDSURFACEDESC2, offset LPS,0
oreax,eax
jnz STOP
mov ddsCaps,DDSCAPS_BACKBUFFER
mov eax,LPS
mov eax, [eax]
call dwordptr [eax+GetAttachedSurface],LPS, offsetddsCaps, offset DDBACK
oreax,eax
jnz STOP
;---------------------------------------------------------------------------------------------------
TIMER: cmp wmsg,WM_TIMER
jnz EXIT1 ; Обробка подій від таймеру
mov eax,DDBACK
mov eax, [eax]
call dwordptr [eax+Surface_Lock], DDBACK, 0, offset DDSURFACEDESC2, DDLOCK_WAIT, 0
or eax,eax
jnz NO_PAINT
call PAINT ; Ваша процедура малювання
moveax,LPS
moveax, [eax]
call [eax+Surface_Flip],LPS,0,0
NO_PAINT:
EXIT1: callDefWindowProcA, hwnd, wmsg, wparam, lparam
ret
WndProcendp
;=====================================================
PAINT: pushad
cld
moveax,BEGIN_COLOR
andeax,0ffffffh
movedx,SCREEN_HEIGHT
movebx,lpSurface ; початок відео-сторінки
L_BLT: movedi,ebx
movecx,SCREEN_WIDTH
addeax,10001h
pusheax
call CONVERT_to_RGB16
notax
repnzstosw ; Прямий запис у відео-пам’ять
popeax
addebx,lPitch ; Перехід на новий рядок
decedx
jnz L_BLT
popad
moveax,DDBACK
moveax, [eax]
call [eax+Surface_Unlock],DDBACK,0
moveax,DDBACK
moveax, [eax]
call [eax+Surface_GetDC],DDBACK,offset HDC
call SetBkMode,HDC,1
;****************************
include MyPic.txt
;****************************
callSelectObject,HDC,HFont
call lstrlen,offset TEXT1
call TextOutA,HDC,X,Y,offset TEXT1,eax
moveax,DDBACK
moveax, [eax]
call [eax+Surface_ReleaseDC],DDBACK,HDC
mov eax,HV
add X,eax
mov eax,VV
add Y,eax
cmp X,300
jb M1
neg HV
M1: cmp Y,290
jb M2
neg VV
M2:
add BEGIN_COLOR,010305h
ret
;---------------------------------- Процедура для перетворення EAX у 16-бітний колір
CONVERT_to_RGB16:
mov B,al
mov G,ah
shreax,16
mov R,al
shr R,3 ; 5 біт = 8-3 на червону компоненту
shr G,2 ; 6 біт = 8-2 на зелену компоненту
shr B,3 ; 5 біт = 8-3 на синю компоненту
xoreax,eax
moval,R
shlax,6
oral,G
shlax,5
oral,B
ret
endStart
Скіншот виконання прорами:
Висновки:Для застосування до відео-сторінки функцій GDI (наприклад, вивід тексту) необхідно застосувати 18-й метод “GetDC” з таблиці віртуальних методів відповідної відео-сторінки. Після закінчення використання функцій GDI в даній відео-сторінці необхідно викликати 27-й метод “ReleaseDC”.