DirectX è Delphi - ââåäåíèå



Àâòîð: Àçèç (JINX)
Ñïåöèàëüíî äëÿ Êîðîëåâñòâà Delphi

Êàê îáû÷íî, íà÷íó ñ îãîâîðîê.
Ïåðâîå – äëÿ ìåíÿ áîëüøàÿ ïðîáëåìà ïåðåâåñòè íåêîòîðûå òåðìèíû. Ïîýòîìó ÿ äóìàþ ìîæåò è íå ñòîèò èõ ïåðåâîäèòü. :-) Âîò ñïèñîê òåðìèíîâ, êîòîðûå âûçûâàþò ó ìåíÿ òðóäíîñòè ñ ïåðåâîäîì:

  • blitting - blit ñîêðàùåíèå îò "bit block transfer" ïåðåñûëêà áëîêîâ äàííûõ èç îäíîé îáëàñòè âèäåîïàìÿòè â äðóãóþ.
  • flip – ïåðåêëþ÷åíèå ìåæäó áóôåðàìè âèäåîïàìÿòè
  • Surface – "ïîâåðõíîñòü" – îáëàñòü âèäåîïàìÿòè
Âòîðîå – ðàçãîâîð èäåò î èñïîëüçîâàíèè DirectDraw â Delphi. Äëÿ òîãî, ÷òîáû âîñïîëüçîâàòüñÿ DirectX âîîáùå è DirectDraw â ÷àñòíîñòè, íóæíî, ÷òîáû âî-ïåðâûõ DirectX áûë óñòàíîâëåí íà êîìïüþòåðå (ñêà÷àòü åãî ìîæíî ó Microsoft íàïðèìåð, âïðî÷åì ÿ íå äóìàþ, ÷òî äëÿ ÷èòàòåëÿ áóäåò ïðîáëåìîé åãî íàéòè), âî-âòîðûõ íóæíû ôàéëû çàãîëîâêîâ DirectX – èõ ñóùåñòâóåò íåìàëî, ÿ ïî-ïðåæäíåìó ñ÷èòàþ êîìïîíåíò DelphiX îò Hiroyuki Hori – ïðåâîñõîäíûì , êðîìå òîãî, ñóùåñòâóåò îôèöèàëüíî ïîääåðæèâàåìûå Borland'îì çàãîëîâêè DirectX, ñîñòàâëåííûå â ðàìêàõ ïðîåêòà "JEDI" – ñêà÷àòü èõ ìîæíî ñ (http://www.delphi-jedi.org/DelphiGraphics/).

Òðåòüå – íåïëîõî åñëè Âû èìååòå íåêîòîðîå îáùåå ïðåäñòàâëåíèå î ðàáîòå âèäåîàäàïòåðà (íó î÷åíü îáùåå – òîíêîñòè íå íóæíû) è åùå áîëåå îáùåå î COM-òåõíîëîãèè (âñåãî-òî íóæíî çíàòü ÷òî òàêîå COM- Interface, âïðî÷åì è ýòî íå îáÿçàòåëüíî).

DirectDraw – èíòåðôåéñ DirectX, ïðåäíàçíà÷åííûé, ïî ñóùåñòâó, äëÿ óïðàâëåíèÿ âèäåîïàìÿòüþ.

Ïðåëåñòü îäíàêî çàêëþ÷àåòñÿ â òîì, ÷òî ñ DirectDraw äîñòóï ê âèäåîïàìÿòè ñòàíîâèòñÿ íå çàâèñèìûì îò òèïà èñïîëüçóåìîé âèäåîïëàòû (íó èëè ïî÷òè íå çàâèñèìûì). DirectDraw îáðàùàåòñÿ ê àïàðàòóðå ïîñðåäñòâîì hardware abstraction layer (HAL) – (óðîâíÿ àáñòàãèðîâàíèÿ îò àïïàðàòóðû). Êðîìå òîãî ñ ïîìîùüþ hardware emulation layer (HEL) (óðîâíÿ ýìóëÿöèè àïïàðàòóðû) òå âîçìîæíîñòè, êîòîðûå íå ðåàëèçîâàíû â äàííîé âèäåîêàðòå ýìóëèðóþòñÿ ïðîãðàììíî (ê ñîæàëåíèþ òóò åñòü ïàðà èñêëþ÷åíèé). Áëàãîäàðÿ òàêîìó ïîäõîäó æèçíü ïðîãðàììèñòà ñòàíîâèòñÿ ëåã÷å è âåñåëåå – åñëè, íàïðèìåð, âèäåîêàðòà ïîääåðæèâàåò hardware blitting – DirectDraw èñïîëüçóåò ýòó âîçìîæíîñòü ÷åðåç HAL – åñëè íåò – ýìóëèðóåò ÷åðåç HEL (åñòåñòâåííî ýìóëÿöèÿ âñåãäà ìåäëåííåå). Íà ðèñóíêå èç SDK ïîêàçàíû îòíîøåíèÿ ìåæäó DirectDraw, GDI, HAL è HEL.

Êàê âèäíî èç ðèñóíêà DirectDraw íàõîäèòñÿ âíå GUI. DirectDraw ìîæåò ïðåäîñòàâëÿòü îáëàñòè ïàìÿòè, ñ êîòîðûìè îí ðàáîòàåò â âèäå êîíòåêñòà óñòðîéñòâà (device context, ïðèâû÷íûé äëÿ Windows-ïðîãðàììèñòà), ÷òî ïîçâîëÿåò èñïîëüçîâàòü ôóíêöèè GDI äëÿ ðàáîòû ñ íèì (íàïðèìåð, âûâîäèòü òåêñò ñ ïîìîùüþ ôóíêöèè TextOut)

DirectDraw ìîæíî èñïîëüçîâàòü êàê ïðè ðèñîâàíèè â îêíå Windows òàê è ïðè ðàáîòå â ïîëíîýêðàííîì ðåæèìå. ß ïîêà áóäó ãîâîðèòü òîëüêî î ïîëíîýêðàííîì ðåæèìå (ñ ýêñêëþçèâíûì óðîâíåì êîîïåðàöèè).

Âèäåî ðåæèìû.

Ðåæèì îïðåäåëÿåò ðàçìåð âèäèìîé îáëàñòè ýêðàíà â ïèêñåëàõ è ÷èñëî áèò, òðåáóåìûõ äëÿ ïðåäñòàâëåíèÿ îäíîãî ïèêñåëà (“ãëóáèíà öâåòà ”) (ïðàêòè÷åñêè âñå ìîíèòîðû ïîääåðæèâàþò íàïðèìåð ðåæèì 640´480´8). ×åì áîëüøå øèðèíà è âûñîòà ýêðàíà â ïèêñåëàõ, è ÷åì áîëüøå áèò òðåáóåòñÿ äëÿ ïðåäñòàâëåíèÿ îäíîãî ïèêñåëà, òåì áîëüøå âèäåîïàìÿòè òðåáóåòñÿ äëÿ ðåæèìà.

Êðîìå òîãî âèäåîðåæèìû áûâàþò ïàëèòðîâûìè (palettized) è áåçïàëèòðîâûìè (non-palettized).  ïàëèòðîâûõ ðåæèìàõ “ãëóáèíà öâåòà” îçíà÷àåò ÷èñëî ýëåìåíòîâ ïàëèòðû äëÿ äàííîãî ðåæèìà, íàïðèìåð 8-áèòîâûé ïàëèòðîâûé ðåæèì îçíà÷àåò, ÷òî èñïîëüçóåòñÿ ïàëèòðà, ðàçìåðîì 256 ýëåìåíòîâ.  áåçïàëèòðîâîì ðåæèìå “ãëóáèíà öâåòà” îçíà÷àåò ÷èñëî áèò äëÿ ïðåäñòàâëåíèÿ öâåòà (8 áèò – 256 öâåòîâ, 16 áèò – 65535 öâåòîâ è ò.ä.)
×òîáû âûÿñíèòü êàêèå ðåæèìû ïîääåðæèâàåò âàøà âèäåîêàðòà ìîæíî èñïîëüçîâàòü èíòåôåéñ IDirectDraw4::EnumDisplayModes.

Ïðèìåð:

âûÿñíèì âñå ïîääåðæèâàåìûå âèäåîðåæèìû {èñïîëüçóåì DirectX headers îò JEDI}


function MyEnumFunction(const lpDDSurfaceDesc: TDDSurfaceDesc; lpContext:
Pointer): HResult; stdcall
var
SMode: string;
begin
SMode := IntToStr(lpDDSurfaceDesc.dwWidth) + ' X ';
SMode := SMode + IntToStr(lpDDSurfaceDesc.dwHeight) + ' X ';
SMode := SMode + IntToStr(lpDDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount);
Form1.ListBox1.Items.Append(SMode);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
DD: IDirectDraw;
hr: HRESULT;
begin
hr := DirectDrawCreate(nil, DD, nil);
if (hr = DD_OK) then
begin
ListBox1.Clear;
DD.EnumDisplayModes(0, nil, nil, MyEnumFunction);
end;
end;

{òî æå èñïîëüçóÿ êîìïîíåíò DelphiX}


procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
SMode: string;
begin
ListBox1.Clear;
for i := 0 to DXDraw1.Display.Count - 1 do
begin
SMode := IntToStr(DXDraw1.Display.Modes[i].Width) + ' X ';
SMode := SMode + IntToStr(DXDraw1.Display.Modes[i].Height) + ' X ';
SMode := SMode + IntToStr(DXDraw1.Display.Modes[i].BitCount);
ListBox1.Items.Append(SMode);
end;
end;

×óâñòâóåòå ïî÷åìó ÿ òàê ëþáëþ Hiroyuki Hori ñ åãî êîìïîíåíòîì DelphiX? :-) Äåéñòâèòåëüíî ïðîùå – íî, óâû, äîêóìåíòàöèÿ ó DelphiX î÷åíü ñêóäíàÿ (è ïî áîëüøåé ÷àñòè íà ÿïîíñêîì). Âîîáùå ãîâîðÿ, íàâåðíîå ïîëåçíî èçó÷èòü “êëàññè÷åñêèé” ñïîñîá ðàáîòû ñ DirectDraw îò JEDI – ïîòîì ëåã÷å ïîëüçîâàòüñÿ è DelphiX.

Óñòàíîâèòü âèäåîðåæèì ìîæíî ìåòîäîì IDirectDraw4::SetDisplayMode.

Óñòàíîâèì âèäåîðåæèì 640x480x8 {èñïîëüçóåì DirectX headers îò JEDI}


procedure TForm1.Button1Click(Sender: TObject);
var
DD: IDirectDraw;
DD4: IDirectDraw4;
hr: HRESULT;
begin
hr := DirectDrawCreate(nil, DD, nil);
if (hr = DD_OK) then
begin
DD.QueryInterface(IID_IDirectDraw4, DD4);
DD4.SetCooperativeLevel(Self.Handle, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN);
DD4.SetDisplayMode(640, 480, 8, 0, 0);
//DD4.RestoreDisplayMode;
end;
end;

{òî æå èñïîëüçóÿ êîìïîíåíò DelphiX}


procedure TForm1.Button1Click(Sender: TObject);
begin
DXDraw1.Display.Width := 640;
DXDraw1.Display.Height := 480;
DXDraw1.Display.BitCount := 8;
DXDraw1.Options := DXDraw1.Options + [doFullScreen];
DXDraw1.Initialize;
end;

Âîññòàíîâèòü òîò âèäåîðåæèì, ÷òî áûë óñòàíîâëåí äî âûçîâà SetDisplayMode ìîæíî ôóíêöèåé IDirectDraw4::RestoreDisplayMode. Âïðî÷åì, äëÿ ïðîãðàìì èñïîëüçóþùèõ ïîëíîýêðàííûé ðåæèì ýòî íå òàê óæ âàæíî – ïðåæíèé ðåæèì áóäåò âîññòàíîâëåí àâòîìàòè÷åñêè.

Êñòàòè ïðèìåð ñ JEDI-çàãîëîâêàìè õîðîø òåì, ÷òî äåìîíñòðèðóåò ñîçäàíèå îáúåêòà IDirectDraw ïîëó÷åíèå ññûëêè íà èíòåðôåéñ IDirectDraw4 âûçîâîì ìåòîäà QueryInterface èç IDirectDraw (IDirectDraw áåç íîìåðà – áàçîâûé (è ñàìûé ñòàðûé) èíòåðôåéñ DirectDraw; IDirectDraw4 – èíòåðôåéñ èç DirectX 6). Âîîáùå îáúåêò IDirectDraw – ýòî ñàìàÿ, ÷òî íè íà åñòü, ñåðäöåâèíà DirectDraw – îí ïðåäñòàâëÿåò ñîáîé íåêóþ àáñòðàêöèþ íàä âèäåîàäàïòåðîì – ñ ïîìîùüþ åãî ìåòîäîâ ñîçäàþòñÿ âñå îñòàëüíûå îáúåêòû DirectDraw (Surface'û, ïàëèòðû è ò.ä.).  ïðèíöèïå ìîæíî ñîçäàâàòü áîëüøå îäíîãî îáúåêòà IDirectDraw – åñëè ó Âàñ áîëüøå îäíîãî âèäåîàäàïòåðà è íåñêîëüêî ìîíèòîðîâ – â òàêîì ñëó÷àå Âû ðîâíî âî ñòîëüêî ðàç êðó÷å ìåíÿ, íà ñêîëüêî ÷èñëî Âàøèõ âèäåîàäàïòåðîâ áîëüøå 1-ãî :-) (äëÿ çíàòîêîâ COM-òåõíîëîãèè – äëÿ ýòîãî ïðè ñîçäàíèè îáúåêòà DirectDraw íóæíî ïåðåäàòü GUID äðóãîãî äèñïëåÿ). Åñëè æå ìîíèòîð ó Âàñ îäèí Âû ìîæåòå ñîçäàâàòü íåñêîëüêî îáúåêòîâ DirectDraw – âñå îíè áóäóò óïðàâëÿòü îäíèì è òåì æå âèäåîàäàïòåðîì – íî ìû ýòîò ñëó÷àé ðàññìàòðèâàòü íå áóäåì.

 ñëó÷àå æå åñëè Âû èñïîëüçóåòå Hori'âñêèé êîìïîíåíò DelphiX – ìó÷åíèÿ ñ èíèöèàëèçàöèåé è äåèíèöèàëèçàöèåé ñâîäÿòñÿ ê íóëþ – äîñòàòî÷íî ïðîñòî ðàçìåñòèòü íà ôîðìå êîìïîíåíò DXDraw – îí ñàì ïîçàáîòèòñÿ î ìåëî÷àõ æèçíè, âðîäå create è release. :-)

Èòàê, ïåðåêëþ÷àòüñÿ ìåæäó âèäåîðåæèìàìè ìû íàó÷èëèñü.

Ïîãîâîðèì òåïåðü î Surface'àõ. (ìîÿ ïîïûòêà íàéòè õîðîøèé ðóññêèé ýêâèâàëåíò ýòîìó ñëîâó, íå óâåí÷àëàñü óñïåõîì). Surface (îáúåêò DirectDrawSurface) – â áóêâàëüíîì ïåðåâîäå ïîâåðõíîñòü, ïðåäñòàâëÿåò ñîáîé ëèíåéíûé ó÷àñòîê â âèäåîïàìÿòè. (âïðî÷åì ìîæíî ñîçäàâàòü Surface'û è â ñèñòåìíîé ïàìÿòè – íî ìû íà ýòîì íå ñòàíåì çàäåðæèâàòüñÿ) Ïî óìîë÷àíèþ Surface ñîçäàåòñÿ òàê, ÷òîáû ïîëó÷èòü ìàêñèìàëüíîå áûñòðîäåéñòâèå – â âèäåîïàìÿòè, åñëè åå íå õâàòàåò – â íåëîêàëüíîé âèäåîïàìÿòè (äëÿ ïëàò AGP) à åñëè è åå íå õâàòàåò òî â ñèñòåìíîé ïàìÿòè (ýòîò ñëó÷àé ñàìûé ìåäëåííûé). Îáúåêò DirectDrawSurface êðîìå óêàçàòåëÿ íà îáëàñòü âèäåîïàìÿòè ñîäåðæèò íåñêîëüêî î÷åíü ïîëåçíûõ ìåòîäîâ (è çâåðñêè ñêîðîñòíûõ) äëÿ áûñòðîãî ïåðåíîñà êâàäðàòèêà âèäåîèçîáðàæåíèÿ èç îäíîãî ó÷àñòêà Surface'à â äðóãîé (blitting), äëÿ áûñòðîé ñìåíû îäíîãî Surface' à íà ýêðàíå äðóãèì – fliping, äëÿ ðàáîòû ñ ïàëèòðàìè è ñïðàéòàìè è äð.

Íó êàê óäàëîñü ìíå âàñ çàèíòåðåñîâàòü? Íó òîãäà äàâàéòå ðàçáåðåìñÿ – êàê ýòè ñàìûå çàìå÷àòåëüíûå Surface'û ñîçäàâàòü. Ïåðâî-íàïåðâî ñêàæåì ÷òî ó êàæäîãî Surface'à äîëæåí áûòü ðàçìåð - øèðèíà è âûñîòà. Êðîìå òîãî Surface'û óñòðîåíû òàê, ÷òî ìåæäó íà÷àëîì îäíîé ñòðî÷êè è äðóãîé ðàññòîÿíèå íå âñåãäà ðàâíîå øèðèíå. Ñêàæåì ìû ñîçäàëè Surface 640X480X8 – êàçàëîñü áû ìåæäó ïåðâîé ñòðî÷êîé è âòîðîé ðîâíî 640 áàéò – àí íåò. Ìîæåò 640 áàéò à ìîæåò è áîëüøå (ýòî çàâèñò îò òîãî ïàðíÿ, êîòîðûé ïèñàë äðàéâåð Âàøåãî âèäåîàäàïòåðà). Ðàññòîÿíèå ìåæäó ñòðî÷êàìè â áàéòàõ íàçûâàåòñÿ Pitch – ïåðåâîäèòñÿ êàê øàã. Ïî÷åìó ýòîò ñàìûé Pitch íå âñåãäà ðàâåí øèðèíå âèäíî èç ðèñóíêà:

Âèäèòå – ñïðàâà îò íàøåãî Front-bufera ìîæåò áûòü êàêîé-òî êýø, åñëè Âû âçäóìàåòå ïèñàòü íàïðÿìóþ â âèäåîïàìÿòü – ïèñàòü òóäà (â êýø) ñòðîãî íå ðåêîìåíäóåòñÿ (çà ïîñëåäñòâèÿ íèêòî íå ðó÷àåòñÿ). Êðîìå òîãî Pitch, â îòëè÷èå îò øèðèíû èçìåðÿåòñÿ â áàéòàõ à íå â ïèêñåëàõ.

Ðàç óæ çàãîâîðèëè, ïðî Front-bufer'û – ñêàæåì óæ è ïðî òî, ÷òî îäèí Surface, íàçûâàåìûé PrimarySurface, ÿâëÿåòñÿ ãëàâíûì - ýòî òîò ñàìûé Surface, êîòîðûé áûë âèäåí íà ýêðàíå â ìîìåíò êîãäà ìû íà÷àëè ñîçäàâàòü ýòè ñàìûå Surface'û.

Surface'û ìîãóò áûòü îáüåäèíåíû â òàê íàçûâàåìûå flip-öåïî÷êè. Êîãäà ïðîèñõîäèò flip ìåæäó Surface'àìè – òîò Surface, ÷òî ñåé÷àñ íà ýêðàíå, çàìåíÿåòñÿ ñëåäóþùèì â öåïî÷êå, íà ñëåäóþùåì flip'å – ýòîò – ñëåäóþùèì è ò.ä. – åñëè äîøëè äî ïîñëåäíåãî â öåïî÷êå – òî îí çàìåíÿåòñÿ íà ïåðâûé. Íó â îáû÷íîé æèçíè öåïî÷êà ìîæåò ñîñòîÿòü èç âñåãî äâóõ Surface' îâ – ïðè êàæäîì îíè ïðîñòî flip'å ñìåíÿþò äðóã äðóãà. Îáðàòèòå âíèìàíèå – ïðè flip'å ñìåíà Surface'îâ ïðîèñõîäèò íå â ðåçóëüòàòå ïåðåñûëêè âñåãî èõ ñîäåðæèìîãî, à ïðîñòî â ðåçóëüòàòå èçìåíåíèÿ óêàçàòåëåé íà îáëàñòè âèäåîïàìÿòè â âèäåîàäàïòåðå – ïîýòîìó flip âûïîëíÿåòñÿ î÷åíü áûñòðî. (Èñêëþ÷åíèå ìîæåò áûòü òîëüêî â ñëó÷àå åñëè Âû ñîçäàëè ñòîëüêî Surface'îâ, ÷òî îíè íå ïîìåñòèëèñü â âèäåîïàìÿòè – òîãäà çà äåëî âîçüìåòñÿ HEL – áåäíÿãå ïðèäåòñÿ âñå ýòî ýìóëèðîâàòü è ñêîðîñòü áóäåò – íå àõòè). C ïîìîùüþ flip ìîæíî ñîçäàâàòü àíèìàöèþ, âûâîäèì êàêóþ-òî êàðòèíêó, çàòåì â BackBuffer'e – ÷óòü-÷óòü ìåíÿåì ýòó êàðòèíêó, âûçûâàåì flip, ÷óòü-÷óòü ìåíÿåì êàðòèíêó â BackBuffer'e, âûçûâàåì flip è ò.ä. â öèêëå.

Âîò ïðèìåð ñîçäàíèÿ Flip-öåïî÷êè èç äâóõ Surface'îâ, îáüåêòîâ IDirectDrawSurface4.

(Ññûëêè íà äâà ñîçäàííûõ Surface'à ñîõðàíÿþòñÿ â ïåðåìåííûõ FPrimarySurface è FbackSurface)
(ýòîò ïðèìåð âçÿò èç ìîåé äåìî-ïðîãðàììóëüêè, êîòîðóþ Âû ìîæåò ñêà÷àòü çäåñü 169K)
{èñïîëüçóþòñÿ JEDI – çàãîëîâêè DirectX}


uses ... DDraw;
var
hr: HRESULT;
SurfaceDesc: TDDSurfaceDesc2;
DDSCaps: TDDSCAPS2;
DD: IDirectDraw;
begin
///  ...íà÷íåì, ïîìîëÿñü
hr := DirectDrawCreate(nil, DD, nil); ///ñîçäàëè DirectDraw
if (hr = DD_OK) then
begin
// Ïîëó÷èì èíòåðôåéñ IDirectDraw4
DD.QueryInterface(IID_IDirectDraw4, FDirectDraw);
// èíòåðôåéñ DirecDraw1 íàì áîëüøå íå íóæåí
DD := nil;
// Óñòàíîâèì ýêñêëþçèâíûé óðîâåíü êîîïåðàöèè è ïîëíîýêðàííûé ðåæèì
hr := FDirectDraw.SetCooperativeLevel(Handle, DDSCL_EXCLUSIVE or
DDSCL_FULLSCREEN);
if (hr = DD_OK) then
begin
hr := FDirectDraw.SetDisplayMode(640, 480, 8, 0, 0);
///ïåðåêëþ÷àåì âèäåîðåæèì íà 640X480X8
if (hr = DD_OK) then
begin
// Ñîçäàåì ãëàâíûé surface ñ îäíèì back buffer'îì
FillChar(SurfaceDesc, SizeOf(SurfaceDesc), 0);
SurfaceDesc.dwSize := SizeOf(SurfaceDesc);
///ãîâîðèì ÷òî íàì íóæíû back buffer'û
SurfaceDesc.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
////ãîâîðèì ÷òî ñîçäàåì ïåðâûé Surface
SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE
or DDSCAPS_FLIP //// âî Flip-öåïî÷êå
or DDSCAPS_COMPLEX; //// à âîîáùå áóäóò è äîïîëíèòåëüíûå Surface'û
//// ÷èñëî ýòèõ ñàìûõ äîïîëíèòåëüíûõ - 1
SurfaceDesc.dwBackBufferCount := 1;
///âñå ãîòîâî, ñîçäàåì Surface'û è çàïîìèíàåì ãëàâíûé â FPrimarySurface
hr := FDirectDraw.CreateSurface(SurfaceDesc, FPrimarySurface, nil);
if (hr = DD_OK) then
begin
// À òåïåðü ïîëó÷èì óêàçàòåëü íà back buffer (ñîçäàëè-òî äâà Surface'a ñðàçó)
ddscaps.dwCaps := DDSCAPS_BACKBUFFER;
///ïîëó÷èëè è çàïîìíèëè â FBackSurface
hr := FPrimarySurface.GetAttachedSurface(ddscaps, FBackSurface);
if (hr = DD_OK) then
begin
{Âñå íîðìàëüíî - Surface'û ñîçäàííû - âûõîäèì}
exit;
end;
end;
end;
end;
end;
{ãäå-òî áûëà îøèáêà - ñîîáùàåì îá ýòîì íåïðèÿòíîì ôàêòå}
MessageBox(Self.Handle, PChar('Íå óäàëîñü èíèöèàëèçèðîâàòü DirectDraw! ' +
ErrorString(Hr)), 'ERROR', MB_OK);
Close();
end;

Ñîçäàëè Surface'û. Òåïåðü áûëî áû èíòåðåñíî ÷òî-íèáóäü íà íèõ íàðèñîâàòü. Èíòåðåñíî òàêæå ïîïðîáîâàòü ïèñàòü ïðÿìî â âèäåîïàìÿòü.
Ïîëó÷èòü óêàçàòåëü íà îáëàñòü âèäåîïàìÿòè Surface'à ìîæíî âûçâàâ ìåòîä Lock – îí âåðíåò óêàçàòåëü â ñòðóêòóðå òèïà TDDSURFACEDESC2, êîòîðóþ ïîëó÷àåò â êà÷åñòâå ïàðàìåòðà.

Ñ ôàíòàçèåé ó ìåíÿ âñåãäà áûëî íå î÷åíü – ïîýòîìó ïðîñòî çàïîëíþ âñþ îáëàñòü Surface'îâ îäíèì öâåòîì, çàïèñàâ â âèäåîïàìÿòü îäíî è òîæå çíà÷åíèå.


var
i, j: integer;
AdresVideo: PByteArray;
SurfaceDesc: TDDSURFACEDESC2;
HR: HResult;
begin
// Ïèøåì ïðÿìî â âèäåîïàìÿòü
FillChar(SurfaceDesc, SizeOf(SurfaceDesc), 0);
SurfaceDesc.dwSize := SizeOf(SurfaceDesc);
HR := FPrimarySurface.Lock(nil, SurfaceDesc, {DDLOCK_WAIT or}
DDLOCK_SURFACEMEMORYPTR, 0);
if (HR = DD_OK) then
begin
AdresVideo := SurfaceDesc.lpSurface;
for i := 0 to SurfaceDesc.dwHeight - 1 do
begin
for j := 0 to SurfaceDesc.dwWidth - 1 do
begin
AdresVideo[j + i * SurfaceDesc.lPitch] := $FF;
end;
end;
FPrimarySurface.Unlock(nil);
end;
end;

Îáðàòèòå âíèìàíèå - êàêîé ÿ àêêóðàòíûé – ïåðåõîæó ìåæäó ñòðî÷êàìè, ó÷èòûâàÿ Pitch. Äà êñòàòè – ÿ ïðîñòî äåìîíñòðèðóþ êàê îáðàòèòñÿ ê êàæäîìó áàéòó âèäåîïàìÿòè Surface'a íà ñàìîì äåëå åñëè íóæíî çàêðàñèòü âåñü Surface îäíèì öâåòîì òî çàíîñèòü çíà÷åíèÿ â êàæäûé áàéò ñëèøêîì ìåäëåííî – äëÿ ýòîãî ìîæíî âîñïîëüçîâàòüñÿ ìåòîäîì IDirectDrawSurface4.Blt, ïåðåäàâ åìó ôëàã DDBLT_COLORFILL. Êðîìå òîãî ìîæíî âûâîäèòü íà Surface è ïðèâû÷íûìè ôóíêöèÿìè GDI – TextOut'îì íàïðèìåð:


var
DC: HDC;
begin
if (FPrimarySurface.GetDC(DC) = DD_OK) then
begin
{Âûâîäèì òåêñò íà 1-é surface, èñïîëüçóÿ GDI-ôóåêöèþ TextOut}
SetBkColor(DC, RGB(255, 255, 255));
SetTextColor(DC, RGB(255, 0, 0));
TextOut(DC, 10, 20, ' Ïðîáà ïåðà', Length(' Ïðîáà ïåðà'));
FPrimarySurface.ReleaseDC(DC);
end;
end;

Íåáîëüøîå ëèðè÷åñêîå îòñòóïëåíèå – ìåæäó âûçîâàìè LOCK è UNLOCK, à òàêæå ìåæäó GetDC è ReleaseDC âûïîëíåíèå âñåõ äðóãèõ ïðîãðàìì îñòàíàâëèâàåòñÿ (â òîì ÷èñëå è îòëàä÷èêà). Îòñþäà âûâîäû – ïåðâîå – íå ñòîèò äåëàòü ÷òî-òî ñëèøêîì äîëãî ìåæäó ýòèìè âûçîâàìè, âòîðîå, îòëàäèòü ïðîãðàììó ïîøàãîâî ìåæäó ýòèìè âûçîâàìè – íåâîçìîæíî (åñëè òîëüêî Âû íå âîîðóæèëèñü Kernel-debuger'îì).

Òåïåðü ïîïðîáóåì flip'àíóòü íàøè Surface'û. Ïåðåêëþ÷èìñÿ íà äðóãîé Surface

hr := FPrimarySurface.Flip(nil, 0);
Ìåòîä Flip ìîæåò îòêàçàòüñÿ flip'îâàòü è âåðíóòü, ñðåäè ïðî÷èõ, òàêèå êîäû îøèáîê:
  • DDERR_NOEXCLUSIVEMODE – ýòîò êîä âîçâðàòà îçíà÷àåò, ÷òî íàøà ïðîãðàììà ïîòåðÿëà ýêñêëþçèâíûé ðåæèì. Ïðîèçîéòè òàêîå ìîæåò, åñëè ìû flip'óåì â öèêëå ïî òàéìåðó, à ïîëüçîâàòåëü çà÷åì-òî óøåë èç íàøåé ïðîãðàììû, ñâåðíóâ åå èëè íàæàâ Alt-TAB.  òàêîì ñëó÷àå, ÷òîáû çðÿ íå òðàòèòü ïðîöåññîðíûå öèêëû, ëó÷øå ïîäîæäàòü åãî âîçâðàùåíèÿ, âûçûâàÿ ôóíêöèþ Sleep(0) èëè WaitMessage.
  • DDERR_SURFACELOST – ïîòåðÿ Surface'îâ ïîëüçîâàòåëü óõîäèë, íî âåðíóëñÿ, Surface'û íóæíî çàáðàòü íàçàä, âûçâàâ IDirectDraw4.RestoreAllSurfaces, ñîäåðæèìîå èõ ïðèäåòñÿ âîññòàíîâèòü.
Âñå âûøåñêàçàííîå êàñàåòñÿ êëàññè÷åñêîãî ñòèëÿ èñïîëüçîâàíèÿ DirectDraw â ñòèëå Ñ îò JEDI. Ïîêëîííèêè æå Hori'âñêîãî íàáîðà DelphiX ìîãóò ïîýêñïåðèìåíòèðîâàòü c Surface'àìè èñïîëüçóÿ TDXDraw.DDraw.SurfaceCount, TDXDraw.DDraw.Surfaces, TDXDraw.Flip – âìåñòå ñ íàáîðîì êîìïîíåíò ðàñïðîñòðàíÿþòñÿ îòëè÷íûå ïðèìåðû.

ß î÷åíü ðàä, ÷òî Âû äî÷èòàëè äî ýòîãî ìåñòà (åñëè Âû ïðîñòî ïðîëèñòàëè â êîíåö, íå ÷èòàÿ, ñäåëàéòå âèä, ÷òî ýòî íå òàê, ïîðàäóéòå ìåíÿ, ñòàðèêà) :-).
Íà ýòîì ïîêà âñå. Åñëè Âû çàèíòåðåñîâàëèñü – ñêà÷àéòå äåìî-ïðîãðàììêó è ïîýêñïåðèìåíòèðóéòå.

Ïèøèòå ìíå – [email protected] èëè [email protected] – ñ óäîâîëüñòâèåì ïðèìó Âàøè ïîæåëàíèÿ è ïðåäëîæåíèÿ (îñîáåííî åñëè ïðåäëîæèòå êàêóþ-íèáóäü ðàáîòó) :-).


Äàëåå: DXInput »»