Subversion Repositories spacemission

Rev

Rev 4 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
 unit DXDraws;
2
 
3
interface
4
 
5
{$INCLUDE DelphiXcfg.inc}
6
 
7
uses
8
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
9
  DXClass, DIB, DXTexImg, DirectX;
10
 
11
type
12
 
13
  {  EDirectDrawError  }
14
 
15
  EDirectDrawError = class(EDirectXError);
16
  EDirectDrawPaletteError = class(EDirectDrawError);
17
  EDirectDrawClipperError = class(EDirectDrawError);
18
  EDirectDrawSurfaceError = class(EDirectDrawError);
19
 
20
  {  TDirectDraw  }
21
 
22
  TDirectDrawClipper = class;
23
  TDirectDrawPalette = class;
24
  TDirectDrawSurface = class;
25
 
26
  TDirectDraw = class(TDirectX)
27
  private
28
    FIDDraw: IDirectDraw;
29
    FIDDraw4: IDirectDraw4;
30
    FIDDraw7: IDirectDraw7;
31
    FDriverCaps: TDDCaps;
32
    FHELCaps: TDDCaps;
33
    FClippers: TList;
34
    FPalettes: TList;
35
    FSurfaces: TList;
36
    function GetClipper(Index: Integer): TDirectDrawClipper;
37
    function GetClipperCount: Integer;
38
    function GetDisplayMode: TDDSurfaceDesc;
39
    function GetIDDraw: IDirectDraw;
40
    function GetIDDraw4: IDirectDraw4;
41
    function GetIDDraw7: IDirectDraw7;
42
    function GetIDraw: IDirectDraw;
43
    function GetIDraw4: IDirectDraw4;
44
    function GetIDraw7: IDirectDraw7;
45
    function GetPalette(Index: Integer): TDirectDrawPalette;
46
    function GetPaletteCount: Integer;
47
    function GetSurface(Index: Integer): TDirectDrawSurface;
48
    function GetSurfaceCount: Integer;
49
  public
50
    constructor Create(GUID: PGUID);
51
    constructor CreateEx(GUID: PGUID; DirectX7Mode: Boolean);
52
    destructor Destroy; override;
53
    class function Drivers: TDirectXDrivers;
54
    property ClipperCount: Integer read GetClipperCount;
55
    property Clippers[Index: Integer]: TDirectDrawClipper read GetClipper;
56
    property DisplayMode: TDDSurfaceDesc read GetDisplayMode;
57
    property DriverCaps: TDDCaps read FDriverCaps;
58
    property HELCaps: TDDCaps read FHELCaps;
59
    property IDDraw: IDirectDraw read GetIDDraw;
60
    property IDDraw4: IDirectDraw4 read GetIDDraw4;
61
    property IDDraw7: IDirectDraw7 read GetIDDraw7;
62
    property IDraw: IDirectDraw read GetIDraw;
63
    property IDraw4: IDirectDraw4 read GetIDraw4;
64
    property IDraw7: IDirectDraw7 read GetIDraw7;
65
    property PaletteCount: Integer read GetPaletteCount;
66
    property Palettes[Index: Integer]: TDirectDrawPalette read GetPalette;
67
    property SurfaceCount: Integer read GetSurfaceCount;
68
    property Surfaces[Index: Integer]: TDirectDrawSurface read GetSurface;
69
  end;
70
 
71
  {  TDirectDrawClipper  }
72
 
73
  TDirectDrawClipper = class(TDirectX)
74
  private
75
    FDDraw: TDirectDraw;
76
    FIDDClipper: IDirectDrawClipper;
77
    function GetIDDClipper: IDirectDrawClipper;
78
    function GetIClipper: IDirectDrawClipper;
79
    procedure SetHandle(Value: THandle);
80
    procedure SetIDDClipper(Value: IDirectDrawClipper);
81
    property Handle: THandle write SetHandle;
82
  public
83
    constructor Create(ADirectDraw: TDirectDraw);
84
    destructor Destroy; override;
85
    procedure SetClipRects(const Rects: array of TRect);
86
    property DDraw: TDirectDraw read FDDraw;
87
    property IClipper: IDirectDrawClipper read GetIClipper;
88
    property IDDClipper: IDirectDrawClipper read GetIDDClipper write SetIDDClipper;
89
  end;
90
 
91
  {  TDirectDrawPalette  }
92
 
93
  TDirectDrawPalette = class(TDirectX)
94
  private
95
    FDDraw: TDirectDraw;
96
    FIDDPalette: IDirectDrawPalette;
97
    function GetEntry(Index: Integer): TPaletteEntry;
98
    function GetIDDPalette: IDirectDrawPalette;
99
    function GetIPalette: IDirectDrawPalette;
100
    procedure SetEntry(Index: Integer; Value: TPaletteEntry);
101
    procedure SetIDDPalette(Value: IDirectDrawPalette);
102
  public
103
    constructor Create(ADirectDraw: TDirectDraw);
104
    destructor Destroy; override;
105
    function CreatePalette(Caps: DWORD; const Entries): Boolean;
106
    function GetEntries(StartIndex, NumEntries: Integer; var Entries): Boolean;
107
    procedure LoadFromDIB(DIB: TDIB);
108
    procedure LoadFromFile(const FileName: string);
109
    procedure LoadFromStream(Stream: TStream);
110
    function SetEntries(StartIndex, NumEntries: Integer; const Entries): Boolean;
111
    property DDraw: TDirectDraw read FDDraw;
112
    property Entries[Index: Integer]: TPaletteEntry read GetEntry write SetEntry;
113
    property IDDPalette: IDirectDrawPalette read GetIDDPalette write SetIDDPalette;
114
    property IPalette: IDirectDrawPalette read GetIPalette;
115
  end;
116
 
117
  {  TDirectDrawSurfaceCanvas  }
118
 
119
  TDirectDrawSurfaceCanvas = class(TCanvas)
120
  private
121
    FDC: HDC;
122
    FSurface: TDirectDrawSurface;
123
  protected
124
    procedure CreateHandle; override;
125
  public
126
    constructor Create(ASurface: TDirectDrawSurface);
127
    destructor Destroy; override;
128
    procedure Release;
129
  end;
130
 
131
  {  TDirectDrawSurface  }
132
 
133
  TDirectDrawSurface = class(TDirectX)
134
  private
135
    FCanvas: TDirectDrawSurfaceCanvas;
136
    FHasClipper: Boolean;
137
    FDDraw: TDirectDraw;
138
    FIDDSurface: IDirectDrawSurface;
139
    FIDDSurface4: IDirectDrawSurface4;
140
    FIDDSurface7: IDirectDrawSurface7;
141
    FSystemMemory: Boolean;
142
    FStretchDrawClipper: IDirectDrawClipper;
143
    FSurfaceDesc: TDDSurfaceDesc;
144
    FGammaControl: IDirectDrawGammaControl;
145
    FLockSurfaceDesc: TDDSurfaceDesc;
146
    FLockCount: Integer;
147
    function GetBitCount: Integer;
148
    function GetCanvas: TDirectDrawSurfaceCanvas;
149
    function GetClientRect: TRect;
150
    function GetHeight: Integer;
151
    function GetIDDSurface: IDirectDrawSurface;
152
    function GetIDDSurface4: IDirectDrawSurface4;
153
    function GetIDDSurface7: IDirectDrawSurface7;
154
    function GetISurface: IDirectDrawSurface;
155
    function GetISurface4: IDirectDrawSurface4;
156
    function GetISurface7: IDirectDrawSurface7;
157
    function GetPixel(X, Y: Integer): Longint;
158
    function GetWidth: Integer;
159
    procedure SetClipper(Value: TDirectDrawClipper);
160
    procedure SetColorKey(Flags: DWORD; const Value: TDDColorKey);
161
    procedure SetIDDSurface(Value: IDirectDrawSurface);
162
    procedure SetIDDSurface4(Value: IDirectDrawSurface4);
163
    procedure SetIDDSurface7(Value: IDirectDrawSurface7);
164
    procedure SetPalette(Value: TDirectDrawPalette);
165
    procedure SetPixel(X, Y: Integer; Value: Longint);
166
    procedure SetTransparentColor(Col: Longint);
167
  public
168
    constructor Create(ADirectDraw: TDirectDraw);
169
    destructor Destroy; override;
170
    procedure Assign(Source: TPersistent); override;
171
    procedure AssignTo(Dest: TPersistent); override;
172
    function Blt(const DestRect, SrcRect: TRect; Flags: DWORD;
173
      const DF: TDDBltFX; Source: TDirectDrawSurface): Boolean;
174
    function BltFast(X, Y: Integer; const SrcRect: TRect;
175
      Flags: DWORD; Source: TDirectDrawSurface): Boolean;
176
    function ColorMatch(Col: TColor): Integer;
177
{$IFDEF DelphiX_Spt4}
178
    function CreateSurface(const SurfaceDesc: TDDSurfaceDesc): Boolean; overload;
179
    function CreateSurface(const SurfaceDesc: TDDSurfaceDesc2): Boolean; overload;
180
{$ELSE}
181
    function CreateSurface(const SurfaceDesc: TDDSurfaceDesc): Boolean;
182
{$ENDIF}
183
{$IFDEF DelphiX_Spt4}
184
    procedure Draw(X, Y: Integer; SrcRect: TRect; Source: TDirectDrawSurface; Transparent: Boolean=True); overload;
185
    procedure Draw(X, Y: Integer; Source: TDirectDrawSurface; Transparent: Boolean=True); overload;
186
    procedure StretchDraw(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
187
      Transparent: Boolean=True); overload;
188
    procedure StretchDraw(const DestRect: TRect; Source: TDirectDrawSurface;
189
      Transparent: Boolean=True); overload;
190
{$ELSE}
191
    procedure Draw(X, Y: Integer; SrcRect: TRect; Source: TDirectDrawSurface;
192
      Transparent: Boolean);
193
    procedure StretchDraw(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
194
      Transparent: Boolean);
195
{$ENDIF}
196
    procedure DrawAdd(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
197
      Transparent: Boolean; Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
198
    procedure DrawAlpha(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
199
      Transparent: Boolean; Alpha: Integer);
200
    procedure DrawSub(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
201
      Transparent: Boolean; Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
202
    procedure DrawRotate(X, Y, Width, Height: Integer; const SrcRect: TRect;
203
      Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle: Integer);
204
    procedure DrawRotateAdd(X, Y, Width, Height: Integer; const SrcRect: TRect;
205
      Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle: Integer;
206
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
207
    procedure DrawRotateAlpha(X, Y, Width, Height: Integer; const SrcRect: TRect;
208
      Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle: Integer;
209
      Alpha: Integer);
210
    procedure DrawRotateSub(X, Y, Width, Height: Integer; const SrcRect: TRect;
211
      Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle: Integer;
212
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
213
    procedure DrawWaveX(X, Y, Width, Height: Integer; const SrcRect: TRect;
214
      Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph: Integer);
215
    procedure DrawWaveXAdd(X, Y, Width, Height: Integer; const SrcRect: TRect;
216
      Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph: Integer;
217
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
218
    procedure DrawWaveXAlpha(X, Y, Width, Height: Integer; const SrcRect: TRect;
219
      Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph: Integer;
220
      Alpha: Integer);
221
    procedure DrawWaveXSub(X, Y, Width, Height: Integer; const SrcRect: TRect;
222
      Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph: Integer;
223
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
224
    procedure Fill(DevColor: Longint);
225
    procedure FillRect(const Rect: TRect; DevColor: Longint);
226
    procedure FillRectAdd(const DestRect: TRect; Color: TColor);
227
    procedure FillRectAlpha(const DestRect: TRect; Color: TColor; Alpha: Integer);
228
    procedure FillRectSub(const DestRect: TRect; Color: TColor);
229
    procedure LoadFromDIB(DIB: TDIB);
230
    procedure LoadFromDIBRect(DIB: TDIB; AWidth, AHeight: Integer; const SrcRect: TRect);
231
    procedure LoadFromGraphic(Graphic: TGraphic);
232
    procedure LoadFromGraphicRect(Graphic: TGraphic; AWidth, AHeight: Integer; const SrcRect: TRect);
233
    procedure LoadFromFile(const FileName: string);
234
    procedure LoadFromStream(Stream: TStream);
235
{$IFDEF DelphiX_Spt4}
236
    function Lock(const Rect: TRect; var SurfaceDesc: TDDSurfaceDesc): Boolean; overload;
237
    function Lock(var SurfaceDesc: TDDSurfaceDesc): Boolean; overload;
238
{$ELSE}
239
    function Lock(const Rect: TRect; var SurfaceDesc: TDDSurfaceDesc): Boolean;
240
{$ENDIF}
241
    procedure UnLock;
242
    function Restore: Boolean;
243
    procedure SetSize(AWidth, AHeight: Integer);
244
    property BitCount: Integer read GetBitCount;
245
    property Canvas: TDirectDrawSurfaceCanvas read GetCanvas;
246
    property ClientRect: TRect read GetClientRect;
247
    property Clipper: TDirectDrawClipper write SetClipper;
248
    property ColorKey[Flags: DWORD]: TDDColorKey write SetColorKey;
249
    property DDraw: TDirectDraw read FDDraw;
250
    property GammaControl: IDirectDrawGammaControl read FGammaControl;
251
    property Height: Integer read GetHeight;
252
    property IDDSurface: IDirectDrawSurface read GetIDDSurface write SetIDDSurface;
253
    property IDDSurface4: IDirectDrawSurface4 read GetIDDSurface4 write SetIDDSurface4;
254
    property IDDSurface7: IDirectDrawSurface7 read GetIDDSurface7 write SetIDDSurface7;
255
    property ISurface: IDirectDrawSurface read GetISurface;
256
    property ISurface4: IDirectDrawSurface4 read GetISurface4;
257
    property ISurface7: IDirectDrawSurface7 read GetISurface7;
258
    property Palette: TDirectDrawPalette write SetPalette;
259
    property Pixels[X, Y: Integer]: Longint read GetPixel write SetPixel;
260
    property SurfaceDesc: TDDSurfaceDesc read FSurfaceDesc;
261
    property SystemMemory: Boolean read FSystemMemory write FSystemMemory;
262
    property TransparentColor: Longint write SetTransparentColor;
263
    property Width: Integer read GetWidth;
264
  end;
265
 
266
  {  TDXDrawDisplay  }
267
 
268
  TCustomDXDraw = class;
269
 
270
  TDXDrawDisplayMode = class(TCollectionItem)
271
  private
272
    FSurfaceDesc: TDDSurfaceDesc;
273
    function GetBitCount: Integer;
274
    function GetHeight: Integer;
275
    function GetWidth: Integer;
276
  public
277
    property BitCount: Integer read GetBitCount;
278
    property Height: Integer read GetHeight;
279
    property SurfaceDesc: TDDSurfaceDesc read FSurfaceDesc;
280
    property Width: Integer read GetWidth;
281
  end;
282
 
283
  TDXDrawDisplay = class(TPersistent)
284
  private
285
    FBitCount: Integer;
286
    FDXDraw: TCustomDXDraw;
287
    FHeight: Integer;
288
    FModes: TCollection;
289
    FWidth: Integer;
290
    FFixedBitCount: Boolean;
291
    FFixedRatio: Boolean;
292
    FFixedSize: Boolean;
293
    function GetCount: Integer;
294
    function GetMode: TDXDrawDisplayMode;
295
    function GetMode2(Index: Integer): TDXDrawDisplayMode;
296
    procedure LoadDisplayModes;
297
    procedure SetBitCount(Value: Integer);
298
    procedure SetHeight(Value: Integer);
299
    procedure SetWidth(Value: Integer);
300
    function SetSize(AWidth, AHeight, ABitCount: Integer): Boolean;
301
    function DynSetSize(AWidth, AHeight, ABitCount: Integer): Boolean;
302
  public
303
    constructor Create(ADXDraw: TCustomDXDraw);
304
    destructor Destroy; override;
305
    procedure Assign(Source: TPersistent); override;
306
    function IndexOf(Width, Height, BitCount: Integer): Integer;
307
    property Count: Integer read GetCount;
308
    property Mode: TDXDrawDisplayMode read GetMode;
309
    property Modes[Index: Integer]: TDXDrawDisplayMode read GetMode2; default;
310
  published
311
    property BitCount: Integer read FBitCount write SetBitCount default 8;
312
    property FixedBitCount: Boolean read FFixedBitCount write FFixedBitCount;
313
    property FixedRatio: Boolean read FFixedRatio write FFixedRatio;
314
    property FixedSize: Boolean read FFixedSize write FFixedSize;
315
    property Height: Integer read FHeight write SetHeight default 480;
316
    property Width: Integer read FWidth write SetWidth default 640;
317
  end;
318
 
319
  TDirectDrawDisplay = TDXDrawDisplay;
320
  TDirectDrawDisplayMode = TDXDrawDisplayMode;
321
 
322
  {  EDXDrawError  }
323
 
324
  EDXDrawError = class(Exception);
325
 
326
  {  TCustomDXDraw  }
327
 
328
  TDXDrawOption = (doFullScreen, doNoWindowChange, doAllowReboot, doWaitVBlank,
329
    doAllowPalette256, doSystemMemory, doStretch, doCenter, doFlip,
330
    do3D, doDirectX7Mode, doRetainedMode, doHardware, doSelectDriver, doZBuffer);
331
 
332
  TDXDrawOptions = set of TDXDrawOption;
333
 
334
  TDXDrawNotifyType = (dxntDestroying, dxntInitializing, dxntInitialize, dxntInitializeSurface,
335
    dxntFinalize, dxntFinalizeSurface, dxntRestore, dxntSetSurfaceSize);
336
 
337
  TDXDrawNotifyEvent = procedure(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType) of object;
338
 
339
  TCustomDXDraw = class(TCustomControl)
340
  private
341
    FAutoInitialize: Boolean;
342
    FAutoSize: Boolean;
343
    FCalledDoInitialize: Boolean;
344
    FCalledDoInitializeSurface: Boolean;
345
    FForm: TCustomForm;
346
    FNotifyEventList: TList;
347
    FInitialized: Boolean;
348
    FInitialized2: Boolean;
349
    FInternalInitialized: Boolean;
350
    FUpdating: Boolean;
351
    FSubClass: TControlSubClass;
352
    FNowOptions: TDXDrawOptions;
353
    FOptions: TDXDrawOptions;
354
    FOnFinalize: TNotifyEvent;
355
    FOnFinalizeSurface: TNotifyEvent;
356
    FOnInitialize: TNotifyEvent;
357
    FOnInitializeSurface: TNotifyEvent;
358
    FOnInitializing: TNotifyEvent;
359
    FOnRestoreSurface: TNotifyEvent;
360
    FOffNotifyRestore: Integer;
361
    { DirectDraw }
362
    FDXDrawDriver: TObject;
363
    FDriver: PGUID;
364
    FDriverGUID: TGUID;
365
    FDDraw: TDirectDraw;
366
    FDisplay: TDXDrawDisplay;
367
    FClipper: TDirectDrawClipper;
368
    FPalette: TDirectDrawPalette;
369
    FPrimary: TDirectDrawSurface;
370
    FSurface: TDirectDrawSurface;
371
    FSurfaceWidth: Integer;
372
    FSurfaceHeight: Integer;
373
    { Direct3D }
374
    FD3D: IDirect3D;
375
    FD3D2: IDirect3D2;
376
    FD3D3: IDirect3D3;
377
    FD3D7: IDirect3D7;
378
    FD3DDevice: IDirect3DDevice;
379
    FD3DDevice2: IDirect3DDevice2;
380
    FD3DDevice3: IDirect3DDevice3;
381
    FD3DDevice7: IDirect3DDevice7;
382
    FD3DRM: IDirect3DRM;
383
    FD3DRM2: IDirect3DRM2;
384
    FD3DRM3: IDirect3DRM3;
385
    FD3DRMDevice: IDirect3DRMDevice;
386
    FD3DRMDevice2: IDirect3DRMDevice2;
387
    FD3DRMDevice3: IDirect3DRMDevice3;
388
    FCamera: IDirect3DRMFrame;
389
    FScene: IDirect3DRMFrame;
390
    FViewport: IDirect3DRMViewport;
391
    FZBuffer: TDirectDrawSurface;
392
    procedure FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
393
    function GetCanDraw: Boolean;
394
    function GetCanPaletteAnimation: Boolean;
395
    function GetSurfaceHeight: Integer;
396
    function GetSurfaceWidth: Integer;
397
    procedure NotifyEventList(NotifyType: TDXDrawNotifyType);
398
    procedure SetAutoSize(Value: Boolean);
399
    procedure SetColorTable(const ColorTable: TRGBQuads);
400
    procedure SetCooperativeLevel;
401
    procedure SetDisplay(Value: TDXDrawDisplay);
402
    procedure SetDriver(Value: PGUID);
403
    procedure SetOptions(Value: TDXDrawOptions);
404
    procedure SetSurfaceHeight(Value: Integer);
405
    procedure SetSurfaceWidth(Value: Integer);
406
    function TryRestore: Boolean;
407
    procedure WMCreate(var Message: TMessage); message WM_CREATE;
408
  protected
409
    procedure DoFinalize; virtual;
410
    procedure DoFinalizeSurface; virtual;
411
    procedure DoInitialize; virtual;
412
    procedure DoInitializeSurface; virtual;
413
    procedure DoInitializing; virtual;
414
    procedure DoRestoreSurface; virtual;
415
    procedure Loaded; override;
416
    procedure Paint; override;
417
    function PaletteChanged(Foreground: Boolean): Boolean; override;
418
    procedure SetParent(AParent: TWinControl); override;
419
  public
420
    ColorTable: TRGBQuads;
421
    DefColorTable: TRGBQuads;
422
    constructor Create(AOwner: TComponent); override;
423
    destructor Destroy; override;
424
    class function Drivers: TDirectXDrivers;
425
    procedure Finalize;
426
    procedure Flip;
427
    procedure Initialize;
428
    procedure Render;
429
    procedure Restore;
430
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
431
    procedure SetSize(ASurfaceWidth, ASurfaceHeight: Integer);
432
    procedure UpdatePalette;
433
    procedure RegisterNotifyEvent(NotifyEvent: TDXDrawNotifyEvent);
434
    procedure UnRegisterNotifyEvent(NotifyEvent: TDXDrawNotifyEvent);
435
 
436
    property AutoInitialize: Boolean read FAutoInitialize write FAutoInitialize;
437
    property AutoSize: Boolean read FAutoSize write SetAutoSize;
438
    property Camera: IDirect3DRMFrame read FCamera;
439
    property CanDraw: Boolean read GetCanDraw;
440
    property CanPaletteAnimation: Boolean read GetCanPaletteAnimation;
441
    property Clipper: TDirectDrawClipper read FClipper;
442
    property Color;
443
    property D3D: IDirect3D read FD3D;
444
    property D3D2: IDirect3D2 read FD3D2;
445
    property D3D3: IDirect3D3 read FD3D3;
446
    property D3D7: IDirect3D7 read FD3D7;
447
    property D3DDevice: IDirect3DDevice read FD3DDevice;
448
    property D3DDevice2: IDirect3DDevice2 read FD3DDevice2;
449
    property D3DDevice3: IDirect3DDevice3 read FD3DDevice3;
450
    property D3DDevice7: IDirect3DDevice7 read FD3DDevice7;
451
    property D3DRM: IDirect3DRM read FD3DRM;
452
    property D3DRM2: IDirect3DRM2 read FD3DRM2;
453
    property D3DRM3: IDirect3DRM3 read FD3DRM3;
454
    property D3DRMDevice: IDirect3DRMDevice read FD3DRMDevice;
455
    property D3DRMDevice2: IDirect3DRMDevice2 read FD3DRMDevice2;
456
    property D3DRMDevice3: IDirect3DRMDevice3 read FD3DRMDevice3;
457
    property DDraw: TDirectDraw read FDDraw;
458
    property Display: TDXDrawDisplay read FDisplay write SetDisplay;
459
    property Driver: PGUID read FDriver write SetDriver;
460
    property Initialized: Boolean read FInitialized;
461
    property NowOptions: TDXDrawOptions read FNowOptions;
462
    property OnFinalize: TNotifyEvent read FOnFinalize write FOnFinalize;
463
    property OnFinalizeSurface: TNotifyEvent read FOnFinalizeSurface write FOnFinalizeSurface;
464
    property OnInitialize: TNotifyEvent read FOnInitialize write FOnInitialize;
465
    property OnInitializeSurface: TNotifyEvent read FOnInitializeSurface write FOnInitializeSurface;
466
    property OnInitializing: TNotifyEvent read FOnInitializing write FOnInitializing;
467
    property OnRestoreSurface: TNotifyEvent read FOnRestoreSurface write FOnRestoreSurface;
468
    property Options: TDXDrawOptions read FOptions write SetOptions;
469
    property Palette: TDirectDrawPalette read FPalette;
470
    property Primary: TDirectDrawSurface read FPrimary;
471
    property Scene: IDirect3DRMFrame read FScene;
472
    property Surface: TDirectDrawSurface read FSurface;
473
    property SurfaceHeight: Integer read GetSurfaceHeight write SetSurfaceHeight default 480;
474
    property SurfaceWidth: Integer read GetSurfaceWidth write SetSurfaceWidth default 640;
475
    property Viewport: IDirect3DRMViewport read FViewport;
476
    property ZBuffer: TDirectDrawSurface read FZBuffer;
477
  end;
478
 
479
  {  TDXDraw  }
480
 
481
  TDXDraw = class(TCustomDXDraw)
482
  published
483
    property AutoInitialize;
484
    property AutoSize;
485
    property Color;
486
    property Display;
487
    property Options;
488
    property SurfaceHeight;
489
    property SurfaceWidth;
490
    property OnFinalize;
491
    property OnFinalizeSurface;
492
    property OnInitialize;
493
    property OnInitializeSurface;
494
    property OnInitializing;
495
    property OnRestoreSurface;
496
 
497
    property Align;
498
    {$IFDEF DelphiX_Spt4}property Anchors;{$ENDIF}
499
    {$IFDEF DelphiX_Spt4}property Constraints;{$ENDIF}
500
    property DragCursor;
501
    property DragMode;
502
    property Enabled;
503
    property ParentShowHint;
504
    property PopupMenu;
505
    property ShowHint;
506
    property TabOrder;
507
    property TabStop;
508
    property Visible;
509
    property OnClick;
510
    property OnDblClick;
511
    property OnDragDrop;
512
    property OnDragOver;
513
    property OnEndDrag;
514
    property OnEnter;
515
    property OnExit;
516
    property OnKeyDown;
517
    property OnKeyPress;
518
    property OnKeyUp;
519
    property OnMouseDown;
520
    property OnMouseMove;
521
    property OnMouseUp;
522
    {$IFDEF DelphiX_Spt4}property OnResize;{$ENDIF}
523
    property OnStartDrag;
524
  end;
525
 
526
  {  EDX3DError  }
527
 
528
  EDX3DError = class(Exception);
529
 
530
  {  TCustomDX3D  }
531
 
532
  TDX3DOption = (toRetainedMode, toSystemMemory, toHardware, toSelectDriver, toZBuffer);
533
 
534
  TDX3DOptions = set of TDX3DOption;
535
 
536
  TCustomDX3D = class(TComponent)
537
  private
538
    FAutoSize: Boolean;
539
    FCamera: IDirect3DRMFrame;
540
    FD3D: IDirect3D;
541
    FD3D2: IDirect3D2;
542
    FD3D3: IDirect3D3;
543
    FD3D7: IDirect3D7;
544
    FD3DDevice: IDirect3DDevice;
545
    FD3DDevice2: IDirect3DDevice2;
546
    FD3DDevice3: IDirect3DDevice3;
547
    FD3DDevice7: IDirect3DDevice7;
548
    FD3DRM: IDirect3DRM;
549
    FD3DRM2: IDirect3DRM2;
550
    FD3DRM3: IDirect3DRM3;
551
    FD3DRMDevice: IDirect3DRMDevice;
552
    FD3DRMDevice2: IDirect3DRMDevice2;
553
    FD3DRMDevice3: IDirect3DRMDevice3;
554
    FDXDraw: TCustomDXDraw;
555
    FInitFlag: Boolean;
556
    FInitialized: Boolean;
557
    FNowOptions: TDX3DOptions;
558
    FOnFinalize: TNotifyEvent;
559
    FOnInitialize: TNotifyEvent;
560
    FOptions: TDX3DOptions;
561
    FScene: IDirect3DRMFrame;
562
    FSurface: TDirectDrawSurface;
563
    FSurfaceHeight: Integer;
564
    FSurfaceWidth: Integer;
565
    FViewport: IDirect3DRMViewport;
566
    FZBuffer: TDirectDrawSurface;
567
    procedure Finalize;
568
    procedure Initialize;
569
    procedure DXDrawNotifyEvent(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType);
570
    function GetCanDraw: Boolean;
571
    function GetSurfaceHeight: Integer;
572
    function GetSurfaceWidth: Integer;
573
    procedure SetAutoSize(Value: Boolean);
574
    procedure SetDXDraw(Value: TCustomDXDraw);
575
    procedure SetOptions(Value: TDX3DOptions);
576
    procedure SetSurfaceHeight(Value: Integer);
577
    procedure SetSurfaceWidth(Value: Integer);
578
  protected
579
    procedure DoFinalize; virtual;
580
    procedure DoInitialize; virtual;
581
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
582
  public
583
    constructor Create(AOwner: TComponent); override;
584
    destructor Destroy; override;
585
    procedure Render;
586
    procedure SetSize(ASurfaceWidth, ASurfaceHeight: Integer);
587
    property AutoSize: Boolean read FAutoSize write SetAutoSize;
588
    property Camera: IDirect3DRMFrame read FCamera;
589
    property CanDraw: Boolean read GetCanDraw;
590
    property D3D: IDirect3D read FD3D;
591
    property D3D2: IDirect3D2 read FD3D2;
592
    property D3D3: IDirect3D3 read FD3D3;
593
    property D3D7: IDirect3D7 read FD3D7;
594
    property D3DDevice: IDirect3DDevice read FD3DDevice;
595
    property D3DDevice2: IDirect3DDevice2 read FD3DDevice2;
596
    property D3DDevice3: IDirect3DDevice3 read FD3DDevice3;
597
    property D3DDevice7: IDirect3DDevice7 read FD3DDevice7;
598
    property D3DRM: IDirect3DRM read FD3DRM;
599
    property D3DRM2: IDirect3DRM2 read FD3DRM2;
600
    property D3DRM3: IDirect3DRM3 read FD3DRM3;
601
    property D3DRMDevice: IDirect3DRMDevice read FD3DRMDevice;
602
    property D3DRMDevice2: IDirect3DRMDevice2 read FD3DRMDevice2;
603
    property D3DRMDevice3: IDirect3DRMDevice3 read FD3DRMDevice3;
604
    property DXDraw: TCustomDXDraw read FDXDraw write SetDXDraw;
605
    property Initialized: Boolean read FInitialized;
606
    property NowOptions: TDX3DOptions read FNowOptions;
607
    property OnFinalize: TNotifyEvent read FOnFinalize write FOnFinalize;
608
    property OnInitialize: TNotifyEvent read FOnInitialize write FOnInitialize;
609
    property Options: TDX3DOptions read FOptions write SetOptions;
610
    property Scene: IDirect3DRMFrame read FScene;
611
    property Surface: TDirectDrawSurface read FSurface;
612
    property SurfaceHeight: Integer read GetSurfaceHeight write SetSurfaceHeight default 480;
613
    property SurfaceWidth: Integer read GetSurfaceWidth write SetSurfaceWidth default 640;
614
    property Viewport: IDirect3DRMViewport read FViewport;
615
    property ZBuffer: TDirectDrawSurface read FZBuffer;
616
  end;
617
 
618
  {  TDX3D  }
619
 
620
  TDX3D = class(TCustomDX3D)
621
  published
622
    property AutoSize;
623
    property DXDraw;
624
    property Options;
625
    property SurfaceHeight;
626
    property SurfaceWidth;
627
    property OnFinalize;
628
    property OnInitialize;
629
  end;
630
 
631
  {  EDirect3DTextureError  }
632
 
633
  EDirect3DTextureError = class(Exception);
634
 
635
  {  TDirect3DTexture  }
636
 
637
  TDirect3DTexture = class
638
  private
639
    FBitCount: DWORD;
640
    FDXDraw: TComponent;
641
    FEnumFormatFlag: Boolean;
642
    FFormat: TDDSurfaceDesc;
643
    FGraphic: TGraphic;
644
    FHandle: TD3DTextureHandle;
645
    FPaletteEntries: TPaletteEntries;
646
    FSurface: TDirectDrawSurface;
647
    FTexture: IDirect3DTexture;
648
    FTransparentColor: TColor;
649
    procedure Clear;
650
    procedure DXDrawNotifyEvent(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType);
651
    function GetHandle: TD3DTextureHandle;
652
    function GetSurface: TDirectDrawSurface;
653
    function GetTexture: IDirect3DTexture;
654
    procedure SetTransparentColor(Value: TColor);
655
  public
656
    constructor Create(Graphic: TGraphic; DXDraw: TComponent);
657
    destructor Destroy; override;
658
    procedure Restore;
659
    property Handle: TD3DTextureHandle read GetHandle;
660
    property Surface: TDirectDrawSurface read GetSurface;
661
    property TransparentColor: TColor read FTransparentColor write SetTransparentColor;
662
    property Texture: IDirect3DTexture read GetTexture;
663
  end;
664
 
665
  {  TDirect3DTexture2  }
666
 
667
  TDirect3DTexture2 = class
668
  private
669
    FDXDraw: TCustomDXDraw;
670
    FSrcImage: TObject;
671
    FImage: TDXTextureImage;
672
    FImage2: TDXTextureImage;
673
    FAutoFreeGraphic: Boolean;
674
    FSurface: TDirectDrawSurface;
675
    FTextureFormat: TDDSurfaceDesc2;
676
    FMipmap: Boolean;
677
    FTransparent: Boolean;
678
    FTransparentColor: TColorRef;
679
    FUseMipmap: Boolean;
680
    FUseColorKey: Boolean;
681
    FOnRestoreSurface: TNotifyEvent;
682
    FNeedLoadTexture: Boolean;
683
    FEnumTextureFormatFlag: Boolean;
684
    FD3DDevDesc: TD3DDeviceDesc;
685
    procedure DXDrawNotifyEvent(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType);
686
    procedure SetDXDraw(ADXDraw: TCustomDXDraw);
687
    procedure LoadSubTexture(Dest: IDirectDrawSurface4; SrcImage: TDXTextureImage);
688
    procedure SetColorKey;
689
    procedure SetDIB(DIB: TDIB);
690
    function GetIsMipmap: Boolean;
691
    function GetSurface: TDirectDrawSurface;
692
    function GetTransparent: Boolean;
693
    procedure SetTransparent(Value: Boolean);
694
    procedure SetTransparentColor(Value: TColorRef);
695
  protected
696
    procedure DoRestoreSurface; virtual;
697
  public
698
    constructor Create(ADXDraw: TCustomDXDraw; Graphic: TObject; AutoFreeGraphic: Boolean);
699
    constructor CreateFromFile(ADXDraw: TCustomDXDraw; const FileName: string);
700
    constructor CreateVideoTexture(ADXDraw: TCustomDXDraw);
701
    destructor Destroy; override;
702
    procedure Finalize;
703
    procedure Load;
704
    procedure Initialize;
705
    property IsMipmap: Boolean read GetIsMipmap;
706
    property Surface: TDirectDrawSurface read GetSurface;
707
    property TextureFormat: TDDSurfaceDesc2 read FTextureFormat write FTextureFormat;
708
    property Transparent: Boolean read GetTransparent write SetTransparent;
709
    property TransparentColor: TColorRef read FTransparentColor write SetTransparentColor;
710
    property OnRestoreSurface: TNotifyEvent read FOnRestoreSurface write FOnRestoreSurface;
711
  end;
712
 
713
  {  EDirect3DRMUserVisualError  }
714
 
715
  EDirect3DRMUserVisualError = class(Exception);
716
 
717
  {  TDirect3DRMUserVisual  }
718
 
719
  TDirect3DRMUserVisual = class
720
  private
721
    FUserVisual: IDirect3DRMUserVisual;
722
  protected
723
    function DoRender(Reason: TD3DRMUserVisualReason;
724
      D3DRMDev: IDirect3DRMDevice; D3DRMView: IDirect3DRMViewport): HRESULT; virtual;
725
  public
726
    constructor Create(D3DRM: IDirect3DRM);
727
    destructor Destroy; override;
728
    property UserVisual: IDirect3DRMUserVisual read FUserVisual;
729
  end;
730
 
731
  {  EPictureCollectionError  }
732
 
733
  EPictureCollectionError = class(Exception);
734
 
735
  {  TPictureCollectionItem  }
736
 
737
  TPictureCollection = class;
738
 
739
  TPictureCollectionItem = class(THashCollectionItem)
740
  private
741
    FPicture: TPicture;
742
    FInitialized: Boolean;
743
    FPatternHeight: Integer;
744
    FPatternWidth: Integer;
745
    FPatterns: TCollection;
746
    FSkipHeight: Integer;
747
    FSkipWidth: Integer;
748
    FSurfaceList: TList;
749
    FSystemMemory: Boolean;
750
    FTransparent: Boolean;
751
    FTransparentColor: TColor;
752
    procedure ClearSurface;
753
    procedure Finalize;
754
    procedure Initialize;
755
    function GetHeight: Integer;
756
    function GetPictureCollection: TPictureCollection;
757
    function GetPatternRect(Index: Integer): TRect;
758
    function GetPatternSurface(Index: Integer): TDirectDrawSurface;
759
    function GetPatternCount: Integer;
760
    function GetWidth: Integer;
761
    procedure SetPicture(Value: TPicture);
762
    procedure SetTransparentColor(Value: TColor);
763
  public
764
    constructor Create(Collection: TCollection); override;
765
    destructor Destroy; override;
766
    procedure Assign(Source: TPersistent); override;
767
    procedure Draw(Dest: TDirectDrawSurface; X, Y: Integer; PatternIndex: Integer);
768
    procedure StretchDraw(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer);
769
    procedure DrawAdd(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer;
770
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
771
    procedure DrawAlpha(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer;
772
      Alpha: Integer);
773
    procedure DrawSub(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer;
774
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
775
    procedure DrawRotate(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
776
      CenterX, CenterY: Double; Angle: Integer);
777
    procedure DrawRotateAdd(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
778
      CenterX, CenterY: Double; Angle: Integer;
779
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
780
    procedure DrawRotateAlpha(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
781
      CenterX, CenterY: Double; Angle: Integer;
782
      Alpha: Integer);
783
    procedure DrawRotateSub(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
784
      CenterX, CenterY: Double; Angle: Integer;
785
      Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
786
    procedure DrawWaveX(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
787
      amp, Len, ph: Integer);
788
    procedure DrawWaveXAdd(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
789
      amp, Len, ph: Integer; Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
790
    procedure DrawWaveXAlpha(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
791
      amp, Len, ph: Integer; Alpha: Integer);
792
    procedure DrawWaveXSub(Dest: TDirectDrawSurface; X, Y, Width, Height: Integer; PatternIndex: Integer;
793
      amp, Len, ph: Integer; Alpha: Integer{$IFDEF DelphiX_Spt4}=255{$ENDIF});
794
    procedure Restore;
795
    property Height: Integer read GetHeight;
796
    property Initialized: Boolean read FInitialized;
797
    property PictureCollection: TPictureCollection read GetPictureCollection;
798
    property PatternCount: Integer read GetPatternCount;
799
    property PatternRects[Index: Integer]: TRect read GetPatternRect;
800
    property PatternSurfaces[Index: Integer]: TDirectDrawSurface read GetPatternSurface;
801
    property Width: Integer read GetWidth;
802
  published
803
    property PatternHeight: Integer read FPatternHeight write FPatternHeight;
804
    property PatternWidth: Integer read FPatternWidth write FPatternWidth;
805
    property Picture: TPicture read FPicture write SetPicture;
806
    property SkipHeight: Integer read FSkipHeight write FSkipHeight default 0;
807
    property SkipWidth: Integer read FSkipWidth write FSkipWidth default 0;
808
    property SystemMemory: Boolean read FSystemMemory write FSystemMemory;
809
    property Transparent: Boolean read FTransparent write FTransparent;
810
    property TransparentColor: TColor read FTransparentColor write SetTransparentColor;
811
  end;
812
 
813
  {  TPictureCollection  }
814
 
815
  TPictureCollection = class(THashCollection)
816
  private
817
    FDXDraw: TCustomDXDraw;
818
    FOwner: TPersistent;
819
    function GetItem(Index: Integer): TPictureCollectionItem;
820
    procedure ReadColorTable(Stream: TStream);
821
    procedure WriteColorTable(Stream: TStream);
822
    function Initialized: Boolean;
823
  protected
824
    procedure DefineProperties(Filer: TFiler); override;
825
    function GetOwner: TPersistent; override;
826
  public                                    
827
    ColorTable: TRGBQuads;
828
    constructor Create(AOwner: TPersistent);
829
    destructor Destroy; override;
830
    function Find(const Name: string): TPictureCollectionItem;
831
    procedure Finalize;
832
    procedure Initialize(DXDraw: TCustomDXDraw);
833
    procedure LoadFromFile(const FileName: string);
834
    procedure LoadFromStream(Stream: TStream);
835
    procedure MakeColorTable;
836
    procedure Restore;
837
    procedure SaveToFile(const FileName: string);
838
    procedure SaveToStream(Stream: TStream);
839
    property DXDraw: TCustomDXDraw read FDXDraw;
840
    property Items[Index: Integer]: TPictureCollectionItem read GetItem; default;
841
  end;
842
 
843
  {  TCustomDXImageList  }
844
 
845
  TCustomDXImageList = class(TComponent)
846
  private
847
    FDXDraw: TCustomDXDraw;
848
    FItems: TPictureCollection;
849
    procedure DXDrawNotifyEvent(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType);
850
    procedure SetDXDraw(Value: TCustomDXDraw);
851
    procedure SetItems(Value: TPictureCollection);
852
  protected
853
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
854
  public
855
    constructor Create(AOnwer: TComponent); override;
856
    destructor Destroy; override;
857
    property DXDraw: TCustomDXDraw read FDXDraw write SetDXDraw;
858
    property Items: TPictureCollection read FItems write SetItems;
859
  end;
860
 
861
  {  TDXImageList  }
862
 
863
  TDXImageList = class(TCustomDXImageList)
864
  published
865
    property DXDraw;
866
    property Items;
867
  end;
868
 
869
  {  EDirectDrawOverlayError  }
870
 
871
  EDirectDrawOverlayError = class(Exception);
872
 
873
  {  TDirectDrawOverlay  }
874
 
875
  TDirectDrawOverlay = class
876
  private
877
    FDDraw: TDirectDraw;
878
    FTargetSurface: TDirectDrawSurface;
879
    FDDraw2: TDirectDraw;
880
    FTargetSurface2: TDirectDrawSurface;
881
    FSurface: TDirectDrawSurface;
882
    FBackSurface: TDirectDrawSurface;
883
    FOverlayColorKey: TColor;
884
    FOverlayRect: TRect;
885
    FVisible: Boolean;
886
    procedure SetOverlayColorKey(Value: TColor);
887
    procedure SetOverlayRect(const Value: TRect);
888
    procedure SetVisible(Value: Boolean);
889
  public
890
    constructor Create(DDraw: TDirectDraw; TargetSurface: TDirectDrawSurface);
891
    constructor CreateWindowed(WindowHandle: HWND);
892
    destructor Destroy; override;
893
    procedure Finalize;
894
    procedure Initialize(const SurfaceDesc: TDDSurfaceDesc);
895
    procedure Flip;
896
    property OverlayColorKey: TColor read FOverlayColorKey write SetOverlayColorKey;
897
    property OverlayRect: TRect read FOverlayRect write SetOverlayRect;
898
    property Surface: TDirectDrawSurface read FSurface;
899
    property BackSurface: TDirectDrawSurface read FBackSurface;
900
    property Visible: Boolean read FVisible write SetVisible;
901
  end;
902
 
903
implementation
904
 
905
uses DXConsts, DXRender;
906
 
907
function DXDirectDrawEnumerate(lpCallback: TDDEnumCallbackA;
908
    lpContext: Pointer): HRESULT;
909
type
910
  TDirectDrawEnumerate = function(lpCallback: TDDEnumCallbackA;
911
    lpContext: Pointer): HRESULT; stdcall;
912
begin
913
  Result := TDirectDrawEnumerate(DXLoadLibrary('DDraw.dll', 'DirectDrawEnumerateA'))
914
    (lpCallback, lpContext);
915
end;
916
 
917
var
918
  DirectDrawDrivers: TDirectXDrivers;
919
 
920
function EnumDirectDrawDrivers: TDirectXDrivers;
921
 
922
  function DDENUMCALLBACK(lpGuid: PGUID; lpstrDescription: LPCSTR;
923
    lpstrModule: LPCSTR; lpContext: Pointer): BOOL; stdcall;
924
  begin
925
    Result := True;
926
    with TDirectXDriver.Create(TDirectXDrivers(lpContext)) do
927
    begin
928
      Guid := lpGuid;
929
      Description := lpstrDescription;
930
      DriverName := lpstrModule;
931
    end;
932
  end;
933
 
934
begin
935
  if DirectDrawDrivers=nil then
936
  begin
937
    DirectDrawDrivers := TDirectXDrivers.Create;
938
    try                    
939
      DXDirectDrawEnumerate(@DDENUMCALLBACK, DirectDrawDrivers);
940
    except
941
      DirectDrawDrivers.Free;
942
      raise;
943
    end;
944
  end;
945
 
946
  Result := DirectDrawDrivers;
947
end;
948
 
949
function ClipRect(var DestRect: TRect; const DestRect2: TRect): Boolean;
950
begin
951
  with DestRect do
952
  begin
953
    Left := Max(Left, DestRect2.Left);
954
    Right := Min(Right, DestRect2.Right);
955
    Top := Max(Top, DestRect2.Top);
956
    Bottom := Min(Bottom, DestRect2.Bottom);
957
 
958
    Result := (Left < Right) and (Top < Bottom);
959
  end;
960
end;
961
 
962
function ClipRect2(var DestRect, SrcRect: TRect; const DestRect2, SrcRect2: TRect): Boolean;
963
begin
964
  if DestRect.Left < DestRect2.Left then
965
  begin
966
    SrcRect.Left := SrcRect.Left + (DestRect2.Left - DestRect.Left);
967
    DestRect.Left := DestRect2.Left;
968
  end;
969
 
970
  if DestRect.Top < DestRect2.Top then
971
  begin
972
    SrcRect.Top := SrcRect.Top + (DestRect2.Top - DestRect.Top);
973
    DestRect.Top := DestRect2.Top;
974
  end;
975
 
976
  if SrcRect.Left < SrcRect2.Left then
977
  begin
978
    DestRect.Left := DestRect.Left + (SrcRect2.Left - SrcRect.Left);
979
    SrcRect.Left := SrcRect2.Left;
980
  end;
981
 
982
  if SrcRect.Top < SrcRect2.Top then
983
  begin
984
    DestRect.Top := DestRect.Top + (SrcRect2.Top - SrcRect.Top);
985
    SrcRect.Top := SrcRect2.Top;
986
  end;
987
 
988
  if DestRect.Right > DestRect2.Right then
989
  begin
990
    SrcRect.Right := SrcRect.Right - (DestRect.Right - DestRect2.Right);
991
    DestRect.Right := DestRect2.Right;
992
  end;
993
 
994
  if DestRect.Bottom > DestRect2.Bottom then
995
  begin
996
    SrcRect.Bottom := SrcRect.Bottom - (DestRect.Bottom - DestRect2.Bottom);
997
    DestRect.Bottom := DestRect2.Bottom;
998
  end;
999
 
1000
  if SrcRect.Right > SrcRect2.Right then
1001
  begin
1002
    DestRect.Right := DestRect.Right - (SrcRect.Right - SrcRect2.Right);
1003
    SrcRect.Right := SrcRect2.Right;
1004
  end;
1005
 
1006
  if SrcRect.Bottom > SrcRect2.Bottom then
1007
  begin
1008
    DestRect.Bottom := DestRect.Bottom - (SrcRect.Bottom - SrcRect2.Bottom);
1009
    SrcRect.Bottom := SrcRect2.Bottom;
1010
  end;
1011
 
1012
  Result := (DestRect.Left < DestRect.Right) and (DestRect.Top < DestRect.Bottom) and
1013
    (SrcRect.Left < SrcRect.Right) and (SrcRect.Top < SrcRect.Bottom);
1014
end;
1015
 
1016
{  TDirectDraw  }
1017
 
1018
constructor TDirectDraw.Create(GUID: PGUID);
1019
begin
1020
  CreateEx(GUID, True);
1021
end;
1022
 
1023
constructor TDirectDraw.CreateEx(GUID: PGUID; DirectX7Mode: Boolean);
1024
type
1025
  TDirectDrawCreate = function(lpGUID: PGUID; out lplpDD: IDirectDraw;
1026
    pUnkOuter: IUnknown): HRESULT; stdcall;
1027
 
1028
  TDirectDrawCreateEx = function(lpGUID: PGUID; out lplpDD: IDirectDraw7; const iid: TGUID;
1029
    pUnkOuter: IUnknown): HRESULT; stdcall;
1030
begin
1031
  inherited Create;
1032
  FClippers := TList.Create;
1033
  FPalettes := TList.Create;
1034
  FSurfaces := TList.Create;
1035
 
1036
  if DirectX7Mode then
1037
  begin
1038
    { DirectX 7 }
1039
    if TDirectDrawCreateEx(DXLoadLibrary('DDraw.dll', 'DirectDrawCreateEx')) (GUID, FIDDraw7, IID_IDirectDraw7, nil)<>DD_OK then
1040
      raise EDirectDrawError.CreateFmt(SCannotInitialized, [SDirectDraw]);
1041
    try
1042
      FIDDraw := FIDDraw7 as IDirectDraw;
1043
      FIDDraw4 := FIDDraw7 as IDirectDraw4;
1044
    except
1045
      raise EDirectDrawError.Create(SSinceDirectX7);
1046
    end;
1047
  end else
1048
  begin
1049
    if TDirectDrawCreate(DXLoadLibrary('DDraw.dll', 'DirectDrawCreate')) (GUID, FIDDraw, nil)<>DD_OK then
1050
      raise EDirectDrawError.CreateFmt(SCannotInitialized, [SDirectDraw]);
1051
    try
1052
      FIDDraw4 := FIDDraw as IDirectDraw4;
1053
    except
1054
      raise EDirectDrawError.Create(SSinceDirectX6);
1055
    end;
1056
  end;
1057
 
1058
  FDriverCaps.dwSize := SizeOf(FDriverCaps);
1059
  FHELCaps.dwSize := SizeOf(FHELCaps);
1060
  FIDDraw.GetCaps(FDriverCaps, FHELCaps);
1061
end;
1062
 
1063
destructor TDirectDraw.Destroy;
1064
begin
1065
  while SurfaceCount>0 do
1066
    Surfaces[SurfaceCount-1].Free;
1067
 
1068
  while PaletteCount>0 do
1069
    Palettes[PaletteCount-1].Free;
1070
 
1071
  while ClipperCount>0 do
1072
    Clippers[ClipperCount-1].Free;
1073
 
1074
  FSurfaces.Free;
1075
  FPalettes.Free;
1076
  FClippers.Free;
1077
  inherited Destroy;
1078
end;
1079
 
1080
class function TDirectDraw.Drivers: TDirectXDrivers;
1081
begin
1082
  Result := EnumDirectDrawDrivers;
1083
end;
1084
 
1085
function TDirectDraw.GetClipper(Index: Integer): TDirectDrawClipper;
1086
begin
1087
  Result := FClippers[Index];
1088
end;
1089
 
1090
function TDirectDraw.GetClipperCount: Integer;
1091
begin
1092
  Result := FClippers.Count;
1093
end;
1094
 
1095
function TDirectDraw.GetDisplayMode: TDDSurfaceDesc;
1096
begin
1097
  Result.dwSize := SizeOf(Result);
1098
  DXResult := IDraw.GetDisplayMode(Result);
1099
  if DXResult<>DD_OK then
1100
    FillChar(Result, SizeOf(Result), 0);
1101
end;
1102
 
1103
function TDirectDraw.GetIDDraw: IDirectDraw;
1104
begin
1105
  if Self<>nil then
1106
    Result := FIDDraw
1107
  else
1108
    Result := nil;
1109
end;
1110
 
1111
function TDirectDraw.GetIDDraw4: IDirectDraw4;
1112
begin
1113
  if Self<>nil then
1114
    Result := FIDDraw4
1115
  else
1116
    Result := nil;
1117
end;
1118
 
1119
function TDirectDraw.GetIDDraw7: IDirectDraw7;
1120
begin
1121
  if Self<>nil then
1122
    Result := FIDDraw7
1123
  else
1124
    Result := nil;
1125
end;
1126
 
1127
function TDirectDraw.GetIDraw: IDirectDraw;
1128
begin
1129
  Result := IDDraw;
1130
  if Result=nil then
1131
    raise EDirectDrawError.CreateFmt(SNotMade, ['IDirectDraw']);
1132
end;
1133
 
1134
function TDirectDraw.GetIDraw4: IDirectDraw4;
1135
begin
1136
  Result := IDDraw4;
1137
  if Result=nil then
1138
    raise EDirectDrawError.CreateFmt(SNotMade, ['IDirectDraw4']);
1139
end;
1140
 
1141
function TDirectDraw.GetIDraw7: IDirectDraw7;
1142
begin
1143
  Result := IDDraw7;
1144
  if Result=nil then
1145
    raise EDirectDrawError.CreateFmt(SNotMade, ['IDirectDraw7']);
1146
end;
1147
 
1148
function TDirectDraw.GetPalette(Index: Integer): TDirectDrawPalette;
1149
begin
1150
  Result := FPalettes[Index];
1151
end;
1152
 
1153
function TDirectDraw.GetPaletteCount: Integer;
1154
begin
1155
  Result := FPalettes.Count;
1156
end;
1157
 
1158
function TDirectDraw.GetSurface(Index: Integer): TDirectDrawSurface;
1159
begin
1160
  Result := FSurfaces[Index];
1161
end;
1162
 
1163
function TDirectDraw.GetSurfaceCount: Integer;
1164
begin
1165
  Result := FSurfaces.Count;
1166
end;
1167
 
1168
{  TDirectDrawPalette  }
1169
 
1170
constructor TDirectDrawPalette.Create(ADirectDraw: TDirectDraw);
1171
begin
1172
  inherited Create;
1173
  FDDraw := ADirectDraw;
1174
  FDDraw.FPalettes.Add(Self);
1175
end;
1176
 
1177
destructor TDirectDrawPalette.Destroy;
1178
begin
1179
  FDDraw.FPalettes.Remove(Self);
1180
  inherited Destroy;
1181
end;
1182
 
1183
function TDirectDrawPalette.CreatePalette(Caps: DWORD; const Entries): Boolean;
1184
var
1185
  TempPalette: IDirectDrawPalette;
1186
begin
1187
  IDDPalette := nil;
1188
 
1189
  FDDraw.DXResult := FDDraw.IDraw.CreatePalette(Caps, @Entries, TempPalette, nil);
1190
  FDXResult := FDDraw.DXResult;
1191
  Result := FDDraw.DXResult=DD_OK;
1192
  if Result then
1193
    IDDPalette := TempPalette;
1194
end;
1195
 
1196
procedure TDirectDrawPalette.LoadFromDIB(DIB: TDIB);
1197
var
1198
  Entries: TPaletteEntries;
1199
begin
1200
  Entries := RGBQuadsToPaletteEntries(DIB.ColorTable);
1201
  CreatePalette(DDPCAPS_8BIT, Entries);
1202
end;
1203
 
1204
procedure TDirectDrawPalette.LoadFromFile(const FileName: string);
1205
var
1206
  Stream: TFileStream;
1207
begin
1208
  Stream := TFileStream.Create(FileName, fmOpenRead);
1209
  try
1210
    LoadFromStream(Stream);
1211
  finally
1212
    Stream.Free;
1213
  end;
1214
end;
1215
 
1216
procedure TDirectDrawPalette.LoadFromStream(Stream: TStream);
1217
var
1218
  DIB: TDIB;
1219
begin
1220
  DIB := TDIB.Create;
1221
  try
1222
    DIB.LoadFromStream(Stream);
1223
    if DIB.Size>0 then
1224
      LoadFromDIB(DIB);
1225
  finally
1226
    DIB.Free;
1227
  end;
1228
end;
1229
 
1230
function TDirectDrawPalette.GetEntries(StartIndex, NumEntries: Integer;
1231
  var Entries): Boolean;
1232
begin
1233
  if IDDPalette<>nil then
1234
  begin
1235
    DXResult := IPalette.GetEntries(0, StartIndex, NumEntries, @Entries);
1236
    Result := DXResult=DD_OK;
1237
  end else
1238
    Result := False;
1239
end;
1240
 
1241
function TDirectDrawPalette.GetEntry(Index: Integer): TPaletteEntry;
1242
begin
1243
  GetEntries(Index, 1, Result);
1244
end;
1245
 
1246
function TDirectDrawPalette.GetIDDPalette: IDirectDrawPalette;
1247
begin
1248
  if Self<>nil then
1249
    Result := FIDDPalette
1250
  else
1251
    Result := nil;
1252
end;
1253
 
1254
function TDirectDrawPalette.GetIPalette: IDirectDrawPalette;
1255
begin
1256
  Result := IDDPalette;
1257
  if Result=nil then
1258
    raise EDirectDrawPaletteError.CreateFmt(SNotMade, ['IDirectDrawPalette']);
1259
end;
1260
 
1261
function TDirectDrawPalette.SetEntries(StartIndex, NumEntries: Integer;
1262
  const Entries): Boolean;
1263
begin
1264
  if IDDPalette<>nil then
1265
  begin
1266
    DXResult := IPalette.SetEntries(0, StartIndex, NumEntries, @Entries);
1267
    Result := DXResult=DD_OK;
1268
  end else
1269
    Result := False;
1270
end;
1271
 
1272
procedure TDirectDrawPalette.SetEntry(Index: Integer; Value: TPaletteEntry);
1273
begin
1274
  SetEntries(Index, 1, Value);
1275
end;
1276
 
1277
procedure TDirectDrawPalette.SetIDDPalette(Value: IDirectDrawPalette);
1278
begin
1279
  if FIDDPalette=Value then Exit;
1280
  FIDDPalette := Value;
1281
end;
1282
 
1283
{  TDirectDrawClipper  }
1284
 
1285
constructor TDirectDrawClipper.Create(ADirectDraw: TDirectDraw);
1286
begin
1287
  inherited Create;
1288
  FDDraw := ADirectDraw;
1289
  FDDraw.FClippers.Add(Self);
1290
 
1291
  FDDraw.DXResult := FDDraw.IDraw.CreateClipper(0, FIDDClipper, nil);
1292
  if FDDraw.DXResult<>DD_OK then
1293
    raise EDirectDrawClipperError.CreateFmt(SCannotMade, [SDirectDrawClipper]);
1294
end;
1295
 
1296
destructor TDirectDrawClipper.Destroy;
1297
begin
1298
  FDDraw.FClippers.Remove(Self);
1299
  inherited Destroy;
1300
end;
1301
 
1302
function TDirectDrawClipper.GetIDDClipper: IDirectDrawClipper;
1303
begin
1304
  if Self<>nil then
1305
    Result := FIDDClipper
1306
  else
1307
    Result := nil;
1308
end;
1309
 
1310
function TDirectDrawClipper.GetIClipper: IDirectDrawClipper;
1311
begin
1312
  Result := IDDClipper;
1313
  if Result=nil then
1314
    raise EDirectDrawClipperError.CreateFmt(SNotMade, ['IDirectDrawClipper']);
1315
end;
1316
 
1317
procedure TDirectDrawClipper.SetClipRects(const Rects: array of TRect);
1318
type
1319
  PArrayRect = ^TArrayRect;
1320
  TArrayRect = array[0..0] of TRect;
1321
var
1322
  RgnData: PRgnData;
1323
  i: Integer;
1324
  BoundsRect: TRect;
1325
begin
1326
  BoundsRect := Rect(MaxInt, MaxInt, -MaxInt, -MaxInt);
1327
  for i:=Low(Rects) to High(Rects) do
1328
  begin
1329
    with BoundsRect do
1330
    begin
1331
      Left := Min(Rects[i].Left, Left);
1332
      Right := Max(Rects[i].Right, Right);
1333
      Top := Min(Rects[i].Top, Top);
1334
      Bottom := Max(Rects[i].Bottom, Bottom);
1335
    end;                          
1336
  end;
1337
 
1338
  GetMem(RgnData, SizeOf(TRgnDataHeader)+SizeOf(TRect)*(High(Rects)-Low(Rects)+1));
1339
  try
1340
    with RgnData^.rdh do
1341
    begin
1342
      dwSize := SizeOf(TRgnDataHeader);
1343
      iType := RDH_RECTANGLES;
1344
      nCount := High(Rects)-Low(Rects)+1;
1345
      nRgnSize := nCount*SizeOf(TRect);
1346
      rcBound := BoundsRect;
1347
    end;
1348
    for i:=Low(Rects) to High(Rects) do
1349
      PArrayRect(@RgnData^.Buffer)^[i-Low(Rects)] := Rects[i];
1350
    DXResult := IClipper.SetClipList(RgnData, 0);
1351
  finally
1352
    FreeMem(RgnData);
1353
  end;
1354
end;
1355
 
1356
procedure TDirectDrawClipper.SetHandle(Value: THandle);
1357
begin
1358
  DXResult := IClipper.SetHWnd(0, Value);
1359
end;
1360
 
1361
procedure TDirectDrawClipper.SetIDDClipper(Value: IDirectDrawClipper);
1362
begin
1363
  if FIDDClipper=Value then Exit;
1364
  FIDDClipper := Value;
1365
end;
1366
 
1367
{  TDirectDrawSurfaceCanvas  }
1368
 
1369
constructor TDirectDrawSurfaceCanvas.Create(ASurface: TDirectDrawSurface);
1370
begin
1371
  inherited Create;
1372
  FSurface := ASurface;
1373
end;
1374
 
1375
destructor TDirectDrawSurfaceCanvas.Destroy;
1376
begin
1377
  Release;
1378
  FSurface.FCanvas := nil;
1379
  inherited Destroy;
1380
end;
1381
 
1382
procedure TDirectDrawSurfaceCanvas.CreateHandle;
1383
begin
1384
  FSurface.DXResult := FSurface.ISurface.GetDC(FDC);
1385
  if FSurface.DXResult=DD_OK then
1386
    Handle := FDC;
1387
end;
1388
 
1389
procedure TDirectDrawSurfaceCanvas.Release;
1390
begin
1391
  if (FSurface.IDDSurface<>nil) and (FDC<>0) then
1392
  begin
1393
    Handle := 0;
1394
    FSurface.IDDSurface.ReleaseDC(FDC);
1395
    FDC := 0;
1396
  end;
1397
end;
1398
 
1399
{  TDirectDrawSurface  }
1400
 
1401
constructor TDirectDrawSurface.Create(ADirectDraw: TDirectDraw);
1402
begin
1403
  inherited Create;
1404
  FDDraw := ADirectDraw;
1405
  FDDraw.FSurfaces.Add(Self);
1406
end;
1407
 
1408
destructor TDirectDrawSurface.Destroy;
1409
begin
1410
  FCanvas.Free;
1411
  IDDSurface := nil;
1412
  FDDraw.FSurfaces.Remove(Self);
1413
  inherited Destroy;
1414
end;
1415
 
1416
function TDirectDrawSurface.GetIDDSurface: IDirectDrawSurface;
1417
begin
1418
  if Self<>nil then
1419
    Result := FIDDSurface
1420
  else
1421
    Result := nil;
1422
end;
1423
 
1424
function TDirectDrawSurface.GetIDDSurface4: IDirectDrawSurface4;
1425
begin
1426
  if Self<>nil then
1427
    Result := FIDDSurface4
1428
  else
1429
    Result := nil;
1430
end;
1431
 
1432
function TDirectDrawSurface.GetIDDSurface7: IDirectDrawSurface7;
1433
begin
1434
  if Self<>nil then
1435
    Result := FIDDSurface7
1436
  else
1437
    Result := nil;
1438
end;
1439
 
1440
function TDirectDrawSurface.GetISurface: IDirectDrawSurface;
1441
begin
1442
  Result := IDDSurface;
1443
  if Result=nil then
1444
    raise EDirectDrawSurfaceError.CreateFmt(SNotMade, ['IDirectDrawSurface']);
1445
end;
1446
 
1447
function TDirectDrawSurface.GetISurface4: IDirectDrawSurface4;
1448
begin
1449
  Result := IDDSurface4;
1450
  if Result=nil then
1451
    raise EDirectDrawSurfaceError.CreateFmt(SNotMade, ['IDirectDrawSurface4']);
1452
end;
1453
 
1454
function TDirectDrawSurface.GetISurface7: IDirectDrawSurface7;
1455
begin
1456
  Result := IDDSurface7;
1457
  if Result=nil then
1458
    raise EDirectDrawSurfaceError.CreateFmt(SNotMade, ['IDirectDrawSurface7']);
1459
end;
1460
 
1461
procedure TDirectDrawSurface.SetIDDSurface(Value: IDirectDrawSurface);
1462
var
1463
  Clipper: IDirectDrawClipper;
1464
begin
1465
  if Value=nil then Exit;
1466
  if Value as IDirectDrawSurface=FIDDSurface then Exit;
1467
 
1468
  FIDDSurface := nil;
1469
  FIDDSurface4 := nil;
1470
  FIDDSurface7 := nil;
1471
 
1472
  FStretchDrawClipper := nil;
1473
  FGammaControl := nil;
1474
  FHasClipper := False;
1475
  FLockCount := 0;
1476
  FillChar(FSurfaceDesc, SizeOf(FSurfaceDesc), 0);
1477
 
1478
  if Value<>nil then
1479
  begin
1480
    FIDDSurface := Value as IDirectDrawSurface;
1481
    FIDDSurface4 := Value as IDirectDrawSurface4;
1482
    if FDDraw.FIDDraw7<>nil then FIDDSurface7 := Value as IDirectDrawSurface7;
1483
 
1484
    FHasClipper := (FIDDSurface.GetClipper(Clipper)=DD_OK) and (Clipper<>nil);
1485
 
1486
    FSurfaceDesc.dwSize := SizeOf(FSurfaceDesc);
1487
    FIDDSurface.GetSurfaceDesc(FSurfaceDesc);
1488
 
1489
    if FDDraw.DriverCaps.dwCaps2 and DDCAPS2_PRIMARYGAMMA<>0 then
1490
      FIDDSurface.QueryInterface(IID_IDirectDrawGammaControl, FGammaControl);
1491
  end;
1492
end;
1493
 
1494
procedure TDirectDrawSurface.SetIDDSurface4(Value: IDirectDrawSurface4);
1495
begin
1496
  if Value=nil then
1497
    SetIDDSurface(nil)
1498
  else
1499
    SetIDDSurface(Value as IDirectDrawSurface);
1500
end;
1501
 
1502
procedure TDirectDrawSurface.SetIDDSurface7(Value: IDirectDrawSurface7);
1503
begin
1504
  if Value=nil then
1505
    SetIDDSurface(nil)
1506
  else
1507
    SetIDDSurface(Value as IDirectDrawSurface);
1508
end;
1509
 
1510
procedure TDirectDrawSurface.Assign(Source: TPersistent);
1511
var
1512
  TempSurface: IDirectDrawSurface;
1513
begin
1514
  if Source=nil then
1515
    IDDSurface := nil
1516
  else if Source is TGraphic then
1517
    LoadFromGraphic(TGraphic(Source))
1518
  else if Source is TPicture then
1519
    LoadFromGraphic(TPicture(Source).Graphic)
1520
  else if Source is TDirectDrawSurface then
1521
  begin
1522
    if TDirectDrawSurface(Source).IDDSurface=nil then
1523
      IDDSurface := nil
1524
    else begin
1525
      FDDraw.DXResult := FDDraw.IDraw.DuplicateSurface(TDirectDrawSurface(Source).IDDSurface,
1526
        TempSurface);
1527
      if FDDraw.DXResult=0 then
1528
      begin
1529
        IDDSurface := TempSurface;
1530
      end;
1531
    end;
1532
  end else
1533
    inherited Assign(Source);
1534
end;
1535
 
1536
procedure TDirectDrawSurface.AssignTo(Dest: TPersistent);
1537
begin
1538
  if Dest is TDIB then
1539
  begin
1540
    TDIB(Dest).SetSize(Width, Height, 24);
1541
    TDIB(Dest).Canvas.CopyRect(Rect(0, 0, TDIB(Dest).Width, TDIB(Dest).Height), Canvas, ClientRect);
1542
    Canvas.Release;
1543
  end else
1544
    inherited AssignTo(Dest);
1545
end;
1546
 
1547
function TDirectDrawSurface.Blt(const DestRect, SrcRect: TRect; Flags: DWORD;
1548
  const DF: TDDBltFX; Source: TDirectDrawSurface): Boolean;
1549
begin
1550
  if IDDSurface<>nil then
1551
  begin
1552
    DXResult := ISurface.Blt(DestRect, Source.IDDSurface, SrcRect, DWORD(Flags), DF);
1553
    Result := DXResult=DD_OK;
1554
  end else
1555
    Result := False;
1556
end;
1557
 
1558
function TDirectDrawSurface.BltFast(X, Y: Integer; const SrcRect: TRect;
1559
  Flags: DWORD; Source: TDirectDrawSurface): Boolean;
1560
begin
1561
  if IDDSurface<>nil then
1562
  begin
1563
    DXResult := ISurface.BltFast(X, Y, Source.IDDSurface, SrcRect, DWORD(Flags));
1564
    Result := DXResult=DD_OK;
1565
  end else
1566
    Result := False;
1567
end;
1568
 
1569
function TDirectDrawSurface.ColorMatch(Col: TColor): Integer;
1570
var
1571
  DIB: TDIB;
1572
  i, oldc: Integer;
1573
begin
1574
  if IDDSurface<>nil then
1575
  begin
1576
    oldc := Pixels[0, 0];
1577
 
1578
    DIB := TDIB.Create;
1579
    try
1580
      i := ColorToRGB(Col);
1581
      DIB.SetSize(1, 1, 8);
1582
      DIB.ColorTable[0] := RGBQuad(GetRValue(i), GetGValue(i), GetBValue(i));
1583
      DIB.UpdatePalette;
1584
      DIB.Pixels[0, 0] := 0;
1585
 
1586
      with Canvas do
1587
      begin
1588
        Draw(0, 0, DIB);
1589
        Release;
1590
      end;
1591
    finally
1592
      DIB.Free;
1593
    end;
1594
    Result := Pixels[0, 0];
1595
    Pixels[0, 0] := oldc;
1596
  end else
1597
    Result := 0;
1598
end;
1599
 
1600
function TDirectDrawSurface.CreateSurface(const SurfaceDesc: TDDSurfaceDesc): Boolean;
1601
var
1602
  TempSurface: IDirectDrawSurface;
1603
begin
1604
  IDDSurface := nil;
1605
 
1606
  FDDraw.DXResult := FDDraw.IDraw.CreateSurface(SurfaceDesc, TempSurface, nil);
1607
  FDXResult := FDDraw.DXResult;
1608
  Result := FDDraw.DXResult=DD_OK;
1609
  if Result then
1610
  begin
1611
    IDDSurface := TempSurface;
1612
    TransparentColor := 0;
1613
  end;
1614
end;
1615
 
1616
{$IFDEF DelphiX_Spt4}
1617
function TDirectDrawSurface.CreateSurface(const SurfaceDesc: TDDSurfaceDesc2): Boolean;
1618
var
1619
  TempSurface4: IDirectDrawSurface4;
1620
begin
1621
  IDDSurface := nil;
1622
  FDDraw.DXResult := FDDraw.IDraw4.CreateSurface(SurfaceDesc, TempSurface4, nil);
1623
  FDXResult := FDDraw.DXResult;
1624
  Result := FDDraw.DXResult=DD_OK;
1625
  if Result then
1626
  begin
1627
    IDDSurface4 := TempSurface4;
1628
    TransparentColor := 0;
1629
  end;
1630
end;
1631
{$ENDIF}
1632
 
1633
procedure TDirectDrawSurface.Draw(X, Y: Integer; SrcRect: TRect; Source: TDirectDrawSurface;
1634
  Transparent: Boolean);
1635
const
1636
  BltFastFlags: array[Boolean] of Integer =
1637
    (DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT, DDBLTFAST_SRCCOLORKEY or DDBLTFAST_WAIT);
1638
  BltFlags: array[Boolean] of Integer =
1639
    (DDBLT_WAIT, DDBLT_KEYSRC or DDBLT_WAIT);
1640
var
1641
  DestRect: TRect;
1642
  DF: TDDBltFX;
1643
  Clipper: IDirectDrawClipper;
1644
  i: Integer;
1645
begin
1646
  if Source<>nil then
1647
  begin
1648
    if (X>Width) or (Y>Height) then Exit;
1649
 
1650
    if (SrcRect.Left>SrcRect.Right) or (SrcRect.Top>SrcRect.Bottom) then
1651
    begin
1652
      {  Mirror  }
1653
      if ((X+Abs(SrcRect.Left-SrcRect.Right))<=0) or
1654
        ((Y+Abs(SrcRect.Top-SrcRect.Bottom))<=0) then Exit;
1655
 
1656
      DF.dwsize := SizeOf(DF);
1657
      DF.dwDDFX := 0;
1658
 
1659
      if SrcRect.Left>SrcRect.Right then
1660
      begin
1661
        i := SrcRect.Left; SrcRect.Left := SrcRect.Right; SrcRect.Right := i;
1662
        DF.dwDDFX := DF.dwDDFX or DDBLTFX_MIRRORLEFTRIGHT;
1663
      end;
1664
 
1665
      if SrcRect.Top>SrcRect.Bottom then
1666
      begin
1667
        i := SrcRect.Top; SrcRect.Top := SrcRect.Bottom; SrcRect.Bottom := i;
1668
        DF.dwDDFX := DF.dwDDFX or DDBLTFX_MIRRORUPDOWN;
1669
      end;
1670
 
1671
      with SrcRect do
1672
        DestRect := Bounds(X, Y, Right-Left, Bottom-Top);
1673
 
1674
      if ClipRect2(DestRect, SrcRect, ClientRect, Source.ClientRect) then
1675
      begin
1676
        if DF.dwDDFX and DDBLTFX_MIRRORLEFTRIGHT<>0 then
1677
        begin
1678
          i := SrcRect.Left;
1679
          SrcRect.Left := Source.Width-SrcRect.Right;
1680
          SrcRect.Right := Source.Width-i;
1681
        end;
1682
 
1683
        if DF.dwDDFX and DDBLTFX_MIRRORUPDOWN<>0 then
1684
        begin
1685
          i := SrcRect.Top;
1686
          SrcRect.Top := Source.Height-SrcRect.Bottom;
1687
          SrcRect.Bottom := Source.Height-i;
1688
        end;
1689
 
1690
        Blt(DestRect, SrcRect, BltFlags[Transparent] or DDBLT_DDFX, df, Source);
1691
      end;
1692
    end else
1693
    begin
1694
      with SrcRect do
1695
        DestRect := Bounds(X, Y, Right-Left, Bottom-Top);
1696
 
1697
      if ClipRect2(DestRect, SrcRect, ClientRect, Source.ClientRect) then
1698
      begin
1699
        if FHasClipper then
1700
        begin
1701
          DF.dwsize := SizeOf(DF);
1702
          DF.dwDDFX := 0;
1703
          Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1704
        end else
1705
        begin
1706
          BltFast(DestRect.Left, DestRect.Top, SrcRect, BltFastFlags[Transparent], Source);
1707
          if DXResult=DDERR_BLTFASTCANTCLIP then
1708
          begin
1709
            ISurface.GetClipper(Clipper);
1710
            if Clipper<>nil then FHasClipper := True;
1711
 
1712
            DF.dwsize := SizeOf(DF);
1713
            DF.dwDDFX := 0;
1714
            Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1715
          end;
1716
        end;
1717
      end;
1718
    end;
1719
  end;
1720
end;
1721
 
1722
{$IFDEF DelphiX_Spt4}
1723
procedure TDirectDrawSurface.Draw(X, Y: Integer; Source: TDirectDrawSurface; Transparent: Boolean);
1724
const
1725
  BltFastFlags: array[Boolean] of Integer =
1726
    (DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT, DDBLTFAST_SRCCOLORKEY or DDBLTFAST_WAIT);
1727
  BltFlags: array[Boolean] of Integer =
1728
    (DDBLT_WAIT, DDBLT_KEYSRC or DDBLT_WAIT);
1729
var
1730
  DestRect, SrcRect: TRect;
1731
  DF: TDDBltFX;
1732
  Clipper: IDirectDrawClipper;
1733
begin
1734
  if Source<>nil then
1735
  begin
1736
    SrcRect := Source.ClientRect;
1737
    DestRect := Bounds(X, Y, Source.Width, Source.Height);
1738
 
1739
    if ClipRect2(DestRect, SrcRect, ClientRect, Source.ClientRect) then
1740
    begin
1741
      if FHasClipper then
1742
      begin
1743
        DF.dwsize := SizeOf(DF);
1744
        DF.dwDDFX := 0;
1745
        Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1746
      end else
1747
      begin
1748
        BltFast(DestRect.Left, DestRect.Top, SrcRect, BltFastFlags[Transparent], Source);
1749
        if DXResult=DDERR_BLTFASTCANTCLIP then
1750
        begin
1751
          ISurface.GetClipper(Clipper);
1752
          if Clipper<>nil then FHasClipper := True;
1753
 
1754
          DF.dwsize := SizeOf(DF);
1755
          DF.dwDDFX := 0;
1756
          Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1757
        end;
1758
      end;
1759
    end;
1760
  end;
1761
end;
1762
{$ENDIF}
1763
 
1764
procedure TDirectDrawSurface.StretchDraw(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
1765
  Transparent: Boolean);
1766
const
1767
  BltFlags: array[Boolean] of Integer =
1768
    (DDBLT_WAIT, DDBLT_KEYSRC or DDBLT_WAIT);
1769
var
1770
  DF: TDDBltFX;
1771
  OldClipper: IDirectDrawClipper;
1772
  Clipper: TDirectDrawClipper;
1773
begin
1774
  if Source<>nil then
1775
  begin
1776
    if (DestRect.Bottom<=DestRect.Top) or (DestRect.Right<=DestRect.Left) then Exit;
1777
    if (SrcRect.Bottom<=SrcRect.Top) or (SrcRect.Right<=SrcRect.Left) then Exit;
1778
 
1779
    if FHasClipper then
1780
    begin
1781
      DF.dwsize := SizeOf(DF);
1782
      DF.dwDDFX := 0;
1783
      Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1784
    end else
1785
    begin
1786
      if FStretchDrawClipper=nil then
1787
      begin
1788
        Clipper := TDirectDrawClipper.Create(DDraw);
1789
        try
1790
          Clipper.SetClipRects([ClientRect]);
1791
          FStretchDrawClipper := Clipper.IClipper;
1792
        finally
1793
          Clipper.Free;
1794
        end;
1795
      end;
1796
 
1797
      ISurface.GetClipper(OldClipper);
1798
      ISurface.SetClipper(FStretchDrawClipper);
1799
      DF.dwsize := SizeOf(DF);
1800
      DF.dwDDFX := 0;
1801
      Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1802
      ISurface.SetClipper(nil);
1803
    end;
1804
  end;
1805
end;
1806
 
1807
{$IFDEF DelphiX_Spt4}
1808
procedure TDirectDrawSurface.StretchDraw(const DestRect: TRect; Source: TDirectDrawSurface;
1809
  Transparent: Boolean);
1810
const
1811
  BltFlags: array[Boolean] of Integer =
1812
 
1813
    (DDBLT_WAIT, DDBLT_KEYSRC or DDBLT_WAIT);
1814
var
1815
  DF: TDDBltFX;
1816
  OldClipper: IDirectDrawClipper;
1817
  Clipper: TDirectDrawClipper;
1818
  SrcRect: TRect;
1819
begin                                                
1820
  if Source<>nil then
1821
  begin
1822
    if (DestRect.Bottom<=DestRect.Top) or (DestRect.Right<=DestRect.Left) then Exit;
1823
    SrcRect := Source.ClientRect;
1824
 
1825
    if ISurface.GetClipper(OldClipper)=DD_OK then
1826
    begin
1827
      DF.dwsize := SizeOf(DF);
1828
      DF.dwDDFX := 0;
1829
      Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1830
    end else
1831
    begin
1832
      if FStretchDrawClipper=nil then
1833
      begin
1834
        Clipper := TDirectDrawClipper.Create(DDraw);
1835
        try
1836
          Clipper.SetClipRects([ClientRect]);
1837
          FStretchDrawClipper := Clipper.IClipper;
1838
        finally
1839
          Clipper.Free;
1840
        end;
1841
      end;
1842
 
1843
      ISurface.SetClipper(FStretchDrawClipper);
1844
      try
1845
        DF.dwsize := SizeOf(DF);
1846
        DF.dwDDFX := 0;
1847
        Blt(DestRect, SrcRect, BltFlags[Transparent], df, Source);
1848
      finally
1849
        ISurface.SetClipper(nil);
1850
      end;
1851
    end;
1852
  end;
1853
 end;
1854
{$ENDIF}
1855
 
1856
procedure TDirectDrawSurface.DrawAdd(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
1857
  Transparent: Boolean; Alpha: Integer);
1858
var
1859
  Src_ddsd: TDDSurfaceDesc;
1860
  DestSurface, SrcSurface: TDXR_Surface;
1861
  Blend: TDXR_Blend;
1862
begin
1863
  if (Self.Width=0) or (Self.Height=0) then Exit;
1864
  if (Width=0) or (Height=0) then Exit;
1865
  if Source=nil then Exit;
1866
  if (Source.Width=0) or (Source.Height=0) then Exit;
1867
 
1868
  if Alpha<=0 then Exit;
1869
 
1870
  if dxrDDSurfaceLock(ISurface, DestSurface) then
1871
  begin
1872
    try
1873
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
1874
      begin
1875
        try
1876
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
1877
          begin
1878
            Blend := DXR_BLEND_ONE1;
1879
          end else
1880
          if Alpha>=255 then
1881
          begin
1882
            Blend := DXR_BLEND_ONE1_ADD_ONE2;
1883
          end else
1884
          begin
1885
            Blend := DXR_BLEND_SRCALPHA1_ADD_ONE2;
1886
          end;
1887
 
1888
          dxrCopyRectBlend(DestSurface, SrcSurface,
1889
            DestRect, SrcRect, Blend, Alpha, Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
1890
        finally
1891
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
1892
        end;
1893
      end;
1894
    finally
1895
      dxrDDSurfaceUnLock(ISurface, DestSurface)
1896
    end;
1897
  end;
1898
end;
1899
 
1900
procedure TDirectDrawSurface.DrawAlpha(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
1901
  Transparent: Boolean; Alpha: Integer);
1902
var
1903
  Src_ddsd: TDDSurfaceDesc;
1904
  DestSurface, SrcSurface: TDXR_Surface;
1905
  Blend: TDXR_Blend;
1906
begin
1907
  if (Self.Width=0) or (Self.Height=0) then Exit;
1908
  if (Width=0) or (Height=0) then Exit;
1909
  if Source=nil then Exit;
1910
  if (Source.Width=0) or (Source.Height=0) then Exit;
1911
 
1912
  if Alpha<=0 then Exit;
1913
 
1914
  if dxrDDSurfaceLock(ISurface, DestSurface) then
1915
  begin
1916
    try
1917
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
1918
      begin
1919
        try
1920
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
1921
          begin
1922
            Blend := DXR_BLEND_ONE1;
1923
          end else
1924
          if Alpha>=255 then
1925
          begin
1926
            Blend := DXR_BLEND_ONE1;
1927
          end else
1928
          begin
1929
            Blend := DXR_BLEND_SRCALPHA1_ADD_INVSRCALPHA2;
1930
          end;
1931
 
1932
          dxrCopyRectBlend(DestSurface, SrcSurface,
1933
            DestRect, SrcRect, Blend, Alpha, Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
1934
        finally
1935
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
1936
        end;
1937
      end;
1938
    finally
1939
      dxrDDSurfaceUnLock(ISurface, DestSurface)
1940
    end;
1941
  end;
1942
end;
1943
 
1944
procedure TDirectDrawSurface.DrawSub(const DestRect, SrcRect: TRect; Source: TDirectDrawSurface;
1945
  Transparent: Boolean; Alpha: Integer);
1946
var
1947
  Src_ddsd: TDDSurfaceDesc;
1948
  DestSurface, SrcSurface: TDXR_Surface;
1949
  Blend: TDXR_Blend;
1950
begin
1951
  if (Self.Width=0) or (Self.Height=0) then Exit;
1952
  if (Width=0) or (Height=0) then Exit;
1953
  if Source=nil then Exit;
1954
  if (Source.Width=0) or (Source.Height=0) then Exit;
1955
 
1956
  if Alpha<=0 then Exit;
1957
 
1958
  if dxrDDSurfaceLock(ISurface, DestSurface) then
1959
  begin
1960
    try
1961
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
1962
      begin
1963
        try
1964
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
1965
          begin
1966
            Blend := DXR_BLEND_ONE1;
1967
          end else
1968
          if Alpha>=255 then
1969
          begin
1970
            Blend := DXR_BLEND_ONE2_SUB_ONE1;
1971
          end else
1972
          begin
1973
            Blend := DXR_BLEND_ONE2_SUB_SRCALPHA1;
1974
          end;
1975
 
1976
          dxrCopyRectBlend(DestSurface, SrcSurface,
1977
            DestRect, SrcRect, Blend, Alpha, Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
1978
        finally
1979
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
1980
        end;
1981
      end;
1982
    finally
1983
      dxrDDSurfaceUnLock(ISurface, DestSurface)
1984
    end;
1985
  end;
1986
end;
1987
 
1988
procedure TDirectDrawSurface.DrawRotate(X, Y, Width, Height: Integer; const SrcRect: TRect;
1989
  Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle: Integer);
1990
var
1991
  Src_ddsd: TDDSurfaceDesc;
1992
  DestSurface, SrcSurface: TDXR_Surface;
1993
begin
1994
  if (Self.Width=0) or (Self.Height=0) then Exit;
1995
  if (Width=0) or (Height=0) then Exit;
1996
  if Source=nil then Exit;
1997
  if (Source.Width=0) or (Source.Height=0) then Exit;
1998
 
1999
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2000
  begin
2001
    try
2002
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2003
      begin
2004
        try
2005
          dxrDrawRotateBlend(DestSurface, SrcSurface,
2006
            X, Y, Width, Height, SrcRect, CenterX, CenterY, Angle, DXR_BLEND_ONE1, 0,
2007
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2008
        finally
2009
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2010
        end;
2011
      end;
2012
    finally
2013
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2014
    end;
2015
  end;
2016
end;
2017
 
2018
procedure TDirectDrawSurface.DrawRotateAdd(X, Y, Width, Height: Integer; const SrcRect: TRect;
2019
  Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle, Alpha: Integer);
2020
var
2021
  Src_ddsd: TDDSurfaceDesc;
2022
  DestSurface, SrcSurface: TDXR_Surface;
2023
  Blend: TDXR_Blend;
2024
begin
2025
  if Alpha<=0 then Exit;
2026
 
2027
  if (Self.Width=0) or (Self.Height=0) then Exit;
2028
  if (Width=0) or (Height=0) then Exit;
2029
  if Source=nil then Exit;
2030
  if (Source.Width=0) or (Source.Height=0) then Exit;
2031
 
2032
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2033
  begin
2034
    try
2035
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2036
      begin
2037
        try
2038
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
2039
          begin
2040
            Blend := DXR_BLEND_ONE1;
2041
          end else
2042
          if Alpha>=255 then
2043
          begin
2044
            Blend := DXR_BLEND_ONE1_ADD_ONE2;
2045
          end else
2046
          begin
2047
            Blend := DXR_BLEND_SRCALPHA1_ADD_ONE2;
2048
          end;
2049
 
2050
          dxrDrawRotateBlend(DestSurface, SrcSurface,
2051
            X, Y, Width, Height, SrcRect, CenterX, CenterY, Angle, Blend, Alpha,
2052
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2053
        finally
2054
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2055
        end;
2056
      end;
2057
    finally
2058
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2059
    end;
2060
  end;
2061
end;
2062
 
2063
procedure TDirectDrawSurface.DrawRotateAlpha(X, Y, Width, Height: Integer; const SrcRect: TRect;
2064
  Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle, Alpha: Integer);
2065
var
2066
  Src_ddsd: TDDSurfaceDesc;
2067
  DestSurface, SrcSurface: TDXR_Surface;
2068
  Blend: TDXR_Blend;
2069
begin
2070
  if Alpha<=0 then Exit;
2071
 
2072
  if (Self.Width=0) or (Self.Height=0) then Exit;
2073
  if (Width=0) or (Height=0) then Exit;
2074
  if Source=nil then Exit;
2075
  if (Source.Width=0) or (Source.Height=0) then Exit;
2076
 
2077
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2078
  begin
2079
    try
2080
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2081
      begin
2082
        try
2083
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
2084
          begin
2085
            Blend := DXR_BLEND_ONE1;
2086
          end else
2087
          if Alpha>=255 then
2088
          begin
2089
            Blend := DXR_BLEND_ONE1;
2090
          end else
2091
          begin
2092
            Blend := DXR_BLEND_SRCALPHA1_ADD_INVSRCALPHA2;
2093
          end;
2094
 
2095
          dxrDrawRotateBlend(DestSurface, SrcSurface,
2096
            X, Y, Width, Height, SrcRect, CenterX, CenterY, Angle, Blend, Alpha,
2097
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2098
        finally
2099
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2100
        end;
2101
      end;
2102
    finally
2103
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2104
    end;
2105
  end;
2106
end;
2107
 
2108
procedure TDirectDrawSurface.DrawRotateSub(X, Y, Width, Height: Integer; const SrcRect: TRect;
2109
  Source: TDirectDrawSurface; CenterX, CenterY: Double; Transparent: Boolean; Angle, Alpha: Integer);
2110
var
2111
  Src_ddsd: TDDSurfaceDesc;
2112
  DestSurface, SrcSurface: TDXR_Surface;
2113
  Blend: TDXR_Blend;
2114
begin
2115
  if Alpha<=0 then Exit;
2116
 
2117
  if (Self.Width=0) or (Self.Height=0) then Exit;
2118
  if (Width=0) or (Height=0) then Exit;
2119
  if Source=nil then Exit;
2120
  if (Source.Width=0) or (Source.Height=0) then Exit;
2121
 
2122
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2123
  begin
2124
    try
2125
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2126
      begin
2127
        try
2128
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
2129
          begin
2130
            Blend := DXR_BLEND_ONE1;
2131
          end else
2132
          if Alpha>=255 then
2133
          begin
2134
            Blend := DXR_BLEND_ONE2_SUB_ONE1;
2135
          end else
2136
          begin
2137
            Blend := DXR_BLEND_ONE2_SUB_SRCALPHA1;
2138
          end;
2139
 
2140
          dxrDrawRotateBlend(DestSurface, SrcSurface,
2141
            X, Y, Width, Height, SrcRect, CenterX, CenterY, Angle, Blend, Alpha,
2142
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2143
        finally
2144
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2145
        end;
2146
      end;
2147
    finally
2148
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2149
    end;
2150
  end;
2151
end;
2152
 
2153
procedure TDirectDrawSurface.DrawWaveX(X, Y, Width, Height: Integer; const SrcRect: TRect;
2154
  Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph: Integer);
2155
var
2156
  Src_ddsd: TDDSurfaceDesc;
2157
  DestSurface, SrcSurface: TDXR_Surface;
2158
begin
2159
  if (Self.Width=0) or (Self.Height=0) then Exit;
2160
  if (Width=0) or (Height=0) then Exit;
2161
  if Source=nil then Exit;
2162
  if (Source.Width=0) or (Source.Height=0) then Exit;
2163
 
2164
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2165
  begin
2166
    try
2167
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2168
      begin
2169
        try
2170
          dxrDrawWaveXBlend(DestSurface, SrcSurface,
2171
            X, Y, Width, Height, SrcRect, amp, Len, ph, DXR_BLEND_ONE1, 0,
2172
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2173
        finally
2174
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2175
        end;
2176
      end;
2177
    finally
2178
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2179
    end;
2180
  end;
2181
end;
2182
 
2183
procedure TDirectDrawSurface.DrawWaveXAdd(X, Y, Width, Height: Integer; const SrcRect: TRect;
2184
  Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph, Alpha: Integer);
2185
var
2186
  Src_ddsd: TDDSurfaceDesc;
2187
  DestSurface, SrcSurface: TDXR_Surface;
2188
  Blend: TDXR_Blend;
2189
begin
2190
  if Alpha<=0 then Exit;
2191
 
2192
  if (Self.Width=0) or (Self.Height=0) then Exit;
2193
  if (Width=0) or (Height=0) then Exit;
2194
  if Source=nil then Exit;
2195
  if (Source.Width=0) or (Source.Height=0) then Exit;
2196
 
2197
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2198
  begin
2199
    try
2200
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2201
      begin
2202
        try
2203
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
2204
          begin
2205
            Blend := DXR_BLEND_ONE1;
2206
          end else
2207
          if Alpha>=255 then
2208
          begin
2209
            Blend := DXR_BLEND_ONE1_ADD_ONE2;
2210
          end else
2211
          begin
2212
            Blend := DXR_BLEND_SRCALPHA1_ADD_ONE2;
2213
          end;
2214
 
2215
          dxrDrawWaveXBlend(DestSurface, SrcSurface,
2216
            X, Y, Width, Height, SrcRect, amp, Len, ph, Blend, Alpha,
2217
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2218
        finally
2219
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2220
        end;
2221
      end;
2222
    finally
2223
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2224
    end;
2225
  end;
2226
end;
2227
 
2228
procedure TDirectDrawSurface.DrawWaveXAlpha(X, Y, Width, Height: Integer; const SrcRect: TRect;
2229
  Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph, Alpha: Integer);
2230
var
2231
  Src_ddsd: TDDSurfaceDesc;
2232
  DestSurface, SrcSurface: TDXR_Surface;
2233
  Blend: TDXR_Blend;
2234
begin
2235
  if Alpha<=0 then Exit;
2236
 
2237
  if (Self.Width=0) or (Self.Height=0) then Exit;
2238
  if (Width=0) or (Height=0) then Exit;
2239
  if Source=nil then Exit;
2240
  if (Source.Width=0) or (Source.Height=0) then Exit;
2241
 
2242
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2243
  begin
2244
    try
2245
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2246
      begin
2247
        try
2248
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
2249
          begin
2250
            Blend := DXR_BLEND_ONE1;
2251
          end else
2252
          if Alpha>=255 then
2253
          begin
2254
            Blend := DXR_BLEND_ONE1;
2255
          end else
2256
          begin
2257
            Blend := DXR_BLEND_SRCALPHA1_ADD_INVSRCALPHA2;
2258
          end;
2259
 
2260
          dxrDrawWaveXBlend(DestSurface, SrcSurface,
2261
            X, Y, Width, Height, SrcRect, amp, Len, ph, Blend, Alpha,
2262
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2263
        finally
2264
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2265
        end;
2266
      end;
2267
    finally
2268
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2269
    end;
2270
  end;
2271
end;
2272
 
2273
procedure TDirectDrawSurface.DrawWaveXSub(X, Y, Width, Height: Integer; const SrcRect: TRect;
2274
  Source: TDirectDrawSurface; Transparent: Boolean; amp, Len, ph, Alpha: Integer);
2275
var
2276
  Src_ddsd: TDDSurfaceDesc;
2277
  DestSurface, SrcSurface: TDXR_Surface;
2278
  Blend: TDXR_Blend;
2279
begin
2280
  if Alpha<=0 then Exit;
2281
 
2282
  if (Self.Width=0) or (Self.Height=0) then Exit;
2283
  if (Width=0) or (Height=0) then Exit;
2284
  if Source=nil then Exit;
2285
  if (Source.Width=0) or (Source.Height=0) then Exit;
2286
 
2287
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2288
  begin
2289
    try
2290
      if dxrDDSurfaceLock2(Source.ISurface, Src_ddsd, SrcSurface) then
2291
      begin
2292
        try
2293
          if DestSurface.ColorType=DXR_COLORTYPE_INDEXED then
2294
          begin
2295
            Blend := DXR_BLEND_ONE1;
2296
          end else
2297
          if Alpha>=255 then
2298
          begin    
2299
            Blend := DXR_BLEND_ONE2_SUB_ONE1;
2300
          end else
2301
          begin
2302
            Blend := DXR_BLEND_ONE2_SUB_SRCALPHA1;
2303
          end;
2304
 
2305
          dxrDrawWaveXBlend(DestSurface, SrcSurface,
2306
            X, Y, Width, Height, SrcRect, amp, Len, ph, Blend, Alpha,
2307
            Transparent, Src_ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
2308
        finally
2309
          dxrDDSurfaceUnLock(Source.ISurface, SrcSurface)
2310
        end;
2311
      end;
2312
    finally
2313
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2314
    end;
2315
  end;
2316
end;
2317
 
2318
procedure TDirectDrawSurface.Fill(DevColor: Longint);
2319
var
2320
  DBltEx: TDDBltFX;
2321
begin
2322
  DBltEx.dwSize := SizeOf(DBltEx);
2323
  DBltEx.dwFillColor := DevColor;
2324
  Blt(TRect(nil^), TRect(nil^), DDBLT_COLORFILL or DDBLT_WAIT, DBltEx, nil);
2325
end;
2326
 
2327
procedure TDirectDrawSurface.FillRect(const Rect: TRect; DevColor: Longint);
2328
var
2329
  DBltEx: TDDBltFX;
2330
  DestRect: TRect;
2331
begin
2332
  DBltEx.dwSize := SizeOf(DBltEx);
2333
  DBltEx.dwFillColor := DevColor;
2334
  DestRect := Rect;
2335
  if ClipRect(DestRect, ClientRect) then
2336
    Blt(DestRect, TRect(nil^), DDBLT_COLORFILL or DDBLT_WAIT, DBltEx, nil);
2337
end;
2338
 
2339
procedure TDirectDrawSurface.FillRectAdd(const DestRect: TRect; Color: TColor);
2340
var
2341
  DestSurface: TDXR_Surface;
2342
begin
2343
  if Color and $FFFFFF=0 then Exit;
2344
  if (Self.Width=0) or (Self.Height=0) then Exit;
2345
  if SurfaceDesc.ddpfPixelFormat.dwFlags and (DDPF_PALETTEINDEXED1 or DDPF_PALETTEINDEXED2 or
2346
    DDPF_PALETTEINDEXED4 or DDPF_PALETTEINDEXED8)<>0 then Exit;
2347
 
2348
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2349
  begin
2350
    try
2351
      dxrFillRectColorBlend(DestSurface, DestRect, DXR_BLEND_ONE1_ADD_ONE2, ColorToRGB(Color));
2352
    finally
2353
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2354
    end;
2355
  end;
2356
end;
2357
 
2358
procedure TDirectDrawSurface.FillRectAlpha(const DestRect: TRect; Color: TColor;
2359
  Alpha: Integer);
2360
var
2361
  DestSurface: TDXR_Surface;
2362
begin
2363
  if (Self.Width=0) or (Self.Height=0) then Exit;
2364
  if SurfaceDesc.ddpfPixelFormat.dwFlags and (DDPF_PALETTEINDEXED1 or DDPF_PALETTEINDEXED2 or
2365
    DDPF_PALETTEINDEXED4 or DDPF_PALETTEINDEXED8)<>0 then Exit;
2366
 
2367
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2368
  begin
2369
    try
2370
      dxrFillRectColorBlend(DestSurface, DestRect, DXR_BLEND_SRCALPHA1_ADD_INVSRCALPHA2, ColorToRGB(Color) or (Byte(Alpha) shl 24));
2371
    finally
2372
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2373
    end;
2374
  end;
2375
end;
2376
 
2377
procedure TDirectDrawSurface.FillRectSub(const DestRect: TRect; Color: TColor);
2378
var
2379
  DestSurface: TDXR_Surface;
2380
begin
2381
  if Color and $FFFFFF=0 then Exit;
2382
  if (Self.Width=0) or (Self.Height=0) then Exit;
2383
  if SurfaceDesc.ddpfPixelFormat.dwFlags and (DDPF_PALETTEINDEXED1 or DDPF_PALETTEINDEXED2 or
2384
    DDPF_PALETTEINDEXED4 or DDPF_PALETTEINDEXED8)<>0 then Exit;
2385
 
2386
  if dxrDDSurfaceLock(ISurface, DestSurface) then
2387
  begin
2388
    try
2389
      dxrFillRectColorBlend(DestSurface, DestRect, DXR_BLEND_ONE2_SUB_ONE1, ColorToRGB(Color));
2390
    finally
2391
      dxrDDSurfaceUnLock(ISurface, DestSurface)
2392
    end;
2393
  end;
2394
end;
2395
 
2396
function TDirectDrawSurface.GetBitCount: Integer;
2397
begin
2398
  Result := SurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
2399
end;
2400
 
2401
function TDirectDrawSurface.GetCanvas: TDirectDrawSurfaceCanvas;
2402
begin
2403
  if FCanvas=nil then
2404
    FCanvas := TDirectDrawSurfaceCanvas.Create(Self);
2405
  Result := FCanvas;
2406
end;
2407
 
2408
function TDirectDrawSurface.GetClientRect: TRect;
2409
begin
2410
  Result := Rect(0, 0, Width, Height);
2411
end;
2412
 
2413
function TDirectDrawSurface.GetHeight: Integer;
2414
begin
2415
  Result := SurfaceDesc.dwHeight;
2416
end;
2417
 
2418
type
2419
  PRGB = ^TRGB;
2420
  TRGB = packed record
2421
    R, G, B: Byte;
2422
  end;
2423
 
2424
function TDirectDrawSurface.GetPixel(X, Y: Integer): Longint;
2425
var
2426
  ddsd: TDDSurfaceDesc;
2427
begin
2428
  Result := 0;
2429
  if (IDDSurface<>nil) and (X>=0) and (X<Width) and (Y>=0) and (Y<Height) then
2430
    if Lock(PRect(nil)^, ddsd) then
2431
    begin
2432
      try
2433
        case ddsd.ddpfPixelFormat.dwRGBBitCount of
2434
          1 : Result := Integer(PByte(Integer(ddsd.lpSurface)+
2435
                Y*ddsd.lPitch+(X shr 3))^ and (1 shl (X and 7))<>0);
2436
          4 : begin
2437
                if X and 1=0 then
2438
                  Result := PByte(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+(X shr 1))^ shr 4
2439
                else
2440
                  Result := PByte(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+(X shr 1))^ and $0F;
2441
              end;
2442
          8 : Result := PByte(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X)^;
2443
          16: Result := PWord(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X*2)^;
2444
          24: with PRGB(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X*3)^ do
2445
                Result := R or (G shl 8) or (B shl 16);
2446
          32: Result := PInteger(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X*4)^;
2447
        end;
2448
      finally
2449
        UnLock;
2450
      end;
2451
    end;
2452
end;
2453
 
2454
function TDirectDrawSurface.GetWidth: Integer;
2455
begin
2456
  Result := SurfaceDesc.dwWidth;
2457
end;
2458
 
2459
procedure TDirectDrawSurface.LoadFromDIB(DIB: TDIB);
2460
begin
2461
  LoadFromGraphic(DIB);
2462
end;
2463
 
2464
procedure TDirectDrawSurface.LoadFromDIBRect(DIB: TDIB; AWidth, AHeight: Integer; const SrcRect: TRect);
2465
begin
2466
  LoadFromGraphicRect(DIB, AWidth, AHeight, SrcRect);
2467
end;
2468
 
2469
procedure TDirectDrawSurface.LoadFromGraphic(Graphic: TGraphic);
2470
begin
2471
  LoadFromGraphicRect(Graphic, 0, 0, Bounds(0, 0, Graphic.Width, Graphic.Height));
2472
end;
2473
 
2474
procedure TDirectDrawSurface.LoadFromGraphicRect(Graphic: TGraphic; AWidth, AHeight: Integer; const SrcRect: TRect);
2475
var
2476
  Temp: TDIB;
2477
begin
2478
  if AWidth=0 then
2479
    AWidth := SrcRect.Right-SrcRect.Left;
2480
  if AHeight=0 then
2481
    AHeight := SrcRect.Bottom-SrcRect.Top;
2482
 
2483
  SetSize(AWidth, AHeight);
2484
 
2485
  with SrcRect do
2486
    if Graphic is TDIB then
2487
    begin
2488
      with Canvas do
2489
      begin
2490
        StretchBlt(Handle, 0, 0, AWidth, AHeight, TDIB(Graphic).Canvas.Handle,
2491
          Left, Top, Right-Left, Bottom-Top,SRCCOPY);
2492
        Release;
2493
      end;
2494
    end else if (Right-Left=AWidth) and (Bottom-Top=AHeight) then
2495
    begin
2496
      with Canvas do
2497
      begin
2498
        Draw(-Left, -Top, Graphic);
2499
        Release;
2500
      end;
2501
    end else
2502
    begin
2503
      Temp := TDIB.Create;
2504
      try
2505
        Temp.SetSize(Right-Left, Bottom-Top, 24);
2506
        Temp.Canvas.Draw(-Left, -Top, Graphic);
2507
 
2508
        with Canvas do
2509
        begin
2510
          StretchDraw(Bounds(0, 0, AWidth, AHeight), Temp);
2511
          Release;
2512
        end;
2513
      finally
2514
        Temp.Free;
2515
      end;
2516
    end;
2517
end;
2518
 
2519
procedure TDirectDrawSurface.LoadFromFile(const FileName: string);
2520
var
2521
  Picture: TPicture;
2522
begin
2523
  Picture := TPicture.Create;
2524
  try
2525
    Picture.LoadFromFile(FileName);
2526
    LoadFromGraphic(Picture.Graphic);
2527
  finally
2528
    Picture.Free;
2529
  end;
2530
end;
2531
 
2532
procedure TDirectDrawSurface.LoadFromStream(Stream: TStream);
2533
var
2534
  DIB: TDIB;
2535
begin
2536
  DIB := TDIB.Create;
2537
  try
2538
    DIB.LoadFromStream(Stream);
2539
    if DIB.Size>0 then
2540
      LoadFromGraphic(DIB);
2541
  finally
2542
    DIB.Free;                
2543
  end;
2544
end;
2545
 
2546
function TDirectDrawSurface.Lock(const Rect: TRect; var SurfaceDesc: TDDSurfaceDesc): Boolean;
2547
begin
2548
  Result := False;
2549
  if IDDSurface=nil then Exit;
2550
 
2551
  if FLockCount>0 then Exit;
2552
 
2553
  FLockSurfaceDesc.dwSize := SizeOf(FLockSurfaceDesc);
2554
 
2555
  if (@Rect<>nil) and ((Rect.Left<>0) or (Rect.Top<>0) or (Rect.Right<>Width) or (Rect.Bottom<>Height)) then
2556
    DXResult := ISurface.Lock(@Rect, FLockSurfaceDesc, DDLOCK_WAIT, 0)
2557
  else                                                                
2558
    DXResult := ISurface.Lock(nil, FLockSurfaceDesc, DDLOCK_WAIT, 0);
2559
  if DXResult<>DD_OK then Exit;
2560
 
2561
  Inc(FLockCount);
2562
  SurfaceDesc := FLockSurfaceDesc;
2563
 
2564
  Result := True;
2565
end;
2566
 
2567
{$IFDEF DelphiX_Spt4}
2568
function TDirectDrawSurface.Lock(var SurfaceDesc: TDDSurfaceDesc): Boolean;
2569
begin
2570
  Result := False;
2571
  if IDDSurface=nil then Exit;
2572
 
2573
  if FLockCount=0 then
2574
  begin
2575
    FLockSurfaceDesc.dwSize := SizeOf(FLockSurfaceDesc);
2576
    DXResult := ISurface.Lock(nil, FLockSurfaceDesc, DDLOCK_WAIT, 0);
2577
    if DXResult<>DD_OK then Exit;
2578
  end;
2579
 
2580
  Inc(FLockCount);
2581
  SurfaceDesc := FLockSurfaceDesc;
2582
  Result := True;
2583
end;
2584
{$ENDIF}
2585
 
2586
procedure TDirectDrawSurface.UnLock;
2587
begin
2588
  if IDDSurface=nil then Exit;
2589
 
2590
  if FLockCount>0 then
2591
  begin
2592
    Dec(FLockCount);
2593
    if FLockCount=0 then
2594
      DXResult := ISurface.UnLock(FLockSurfaceDesc.lpSurface);
2595
  end;
2596
end;
2597
 
2598
function TDirectDrawSurface.Restore: Boolean;
2599
begin
2600
  if IDDSurface<>nil then
2601
  begin
2602
    DXResult := ISurface.Restore;
2603
    Result := DXResult=DD_OK;
2604
  end else
2605
    Result := False;
2606
end;
2607
 
2608
procedure TDirectDrawSurface.SetClipper(Value: TDirectDrawClipper);
2609
begin
2610
  if IDDSurface<>nil then
2611
    DXResult := ISurface.SetClipper(Value.IDDClipper);
2612
  FHasClipper := (Value<>nil) and (DXResult=DD_OK);
2613
end;
2614
 
2615
procedure TDirectDrawSurface.SetColorKey(Flags: DWORD; const Value: TDDColorKey);
2616
begin
2617
  if IDDSurface<>nil then
2618
    DXResult := ISurface.SetColorKey(Flags, Value);
2619
end;
2620
 
2621
procedure TDirectDrawSurface.SetPalette(Value: TDirectDrawPalette);
2622
begin
2623
  if IDDSurface<>nil then
2624
    DXResult := ISurface.SetPalette(Value.IDDPalette);
2625
end;
2626
 
2627
procedure TDirectDrawSurface.SetPixel(X, Y: Integer; Value: Longint);
2628
var
2629
  ddsd: TDDSurfaceDesc;
2630
  P: PByte;
2631
begin
2632
  if (IDDSurface<>nil) and (X>=0) and (X<Width) and (Y>=0) and (Y<Height) then
2633
    if Lock(PRect(nil)^, ddsd) then
2634
    begin
2635
      try
2636
        case ddsd.ddpfPixelFormat.dwRGBBitCount of
2637
          1 : begin
2638
                P := PByte(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+(X shr 3));
2639
                if Value=0 then
2640
                  P^ := P^ and (not (1 shl (7-(X and 7))))
2641
                else
2642
                  P^ := P^ or (1 shl (7-(X and 7)));
2643
              end;
2644
          4 : begin
2645
                P := PByte(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+(X shr 1));
2646
                if X and 1=0 then
2647
                  P^ := (P^ and $0F) or (Value shl 4)
2648
                else
2649
                  P^ := (P^ and $F0) or (Value and $0F);
2650
              end;
2651
          8 : PByte(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X)^ := Value;
2652
          16: PWord(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X*2)^ := Value;
2653
          24: with PRGB(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X*3)^ do
2654
              begin
2655
                R := Byte(Value);
2656
                G := Byte(Value shr 8);
2657
                B := Byte(Value shr 16);
2658
              end;
2659
          32: PInteger(Integer(ddsd.lpSurface)+Y*ddsd.lPitch+X*4)^ := Value;
2660
        end;
2661
      finally
2662
        UnLock;
2663
      end;
2664
    end;
2665
end;
2666
 
2667
procedure TDirectDrawSurface.SetSize(AWidth, AHeight: Integer);
2668
var
2669
  ddsd: TDDSurfaceDesc;
2670
begin
2671
  if (AWidth<=0) or (AHeight<=0) then
2672
  begin
2673
    IDDSurface := nil;
2674
    Exit;
2675
  end;
2676
 
2677
  with ddsd do
2678
  begin
2679
    dwSize := SizeOf(ddsd);
2680
    dwFlags := DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT;
2681
    ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;
2682
    if FSystemMemory then
2683
      ddsCaps.dwCaps := ddsCaps.dwCaps or DDSCAPS_SYSTEMMEMORY;
2684
    dwHeight := AHeight;
2685
    dwWidth := AWidth;
2686
  end;
2687
 
2688
  if CreateSurface(ddsd) then Exit;
2689
 
2690
  {  When the Surface cannot be made,  making is attempted to the system memory.  }
2691
  if ddsd.ddsCaps.dwCaps and DDSCAPS_SYSTEMMEMORY=0 then
2692
  begin
2693
    ddsd.ddsCaps.dwCaps := (ddsd.ddsCaps.dwCaps and (not DDSCAPS_VIDEOMEMORY)) or DDSCAPS_SYSTEMMEMORY;
2694
    if CreateSurface(ddsd) then
2695
    begin
2696
      FSystemMemory := True;
2697
      Exit;
2698
    end;
2699
  end;
2700
 
2701
  raise EDirectDrawSurfaceError.CreateFmt(SCannotMade, [SDirectDrawSurface]);
2702
end;
2703
 
2704
procedure TDirectDrawSurface.SetTransparentColor(Col: Longint);
2705
var
2706
  ddck: TDDColorKey;
2707
begin
2708
  ddck.dwColorSpaceLowValue := Col;
2709
  ddck.dwColorSpaceHighValue := Col;
2710
  ColorKey[DDCKEY_SRCBLT] := ddck;
2711
end;
2712
 
2713
{  TDXDrawDisplayMode  }
2714
 
2715
function TDXDrawDisplayMode.GetBitCount: Integer;
2716
begin
2717
  Result := FSurfaceDesc.ddpfPixelFormat.dwRGBBitCount;
2718
end;
2719
 
2720
function TDXDrawDisplayMode.GetHeight: Integer;
2721
begin
2722
  Result := FSurfaceDesc.dwHeight;
2723
end;
2724
 
2725
function TDXDrawDisplayMode.GetWidth: Integer;
2726
begin
2727
  Result := FSurfaceDesc.dwWidth;
2728
end;
2729
 
2730
{  TDXDrawDisplay  }
2731
 
2732
constructor TDXDrawDisplay.Create(ADXDraw: TCustomDXDraw);
2733
begin
2734
  inherited Create;
2735
  FDXDraw := ADXDraw;
2736
  FModes := TCollection.Create(TDXDrawDisplayMode);
2737
  FWidth := 640;
2738
  FHeight := 480;
2739
  FBitCount := 8;
2740
  FFixedBitCount := True;
2741
  FFixedRatio := True;
2742
  FFixedSize := False;
2743
end;
2744
 
2745
destructor TDXDrawDisplay.Destroy;
2746
begin
2747
  FModes.Free;
2748
  inherited Destroy;
2749
end;
2750
 
2751
procedure TDXDrawDisplay.Assign(Source: TPersistent);
2752
begin
2753
  if Source is TDXDrawDisplay then
2754
  begin
2755
    if Source<>Self then
2756
    begin
2757
      FBitCount := TDXDrawDisplay(Source).BitCount;
2758
      FHeight := TDXDrawDisplay(Source).Height;
2759
      FWidth := TDXDrawDisplay(Source).Width;
2760
 
2761
      FFixedBitCount := TDXDrawDisplay(Source).FFixedBitCount;
2762
      FFixedRatio := TDXDrawDisplay(Source).FFixedRatio;
2763
      FFixedSize := TDXDrawDisplay(Source).FFixedSize;
2764
    end;
2765
  end else
2766
    inherited Assign(Source);
2767
end;
2768
 
2769
function TDXDrawDisplay.GetCount: Integer;
2770
begin
2771
  if FModes.Count=0 then
2772
    LoadDisplayModes;
2773
  Result := FModes.Count;
2774
end;
2775
 
2776
function TDXDrawDisplay.GetMode: TDXDrawDisplayMode;
2777
var
2778
  i: Integer;
2779
  ddsd: TDDSurfaceDesc;
2780
begin
2781
  Result := nil;
2782
  if FDXDraw.DDraw<>nil then
2783
  begin
2784
    ddsd := FDXDraw.DDraw.DisplayMode;
2785
    with ddsd do
2786
      i := IndexOf(dwWidth, dwHeight, ddpfPixelFormat.dwRGBBitCount);
2787
    if i<>-1 then
2788
      Result := Modes[i];
2789
  end;
2790
  if Result=nil then
2791
    raise EDirectDrawError.Create(SDisplayModeCannotAcquired);
2792
end;
2793
 
2794
function TDXDrawDisplay.GetMode2(Index: Integer): TDXDrawDisplayMode;
2795
begin
2796
  if FModes.Count=0 then
2797
    LoadDisplayModes;
2798
  Result := TDXDrawDisplayMode(FModes.Items[Index]);
2799
end;
2800
 
2801
function TDXDrawDisplay.IndexOf(Width, Height, BitCount: Integer): Integer;
2802
var
2803
  i: Integer;
2804
begin
2805
  Result := -1;
2806
  for i:=0 to Count-1 do
2807
    if (Modes[i].Width=Width) and (Modes[i].Height=Height) and (Modes[i].BitCount=BitCount) then
2808
    begin
2809
      Result := i;
2810
      Exit;
2811
    end;
2812
end;
2813
 
2814
procedure TDXDrawDisplay.LoadDisplayModes;
2815
 
2816
  function EnumDisplayModesProc(const lpTDDSurfaceDesc: TDDSurfaceDesc;
2817
    lpContext: Pointer): HRESULT; stdcall;
2818
  begin
2819
    with TDXDrawDisplayMode.Create(TCollection(lpContext)) do
2820
      FSurfaceDesc := lpTDDSurfaceDesc;
2821
    Result := DDENUMRET_OK;
2822
  end;
2823
 
2824
  function Compare(Item1, Item2: TDXDrawDisplayMode): Integer;
2825
  begin
2826
    if Item1.Width<>Item2.Width then
2827
      Result := Item1.Width-Item2.Width
2828
    else if Item1.Height<>Item2.Height then
2829
      Result := Item1.Height-Item2.Height
2830
    else
2831
      Result := Item1.BitCount-Item2.BitCount;
2832
  end;
2833
 
2834
var
2835
  DDraw: TDirectDraw;
2836
  TempList: TList;
2837
  i: Integer;
2838
begin
2839
  FModes.Clear;
2840
 
2841
  if FDXDraw.DDraw<>nil then
2842
  begin
2843
    FDXDraw.DDraw.DXResult := FDXDraw.DDraw.IDraw.EnumDisplayModes(0, PDDSurfaceDesc(nil)^,
2844
      FModes, @EnumDisplayModesProc);
2845
  end else
2846
  begin
2847
    DDraw := TDirectDraw.Create(PGUID(FDXDraw.FDriver));
2848
    try
2849
      DDraw.IDraw.EnumDisplayModes(0, PDDSurfaceDesc(nil)^, FModes, @EnumDisplayModesProc);
2850
    finally
2851
      DDraw.Free;
2852
    end;
2853
  end;
2854
 
2855
  TempList := TList.Create;
2856
  try
2857
    for i:=0 to FModes.Count-1 do
2858
      TempList.Add(FModes.Items[i]);
2859
    TempList.Sort(@Compare);
2860
 
2861
    for i:=FModes.Count-1 downto 0 do
2862
      TDXDrawDisplayMode(TempList[i]).Index := i;
2863
  finally
2864
    TempList.Free;
2865
  end;
2866
end;
2867
 
2868
function TDXDrawDisplay.SetSize(AWidth, AHeight, ABitCount: Integer): Boolean;
2869
begin
2870
  Result := False;
2871
  if FDXDraw.DDraw<>nil then
2872
  begin
2873
    FDXDraw.DDraw.DXResult := FDXDraw.DDraw.IDraw.SetDisplayMode(AWidth, AHeight, ABitCount);
2874
    Result := FDXDraw.DDraw.DXResult=DD_OK;
2875
 
2876
    if Result then
2877
    begin
2878
      FWidth := AWidth;
2879
      FHeight := AHeight;
2880
      FBitCount := ABitCount;
2881
    end;
2882
  end;
2883
end;
2884
 
2885
function TDXDrawDisplay.DynSetSize(AWidth, AHeight, ABitCount: Integer): Boolean;
2886
 
2887
  function TestBitCount(BitCount, ABitCount: Integer): Boolean;
2888
  begin
2889
    if (BitCount>8) and (ABitCount>8) then
2890
    begin
2891
      Result := True;
2892
    end else
2893
    begin
2894
      Result := BitCount>=ABitCount;
2895
    end;
2896
  end;
2897
 
2898
  function SetSize2(Ratio: Boolean): Boolean;
2899
  var
2900
    DWidth, DHeight, DBitCount, i: Integer;
2901
    Flag: Boolean;
2902
  begin
2903
    Result := False;
2904
 
2905
    DWidth := Maxint;
2906
    DHeight := Maxint;
2907
    DBitCount := ABitCount;
2908
 
2909
    Flag := False;
2910
    for i:=0 to Count-1 do
2911
      with Modes[i] do
2912
      begin
2913
        if ((DWidth>=Width) and (DHeight>=Width) and
2914
          ((not Ratio) or (Width/Height=AWidth/AHeight)) and
2915
          ((FFixedSize and (Width=AWidth) and (Height=Height)) or
2916
          ((not FFixedSize) and (Width>=AWidth) and (Height>=AHeight))) and
2917
 
2918
          ((FFixedBitCount and (BitCount=ABitCount)) or
2919
          ((not FFixedBitCount) and TestBitCount(BitCount, ABitCount)))) then
2920
        begin
2921
          DWidth := Width;
2922
          DHeight := Height;
2923
          DBitCount := BitCount;
2924
          Flag := True;
2925
        end;
2926
      end;
2927
 
2928
    if Flag then
2929
    begin
2930
      if (DBitCount<>ABitCount) then
2931
      begin
2932
        if IndexOf(DWidth, DHEight, ABitCount)<>-1 then
2933
          DBitCount := ABitCount;
2934
      end;
2935
 
2936
      Result := SetSize(DWidth, DHeight, DBitCount);
2937
    end;
2938
  end;
2939
 
2940
begin
2941
  Result := False;
2942
 
2943
  if (AWidth<=0) or (AHeight<=0) or (not (ABitCount in [8, 16, 24, 32])) then Exit;
2944
 
2945
  {  The change is attempted by the size of default.  }
2946
  if SetSize(AWidth, AHeight, ABitCount) then
2947
  begin
2948
    Result := True;
2949
    Exit;
2950
  end;
2951
 
2952
  {  The change is attempted by the screen ratio fixation.  }
2953
  if FFixedRatio then
2954
    if SetSize2(True) then
2955
    begin
2956
      Result := True;
2957
      Exit;
2958
    end;
2959
 
2960
  {  The change is unconditionally attempted.  }
2961
  if SetSize2(False) then
2962
  begin
2963
    Result := True;
2964
    Exit;
2965
  end;
2966
end;
2967
 
2968
procedure TDXDrawDisplay.SetBitCount(Value: Integer);
2969
begin
2970
  if not (Value in [8, 16, 24, 32]) then
2971
    raise EDirectDrawError.Create(SInvalidDisplayBitCount);
2972
  FBitCount := Value;
2973
end;
2974
 
2975
procedure TDXDrawDisplay.SetHeight(Value: Integer);
2976
begin
2977
  FHeight := Max(Value, 0);
2978
end;
2979
 
2980
procedure TDXDrawDisplay.SetWidth(Value: Integer);
2981
begin
2982
  FWidth := Max(Value, 0);
2983
end;
2984
 
2985
{  TCustomDXDraw  }
2986
 
2987
function BPPToDDBD(BPP: DWORD): DWORD;
2988
begin
2989
  case BPP of
2990
    1: Result := DDBD_1;
2991
    2: Result := DDBD_2;
2992
    4: Result := DDBD_4;
2993
    8: Result := DDBD_8;
2994
    16: Result := DDBD_16;
2995
    24: Result := DDBD_24;
2996
    32: Result := DDBD_32;
2997
  else
2998
    Result := 0;
2999
  end;
3000
end;
3001
 
3002
procedure FreeZBufferSurface(Surface: TDirectDrawSurface; var ZBuffer: TDirectDrawSurface);
3003
begin
3004
  if ZBuffer<>nil then
3005
  begin
3006
    if (Surface.IDDSurface<>nil) and (ZBuffer.IDDSurface<>nil) then
3007
      Surface.ISurface.DeleteAttachedSurface(0, ZBuffer.IDDSurface);
3008
    ZBuffer.Free; ZBuffer := nil;
3009
  end;
3010
end;
3011
 
3012
type
3013
  TInitializeDirect3DOption = (idoSelectDriver, idoOptimizeDisplayMode,
3014
    idoHardware, idoRetainedMode, idoZBuffer);
3015
 
3016
  TInitializeDirect3DOptions = set of TInitializeDirect3DOption;
3017
 
3018
procedure Direct3DInitializing(Options: TInitializeDirect3DOptions;
3019
  var BitCount: Integer; var Driver: PGUID; var DriverGUID: TGUID);
3020
type
3021
  PDirect3DInitializingRecord = ^TDirect3DInitializingRecord;
3022
  TDirect3DInitializingRecord = record
3023
    Options: TInitializeDirect3DOptions;
3024
    Driver: ^PGUID;
3025
    DriverGUID: PGUID;
3026
    BitCount: Integer;
3027
 
3028
    Flag: Boolean;
3029
    DriverCaps: TDDCaps;
3030
    HELCaps: TDDCaps;
3031
    HWDeviceDesc: TD3DDeviceDesc;
3032
    HELDeviceDesc: TD3DDeviceDesc;
3033
    DeviceDesc: TD3DDeviceDesc;
3034
 
3035
    D3DFlag: Boolean;
3036
    HWDeviceDesc2: TD3DDeviceDesc;
3037
    HELDeviceDesc2: TD3DDeviceDesc;
3038
    DeviceDesc2: TD3DDeviceDesc;
3039
  end;
3040
 
3041
  function EnumDeviceCallBack(const lpGuid: TGUID; lpDeviceDescription, lpDeviceName: PChar;
3042
    const lpD3DHWDeviceDesc, lpD3DHELDeviceDesc: TD3DDeviceDesc;
3043
    rec: PDirect3DInitializingRecord): HRESULT; stdcall;
3044
 
3045
    procedure UseThisDevice;
3046
    begin
3047
      rec.D3DFlag := True;
3048
      rec.HWDeviceDesc2 := lpD3DHWDeviceDesc;
3049
      rec.HELDeviceDesc2 := lpD3DHELDeviceDesc;
3050
      rec.DeviceDesc2 := lpD3DHWDeviceDesc;
3051
    end;
3052
 
3053
  begin
3054
    Result := D3DENUMRET_OK;
3055
 
3056
    if lpD3DHWDeviceDesc.dcmColorModel=0 then Exit;
3057
 
3058
    if idoOptimizeDisplayMode in rec.Options then
3059
    begin
3060
      if (lpD3DHWDeviceDesc.dwDeviceRenderBitDepth and (DDBD_16 or DDBD_24 or DDBD_32))=0 then Exit;
3061
    end else
3062
    begin
3063
      if (lpD3DHWDeviceDesc.dwDeviceRenderBitDepth and BPPToDDBD(rec.BitCount))=0 then Exit;
3064
    end;
3065
 
3066
    UseThisDevice;
3067
  end;
3068
 
3069
  function EnumDirectDrawDriverCallback(lpGUID: PGUID; lpDriverDescription: LPSTR;
3070
    lpDriverName: LPSTR; rec: PDirect3DInitializingRecord): HRESULT; stdcall;
3071
  var
3072
    DDraw: TDirectDraw;
3073
    Direct3D: IDirect3D;
3074
    Direct3D7: IDirect3D7;
3075
 
3076
    function CountBitMask(i: DWORD; const Bits: array of DWORD): DWORD;
3077
    var
3078
      j: Integer;
3079
    begin
3080
      Result := 0;
3081
 
3082
      for j:=Low(Bits) to High(Bits) do
3083
      begin
3084
        if i and Bits[j]<>0 then
3085
          Inc(Result);
3086
      end;
3087
    end;
3088
 
3089
    function CompareCountBitMask(i, i2: DWORD; const Bits: array of DWORD): Integer;
3090
    var
3091
      j, j2: DWORD;
3092
    begin
3093
      j := CountBitMask(i, Bits);
3094
      j2 := CountBitMask(i2, Bits);
3095
 
3096
      if j<j2 then
3097
        Result := -1
3098
      else if i>j2 then
3099
        Result := 1
3100
      else
3101
        Result := 0;
3102
    end;
3103
 
3104
    function CountBit(i: DWORD): DWORD;
3105
    var
3106
      j: Integer;
3107
    begin
3108
      Result := 0;
3109
 
3110
      for j:=0 to 31 do
3111
        if i and (1 shl j)<>0 then
3112
          Inc(Result);
3113
    end;
3114
 
3115
    function CompareCountBit(i, i2: DWORD): Integer;
3116
    begin
3117
      Result := CountBit(i)-CountBit(i2);
3118
      if Result<0 then Result := -1;
3119
      if Result>0 then Result := 1;
3120
    end;
3121
 
3122
    function FindDevice: Boolean;
3123
    begin
3124
      {  The Direct3D driver is examined.  }
3125
      rec.D3DFlag := False;
3126
      Direct3D.EnumDevices(@EnumDeviceCallBack, rec);
3127
      Result := rec.D3DFlag;
3128
 
3129
      if not Result then Exit;
3130
 
3131
      {  Comparison of DirectDraw driver.  }
3132
      if not rec.Flag then
3133
      begin
3134
        rec.HWDeviceDesc := rec.HWDeviceDesc2;
3135
        rec.HELDeviceDesc := rec.HELDeviceDesc2;
3136
        rec.DeviceDesc := rec.DeviceDesc2;
3137
        rec.Flag := True;
3138
      end else
3139
      begin
3140
        {  Comparison of hardware. (One with large number of functions to support is chosen.  }
3141
        Result := False;
3142
 
3143
        if DDraw.DriverCaps.dwVidMemTotal<rec.DriverCaps.dwVidMemTotal then Exit;
3144
 
3145
        if CompareCountBitMask(DDraw.DriverCaps.ddscaps.dwCaps, rec.DriverCaps.ddscaps.dwCaps, [DDSCAPS_TEXTURE, DDSCAPS_ZBUFFER, DDSCAPS_MIPMAP])+
3146
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwMiscCaps, rec.HWDeviceDesc2.dpcLineCaps.dwMiscCaps)+
3147
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwRasterCaps, rec.HWDeviceDesc2.dpcLineCaps.dwRasterCaps)+
3148
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwAlphaCmpCaps, rec.HWDeviceDesc2.dpcLineCaps.dwAlphaCmpCaps)+
3149
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwSrcBlendCaps, rec.HWDeviceDesc2.dpcLineCaps.dwSrcBlendCaps)+
3150
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwDestBlendCaps, rec.HWDeviceDesc2.dpcLineCaps.dwDestBlendCaps)+
3151
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwShadeCaps, rec.HWDeviceDesc2.dpcLineCaps.dwShadeCaps)+
3152
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwTextureCaps, rec.HWDeviceDesc2.dpcLineCaps.dwTextureCaps)+
3153
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwTextureFilterCaps, rec.HWDeviceDesc2.dpcLineCaps.dwTextureFilterCaps)+
3154
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwTextureBlendCaps, rec.HWDeviceDesc2.dpcLineCaps.dwTextureBlendCaps)+
3155
          CompareCountBit(rec.HWDeviceDesc.dpcLineCaps.dwTextureAddressCaps, rec.HWDeviceDesc2.dpcLineCaps.dwTextureAddressCaps)<0 then Exit;
3156
 
3157
        Result := True;
3158
      end;
3159
    end;
3160
 
3161
  begin
3162
    Result := DDENUMRET_OK;
3163
 
3164
    DDraw := TDirectDraw.Create(lpGUID);
3165
    try
3166
      if (DDraw.DriverCaps.dwCaps and DDCAPS_3D<>0) and
3167
        (DDraw.DriverCaps.ddsCaps.dwCaps and DDSCAPS_TEXTURE<>0) then
3168
      begin
3169
        if DDraw.IDDraw7<>nil then
3170
          Direct3D7 := DDraw.IDraw7 as IDirect3D7
3171
        else
3172
          Direct3D := DDraw.IDraw as IDirect3D;
3173
        try
3174
          if FindDevice then
3175
          begin
3176
            rec.DriverCaps := DDraw.DriverCaps;
3177
            rec.HELCaps := DDraw.HELCaps;
3178
 
3179
            if lpGUID=nil then
3180
              rec.Driver := nil
3181
            else begin
3182
              rec.DriverGUID^ := lpGUID^;
3183
              rec.Driver^ := @rec.DriverGUID;
3184
            end;
3185
          end;
3186
        finally
3187
          Direct3D := nil;
3188
          Direct3D7 := nil;
3189
        end;
3190
      end;
3191
    finally
3192
      DDraw.Free;
3193
    end;
3194
  end;
3195
 
3196
var
3197
  rec: TDirect3DInitializingRecord;
3198
  DDraw: TDirectDraw;
3199
begin
3200
  FillChar(rec, SizeOf(rec), 0);
3201
  rec.BitCount := BitCount;
3202
  rec.Options := Options;
3203
 
3204
  {  Driver selection   }
3205
  if idoSelectDriver in Options then
3206
  begin
3207
    rec.Flag := False;
3208
    rec.Options := Options;
3209
    rec.Driver := @Driver;
3210
    rec.DriverGUID := @DriverGUID;
3211
    DXDirectDrawEnumerate(@EnumDirectDrawDriverCallback, @rec)
3212
  end else
3213
  begin
3214
    DDraw := TDirectDraw.Create(Driver);
3215
    try
3216
      rec.DriverCaps := DDraw.DriverCaps;
3217
      rec.HELCaps := DDraw.HELCaps;
3218
 
3219
      rec.D3DFlag := False;
3220
      (DDraw.IDraw as IDirect3D).EnumDevices(@EnumDeviceCallBack, @rec);
3221
 
3222
      if rec.D3DFlag then
3223
        rec.DeviceDesc := rec.DeviceDesc2;
3224
    finally
3225
      DDraw.Free;
3226
    end;
3227
    rec.Flag := True;
3228
  end;
3229
 
3230
  {  Display mode optimization  }
3231
  if rec.Flag and (idoOptimizeDisplayMode in Options) then
3232
  begin
3233
    if (rec.DeviceDesc.dwDeviceRenderBitDepth and BPPToDDBD(rec.BitCount))=0 then
3234
    begin
3235
      if rec.DeviceDesc.dwDeviceRenderBitDepth and DDBD_16<>0 then
3236
        rec.BitCount := 16
3237
      else if rec.DeviceDesc.dwDeviceRenderBitDepth and DDBD_24<>0 then
3238
        rec.BitCount := 24
3239
      else if rec.DeviceDesc.dwDeviceRenderBitDepth and DDBD_32<>0 then
3240
        rec.BitCount := 32;
3241
    end;
3242
  end;
3243
 
3244
  BitCount := rec.BitCount;
3245
end;
3246
 
3247
procedure Direct3DInitializing_DXDraw(Options: TInitializeDirect3DOptions;
3248
  DXDraw: TCustomDXDraw);
3249
var
3250
  BitCount: Integer;
3251
  Driver: PGUID;
3252
  DriverGUID: TGUID;
3253
begin
3254
  BitCount := DXDraw.Display.BitCount;
3255
  Driver := DXDraw.Driver;
3256
  Direct3DInitializing(Options, BitCount, Driver, DriverGUID);
3257
  DXDraw.Driver := Driver;
3258
  DXDraw.Display.BitCount := BitCount;
3259
end;
3260
 
3261
procedure InitializeDirect3D(Surface: TDirectDrawSurface;
3262
  var ZBuffer: TDirectDrawSurface;
3263
  out D3D: IDirect3D;
3264
  out D3D2: IDirect3D2;
3265
  out D3D3: IDirect3D3;
3266
  out D3DDevice: IDirect3DDevice;
3267
  out D3DDevice2: IDirect3DDevice2;
3268
  out D3DDevice3: IDirect3DDevice3;
3269
  var D3DRM: IDirect3DRM;
3270
  var D3DRM2: IDirect3DRM2;
3271
  var D3DRM3: IDirect3DRM3;
3272
  out D3DRMDevice: IDirect3DRMDevice;
3273
  out D3DRMDevice2: IDirect3DRMDevice2;
3274
  out D3DRMDevice3: IDirect3DRMDevice3;
3275
  out Viewport: IDirect3DRMViewport;
3276
  var Scene: IDirect3DRMFrame;
3277
  var Camera: IDirect3DRMFrame;
3278
  var NowOptions: TInitializeDirect3DOptions);
3279
type
3280
  TInitializeDirect3DRecord = record
3281
    Flag: Boolean;
3282
    BitCount: Integer;
3283
    HWDeviceDesc: TD3DDeviceDesc;
3284
    HELDeviceDesc: TD3DDeviceDesc;
3285
    DeviceDesc: TD3DDeviceDesc;
3286
    Hardware: Boolean;
3287
    Options: TInitializeDirect3DOptions;
3288
    GUID: TGUID;
3289
    SupportHardware: Boolean;
3290
  end;
3291
 
3292
  function CreateZBufferSurface(Surface: TDirectDrawSurface; var ZBuffer: TDirectDrawSurface;
3293
    const DeviceDesc: TD3DDeviceDesc; Hardware: Boolean): Boolean;
3294
  const
3295
    MemPosition: array[Boolean] of Integer = (DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY);
3296
  var
3297
    ZBufferBitDepth: Integer;
3298
    ddsd: TDDSurfaceDesc;
3299
  begin
3300
    Result := False;
3301
    FreeZBufferSurface(Surface, ZBuffer);
3302
 
3303
    if DeviceDesc.dwDeviceZBufferBitDepth and DDBD_16<>0 then
3304
      ZBufferBitDepth := 16
3305
    else if DeviceDesc.dwDeviceZBufferBitDepth and DDBD_24<>0 then
3306
      ZBufferBitDepth := 24
3307
    else if DeviceDesc.dwDeviceZBufferBitDepth and DDBD_32<>0 then
3308
      ZBufferBitDepth := 32
3309
    else
3310
      ZBufferBitDepth := 0;
3311
 
3312
    if ZBufferBitDepth<>0 then
3313
    begin
3314
      with ddsd do
3315
      begin
3316
        dwSize := SizeOf(ddsd);
3317
        Surface.ISurface.GetSurfaceDesc(ddsd);
3318
        dwFlags := DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT or DDSD_ZBUFFERBITDEPTH;
3319
        ddsCaps.dwCaps := DDSCAPS_ZBUFFER or MemPosition[Hardware];
3320
        dwHeight := Surface.Height;
3321
        dwWidth := Surface.Width;
3322
        dwZBufferBitDepth := ZBufferBitDepth;
3323
      end;
3324
 
3325
      ZBuffer := TDirectDrawSurface.Create(Surface.DDraw);
3326
      if ZBuffer.CreateSurface(ddsd) then
3327
      begin
3328
        if Surface.ISurface.AddAttachedSurface(ZBuffer.ISurface)<>DD_OK then
3329
        begin
3330
          ZBuffer.Free; ZBuffer := nil;
3331
          Exit;
3332
        end;
3333
        Result := True;
3334
      end else
3335
      begin
3336
        ZBuffer.Free; ZBuffer := nil;
3337
        Exit;
3338
      end;
3339
    end;
3340
  end;
3341
 
3342
 
3343
  function EnumDeviceCallBack(const lpGuid: TGUID; lpDeviceDescription, lpDeviceName: PChar;
3344
    const lpD3DHWDeviceDesc, lpD3DHELDeviceDesc: TD3DDeviceDesc;
3345
    lpUserArg: Pointer): HRESULT; stdcall;
3346
  var
3347
    dev: ^TD3DDeviceDesc;
3348
    Hardware: Boolean;
3349
    rec: ^TInitializeDirect3DRecord;
3350
 
3351
    procedure UseThisDevice;
3352
    begin
3353
      rec.Flag := True;
3354
      rec.GUID := lpGUID;
3355
      rec.HWDeviceDesc := lpD3DHWDeviceDesc;
3356
      rec.HELDeviceDesc := lpD3DHELDeviceDesc;
3357
      rec.DeviceDesc := dev^;
3358
      rec.Hardware := Hardware;
3359
    end;
3360
 
3361
  begin
3362
    Result := D3DENUMRET_OK;
3363
    rec := lpUserArg;
3364
 
3365
    Hardware := lpD3DHWDeviceDesc.dcmColorModel<>0;
3366
    if Hardware then
3367
      dev := @lpD3DHWDeviceDesc
3368
    else
3369
      dev := @lpD3DHELDeviceDesc;
3370
 
3371
    if (Hardware) and (not rec.SupportHardware) then Exit;
3372
    if dev.dcmColorModel<>D3DCOLOR_RGB then Exit;
3373
    if CompareMem(@lpGUID, @IID_IDirect3DRefDevice, SizeOf(TGUID)) then Exit;
3374
 
3375
    {  Bit depth test.  }
3376
    if (dev.dwDeviceRenderBitDepth and BPPToDDBD(rec.BitCount))=0 then Exit;
3377
 
3378
    if Hardware then
3379
    begin
3380
      {  Hardware  }
3381
      UseThisDevice;
3382
    end else
3383
    begin
3384
      {  Software  }
3385
      if not rec.Hardware then
3386
        UseThisDevice;
3387
    end;
3388
  end;
3389
 
3390
var
3391
  Hardware: Boolean;
3392
  SupportHardware: Boolean;
3393
  D3DDeviceGUID: TGUID;
3394
  Options: TInitializeDirect3DOptions;
3395
 
3396
  procedure InitDevice;
3397
  var
3398
    rec: TInitializeDirect3DRecord;
3399
  begin
3400
    {  Device search  }
3401
    rec.Flag := False;
3402
    rec.BitCount := Surface.BitCount;
3403
    rec.Hardware := False;
3404
    rec.Options := Options;
3405
    rec.SupportHardware := SupportHardware;
3406
 
3407
    D3D3.EnumDevices(@EnumDeviceCallBack, @rec);
3408
    if not rec.Flag then
3409
      raise EDXDrawError.Create(S3DDeviceNotFound);
3410
 
3411
    Hardware := rec.Hardware;
3412
    D3DDeviceGUID := rec.GUID;
3413
 
3414
    if Hardware then
3415
      NowOptions := NowOptions + [idoHardware];
3416
 
3417
    {  Z buffer making  }
3418
    NowOptions := NowOptions - [idoZBuffer];
3419
    if idoZBuffer in Options then
3420
    begin
3421
      if CreateZBufferSurface(Surface, ZBuffer, rec.DeviceDesc, Hardware) then
3422
        NowOptions := NowOptions + [idoZBuffer];
3423
    end;
3424
  end;
3425
 
3426
type
3427
  TDirect3DRMCreate= function(out lplpDirect3DRM: IDirect3DRM): HRESULT; stdcall;
3428
begin
3429
  try
3430
    Options := NowOptions;
3431
    NowOptions := [];
3432
 
3433
    D3D3 := Surface.DDraw.IDraw as IDirect3D3;
3434
    D3D2 := D3D3 as IDirect3D2;
3435
    D3D := D3D3 as IDirect3D;
3436
 
3437
    {  Whether hardware can be used is tested.  }
3438
    SupportHardware := (Surface.SurfaceDesc.ddsCaps.dwCaps and DDSCAPS_VIDEOMEMORY<>0) and
3439
      (idoHardware in Options) and (Surface.DDraw.DriverCaps.dwCaps and DDCAPS_3D<>0);
3440
 
3441
    if Surface.DDraw.DriverCaps.ddsCaps.dwCaps and DDSCAPS_TEXTURE=0 then
3442
      SupportHardware := False;
3443
 
3444
    {  Direct3D  }
3445
    InitDevice;
3446
 
3447
    if D3D3.CreateDevice(D3DDeviceGUID, Surface.ISurface4, D3DDevice3, nil)<>D3D_OK then
3448
    begin
3449
      SupportHardware := False;
3450
      InitDevice;
3451
      if D3D3.CreateDevice(D3DDeviceGUID, Surface.ISurface4, D3DDevice3, nil)<>D3D_OK then
3452
        raise EDXDrawError.CreateFmt(SCannotMade, ['IDirect3DDevice3']);
3453
    end;
3454
 
3455
    if SupportHardware then NowOptions := NowOptions + [idoHardware];
3456
 
3457
    D3DDevice2 := D3DDevice3 as IDirect3DDevice2;
3458
    D3DDevice := D3DDevice3 as IDirect3DDevice;
3459
 
3460
    with D3DDevice3 do
3461
    begin
3462
      SetRenderState(TD3DRenderStateType(D3DRENDERSTATE_DITHERENABLE), 1);
3463
      SetRenderState(TD3DRenderStateType(D3DRENDERSTATE_ZENABLE), Ord(ZBuffer<>nil));
3464
      SetRenderState(TD3DRenderStateType(D3DRENDERSTATE_ZWRITEENABLE), Ord(ZBuffer<>nil));
3465
    end;
3466
 
3467
    {  Direct3D Retained Mode}
3468
    if idoRetainedMode in Options then
3469
    begin
3470
      NowOptions := NowOptions + [idoRetainedMode];
3471
 
3472
      if D3DRM=nil then
3473
      begin
3474
        if TDirect3DRMCreate(DXLoadLibrary('D3DRM.dll', 'Direct3DRMCreate'))(D3DRM)<>D3DRM_OK then
3475
          raise EDXDrawError.CreateFmt(SCannotInitialized, [SDirect3DRM]);
3476
        D3DRM2 := D3DRM as IDirect3DRM2;
3477
        D3DRM3 := D3DRM as IDirect3DRM3;
3478
      end;
3479
 
3480
      if D3DRM3.CreateDeviceFromD3D(D3D2, D3DDevice2, D3DRMDevice3)<>D3DRM_OK then
3481
        raise EDXDrawError.CreateFmt(SCannotMade, ['IDirect3DRMDevice2']);
3482
 
3483
      D3DRMDevice3.SetBufferCount(2);
3484
      D3DRMDevice := D3DRMDevice3 as IDirect3DRMDevice;
3485
      D3DRMDevice2 := D3DRMDevice3 as IDirect3DRMDevice2;
3486
 
3487
      {  Rendering state setting  }
3488
      D3DRMDevice.SetQuality(D3DRMLIGHT_ON or D3DRMFILL_SOLID or D3DRMSHADE_GOURAUD);
3489
      D3DRMDevice.SetTextureQuality(D3DRMTEXTURE_NEAREST);
3490
      D3DRMDevice.SetDither(True);
3491
 
3492
      if Surface.BitCount=8 then
3493
      begin
3494
        D3DRMDevice.SetShades(8);
3495
        D3DRM.SetDefaultTextureColors(64);
3496
        D3DRM.SetDefaultTextureShades(32);
3497
      end else
3498
      begin
3499
        D3DRM.SetDefaultTextureColors(64);
3500
        D3DRM.SetDefaultTextureShades(32);
3501
      end;
3502
 
3503
      {  Frame making  }
3504
      if Scene=nil then
3505
      begin
3506
        D3DRM.CreateFrame(nil, Scene);
3507
        D3DRM.CreateFrame(Scene, Camera);
3508
        Camera.SetPosition(Camera, 0, 0, 0);
3509
      end;
3510
 
3511
      {  Viewport making  }
3512
      D3DRM.CreateViewport(D3DRMDevice, Camera, 0, 0,
3513
        Surface.Width, Surface.Height, Viewport);
3514
      Viewport.SetBack(5000.0);
3515
    end;
3516
  except
3517
    FreeZBufferSurface(Surface, ZBuffer);
3518
    D3D := nil;
3519
    D3D2 := nil;
3520
    D3D3 := nil;
3521
    D3DDevice := nil;
3522
    D3DDevice2 := nil;
3523
    D3DDevice3 := nil;
3524
    D3DRM := nil;
3525
    D3DRM2 := nil;
3526
    D3DRMDevice := nil;
3527
    D3DRMDevice2 := nil;
3528
    Viewport := nil;
3529
    Scene := nil;
3530
    Camera := nil;
3531
    raise;
3532
  end;
3533
end;
3534
 
3535
procedure InitializeDirect3D7(Surface: TDirectDrawSurface;
3536
  var ZBuffer: TDirectDrawSurface;
3537
  out D3D7: IDirect3D7;
3538
  out D3DDevice7: IDirect3DDevice7;
3539
  var NowOptions: TInitializeDirect3DOptions);
3540
type
3541
  TInitializeDirect3DRecord = record
3542
    Flag: Boolean;
3543
    BitCount: Integer;
3544
    DeviceDesc: TD3DDeviceDesc7;
3545
    Hardware: Boolean;
3546
    Options: TInitializeDirect3DOptions;
3547
    SupportHardware: Boolean;
3548
  end;
3549
 
3550
  function CreateZBufferSurface(Surface: TDirectDrawSurface; var ZBuffer: TDirectDrawSurface;
3551
    const DeviceDesc: TD3DDeviceDesc7; Hardware: Boolean): Boolean;
3552
  const
3553
    MemPosition: array[Boolean] of Integer = (DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY);
3554
  var
3555
    ZBufferBitDepth: Integer;
3556
    ddsd: TDDSurfaceDesc;
3557
  begin
3558
    Result := False;
3559
    FreeZBufferSurface(Surface, ZBuffer);
3560
 
3561
    if DeviceDesc.dwDeviceZBufferBitDepth and DDBD_16<>0 then
3562
      ZBufferBitDepth := 16
3563
    else if DeviceDesc.dwDeviceZBufferBitDepth and DDBD_24<>0 then
3564
      ZBufferBitDepth := 24
3565
    else if DeviceDesc.dwDeviceZBufferBitDepth and DDBD_32<>0 then
3566
      ZBufferBitDepth := 32
3567
    else
3568
      ZBufferBitDepth := 0;
3569
 
3570
    if ZBufferBitDepth<>0 then
3571
    begin
3572
      with ddsd do
3573
      begin
3574
        dwSize := SizeOf(ddsd);
3575
        Surface.ISurface.GetSurfaceDesc(ddsd);
3576
        dwFlags := DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT or DDSD_ZBUFFERBITDEPTH;
3577
        ddsCaps.dwCaps := DDSCAPS_ZBUFFER or MemPosition[Hardware];
3578
        dwHeight := Surface.Height;
3579
        dwWidth := Surface.Width;
3580
        dwZBufferBitDepth := ZBufferBitDepth;
3581
      end;
3582
 
3583
      ZBuffer := TDirectDrawSurface.Create(Surface.DDraw);
3584
      if ZBuffer.CreateSurface(ddsd) then
3585
      begin
3586
        if Surface.ISurface.AddAttachedSurface(ZBuffer.ISurface)<>DD_OK then
3587
        begin
3588
          ZBuffer.Free; ZBuffer := nil;
3589
          Exit;
3590
        end;
3591
        Result := True;
3592
      end else
3593
      begin
3594
        ZBuffer.Free; ZBuffer := nil;
3595
        Exit;
3596
      end;
3597
    end;
3598
  end;
3599
 
3600
  function EnumDeviceCallBack(lpDeviceDescription, lpDeviceName: PChar;
3601
    const lpTD3DDeviceDesc: TD3DDeviceDesc7; lpUserArg: Pointer): HRESULT; stdcall;
3602
  var
3603
    Hardware: Boolean;
3604
    rec: ^TInitializeDirect3DRecord;
3605
 
3606
    procedure UseThisDevice;
3607
    begin
3608
      rec.Flag := True;
3609
      rec.DeviceDesc := lpTD3DDeviceDesc;
3610
      rec.Hardware := Hardware;
3611
    end;
3612
 
3613
  begin
3614
    Result := D3DENUMRET_OK;
3615
    rec := lpUserArg;
3616
 
3617
    Hardware := lpTD3DDeviceDesc.dwDevCaps and D3DDEVCAPS_HWRASTERIZATION<>0;
3618
 
3619
    if Hardware and (not rec.SupportHardware) then Exit;
3620
    if CompareMem(@lpTD3DDeviceDesc.deviceGUID, @IID_IDirect3DRefDevice, SizeOf(TGUID)) then Exit;
3621
 
3622
    {  Bit depth test.  }
3623
    if (lpTD3DDeviceDesc.dwDeviceRenderBitDepth and BPPToDDBD(rec.BitCount))=0 then Exit;
3624
 
3625
    if Hardware then
3626
    begin
3627
      {  Hardware  }
3628
      UseThisDevice;
3629
    end else
3630
    begin
3631
      {  Software  }
3632
      if not rec.Hardware then
3633
        UseThisDevice;
3634
    end;
3635
  end;
3636
 
3637
var
3638
  Hardware: Boolean;
3639
  SupportHardware: Boolean;
3640
  D3DDeviceGUID: TGUID;
3641
  Options: TInitializeDirect3DOptions;
3642
 
3643
  procedure InitDevice;
3644
  var
3645
    rec: TInitializeDirect3DRecord;
3646
  begin
3647
    {  Device search  }
3648
    rec.Flag := False;
3649
    rec.BitCount := Surface.BitCount;
3650
    rec.Hardware := False;
3651
    rec.Options := Options;
3652
    rec.SupportHardware := SupportHardware;
3653
 
3654
    D3D7.EnumDevices(@EnumDeviceCallBack, @rec);
3655
    if not rec.Flag then
3656
      raise EDXDrawError.Create(S3DDeviceNotFound);
3657
 
3658
    Hardware := rec.Hardware;
3659
    D3DDeviceGUID := rec.DeviceDesc.deviceGUID;
3660
 
3661
    if Hardware then
3662
      NowOptions := NowOptions + [idoHardware];
3663
 
3664
    {  Z buffer making  }
3665
    NowOptions := NowOptions - [idoZBuffer];
3666
    if idoZBuffer in Options then
3667
    begin
3668
      if CreateZBufferSurface(Surface, ZBuffer, rec.DeviceDesc, Hardware) then
3669
        NowOptions := NowOptions + [idoZBuffer];
3670
    end;
3671
  end;
3672
 
3673
begin
3674
  try
3675
    Options := NowOptions - [idoRetainedMode];
3676
    NowOptions := [];
3677
 
3678
    D3D7 := Surface.DDraw.IDraw7 as IDirect3D7;
3679
 
3680
    {  Whether hardware can be used is tested.  }
3681
    SupportHardware := (Surface.SurfaceDesc.ddsCaps.dwCaps and DDSCAPS_VIDEOMEMORY<>0) and
3682
      (idoHardware in Options) and (Surface.DDraw.DriverCaps.dwCaps and DDCAPS_3D<>0);
3683
 
3684
    if Surface.DDraw.DriverCaps.ddsCaps.dwCaps and DDSCAPS_TEXTURE=0 then
3685
      SupportHardware := False;
3686
 
3687
    {  Direct3D  }
3688
    InitDevice;
3689
 
3690
    if D3D7.CreateDevice(D3DDeviceGUID, Surface.ISurface7, D3DDevice7)<>D3D_OK then
3691
    begin
3692
      SupportHardware := False;
3693
      InitDevice;
3694
      if D3D7.CreateDevice(D3DDeviceGUID, Surface.ISurface7, D3DDevice7)<>D3D_OK then
3695
        raise EDXDrawError.CreateFmt(SCannotMade, ['IDirect3DDevice7']);
3696
    end;
3697
 
3698
    if SupportHardware then NowOptions := NowOptions + [idoHardware];
3699
  except
3700
    FreeZBufferSurface(Surface, ZBuffer);
3701
    D3D7 := nil;
3702
    D3DDevice7 := nil;
3703
    raise;
3704
  end;
3705
end;
3706
 
3707
type
3708
  {  TDXDrawDriver  }
3709
 
3710
  TDXDrawDriver = class
3711
  private
3712
    FDXDraw: TCustomDXDraw;
3713
    constructor Create(ADXDraw: TCustomDXDraw); virtual;
3714
    destructor Destroy; override;
3715
    procedure Finalize; virtual;
3716
    procedure Flip; virtual; abstract;
3717
    procedure Initialize; virtual; abstract;
3718
    procedure Initialize3D;
3719
    function SetSize(AWidth, AHeight: Integer): Boolean; virtual;
3720
    function Restore: Boolean;
3721
  end;
3722
 
3723
  TDXDrawDriverBlt = class(TDXDrawDriver)
3724
  private
3725
    procedure Flip; override;
3726
    procedure Initialize; override;
3727
    procedure InitializeSurface;
3728
    function SetSize(AWidth, AHeight: Integer): Boolean; override;
3729
  end;
3730
 
3731
  TDXDrawDriverFlip = class(TDXDrawDriver)
3732
  private
3733
    procedure Flip; override;
3734
    procedure Initialize; override;
3735
  end;
3736
 
3737
{  TDXDrawDriver  }
3738
 
3739
constructor TDXDrawDriver.Create(ADXDraw: TCustomDXDraw);
3740
var
3741
  AOptions: TInitializeDirect3DOptions;
3742
begin
3743
  inherited Create;
3744
  FDXDraw := ADXDraw;
3745
 
3746
  {  Driver selection and Display mode optimizationn }
3747
  if FDXDraw.FOptions*[doFullScreen, doSystemMemory, do3D, doHardware]=
3748
    [doFullScreen, do3D, doHardware] then
3749
  begin
3750
    AOptions := [];
3751
    with FDXDraw do
3752
    begin
3753
      if doSelectDriver in Options then AOptions := AOptions + [idoSelectDriver];
3754
      if not FDXDraw.Display.FixedBitCount then AOptions := AOptions + [idoOptimizeDisplayMode];
3755
 
3756
      if doHardware in Options then AOptions := AOptions + [idoHardware];
3757
      if doRetainedMode in Options then AOptions := AOptions + [idoRetainedMode];
3758
      if doZBuffer in Options then AOptions := AOptions + [idoZBuffer];
3759
    end;
3760
 
3761
    Direct3DInitializing_DXDraw(AOptions, FDXDraw);
3762
  end;
3763
 
3764
  if FDXDraw.Options*[doFullScreen, doHardware, doSystemMemory]=[doFullScreen, doHardware] then
3765
    FDXDraw.FDDraw := TDirectDraw.CreateEx(PGUID(FDXDraw.FDriver), doDirectX7Mode in FDXDraw.Options)
3766
  else
3767
    FDXDraw.FDDraw := TDirectDraw.CreateEx(nil, doDirectX7Mode in FDXDraw.Options);
3768
end;
3769
 
3770
procedure TDXDrawDriver.Initialize3D;
3771
const
3772
  DXDrawOptions3D = [doHardware, doRetainedMode, doSelectDriver, doZBuffer];
3773
var
3774
  AOptions: TInitializeDirect3DOptions;
3775
begin
3776
  AOptions := [];
3777
  with FDXDraw do
3778
  begin
3779
    if doHardware in FOptions then AOptions := AOptions + [idoHardware];
3780
    if doRetainedMode in FNowOptions then AOptions := AOptions + [idoRetainedMode];
3781
    if doSelectDriver in FOptions then AOptions := AOptions + [idoSelectDriver];
3782
    if doZBuffer in FOptions then AOptions := AOptions + [idoZBuffer];
3783
 
3784
    if doDirectX7Mode in FOptions then
3785
    begin
3786
      InitializeDirect3D7(FSurface, FZBuffer, FD3D7, FD3DDevice7, AOptions);
3787
    end else
3788
    begin
3789
      InitializeDirect3D(FSurface, FZBuffer, FD3D, FD3D2, FD3D3, FD3DDevice, FD3DDevice2, FD3DDevice3,
3790
        FD3DRM, FD3DRM2, FD3DRM3, FD3DRMDevice, FD3DRMDevice2, FD3DRMDevice3, FViewport, FScene, FCamera, AOptions);
3791
    end;
3792
 
3793
    FNowOptions := FNowOptions - DXDrawOptions3D;
3794
    if idoHardware in AOptions then FNowOptions := FNowOptions + [doHardware];
3795
    if idoRetainedMode in AOptions then FNowOptions := FNowOptions + [doRetainedMode];
3796
    if idoSelectDriver in AOptions then FNowOptions := FNowOptions + [doSelectDriver];
3797
    if idoZBuffer in AOptions then FNowOptions := FNowOptions + [doZBuffer];
3798
  end;
3799
end;
3800
 
3801
destructor TDXDrawDriver.Destroy;
3802
begin
3803
  Finalize;
3804
  FDXDraw.FDDraw.Free;
3805
  inherited Destroy;
3806
end;
3807
 
3808
procedure TDXDrawDriver.Finalize;
3809
begin
3810
  with FDXDraw do
3811
  begin
3812
    FViewport := nil;
3813
    FCamera := nil;
3814
    FScene := nil;
3815
 
3816
    FD3DRMDevice := nil;
3817
    FD3DRMDevice2 := nil;
3818
    FD3DRMDevice3 := nil;
3819
    FD3DDevice := nil;
3820
    FD3DDevice2 := nil;
3821
    FD3DDevice3 := nil;
3822
    FD3DDevice7 := nil;
3823
    FD3D := nil;
3824
    FD3D2 := nil;
3825
    FD3D3 := nil;
3826
    FD3D7 := nil;
3827
 
3828
    FreeZBufferSurface(FSurface, FZBuffer);
3829
 
3830
    FClipper.Free;  FClipper := nil;
3831
    FPalette.Free;  FPalette := nil;
3832
    FSurface.Free;  FSurface := nil;
3833
    FPrimary.Free;  FPrimary := nil;
3834
 
3835
    FD3DRM3 := nil;
3836
    FD3DRM2 := nil;
3837
    FD3DRM := nil;
3838
  end;
3839
end;
3840
 
3841
function TDXDrawDriver.Restore: Boolean;
3842
begin
3843
  Result := FDXDraw.FPrimary.Restore and FDXDraw.FSurface.Restore;
3844
  if Result then
3845
  begin
3846
    FDXDraw.FPrimary.Fill(0);
3847
    FDXDraw.FSurface.Fill(0);
3848
  end;
3849
end;
3850
 
3851
function TDXDrawDriver.SetSize(AWidth, AHeight: Integer): Boolean;
3852
begin
3853
  Result := False;
3854
end;
3855
 
3856
{  TDXDrawDriverBlt  }
3857
 
3858
function TDXDrawRGBQuadsToPaletteEntries(const RGBQuads: TRGBQuads;
3859
  AllowPalette256: Boolean): TPaletteEntries;
3860
var
3861
  Entries: TPaletteEntries;
3862
  dc: THandle;
3863
  i: Integer;
3864
begin
3865
  Result := RGBQuadsToPaletteEntries(RGBQuads);
3866
 
3867
  if not AllowPalette256 then
3868
  begin
3869
    dc := GetDC(0);
3870
    GetSystemPaletteEntries(dc, 0, 256, Entries);
3871
    ReleaseDC(0, dc);
3872
 
3873
    for i:=0 to 9 do
3874
      Result[i] := Entries[i];
3875
 
3876
    for i:=256-10 to 255 do
3877
      Result[i] := Entries[i];
3878
  end;
3879
 
3880
  for i:=0 to 255 do
3881
    Result[i].peFlags := D3DPAL_READONLY;
3882
end;
3883
 
3884
procedure TDXDrawDriverBlt.Flip;
3885
var
3886
  pt: TPoint;
3887
  Dest: TRect;
3888
  DF: TDDBltFX;
3889
begin
3890
  pt := FDXDraw.ClientToScreen(Point(0, 0));
3891
 
3892
  if doStretch in FDXDraw.NowOptions then
3893
  begin
3894
    Dest := Bounds(pt.x, pt.y, FDXDraw.Width, FDXDraw.Height);
3895
  end else
3896
  begin
3897
    if doCenter in FDXDraw.NowOptions then
3898
    begin
3899
      Inc(pt.x, (FDXDraw.Width-FDXDraw.FSurface.Width) div 2);
3900
      Inc(pt.y, (FDXDraw.Height-FDXDraw.FSurface.Height) div 2);
3901
    end;
3902
 
3903
    Dest := Bounds(pt.x, pt.y, FDXDraw.FSurface.Width, FDXDraw.FSurface.Height);
3904
  end;
3905
 
3906
  if doWaitVBlank in FDXDraw.NowOptions then
3907
    FDXDraw.FDDraw.DXResult := FDXDraw.FDDraw.IDraw.WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
3908
 
3909
  DF.dwsize := SizeOf(DF);
3910
  DF.dwDDFX := 0;
3911
 
3912
  FDXDraw.FPrimary.Blt(Dest, FDXDraw.FSurface.ClientRect, DDBLT_WAIT, df, FDXDraw.FSurface);
3913
end;
3914
 
3915
procedure TDXDrawDriverBlt.Initialize;
3916
const
3917
  PrimaryDesc: TDDSurfaceDesc = (
3918
      dwSize: SizeOf(PrimaryDesc);
3919
      dwFlags: DDSD_CAPS;
3920
      ddsCaps: (dwCaps: DDSCAPS_PRIMARYSURFACE)
3921
      );
3922
var
3923
  Entries: TPaletteEntries;
3924
  PaletteCaps: Integer;
3925
begin
3926
  {  Surface making  }
3927
  FDXDraw.FPrimary := TDirectDrawSurface.Create(FDXDraw.FDDraw);
3928
  if not FDXDraw.FPrimary.CreateSurface(PrimaryDesc) then
3929
    raise EDXDrawError.CreateFmt(SCannotMade, [SDirectDrawPrimarySurface]);
3930
 
3931
  FDXDraw.FSurface := TDirectDrawSurface.Create(FDXDraw.FDDraw);
3932
 
3933
  {  Clipper making  }
3934
  FDXDraw.FClipper := TDirectDrawClipper.Create(FDXDraw.FDDraw);
3935
  FDXDraw.FClipper.Handle := FDXDraw.Handle;
3936
  FDXDraw.FPrimary.Clipper := FDXDraw.FClipper;
3937
 
3938
  {  Palette making  }
3939
  PaletteCaps := DDPCAPS_8BIT or DDPCAPS_INITIALIZE;
3940
  if doAllowPalette256 in FDXDraw.NowOptions then
3941
    PaletteCaps := PaletteCaps or DDPCAPS_ALLOW256;
3942
 
3943
  FDXDraw.FPalette := TDirectDrawPalette.Create(FDXDraw.FDDraw);
3944
  Entries := TDXDrawRGBQuadsToPaletteEntries(FDXDraw.ColorTable,
3945
    doAllowPalette256 in FDXDraw.NowOptions);
3946
  FDXDraw.FPalette.CreatePalette(PaletteCaps, Entries);
3947
 
3948
  FDXDraw.FPrimary.Palette := FDXDraw.Palette;
3949
 
3950
  InitializeSurface;
3951
end;
3952
 
3953
procedure TDXDrawDriverBlt.InitializeSurface;
3954
var
3955
  ddsd: TDDSurfaceDesc;
3956
begin
3957
  FDXDraw.FSurface.IDDSurface := nil;
3958
 
3959
  {  Surface making  }
3960
  FDXDraw.FNowOptions := FDXDraw.FNowOptions - [doSystemMemory];
3961
 
3962
  FillChar(ddsd, SizeOf(ddsd), 0);
3963
  with ddsd do
3964
  begin
3965
    dwSize := SizeOf(ddsd);
3966
    dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS;
3967
    dwWidth := Max(FDXDraw.FSurfaceWidth, 1);
3968
    dwHeight := Max(FDXDraw.FSurfaceHeight, 1);
3969
    ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;
3970
    if doSystemMemory in FDXDraw.Options then
3971
      ddsCaps.dwCaps := ddsCaps.dwCaps or DDSCAPS_SYSTEMMEMORY;
3972
    if do3D in FDXDraw.FNowOptions then
3973
      ddsCaps.dwCaps := ddsCaps.dwCaps or DDSCAPS_3DDEVICE;
3974
  end;
3975
 
3976
  if not FDXDraw.FSurface.CreateSurface(ddsd) then
3977
  begin
3978
    ddsd.ddsCaps.dwCaps := ddsd.ddsCaps.dwCaps or DDSCAPS_SYSTEMMEMORY;
3979
    if not FDXDraw.FSurface.CreateSurface(ddsd) then
3980
      raise EDXDrawError.CreateFmt(SCannotMade, [SDirectDrawSurface]);
3981
  end;
3982
 
3983
  if FDXDraw.FSurface.SurfaceDesc.ddscaps.dwCaps and DDSCAPS_VIDEOMEMORY=0 then
3984
    FDXDraw.FNowOptions := FDXDraw.FNowOptions + [doSystemMemory];
3985
 
3986
  FDXDraw.FSurface.Palette := FDXDraw.Palette;
3987
  FDXDraw.FSurface.Fill(0);
3988
 
3989
  if do3D in FDXDraw.FNowOptions then
3990
    Initialize3D;
3991
end;
3992
 
3993
function TDXDrawDriverBlt.SetSize(AWidth, AHeight: Integer): Boolean;
3994
begin
3995
  Result := True;
3996
 
3997
  FDXDraw.FSurfaceWidth := Max(AWidth, 1);
3998
  FDXDraw.FSurfaceHeight := Max(AHeight, 1);
3999
 
4000
  Inc(FDXDraw.FOffNotifyRestore);
4001
  try
4002
    FDXDraw.NotifyEventList(dxntFinalizeSurface);
4003
 
4004
    if FDXDraw.FCalledDoInitializeSurface then
4005
    begin
4006
      FDXDraw.FCalledDoInitializeSurface := False;
4007
      FDXDraw.DoFinalizeSurface;
4008
    end;                    
4009
 
4010
    InitializeSurface;
4011
 
4012
    FDXDraw.NotifyEventList(dxntInitializeSurface);
4013
    FDXDraw.FCalledDoInitializeSurface := True; FDXDraw.DoInitializeSurface;
4014
  finally
4015
    Dec(FDXDraw.FOffNotifyRestore);
4016
  end;
4017
end;
4018
 
4019
{  TDXDrawDriverFlip  }
4020
 
4021
procedure TDXDrawDriverFlip.Flip;
4022
begin                                        
4023
  if (FDXDraw.FForm<>nil) and (FDXDraw.FForm.Active) then
4024
    FDXDraw.FPrimary.DXResult := FDXDraw.FPrimary.ISurface.Flip(nil, DDFLIP_WAIT)
4025
  else
4026
    FDXDraw.FPrimary.DXResult := 0;
4027
end;
4028
 
4029
procedure TDXDrawDriverFlip.Initialize;
4030
const
4031
  DefPrimaryDesc: TDDSurfaceDesc = (
4032
      dwSize: SizeOf(DefPrimaryDesc);
4033
      dwFlags: DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
4034
      dwBackBufferCount: 1;
4035
      ddsCaps: (dwCaps: DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or DDSCAPS_COMPLEX)
4036
      );
4037
  BackBufferCaps: TDDSCaps = (dwCaps: DDSCAPS_BACKBUFFER);
4038
var
4039
  PrimaryDesc: TDDSurfaceDesc;
4040
  PaletteCaps: Integer;
4041
  Entries: TPaletteEntries;
4042
  DDSurface: IDirectDrawSurface;
4043
begin
4044
  {  Surface making  }
4045
  PrimaryDesc := DefPrimaryDesc;
4046
 
4047
  if do3D in FDXDraw.FNowOptions then
4048
    PrimaryDesc.ddsCaps.dwCaps := PrimaryDesc.ddsCaps.dwCaps or DDSCAPS_3DDEVICE;
4049
 
4050
  FDXDraw.FPrimary := TDirectDrawSurface.Create(FDXDraw.FDDraw);
4051
  if not FDXDraw.FPrimary.CreateSurface(PrimaryDesc) then
4052
    raise EDXDrawError.CreateFmt(SCannotMade, [SDirectDrawPrimarySurface]);
4053
 
4054
  FDXDraw.FSurface := TDirectDrawSurface.Create(FDXDraw.FDDraw);
4055
  if FDXDraw.FPrimary.ISurface.GetAttachedSurface(BackBufferCaps, DDSurface)=DD_OK then
4056
    FDXDraw.FSurface.IDDSurface := DDSurface;
4057
 
4058
  FDXDraw.FNowOptions := FDXDraw.FNowOptions - [doSystemMemory];
4059
  if FDXDraw.FSurface.SurfaceDesc.ddscaps.dwCaps and DDSCAPS_SYSTEMMEMORY<>0 then
4060
    FDXDraw.FNowOptions := FDXDraw.FNowOptions + [doSystemMemory];
4061
 
4062
  {  Clipper making of dummy  }
4063
  FDXDraw.FClipper := TDirectDrawClipper.Create(FDXDraw.FDDraw);
4064
 
4065
  {  Palette making  }
4066
  PaletteCaps := DDPCAPS_8BIT;
4067
  if doAllowPalette256 in FDXDraw.Options then
4068
    PaletteCaps := PaletteCaps or DDPCAPS_ALLOW256;
4069
 
4070
  FDXDraw.FPalette := TDirectDrawPalette.Create(FDXDraw.FDDraw);
4071
  Entries := TDXDrawRGBQuadsToPaletteEntries(FDXDraw.ColorTable,
4072
    doAllowPalette256 in FDXDraw.NowOptions);
4073
  FDXDraw.FPalette.CreatePalette(PaletteCaps, Entries);
4074
 
4075
  FDXDraw.FPrimary.Palette := FDXDraw.Palette;
4076
  FDXDraw.FSurface.Palette := FDXDraw.Palette;
4077
 
4078
  if do3D in FDXDraw.FNowOptions then
4079
    Initialize3D;
4080
end;
4081
 
4082
constructor TCustomDXDraw.Create(AOwner: TComponent);
4083
var
4084
  Entries: TPaletteEntries;
4085
  dc: THandle;
4086
begin
4087
  FNotifyEventList := TList.Create;
4088
  inherited Create(AOwner);
4089
  FAutoInitialize := True;
4090
  FDisplay := TDXDrawDisplay.Create(Self);
4091
 
4092
  Options := [doAllowReboot, doWaitVBlank, doCenter, doDirectX7Mode, doHardware, doSelectDriver];
4093
 
4094
  FAutoSize := True;
4095
 
4096
  dc := GetDC(0);
4097
  GetSystemPaletteEntries(dc, 0, 256, Entries);
4098
  ReleaseDC(0, dc);
4099
 
4100
  ColorTable := PaletteEntriesToRGBQuads(Entries);
4101
  DefColorTable := ColorTable;
4102
 
4103
  Width := 100;
4104
  Height := 100;
4105
  ParentColor := False;
4106
  Color := clBtnFace;
4107
end;
4108
 
4109
destructor TCustomDXDraw.Destroy;
4110
begin
4111
  Finalize;
4112
  NotifyEventList(dxntDestroying);
4113
  FDisplay.Free;
4114
  FSubClass.Free; FSubClass := nil;
4115
  FNotifyEventList.Free;
4116
  inherited Destroy;
4117
end;
4118
 
4119
class function TCustomDXDraw.Drivers: TDirectXDrivers;
4120
begin
4121
  Result := EnumDirectDrawDrivers;
4122
end;
4123
 
4124
type
4125
  PDXDrawNotifyEvent = ^TDXDrawNotifyEvent;
4126
 
4127
procedure TCustomDXDraw.RegisterNotifyEvent(NotifyEvent: TDXDrawNotifyEvent);
4128
var
4129
  Event: PDXDrawNotifyEvent;
4130
begin
4131
  UnRegisterNotifyEvent(NotifyEvent);
4132
 
4133
  New(Event);
4134
  Event^ := NotifyEvent;
4135
  FNotifyEventList.Add(Event);
4136
 
4137
  NotifyEvent(Self, dxntSetSurfaceSize);
4138
 
4139
  if Initialized then
4140
  begin
4141
    NotifyEvent(Self, dxntInitialize);
4142
    if FCalledDoInitializeSurface then
4143
      NotifyEvent(Self, dxntInitializeSurface);
4144
    if FOffNotifyRestore=0 then
4145
      NotifyEvent(Self, dxntRestore);
4146
  end;
4147
end;
4148
 
4149
procedure TCustomDXDraw.UnRegisterNotifyEvent(NotifyEvent: TDXDrawNotifyEvent);
4150
var
4151
  Event: PDXDrawNotifyEvent;
4152
  i: Integer;
4153
begin
4154
  for i:=0 to FNotifyEventList.Count-1 do
4155
  begin
4156
    Event := FNotifyEventList[i];
4157
    if (TMethod(Event^).Code = TMethod(NotifyEvent).Code) and
4158
      (TMethod(Event^).Data = TMethod(NotifyEvent).Data) then
4159
    begin
4160
      FreeMem(Event);
4161
      FNotifyEventList.Delete(i);
4162
 
4163
      if FCalledDoInitializeSurface then
4164
        NotifyEvent(Self, dxntFinalizeSurface);
4165
      if Initialized then
4166
        NotifyEvent(Self, dxntFinalize);
4167
 
4168
      Break;
4169
    end;
4170
  end;
4171
end;
4172
 
4173
procedure TCustomDXDraw.NotifyEventList(NotifyType: TDXDrawNotifyType);
4174
var
4175
  i: Integer;
4176
begin
4177
  for i:=FNotifyEventList.Count-1 downto 0 do
4178
    PDXDrawNotifyEvent(FNotifyEventList[i])^(Self, NotifyType);
4179
end;
4180
 
4181
procedure TCustomDXDraw.FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
4182
 
4183
  procedure FlipToGDISurface;
4184
  begin
4185
    if Initialized and (FNowOptions*[doFullScreen, doFlip]=[doFullScreen, doFlip]) then
4186
      DDraw.IDraw.FlipToGDISurface;
4187
  end;
4188
 
4189
begin
4190
  case Message.Msg of
4191
    {CM_ACTIVATE:
4192
        begin
4193
          DefWindowProc(Message);
4194
          if AutoInitialize and (not FInitalized2) then
4195
            Initialize;
4196
          Exit;
4197
        end;   }
4198
    WM_WINDOWPOSCHANGED:
4199
        begin
4200
          if TWMWindowPosChanged(Message).WindowPos^.flags and SWP_SHOWWINDOW<>0 then
4201
          begin
4202
            DefWindowProc(Message);
4203
            if AutoInitialize and (not FInitialized2) then
4204
              Initialize;
4205
            Exit;
4206
          end;
4207
        end;
4208
    WM_ACTIVATE:
4209
        begin
4210
          if TWMActivate(Message).Active=WA_INACTIVE then
4211
            FlipToGDISurface;
4212
        end;
4213
    WM_INITMENU:
4214
        begin
4215
          FlipToGDISurface;
4216
        end;
4217
    WM_DESTROY:
4218
        begin
4219
          Finalize;
4220
        end;
4221
  end;      
4222
  DefWindowProc(Message);
4223
end;
4224
 
4225
procedure TCustomDXDraw.DoFinalize;
4226
begin
4227
  if Assigned(FOnFinalize) then FOnFinalize(Self);
4228
end;
4229
 
4230
procedure TCustomDXDraw.DoFinalizeSurface;
4231
begin
4232
  if Assigned(FOnFinalizeSurface) then FOnFinalizeSurface(Self);
4233
end;
4234
 
4235
procedure TCustomDXDraw.DoInitialize;
4236
begin
4237
  if Assigned(FOnInitialize) then FOnInitialize(Self);
4238
end;
4239
 
4240
procedure TCustomDXDraw.DoInitializeSurface;
4241
begin
4242
  if Assigned(FOnInitializeSurface) then FOnInitializeSurface(Self);
4243
end;
4244
 
4245
procedure TCustomDXDraw.DoInitializing;
4246
begin
4247
  if Assigned(FOnInitializing) then FOnInitializing(Self);
4248
end;
4249
 
4250
procedure TCustomDXDraw.DoRestoreSurface;
4251
begin
4252
  if Assigned(FOnRestoreSurface) then FOnRestoreSurface(Self);
4253
end;
4254
 
4255
procedure TCustomDXDraw.Finalize;
4256
begin
4257
  if FInternalInitialized then
4258
  begin
4259
    FSurfaceWidth := SurfaceWidth;
4260
    FSurfaceHeight := SurfaceHeight;
4261
 
4262
    FDisplay.FModes.Clear;
4263
 
4264
    FUpdating := True;
4265
    try
4266
      try
4267
        try
4268
          if FCalledDoInitializeSurface then
4269
          begin
4270
            FCalledDoInitializeSurface := False;
4271
            DoFinalizeSurface;
4272
          end;
4273
        finally
4274
          NotifyEventList(dxntFinalizeSurface);
4275
        end;
4276
      finally
4277
        try
4278
          if FCalledDoInitialize then
4279
          begin
4280
            FCalledDoInitialize := False;
4281
            DoFinalize;
4282
          end;
4283
        finally
4284
          NotifyEventList(dxntFinalize);
4285
        end;
4286
      end;
4287
    finally
4288
      FInternalInitialized := False;
4289
      FInitialized := False;
4290
 
4291
      SetOptions(FOptions);
4292
 
4293
      FDXDrawDriver.Free; FDXDrawDriver := nil;
4294
      FUpdating := False;
4295
    end;
4296
  end;
4297
end;
4298
 
4299
procedure TCustomDXDraw.Flip;
4300
begin
4301
  if Initialized and (not FUpdating) then
4302
  begin
4303
    if TryRestore then
4304
      TDXDrawDriver(FDXDrawDriver).Flip;
4305
  end;
4306
end;
4307
 
4308
function TCustomDXDraw.GetCanDraw: Boolean;
4309
begin
4310
  Result := Initialized and (not FUpdating) and (Surface.IDDSurface<>nil) and
4311
    TryRestore;
4312
end;
4313
 
4314
function TCustomDXDraw.GetCanPaletteAnimation: Boolean;
4315
begin
4316
  Result := Initialized and (not FUpdating) and (doFullScreen in FNowOptions)
4317
    and (DDraw.DisplayMode.ddpfPixelFormat.dwRGBBitCount<=8);
4318
end;
4319
 
4320
function TCustomDXDraw.GetSurfaceHeight: Integer;
4321
begin
4322
  if Surface.IDDSurface<>nil then
4323
    Result := Surface.Height
4324
  else
4325
    Result := FSurfaceHeight;
4326
end;
4327
 
4328
function TCustomDXDraw.GetSurfaceWidth: Integer;
4329
begin
4330
  if Surface.IDDSurface<>nil then
4331
    Result := Surface.Width
4332
  else
4333
    Result := FSurfaceWidth;
4334
end;
4335
 
4336
procedure TCustomDXDraw.Loaded;
4337
begin
4338
  inherited Loaded;
4339
 
4340
  if AutoSize then
4341
  begin
4342
    FSurfaceWidth := Width;
4343
    FSurfaceHeight := Height;
4344
  end;
4345
 
4346
  NotifyEventList(dxntSetSurfaceSize);
4347
 
4348
  if FAutoInitialize and (not (csDesigning in ComponentState)) then
4349
  begin                                      
4350
    if {(not (doFullScreen in FOptions)) or }(FSubClass=nil) then
4351
      Initialize;
4352
  end;
4353
end;
4354
 
4355
procedure TCustomDXDraw.Initialize;
4356
begin
4357
  FInitialized2 := True;
4358
 
4359
  Finalize;
4360
 
4361
  if FForm=nil then
4362
    raise EDXDrawError.Create(SNoForm);
4363
 
4364
  try
4365
    DoInitializing;
4366
 
4367
    {  Initialization.  }
4368
    FUpdating := True;
4369
    try
4370
      FInternalInitialized := True;
4371
 
4372
      NotifyEventList(dxntInitializing);
4373
 
4374
      {  DirectDraw initialization.  }
4375
      if doFlip in FNowOptions then
4376
        FDXDrawDriver := TDXDrawDriverFlip.Create(Self)
4377
      else
4378
        FDXDrawDriver := TDXDrawDriverBlt.Create(Self);
4379
 
4380
      {  Window handle setting.  }
4381
      SetCooperativeLevel;
4382
 
4383
      {  Set display mode.  }
4384
      if doFullScreen in FNowOptions then
4385
      begin
4386
        if not Display.DynSetSize(Display.Width, Display.Height, Display.BitCount) then
4387
          raise EDXDrawError.CreateFmt(SDisplaymodeChange, [Display.Width, Display.Height, Display.BitCount]);
4388
      end;
4389
 
4390
      {  Resource initialization.  }
4391
      if AutoSize then
4392
      begin
4393
        FSurfaceWidth := Width;
4394
        FSurfaceHeight := Height;
4395
      end;
4396
 
4397
      TDXDrawDriver(FDXDrawDriver).Initialize;
4398
    finally
4399
      FUpdating := False;
4400
    end;
4401
  except
4402
    Finalize;
4403
    raise;
4404
  end;
4405
 
4406
  FInitialized := True;
4407
 
4408
  Inc(FOffNotifyRestore);
4409
  try
4410
    NotifyEventList(dxntSetSurfaceSize);
4411
    NotifyEventList(dxntInitialize);
4412
    FCalledDoInitialize := True; DoInitialize;
4413
 
4414
    NotifyEventList(dxntInitializeSurface);
4415
    FCalledDoInitializeSurface := True; DoInitializeSurface;
4416
  finally
4417
    Dec(FOffNotifyRestore);
4418
  end;
4419
 
4420
  Restore;
4421
end;
4422
 
4423
procedure TCustomDXDraw.Paint;
4424
var
4425
  Old: TDXDrawOptions;
4426
  w, h: Integer;
4427
  s: string;
4428
begin
4429
  inherited Paint;
4430
  if (csDesigning in ComponentState) then
4431
  begin
4432
    Canvas.Brush.Style := bsClear;
4433
    Canvas.Pen.Color := clBlack;
4434
    Canvas.Pen.Style := psDash;
4435
    Canvas.Rectangle(0, 0, Width, Height);
4436
 
4437
    Canvas.Pen.Style := psSolid;
4438
    Canvas.Pen.Color := clGray;
4439
    Canvas.MoveTo(0, 0);
4440
    Canvas.LineTo(Width, Height);
4441
 
4442
    Canvas.MoveTo(0, Height);
4443
    Canvas.LineTo(Width, 0);
4444
 
4445
    s := Format('(%s)', [ClassName]);
4446
 
4447
    w := Canvas.TextWidth(s);
4448
    h := Canvas.TextHeight(s);
4449
 
4450
    Canvas.Brush.Style := bsSolid;
4451
    Canvas.Brush.Color := clBtnFace;
4452
    Canvas.TextOut(Width div 2-w div 2, Height div 2-h div 2, s);
4453
  end else
4454
  begin
4455
    Old := FNowOptions;
4456
    try
4457
      FNowOptions := FNowOptions - [doWaitVBlank];
4458
      Flip;
4459
    finally        
4460
      FNowOptions := Old;
4461
    end;    
4462
    if (Parent<>nil) and (Initialized) and (Surface.SurfaceDesc.ddscaps.dwCaps and DDSCAPS_VIDEOMEMORY<>0) then
4463
      Parent.Invalidate;                                                                                
4464
  end;
4465
end;
4466
 
4467
function TCustomDXDraw.PaletteChanged(Foreground: Boolean): Boolean;
4468
begin
4469
  if Foreground then
4470
  begin
4471
    Restore;
4472
    Result := True;
4473
  end else
4474
    Result := False;
4475
end;
4476
 
4477
procedure TCustomDXDraw.Render;
4478
begin
4479
  if FInitialized and (do3D in FNowOptions) and (doRetainedMode in FNowOptions) then
4480
  begin
4481
    asm FInit end;
4482
    FViewport.Clear;
4483
    FViewport.Render(FScene);
4484
    FD3DRMDevice.Update;
4485
    asm FInit end;
4486
  end;
4487
end;
4488
 
4489
procedure TCustomDXDraw.Restore;
4490
begin
4491
  if Initialized and (not FUpdating) then
4492
  begin
4493
    FUpdating := True;
4494
    try
4495
      if TDXDrawDriver(FDXDrawDriver).Restore then
4496
      begin
4497
        Primary.Palette := Palette;
4498
        Surface.Palette := Palette;
4499
 
4500
        SetColorTable(DefColorTable);
4501
        NotifyEventList(dxntRestore);
4502
        DoRestoreSurface;
4503
        SetColorTable(ColorTable);
4504
      end;
4505
    finally
4506
      FUpdating := False;
4507
    end;
4508
  end;
4509
end;
4510
 
4511
procedure TCustomDXDraw.SetAutoSize(Value: Boolean);
4512
begin
4513
  if FAutoSize<>Value then
4514
  begin
4515
    FAutoSize := Value;
4516
    if FAutoSize then
4517
      SetSize(Width, Height);
4518
  end;
4519
end;
4520
 
4521
procedure TCustomDXDraw.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
4522
begin
4523
  inherited SetBounds(ALeft, ATop, AWidth, AHeight);
4524
  if FAutoSize and (not FUpdating) then
4525
    SetSize(AWidth, AHeight);
4526
end;
4527
 
4528
procedure TCustomDXDraw.SetColorTable(const ColorTable: TRGBQuads);
4529
var
4530
  Entries: TPaletteEntries;
4531
begin
4532
  if Initialized and (Palette<>nil) then
4533
  begin
4534
    Entries := TDXDrawRGBQuadsToPaletteEntries(ColorTable,
4535
      doAllowPalette256 in FNowOptions);
4536
    Palette.SetEntries(0, 256, Entries);
4537
  end;
4538
end;
4539
 
4540
procedure TCustomDXDraw.SetCooperativeLevel;
4541
var
4542
  Flags: Integer;
4543
  Control: TWinControl;
4544
begin
4545
  Control := FForm;
4546
  if Control=nil then
4547
    Control := Self;
4548
 
4549
  if doFullScreen in FNowOptions then
4550
  begin
4551
    Flags := DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE or DDSCL_ALLOWMODEX;
4552
    if doNoWindowChange in FNowOptions then
4553
      Flags := Flags or DDSCL_NOWINDOWCHANGES;
4554
    if doAllowReboot in FNowOptions then
4555
      Flags := Flags or DDSCL_ALLOWREBOOT;
4556
  end else
4557
    Flags := DDSCL_NORMAL;
4558
 
4559
  DDraw.DXResult := DDraw.IDraw.SetCooperativeLevel(Control.Handle, Flags);
4560
end;
4561
 
4562
procedure TCustomDXDraw.SetDisplay(Value: TDXDrawDisplay);
4563
begin
4564
  FDisplay.Assign(Value);
4565
end;
4566
 
4567
procedure TCustomDXDraw.SetDriver(Value: PGUID);
4568
begin
4569
  if not IsBadHugeReadPtr(Value, SizeOf(TGUID)) then
4570
  begin
4571
    FDriverGUID := Value^;
4572
    FDriver := @FDriverGUID;
4573
  end else
4574
    FDriver := Value;
4575
end;
4576
 
4577
procedure TCustomDXDraw.SetOptions(Value: TDXDrawOptions);
4578
const
4579
  InitOptions = [doDirectX7Mode, doFullScreen, doNoWindowChange, doAllowReboot,
4580
    doAllowPalette256, doSystemMemory, doFlip, do3D,
4581
    doRetainedMode, doHardware, doSelectDriver, doZBuffer];
4582
var
4583
  OldOptions: TDXDrawOptions;
4584
begin
4585
  FOptions := Value;
4586
 
4587
  if Initialized then
4588
  begin
4589
    OldOptions := FNowOptions;
4590
    FNowOptions := FNowOptions*InitOptions+(FOptions-InitOptions);
4591
 
4592
    if not (do3D in FNowOptions) then
4593
      FNowOptions := FNowOptions - [doHardware, doRetainedMode, doSelectDriver, doZBuffer];
4594
  end else
4595
  begin
4596
    FNowOptions := FOptions;
4597
 
4598
    if not (doFullScreen in FNowOptions) then
4599
      FNowOptions := FNowOptions - [doNoWindowChange, doAllowReBoot, doAllowPalette256, doFlip];
4600
 
4601
    if not (do3D in FNowOptions) then
4602
      FNowOptions := FNowOptions - [doDirectX7Mode, doRetainedMode, doHardware, doSelectDriver, doZBuffer];
4603
 
4604
    if doSystemMemory in FNowOptions then
4605
      FNowOptions := FNowOptions - [doFlip];
4606
 
4607
    if doDirectX7Mode in FNowOptions then
4608
      FNowOptions := FNowOptions - [doRetainedMode];
4609
 
4610
    FNowOptions := FNowOptions - [doHardware];
4611
  end;
4612
end;
4613
 
4614
procedure TCustomDXDraw.SetParent(AParent: TWinControl);
4615
var
4616
  Control: TWinControl;
4617
begin
4618
  inherited SetParent(AParent);
4619
 
4620
  FForm := nil;
4621
  FSubClass.Free; FSubClass := nil;
4622
 
4623
  if not (csDesigning in ComponentState) then
4624
  begin
4625
    Control := Parent;
4626
    while (Control<>nil) and (not (Control is TCustomForm)) do
4627
      Control := Control.Parent;
4628
    if Control<>nil then
4629
    begin
4630
      FForm := TCustomForm(Control);
4631
      FSubClass := TControlSubClass.Create(Control, FormWndProc);
4632
    end;
4633
  end;
4634
end;
4635
 
4636
procedure TCustomDXDraw.SetSize(ASurfaceWidth, ASurfaceHeight: Integer);
4637
begin
4638
  if ((ASurfaceWidth<>SurfaceWidth) or (ASurfaceHeight<>SurfaceHeight)) and
4639
    (not FUpdating) then
4640
  begin
4641
    if Initialized then
4642
    begin
4643
      try
4644
        if not TDXDrawDriver(FDXDrawDriver).SetSize(ASurfaceWidth, ASurfaceHeight) then
4645
          Exit;
4646
      except
4647
        Finalize;
4648
        raise;
4649
      end;
4650
    end else
4651
    begin
4652
      FSurfaceWidth := ASurfaceWidth;
4653
      FSurfaceHeight := ASurfaceHeight;
4654
    end;
4655
 
4656
    NotifyEventList(dxntSetSurfaceSize);
4657
  end;
4658
end;
4659
 
4660
procedure TCustomDXDraw.SetSurfaceHeight(Value: Integer);
4661
begin
4662
  if ComponentState*[csReading, csLoading]=[] then
4663
    SetSize(SurfaceWidth, Value)
4664
  else
4665
    FSurfaceHeight := Value;
4666
end;
4667
 
4668
procedure TCustomDXDraw.SetSurfaceWidth(Value: Integer);
4669
begin
4670
  if ComponentState*[csReading, csLoading]=[] then
4671
    SetSize(Value, SurfaceHeight)
4672
  else
4673
    FSurfaceWidth := Value;
4674
end;
4675
 
4676
function TCustomDXDraw.TryRestore: Boolean;
4677
begin
4678
  Result := False;
4679
 
4680
  if Initialized and (not FUpdating) and (Primary.IDDSurface<>nil) then
4681
  begin
4682
    if (Primary.ISurface.IsLost=DDERR_SURFACELOST) or
4683
      (Surface.ISurface.IsLost=DDERR_SURFACELOST) then
4684
    begin
4685
      Restore;
4686
      Result := (Primary.ISurface.IsLost=DD_OK) and (Surface.ISurface.IsLost=DD_OK);
4687
    end else
4688
      Result := True;
4689
  end;
4690
end;
4691
 
4692
procedure TCustomDXDraw.UpdatePalette;
4693
begin
4694
  if Initialized and (doWaitVBlank in FNowOptions) then
4695
  begin
4696
    if FDDraw.FDriverCaps.dwPalCaps and DDPCAPS_VSYNC=0 then
4697
      FDDraw.IDraw.WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
4698
  end;
4699
 
4700
  SetColorTable(ColorTable);
4701
end;
4702
 
4703
procedure TCustomDXDraw.WMCreate(var Message: TMessage);
4704
begin
4705
  inherited;
4706
  if Initialized and (not FUpdating) then
4707
  begin
4708
    if Clipper<>nil then
4709
      Clipper.Handle := Handle;
4710
    SetCooperativeLevel;
4711
  end;
4712
end;
4713
 
4714
{  TCustomDX3D  }
4715
 
4716
constructor TCustomDX3D.Create(AOwner: TComponent);
4717
begin
4718
  inherited Create(AOwner);
4719
  Options := [toHardware, toRetainedMode, toSelectDriver];
4720
  FSurfaceWidth := 320;
4721
  FSurfaceHeight := 240;
4722
end;
4723
 
4724
destructor TCustomDX3D.Destroy;
4725
begin
4726
  DXDraw := nil;
4727
  inherited Destroy;
4728
end;
4729
 
4730
procedure TCustomDX3D.DoFinalize;
4731
begin
4732
  if Assigned(FOnFinalize) then FOnFinalize(Self);
4733
end;
4734
 
4735
procedure TCustomDX3D.DoInitialize;
4736
begin
4737
  if Assigned(FOnInitialize) then FOnInitialize(Self);
4738
end;
4739
 
4740
procedure TCustomDX3D.Finalize;
4741
begin
4742
  if FInitialized then
4743
  begin
4744
    try
4745
      if FInitFlag then
4746
      begin
4747
        FInitFlag := False;
4748
        DoFinalize;
4749
      end;
4750
    finally
4751
      FInitialized := False;
4752
 
4753
      SetOptions(FOptions);
4754
 
4755
      FViewport := nil;
4756
      FCamera := nil;
4757
      FScene := nil;
4758
 
4759
      FD3DRMDevice := nil;
4760
      FD3DRMDevice2 := nil;
4761
      FD3DRMDevice3 := nil;
4762
      FD3DDevice := nil;
4763
      FD3DDevice2 := nil;
4764
      FD3DDevice3 := nil;
4765
      FD3DDevice7 := nil;
4766
      FD3D := nil;
4767
      FD3D2 := nil;
4768
      FD3D3 := nil;
4769
      FD3D7 := nil;
4770
 
4771
      FreeZBufferSurface(FSurface, FZBuffer);
4772
 
4773
      FSurface.Free;   FSurface := nil;
4774
 
4775
      FD3DRM3 := nil;
4776
      FD3DRM2 := nil;
4777
      FD3DRM := nil;
4778
    end;
4779
  end;
4780
end;
4781
 
4782
procedure TCustomDX3D.Initialize;
4783
var
4784
  ddsd: TDDSurfaceDesc;
4785
  AOptions: TInitializeDirect3DOptions;
4786
begin
4787
  Finalize;
4788
  try
4789
    FInitialized := True;
4790
 
4791
    {  Make surface.  }
4792
    FillChar(ddsd, SizeOf(ddsd), 0);
4793
    ddsd.dwSize := SizeOf(ddsd);
4794
    ddsd.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS;
4795
    ddsd.dwWidth := Max(FSurfaceWidth, 1);
4796
    ddsd.dwHeight := Max(FSurfaceHeight, 1);
4797
    ddsd.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_3DDEVICE;
4798
    if toSystemMemory in FNowOptions then
4799
      ddsd.ddsCaps.dwCaps := ddsd.ddsCaps.dwCaps or DDSCAPS_SYSTEMMEMORY
4800
    else
4801
      ddsd.ddsCaps.dwCaps := ddsd.ddsCaps.dwCaps or DDSCAPS_VIDEOMEMORY;
4802
 
4803
    FSurface := TDirectDrawSurface.Create(FDXDraw.DDraw);
4804
    if not FSurface.CreateSurface(ddsd) then
4805
    begin
4806
      ddsd.ddsCaps.dwCaps := ddsd.ddsCaps.dwCaps and (not DDSCAPS_VIDEOMEMORY) or DDSCAPS_SYSTEMMEMORY;
4807
      if not FSurface.CreateSurface(ddsd) then
4808
        raise EDX3DError.CreateFmt(SCannotMade, [SDirectDrawSurface]);
4809
    end;
4810
 
4811
    AOptions := [];
4812
 
4813
    if toHardware in FNowOptions then AOptions := AOptions + [idoHardware];
4814
    if toRetainedMode in FNowOptions then AOptions := AOptions + [idoRetainedMode];
4815
    if toSelectDriver in FNowOptions then AOptions := AOptions + [idoSelectDriver];
4816
    if toZBuffer in FNowOptions then AOptions := AOptions + [idoZBuffer];
4817
 
4818
    if doDirectX7Mode in FDXDraw.NowOptions then
4819
    begin
4820
      InitializeDirect3D7(FSurface, FZBuffer, FD3D7, FD3DDevice7, AOptions);
4821
    end else
4822
    begin
4823
      InitializeDirect3D(FSurface, FZBuffer, FD3D, FD3D2, FD3D3, FD3DDevice, FD3DDevice2, FD3DDevice3,
4824
        FD3DRM, FD3DRM2, FD3DRM3, FD3DRMDevice, FD3DRMDevice2, FD3DRMDevice3, FViewport, FScene, FCamera, AOptions);
4825
    end;
4826
 
4827
    FNowOptions := [];
4828
 
4829
    if idoHardware in AOptions then FNowOptions := FNowOptions + [toHardware];
4830
    if idoRetainedMode in AOptions then FNowOptions := FNowOptions + [toRetainedMode];
4831
    if idoSelectDriver in AOptions then FNowOptions := FNowOptions + [toSelectDriver];
4832
    if idoZBuffer in AOptions then FNowOptions := FNowOptions + [toZBuffer];
4833
  except
4834
    Finalize;
4835
    raise;
4836
  end;
4837
 
4838
  FInitFlag := True; DoInitialize;
4839
end;
4840
 
4841
procedure TCustomDX3D.Render;
4842
begin
4843
  if FInitialized and (toRetainedMode in FNowOptions) then
4844
  begin
4845
    asm FInit end;
4846
    FViewport.Clear;
4847
    FViewport.Render(FScene);
4848
    FD3DRMDevice.Update;
4849
    asm FInit end;
4850
  end;
4851
end;
4852
 
4853
function TCustomDX3D.GetCanDraw: Boolean;
4854
begin
4855
  Result := Initialized and (Surface.IDDSurface<>nil) and
4856
    (Surface.ISurface.IsLost=DD_OK);
4857
end;
4858
 
4859
function TCustomDX3D.GetSurfaceHeight: Integer;
4860
begin
4861
  if FSurface.IDDSurface<>nil then
4862
    Result := FSurface.Height
4863
  else
4864
    Result := FSurfaceHeight;
4865
end;
4866
 
4867
function TCustomDX3D.GetSurfaceWidth: Integer;
4868
begin
4869
  if FSurface.IDDSurface<>nil then
4870
    Result := FSurface.Width
4871
  else
4872
    Result := FSurfaceWidth;
4873
end;
4874
 
4875
procedure TCustomDX3D.SetAutoSize(Value: Boolean);
4876
begin
4877
  if FAutoSize<>Value then
4878
  begin
4879
    FAutoSize := Value;
4880
    if FAutoSize and (DXDraw<>nil) then
4881
      SetSize(DXDraw.SurfaceWidth, DXDraw.SurfaceHeight);
4882
  end;
4883
end;
4884
 
4885
procedure TCustomDX3D.SetOptions(Value: TDX3DOptions);
4886
const
4887
  DX3DOptions = [toRetainedMode, toSystemMemory, toHardware, toSelectDriver, toZBuffer];
4888
  InitOptions = [toSystemMemory, toHardware, toSelectDriver, toZBuffer];
4889
var
4890
  OldOptions: TDX3DOptions;
4891
begin
4892
  FOptions := Value;
4893
 
4894
  if Initialized then
4895
  begin
4896
    OldOptions := FNowOptions;
4897
    FNowOptions := FNowOptions*InitOptions+FOptions*(DX3DOptions - InitOptions);
4898
  end else
4899
  begin
4900
    FNowOptions := FOptions;
4901
 
4902
    if (FDXDraw<>nil) and (doDirectX7Mode in FDXDraw.FNowOptions) then
4903
      FNowOptions := FNowOptions - [toRetainedMode];
4904
  end;
4905
end;
4906
 
4907
procedure TCustomDX3D.SetSize(ASurfaceWidth, ASurfaceHeight: Integer);
4908
begin
4909
  if (ASurfaceWidth<>SurfaceWidth) or (ASurfaceHeight<>SurfaceHeight) then
4910
  begin
4911
    FSurfaceWidth := ASurfaceWidth;
4912
    FSurfaceHeight := ASurfaceHeight;
4913
 
4914
    if Initialized then
4915
      Initialize;
4916
  end;
4917
end;
4918
 
4919
procedure TCustomDX3D.SetSurfaceHeight(Value: Integer);
4920
begin
4921
  if ComponentState*[csReading, csLoading]=[] then
4922
    SetSize(SurfaceWidth, Value)
4923
  else
4924
    FSurfaceHeight := Value;
4925
end;
4926
 
4927
procedure TCustomDX3D.SetSurfaceWidth(Value: Integer);
4928
begin
4929
  if ComponentState*[csReading, csLoading]=[] then
4930
    SetSize(Value, SurfaceHeight)
4931
  else
4932
    FSurfaceWidth := Value;
4933
end;
4934
 
4935
procedure TCustomDX3D.Notification(AComponent: TComponent;
4936
  Operation: TOperation);
4937
begin
4938
  inherited Notification(AComponent, Operation);
4939
  if (Operation=opRemove) and (FDXDraw=AComponent) then
4940
    DXDraw := nil;
4941
end;
4942
 
4943
procedure TCustomDX3D.DXDrawNotifyEvent(Sender: TCustomDXDraw;
4944
  NotifyType: TDXDrawNotifyType);
4945
var
4946
  AOptions: TInitializeDirect3DOptions;
4947
begin
4948
  case NotifyType of
4949
    dxntDestroying:
4950
        begin
4951
          DXDraw := nil;
4952
        end;
4953
    dxntInitializing:
4954
        begin
4955
          if (FDXDraw.FOptions*[do3D, doFullScreen]=[doFullScreen])
4956
            and (FOptions*[toSystemMemory, toSelectDriver]=[toSelectDriver]) then
4957
          begin
4958
            AOptions := [];
4959
            with FDXDraw do
4960
            begin
4961
              if doHardware in Options then AOptions := AOptions + [idoHardware];
4962
              if doRetainedMode in Options then AOptions := AOptions + [idoRetainedMode];
4963
              if doSelectDriver in Options then AOptions := AOptions + [idoSelectDriver];
4964
              if doZBuffer in Options then AOptions := AOptions + [idoZBuffer];
4965
            end;
4966
 
4967
            Direct3DInitializing_DXDraw(AOptions, FDXDraw);
4968
          end;
4969
        end;
4970
    dxntInitialize:
4971
        begin
4972
          Initialize;
4973
        end;
4974
    dxntFinalize:
4975
        begin
4976
          Finalize;
4977
        end;
4978
    dxntRestore:
4979
        begin
4980
          FSurface.Restore;
4981
          if FZBuffer<>nil then
4982
            FZBuffer.Restore;
4983
          FSurface.Palette := FDXDraw.Palette;
4984
        end;
4985
    dxntSetSurfaceSize:
4986
        begin
4987
          if AutoSize then
4988
            SetSize(Sender.SurfaceWidth, Sender.SurfaceHeight);
4989
        end;
4990
  end;
4991
end;
4992
 
4993
procedure TCustomDX3D.SetDXDraw(Value: TCustomDXDraw);
4994
begin
4995
  if FDXDraw<>Value then
4996
  begin
4997
    if FDXDraw<>nil then
4998
      FDXDraw.UnRegisterNotifyEvent(DXDrawNotifyEvent);
4999
 
5000
    FDXDraw := Value;
5001
 
5002
    if FDXDraw<>nil then
5003
      FDXDraw.RegisterNotifyEvent(DXDrawNotifyEvent);
5004
  end;
5005
end;
5006
 
5007
{  TDirect3DTexture  }
5008
 
5009
constructor TDirect3DTexture.Create(Graphic: TGraphic; DXDraw: TComponent);
5010
var
5011
  i: Integer;
5012
begin
5013
  inherited Create;
5014
  FDXDraw := DXDraw;
5015
  FGraphic := Graphic;
5016
 
5017
  {  The palette is acquired.  }
5018
  i := GetPaletteEntries(FGraphic.Palette, 0, 256, FPaletteEntries);
5019
  case i of
5020
    1..2   : FBitCount := 1;
5021
    3..16  : FBitCount := 4;
5022
    17..256: FBitCount := 8;
5023
  else
5024
    FBitCount := 24;
5025
  end;
5026
 
5027
  if FDXDraw is TCustomDXDraw then
5028
  begin
5029
    with (FDXDraw as TCustomDXDraw) do
5030
    begin
5031
      if (not Initialized) or (not (do3D in NowOptions)) then
5032
        raise EDirect3DTextureError.CreateFmt(SNotMade, [FDXDraw.ClassName]);
5033
    end;
5034
    FSurface := TDirectDrawSurface.Create((FDXDraw as TCustomDXDraw).Surface.DDraw);
5035
    (FDXDraw as TCustomDXDraw).RegisterNotifyEvent(DXDrawNotifyEvent);
5036
  end else if FDXDraw is TCustomDX3D then
5037
  begin
5038
    with (FDXDraw as TDX3D) do
5039
    begin
5040
      if not Initialized then
5041
        raise EDirect3DTextureError.CreateFmt(SNotMade, [FDXDraw.ClassName]);
5042
    end;
5043
 
5044
    FSurface := TDirectDrawSurface.Create((FDXDraw as TCustomDX3D).Surface.DDraw);
5045
    (FDXDraw as TCustomDX3D).FDXDraw.RegisterNotifyEvent(DXDrawNotifyEvent);
5046
  end else
5047
    raise EDirect3DTextureError.CreateFmt(SNotSupported, [FDXDraw.ClassName]);
5048
end;
5049
 
5050
destructor TDirect3DTexture.Destroy;
5051
begin
5052
  if FDXDraw is TCustomDXDraw then
5053
  begin
5054
    (FDXDraw as TCustomDXDraw).UnRegisterNotifyEvent(DXDrawNotifyEvent);
5055
  end else if FDXDraw is TCustomDX3D then
5056
  begin
5057
    (FDXDraw as TCustomDX3D).FDXDraw.UnRegisterNotifyEvent(DXDrawNotifyEvent);
5058
  end;
5059
 
5060
  Clear;
5061
  FSurface.Free;
5062
  inherited Destroy;
5063
end;
5064
 
5065
procedure TDirect3DTexture.Clear;
5066
begin
5067
  FHandle := 0;
5068
  FTexture := nil;
5069
  FSurface.IDDSurface := nil;
5070
end;
5071
 
5072
function TDirect3DTexture.GetHandle: TD3DTextureHandle;
5073
begin
5074
  if FTexture=nil then
5075
    Restore;
5076
  Result := FHandle;
5077
end;
5078
 
5079
function TDirect3DTexture.GetSurface: TDirectDrawSurface;
5080
begin
5081
  if FTexture=nil then
5082
    Restore;
5083
  Result := FSurface;
5084
end;
5085
 
5086
function TDirect3DTexture.GetTexture: IDirect3DTexture;
5087
begin
5088
  if FTexture=nil then
5089
    Restore;
5090
  Result := FTexture;
5091
end;
5092
 
5093
procedure TDirect3DTexture.SetTransparentColor(Value: TColor);
5094
begin
5095
  if FTransparentColor<>Value then
5096
  begin
5097
    FTransparentColor := Value;
5098
 
5099
    if FSurface<>nil then
5100
      FSurface.TransparentColor := FSurface.ColorMatch(Value);
5101
  end;
5102
end;
5103
 
5104
procedure TDirect3DTexture.Restore;
5105
 
5106
  function EnumTextureFormatCallback(const ddsd: TDDSurfaceDesc;
5107
    lParam: Pointer): HRESULT; stdcall;
5108
  var
5109
    tex: TDirect3DTexture;
5110
 
5111
    procedure UseThisFormat;
5112
    begin
5113
      tex.FFormat := ddsd;
5114
      tex.FEnumFormatFlag := True;
5115
    end;
5116
 
5117
  begin
5118
    Result := DDENUMRET_OK;
5119
    tex := lParam;
5120
 
5121
    if ddsd.ddpfPixelFormat.dwFlags and (DDPF_ALPHA or DDPF_ALPHAPIXELS)<>0 then
5122
      Exit;
5123
 
5124
    if not tex.FEnumFormatFlag then
5125
    begin
5126
      {  When called first,  this format is unconditionally selected.  }
5127
      UseThisFormat;
5128
    end else
5129
    begin
5130
      if (tex.FBitCount<=8) and (ddsd.ddpfPixelFormat.dwRGBBitCount>=tex.FBitCount) and
5131
        (ddsd.ddpfPixelFormat.dwRGBBitCount>=8) and
5132
        (ddsd.ddpfPixelFormat.dwFlags and DDPF_RGB<>0) then
5133
      begin
5134
        if tex.FFormat.ddpfPixelFormat.dwRGBBitCount>ddsd.ddpfPixelFormat.dwRGBBitCount then
5135
          UseThisFormat;
5136
      end else
5137
      begin
5138
        if (tex.FFormat.ddpfPixelFormat.dwRGBBitCount>ddsd.ddpfPixelFormat.dwRGBBitCount) and
5139
          (ddsd.ddpfPixelFormat.dwRGBBitCount>8) and
5140
          (ddsd.ddpfPixelFormat.dwFlags and DDPF_RGB<>0) then
5141
          UseThisFormat;
5142
      end;
5143
    end;
5144
  end;
5145
 
5146
  function GetBitCount(i: Integer): Integer;
5147
  var
5148
    j: Integer;
5149
  begin
5150
    for j:=32 downto 1 do
5151
      if (1 shl j) and i<>0 then
5152
      begin
5153
        Result := j;
5154
        if 1 shl j<>i then
5155
          Dec(Result);
5156
        Exit;
5157
      end;
5158
    Result := 0;
5159
  end;
5160
 
5161
  function CreateHalftonePalette(R, G, B: Integer): TPaletteEntries;
5162
  var
5163
    i: Integer;
5164
  begin
5165
    for i:=0 to 255 do
5166
      with Result[i] do
5167
      begin
5168
        peRed   := ((i shr (G+B-1)) and (1 shl R-1)) * 255 div (1 shl R-1);
5169
        peGreen := ((i shr (B-1)) and (1 shl G-1)) * 255 div (1 shl G-1);
5170
        peBlue  := ((i shr 0) and (1 shl B-1)) * 255 div (1 shl B-1);
5171
        peFlags := 0;
5172
      end;
5173
  end;
5174
 
5175
var
5176
  ddsd: TDDSurfaceDesc;
5177
  Palette: TDirectDrawPalette;
5178
  PaletteCaps: Integer;
5179
  TempSurface: TDirectDrawSurface;
5180
  Width2, Height2: Integer;
5181
  D3DDevice: IDirect3DDevice;
5182
  Hardware: Boolean;
5183
  DDraw: TDirectDraw;
5184
begin
5185
  Clear;
5186
  try
5187
    DDraw := nil;
5188
    Hardware := False;
5189
    if FDXDraw is TCustomDXDraw then
5190
    begin
5191
      DDraw := (FDXDraw as TCustomDXDraw).DDraw;
5192
      D3DDevice := (FDXDraw as TCustomDXDraw).D3DDevice;
5193
      Hardware := doHardware in (FDXDraw as TCustomDXDraw).NowOptions;
5194
    end else if FDXDraw is TCustomDX3D then
5195
    begin
5196
      DDraw := (FDXDraw as TCustomDX3D).Surface.DDraw;
5197
      D3DDevice := (FDXDraw as TCustomDX3D).D3DDevice;
5198
      Hardware := toHardware in (FDXDraw as TCustomDX3D).NowOptions;
5199
    end;
5200
 
5201
    if (DDraw=nil) or (D3DDevice=nil) then Exit;
5202
 
5203
    {  The size of texture is arranged in the size of the square of two.  }
5204
    Width2 := Max(1 shl GetBitCount(FGraphic.Width), 1);
5205
    Height2 := Max(1 shl GetBitCount(FGraphic.Height), 1);
5206
 
5207
    {  Selection of format of texture.  }
5208
    FEnumFormatFlag := False;
5209
    D3DDevice.EnumTextureFormats(@EnumTextureFormatCallback, Self);
5210
 
5211
    TempSurface := TDirectDrawSurface.Create(FSurface.DDraw);
5212
    try
5213
      {  Make source surface.  }
5214
      with ddsd do
5215
      begin
5216
        dwSize := SizeOf(ddsd);
5217
        dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT;
5218
        ddsCaps.dwCaps := DDSCAPS_TEXTURE or DDSCAPS_SYSTEMMEMORY;
5219
        dwWidth := Width2;
5220
        dwHeight := Height2;
5221
        ddpfPixelFormat := FFormat.ddpfPixelFormat;
5222
      end;
5223
 
5224
      if not TempSurface.CreateSurface(ddsd) then
5225
        raise EDirect3DTextureError.CreateFmt(SCannotMade, [STexture]);
5226
 
5227
      {  Make surface.  }
5228
      with ddsd do
5229
      begin
5230
        dwSize := SizeOf(ddsd);
5231
        dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT;
5232
        if Hardware then
5233
          ddsCaps.dwCaps := DDSCAPS_TEXTURE or DDSCAPS_VIDEOMEMORY
5234
        else
5235
          ddsCaps.dwCaps := DDSCAPS_TEXTURE or DDSCAPS_SYSTEMMEMORY;
5236
        ddsCaps.dwCaps := ddsCaps.dwCaps or DDSCAPS_ALLOCONLOAD;
5237
        dwWidth := Width2;
5238
        dwHeight := Height2;
5239
        ddpfPixelFormat := FFormat.ddpfPixelFormat;
5240
      end;
5241
 
5242
      if not FSurface.CreateSurface(ddsd) then
5243
        raise EDirect3DTextureError.CreateFmt(SCannotMade, [STexture]);
5244
 
5245
      {  Make palette.  }
5246
      if ddsd.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED8<>0 then
5247
      begin
5248
        PaletteCaps := DDPCAPS_8BIT or DDPCAPS_ALLOW256;
5249
        if FBitCount=24 then
5250
          CreateHalftonePalette(3, 3, 2);
5251
      end else if ddsd.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED4<>0 then
5252
      begin
5253
        PaletteCaps := DDPCAPS_4BIT;
5254
        if FBitCount=24 then
5255
          CreateHalftonePalette(1, 2, 1);
5256
      end else if ddsd.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED1<>0 then
5257
      begin
5258
        PaletteCaps := DDPCAPS_1BIT;
5259
        if FBitCount=24 then
5260
        begin
5261
          FPaletteEntries[0] := RGBQuadToPaletteEntry(RGBQuad(0, 0, 0));
5262
          FPaletteEntries[1] := RGBQuadToPaletteEntry(RGBQuad(255, 255, 255));
5263
        end;
5264
      end else
5265
        PaletteCaps := 0;
5266
 
5267
      if PaletteCaps<>0 then
5268
      begin
5269
        Palette := TDirectDrawPalette.Create(DDraw);
5270
        try
5271
          Palette.CreatePalette(PaletteCaps, FPaletteEntries);
5272
          TempSurface.Palette := Palette;
5273
          FSurface.Palette := Palette;
5274
        finally
5275
          Palette.Free;
5276
        end;
5277
      end;
5278
 
5279
      {  The image is loaded into source surface.  }
5280
      with TempSurface.Canvas do
5281
      begin
5282
        StretchDraw(TempSurface.ClientRect, FGraphic);
5283
        Release;
5284
      end;
5285
 
5286
      {  Source surface is loaded into surface.  }
5287
      FTexture := FSurface.ISurface as IDirect3DTexture;
5288
      FTexture.Load(TempSurface.ISurface as IDirect3DTexture);
5289
    finally
5290
      TempSurface.Free;
5291
    end;
5292
 
5293
    if FTexture.GetHandle(D3DDevice, FHandle)<>D3D_OK then
5294
      raise EDirect3DTextureError.CreateFmt(SCannotMade, [STexture]);
5295
 
5296
    FSurface.TransparentColor := FSurface.ColorMatch(FTransparentColor);
5297
  except
5298
    Clear;
5299
    raise;
5300
  end;
5301
end;
5302
 
5303
procedure TDirect3DTexture.DXDrawNotifyEvent(Sender: TCustomDXDraw;
5304
  NotifyType: TDXDrawNotifyType);
5305
begin
5306
  case NotifyType of
5307
    dxntInitializeSurface:
5308
        begin
5309
          Restore;
5310
        end;
5311
    dxntRestore:
5312
        begin
5313
          Restore;
5314
        end;
5315
  end;
5316
end;
5317
 
5318
{  TDirect3DTexture2  }
5319
 
5320
constructor TDirect3DTexture2.Create(ADXDraw: TCustomDXDraw; Graphic: TObject;
5321
  AutoFreeGraphic: Boolean);
5322
begin
5323
  inherited Create;
5324
  FSrcImage := Graphic;
5325
  FAutoFreeGraphic := AutoFreeGraphic;
5326
  FNeedLoadTexture := True;
5327
 
5328
  if FSrcImage is TDXTextureImage then
5329
    FImage := TDXTextureImage(FSrcImage)
5330
  else if FSrcImage is TDIB then
5331
    SetDIB(TDIB(FSrcImage))
5332
  else if FSrcImage is TGraphic then
5333
  begin
5334
    FSrcImage := TDIB.Create;
5335
    try
5336
      TDIB(FSrcImage).Assign(TGraphic(Graphic));
5337
      SetDIB(TDIB(FSrcImage));
5338
    finally
5339
      if FAutoFreeGraphic then
5340
        Graphic.Free;
5341
      FAutoFreeGraphic := True;
5342
    end;
5343
  end else
5344
  if FSrcImage is TPicture then
5345
  begin
5346
    FSrcImage := TDIB.Create;
5347
    try
5348
      TDIB(FSrcImage).Assign(TPicture(Graphic).Graphic);
5349
      SetDIB(TDIB(FSrcImage));
5350
    finally
5351
      if FAutoFreeGraphic then
5352
        Graphic.Free;
5353
      FAutoFreeGraphic := True;
5354
    end;
5355
  end else
5356
    raise Exception.CreateFmt(SCannotLoadGraphic, [Graphic.ClassName]);
5357
 
5358
  FMipmap := FImage.SubGroupImageCount[DXTextureImageGroupType_Mipmap]>0;
5359
 
5360
  FTransparent := FImage.Transparent;
5361
  case FImage.ImageType of
5362
    DXTextureImageType_PaletteIndexedColor:
5363
      begin
5364
        FTransparentColor := PaletteIndex(dxtDecodeChannel(FImage.idx_index, FImage.TransparentColor));
5365
      end;
5366
    DXTextureImageType_RGBColor:
5367
      begin
5368
        FTransparentColor := RGB(dxtDecodeChannel(FImage.rgb_red, FImage.TransparentColor),
5369
          dxtDecodeChannel(FImage.rgb_green, FImage.TransparentColor),
5370
          dxtDecodeChannel(FImage.rgb_blue, FImage.TransparentColor));
5371
      end;
5372
  end;
5373
 
5374
  SetDXDraw(ADXDraw);
5375
end;
5376
 
5377
constructor TDirect3DTexture2.CreateFromFile(ADXDraw: TCustomDXDraw; const FileName: string);
5378
var
5379
  Image: TObject;
5380
begin
5381
  Image := nil;
5382
  try
5383
    {  TDXTextureImage  }
5384
    Image := TDXTextureImage.Create;
5385
    try
5386
      TDXTextureImage(Image).LoadFromFile(FileName);
5387
    except
5388
      Image.Free;
5389
      Image := nil;
5390
    end;
5391
 
5392
    {  TDIB  }
5393
    if Image=nil then
5394
    begin
5395
      Image := TDIB.Create;
5396
      try
5397
        TDIB(Image).LoadFromFile(FileName);
5398
      except
5399
        Image.Free;
5400
        Image := nil;
5401
      end;
5402
    end;
5403
 
5404
    {  TPicture  }
5405
    if Image=nil then
5406
    begin
5407
      Image := TPicture.Create;
5408
      try
5409
        TPicture(Image).LoadFromFile(FileName);
5410
      except
5411
        Image.Free;
5412
        Image := nil;
5413
        raise;
5414
      end;
5415
    end;
5416
  except
5417
    Image.Free;
5418
    raise;
5419
  end;
5420
 
5421
  Create(ADXDraw, Image, True);
5422
end;
5423
 
5424
constructor TDirect3DTexture2.CreateVideoTexture(ADXDraw: TCustomDXDraw);
5425
begin
5426
  inherited Create;
5427
  SetDXDraw(ADXDraw);
5428
end;
5429
 
5430
destructor TDirect3DTexture2.Destroy;
5431
begin
5432
  Finalize;
5433
 
5434
  SetDXDraw(nil);
5435
 
5436
  if FAutoFreeGraphic then
5437
    FSrcImage.Free;
5438
  FImage2.Free;
5439
  inherited Destroy;
5440
end;
5441
 
5442
procedure TDirect3DTexture2.DXDrawNotifyEvent(Sender: TCustomDXDraw;
5443
  NotifyType: TDXDrawNotifyType);
5444
begin
5445
  case NotifyType of
5446
    dxntDestroying:
5447
        begin
5448
          SetDXDraw(nil);
5449
        end;
5450
    dxntInitializeSurface:
5451
        begin
5452
          Initialize;
5453
        end;
5454
    dxntFinalizeSurface:
5455
        begin
5456
          Finalize;
5457
        end;
5458
    dxntRestore:
5459
        begin
5460
          Load;
5461
        end;
5462
  end;
5463
end;
5464
 
5465
procedure TDirect3DTexture2.SetDXDraw(ADXDraw: TCustomDXDraw);
5466
begin
5467
  if FDXDraw<>ADXDraw then
5468
  begin
5469
    if FDXDraw<>nil then
5470
      FDXDraw.UnRegisterNotifyEvent(DXDrawNotifyEvent);
5471
 
5472
    FDXDraw := ADXDraw;
5473
 
5474
    if FDXDraw<>nil then
5475
      FDXDraw.RegisterNotifyEvent(DXDrawNotifyEvent);
5476
  end;
5477
end;
5478
 
5479
procedure TDirect3DTexture2.DoRestoreSurface;
5480
begin
5481
  if Assigned(FOnRestoreSurface) then
5482
    FOnRestoreSurface(Self);
5483
end;
5484
 
5485
procedure TDirect3DTexture2.SetDIB(DIB: TDIB);
5486
var
5487
  i: Integer;
5488
begin
5489
  if FImage2=nil then
5490
    FImage2 := TDXTextureImage.Create;
5491
 
5492
  if DIB.BitCount<=8 then
5493
  begin
5494
    FImage2.SetImage(DXTextureImageType_PaletteIndexedColor, DIB.Width, DIB.Height, DIB.BitCount,
5495
      DIB.WidthBytes, DIB.NextLine, DIB.PBits, DIB.TopPBits, DIB.Size, False);
5496
 
5497
    FImage2.idx_index := dxtMakeChannel((1 shl DIB.BitCount)-1, True);
5498
    for i:=0 to 255 do
5499
      FImage2.idx_palette[i] := RGBQuadToPaletteEntry(DIB.ColorTable[i]);
5500
  end else
5501
  begin
5502
    FImage2.SetImage(DXTextureImageType_RGBColor, DIB.Width, DIB.Height, DIB.BitCount,
5503
      DIB.WidthBytes, DIB.NextLine, DIB.PBits, DIB.TopPBits, DIB.Size, False);
5504
 
5505
    FImage2.rgb_red := dxtMakeChannel(DIB.NowPixelFormat.RBitMask, False);
5506
    FImage2.rgb_green := dxtMakeChannel(DIB.NowPixelFormat.GBitMask, False);
5507
    FImage2.rgb_blue := dxtMakeChannel(DIB.NowPixelFormat.BBitMask, False);
5508
 
5509
    i := DIB.NowPixelFormat.RBitCount+DIB.NowPixelFormat.GBitCount+DIB.NowPixelFormat.BBitCount;
5510
    if i<DIB.BitCount then
5511
      FImage2.rgb_alpha := dxtMakeChannel(((1 shl (DIB.BitCount-i))-1) shl i, False);
5512
  end;
5513
 
5514
  FImage := FImage2;
5515
end;
5516
 
5517
function TDirect3DTexture2.GetIsMipmap: Boolean;
5518
begin
5519
  if FSurface<>nil then
5520
    Result := FUseMipmap
5521
  else
5522
    Result := FMipmap;
5523
end;
5524
 
5525
function TDirect3DTexture2.GetSurface: TDirectDrawSurface;
5526
begin
5527
  Result := FSurface;
5528
  if (Result<>nil) and FNeedLoadTexture then
5529
    Load;
5530
end;
5531
 
5532
function TDirect3DTexture2.GetTransparent: Boolean;
5533
begin
5534
  if FSurface<>nil then
5535
    Result := FUseColorKey
5536
  else
5537
    Result := FTransparent;
5538
end;
5539
 
5540
procedure TDirect3DTexture2.SetTransparent(Value: Boolean);
5541
begin
5542
  if FTransparent<>Value then
5543
  begin
5544
    FTransparent := Value;
5545
    if FSurface<>nil then
5546
      SetColorKey;
5547
  end;
5548
end;
5549
 
5550
procedure TDirect3DTexture2.SetTransparentColor(Value: TColorRef);
5551
begin
5552
  if FTransparentColor<>Value then
5553
  begin
5554
    FTransparentColor := Value;
5555
    if (FSurface<>nil) and FTransparent then
5556
      SetColorKey;
5557
  end;
5558
end;
5559
 
5560
procedure TDirect3DTexture2.Finalize;
5561
begin
5562
  FSurface.Free; FSurface := nil;
5563
 
5564
  FUseColorKey := False;
5565
  FUseMipmap := False;
5566
  FNeedLoadTexture := False;
5567
end;
5568
 
5569
const
5570
  DDPF_PALETTEINDEXED = DDPF_PALETTEINDEXED1 or DDPF_PALETTEINDEXED2 or
5571
    DDPF_PALETTEINDEXED4 or DDPF_PALETTEINDEXED8;
5572
 
5573
procedure TDirect3DTexture2.Initialize;
5574
 
5575
  function GetBitCount(i: Integer): Integer;
5576
  begin
5577
    Result := 31;
5578
    while (i>=0) and (((1 shl Result) and i)=0) do Dec(Result);
5579
  end;
5580
 
5581
  function GetMaskBitCount(b: Integer): Integer;
5582
  var
5583
    i: Integer;
5584
  begin
5585
    i := 0;
5586
    while (i<31) and (((1 shl i) and b)=0) do Inc(i);
5587
 
5588
    Result := 0;
5589
    while ((1 shl i) and b)<>0 do
5590
    begin
5591
      Inc(i);
5592
      Inc(Result);
5593
    end;
5594
  end;
5595
 
5596
  function GetPaletteBitCount(const ddpfPixelFormat: TDDPixelFormat): Integer;
5597
  begin
5598
    if ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED8<>0 then
5599
      Result := 8
5600
    else if ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED4<>0 then
5601
      Result := 4
5602
    else if ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED2<>0 then
5603
      Result := 2
5604
    else if ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED1<>0 then
5605
      Result := 1
5606
    else
5607
      Result := 0;
5608
  end;
5609
 
5610
  function EnumTextureFormatCallback(const lpDDPixFmt: TDDPixelFormat;
5611
    lParam: Pointer): HRESULT; stdcall;
5612
  var
5613
    tex: TDirect3DTexture2;
5614
 
5615
    procedure UseThisFormat;
5616
    begin
5617
      tex.FTextureFormat.ddpfPixelFormat := lpDDPixFmt;
5618
      tex.FEnumTextureFormatFlag := True;
5619
    end;
5620
 
5621
  var
5622
    rgb_red, rgb_green, rgb_blue, rgb_alpha, idx_index: Integer;
5623
    sum1, sum2: Integer;
5624
  begin
5625
    Result := DDENUMRET_OK;
5626
    tex := lParam;
5627
 
5628
    {  Form acquisition of source image  }
5629
    rgb_red := 0;
5630
    rgb_green := 0;
5631
    rgb_blue := 0;
5632
    rgb_alpha := 0;
5633
    idx_index := 0;
5634
 
5635
    case tex.FImage.ImageType of
5636
      DXTextureImageType_RGBColor:
5637
        begin
5638
          {  RGB Color  }
5639
          rgb_red := tex.FImage.rgb_red.bitcount;
5640
          rgb_green := tex.FImage.rgb_green.bitcount;
5641
          rgb_blue := tex.FImage.rgb_blue.bitcount;
5642
          rgb_alpha := tex.FImage.rgb_alpha.bitcount;
5643
          idx_index := 8;
5644
        end;
5645
      DXTextureImageType_PaletteIndexedColor:
5646
        begin
5647
          {  Index Color  }
5648
          rgb_red := 8;
5649
          rgb_green := 8;
5650
          rgb_blue := 8;
5651
          rgb_alpha := tex.FImage.idx_alpha.bitcount;
5652
          idx_index := tex.FImage.idx_index.bitcount;
5653
        end;
5654
    end;
5655
 
5656
    {  The texture examines whether this pixel format can be used.  }
5657
    if lpDDPixFmt.dwFlags and DDPF_RGB=0 then Exit;
5658
 
5659
    case tex.FImage.ImageType of
5660
      DXTextureImageType_RGBColor:
5661
        begin
5662
          if lpDDPixFmt.dwFlags and DDPF_PALETTEINDEXED<>0 then Exit;
5663
        end;
5664
      DXTextureImageType_PaletteIndexedColor:
5665
        begin
5666
          if (lpDDPixFmt.dwFlags and DDPF_PALETTEINDEXED<>0) and
5667
            (GetPaletteBitCount(lpDDPixFmt)<idx_index) then Exit;
5668
        end;
5669
    end;
5670
 
5671
    {  The pixel format which can be used is selected carefully.  }
5672
    if tex.FEnumTextureFormatFlag then
5673
    begin
5674
      if lpDDPixFmt.dwFlags and DDPF_PALETTEINDEXED<>0 then
5675
      begin
5676
        {  Bit count check  }
5677
        if Abs(Integer(lpDDPixFmt.dwRGBBitCount)-idx_index)>
5678
          Abs(Integer(tex.FTextureFormat.ddpfPixelFormat.dwRGBBitCount)-idx_index) then Exit;
5679
 
5680
        {  Alpha channel check  }
5681
        if rgb_alpha>0 then Exit;
5682
      end else
5683
      if lpDDPixFmt.dwFlags and DDPF_RGB<>0 then
5684
      begin
5685
        {  The alpha channel is indispensable.  }
5686
        if (rgb_alpha>0) and (tex.FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_ALPHAPIXELS=0) and
5687
          (lpDDPixFmt.dwFlags and DDPF_ALPHAPIXELS<>0) then
5688
        begin
5689
          UseThisFormat;
5690
          Exit;
5691
        end;
5692
 
5693
        {  Alpha channel check  }
5694
        if (rgb_alpha>0) and (tex.FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_ALPHAPIXELS<>0) and
5695
          (lpDDPixFmt.dwFlags and DDPF_ALPHAPIXELS=0) then
5696
        begin
5697
          Exit;
5698
        end;
5699
 
5700
        {  Bit count check  }
5701
        if tex.FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED=0 then
5702
        begin
5703
          sum1 := Sqr(GetMaskBitCount(lpDDPixFmt.dwRBitMask)-rgb_red)+
5704
            Sqr(GetMaskBitCount(lpDDPixFmt.dwGBitMask)-rgb_green)+
5705
            Sqr(GetMaskBitCount(lpDDPixFmt.dwBBitMask)-rgb_blue)+
5706
            Sqr(GetMaskBitCount(lpDDPixFmt.dwRGBAlphaBitMask)-rgb_alpha);
5707
 
5708
          sum2 := Sqr(GetMaskBitCount(tex.FTextureFormat.ddpfPixelFormat.dwRBitMask)-rgb_red)+
5709
            Sqr(GetMaskBitCount(tex.FTextureFormat.ddpfPixelFormat.dwGBitMask)-rgb_green)+
5710
            Sqr(GetMaskBitCount(tex.FTextureFormat.ddpfPixelFormat.dwBBitMask)-rgb_blue)+
5711
            Sqr(GetMaskBitCount(tex.FTextureFormat.ddpfPixelFormat.dwRGBAlphaBitMask)-rgb_alpha);
5712
 
5713
          if sum1>sum2 then Exit;
5714
        end;
5715
      end;
5716
    end;
5717
 
5718
    UseThisFormat;
5719
  end;
5720
 
5721
var
5722
  Width, Height: Integer;
5723
  PaletteCaps: DWORD;
5724
  Palette: IDirectDrawPalette;
5725
  TempD3DDevDesc: TD3DDeviceDesc;
5726
  D3DDevDesc7: TD3DDeviceDesc7;
5727
  TempSurface: IDirectDrawSurface4;
5728
begin
5729
  Finalize;
5730
  try
5731
    if FDXDraw.D3DDevice7<>nil then
5732
    begin
5733
      FDXDraw.D3DDevice7.GetCaps(D3DDevDesc7);
5734
      FD3DDevDesc.dpcLineCaps.dwTextureCaps := D3DDevDesc7.dpcLineCaps.dwTextureCaps;
5735
      FD3DDevDesc.dpcTriCaps.dwTextureCaps := D3DDevDesc7.dpcTriCaps.dwTextureCaps;
5736
      FD3DDevDesc.dwMinTextureWidth := D3DDevDesc7.dwMinTextureWidth;
5737
      FD3DDevDesc.dwMaxTextureWidth := D3DDevDesc7.dwMaxTextureWidth;
5738
    end else
5739
    begin
5740
      FD3DDevDesc.dwSize := SizeOf(FD3DDevDesc);
5741
      TempD3DDevDesc.dwSize := SizeOf(TempD3DDevDesc);
5742
      FDXDraw.D3DDevice3.GetCaps(FD3DDevDesc, TempD3DDevDesc);
5743
    end;
5744
 
5745
    if FImage<>nil then
5746
    begin
5747
      {  Size adjustment of texture  }
5748
      if FD3DDevDesc.dpcTriCaps.dwTextureCaps and D3DPTEXTURECAPS_POW2<>0 then
5749
      begin
5750
        {  The size of the texture is only Sqr(n).  }
5751
        Width := Max(1 shl GetBitCount(FImage.Width), 1);
5752
        Height := Max(1 shl GetBitCount(FImage.Height), 1);
5753
      end else
5754
      begin
5755
        Width := FImage.Width;
5756
        Height := FImage.Height;
5757
      end;
5758
 
5759
      if FD3DDevDesc.dpcTriCaps.dwTextureCaps and D3DPTEXTURECAPS_SQUAREONLY<>0 then
5760
      begin
5761
        {  The size of the texture is only a square.  }
5762
        if Width<Height then Width := Height;
5763
        Height := Width;
5764
      end;
5765
 
5766
      if FD3DDevDesc.dwMinTextureWidth>0 then
5767
        Width := Max(Width, FD3DDevDesc.dwMinTextureWidth);
5768
 
5769
      if FD3DDevDesc.dwMaxTextureWidth>0 then
5770
        Width := Min(Width, FD3DDevDesc.dwMaxTextureWidth);
5771
 
5772
      if FD3DDevDesc.dwMinTextureHeight>0 then
5773
        Height := Max(Height, FD3DDevDesc.dwMinTextureHeight);
5774
 
5775
      if FD3DDevDesc.dwMaxTextureHeight>0 then
5776
        Height := Min(Height, FD3DDevDesc.dwMaxTextureHeight);
5777
 
5778
      {  Pixel format selection  }
5779
      FEnumTextureFormatFlag := False;
5780
      if FDXDraw.D3DDevice7<>nil then
5781
        FDXDraw.D3DDevice7.EnumTextureFormats(@EnumTextureFormatCallback, Self)
5782
      else
5783
        FDXDraw.D3DDevice3.EnumTextureFormats(@EnumTextureFormatCallback, Self);
5784
 
5785
      if not FEnumTextureFormatFlag then
5786
        raise EDirect3DTextureError.CreateFmt(SCannotInitialized, [STexture]);
5787
 
5788
      {  Is Mipmap surface used ?  }
5789
      FUseMipmap := FMipmap and (FTextureFormat.ddpfPixelFormat.dwRGBBitCount>8) and
5790
        (FImage.SubGroupImageCount[DXTextureImageGroupType_Mipmap]>0) and (FDXDraw.DDraw.DriverCaps.ddsCaps.dwCaps and DDSCAPS_MIPMAP<>0);
5791
 
5792
      {  Surface form setting  }
5793
      with FTextureFormat do
5794
      begin
5795
        dwSize := SizeOf(FTextureFormat);
5796
        dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT;
5797
        ddsCaps.dwCaps := DDSCAPS_TEXTURE;
5798
        ddsCaps.dwCaps2 := 0;
5799
        dwWidth := Width;
5800
        dwHeight := Height;
5801
 
5802
        if doHardware in FDXDraw.NowOptions then
5803
          ddsCaps.dwCaps2 := ddsCaps.dwCaps2 or DDSCAPS2_TEXTUREMANAGE
5804
        else
5805
          ddsCaps.dwCaps := ddsCaps.dwCaps or DDSCAPS_SYSTEMMEMORY;
5806
 
5807
        if FUseMipmap then
5808
        begin
5809
          dwFlags := dwFlags or DDSD_MIPMAPCOUNT;
5810
          ddsCaps.dwCaps := ddsCaps.dwCaps or DDSCAPS_MIPMAP or DDSCAPS_COMPLEX;
5811
          dwMipMapCount := FImage.SubGroupImageCount[DXTextureImageGroupType_Mipmap];
5812
        end;
5813
      end;
5814
    end;
5815
 
5816
    FSurface := TDirectDrawSurface.Create(FDXDraw.DDraw);
5817
    FSurface.DDraw.DXResult := FSurface.DDraw.IDraw4.CreateSurface(FTextureFormat, TempSurface, nil);
5818
    if FSurface.DDraw.DXResult<>DD_OK then
5819
      raise EDirect3DTextureError.CreateFmt(SCannotInitialized, [STexture]);
5820
    FSurface.IDDSurface4 := TempSurface;
5821
 
5822
    {  Palette making  }
5823
    if (FImage<>nil) and (FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED<>0) then
5824
    begin
5825
      if FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED8<>0 then
5826
        PaletteCaps := DDPCAPS_8BIT or DDPCAPS_ALLOW256
5827
      else if FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED4<>0 then
5828
        PaletteCaps := DDPCAPS_4BIT
5829
      else if FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED2<>0 then
5830
        PaletteCaps := DDPCAPS_2BIT
5831
      else if FTextureFormat.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED1<>0 then
5832
        PaletteCaps := DDPCAPS_1BIT
5833
      else
5834
        PaletteCaps := 0;
5835
 
5836
      if PaletteCaps<>0 then
5837
      begin
5838
        if FDXDraw.DDraw.IDraw.CreatePalette(PaletteCaps, @FImage.idx_palette, Palette, nil)<>0 then
5839
          Exit;
5840
 
5841
        FSurface.ISurface.SetPalette(Palette);
5842
      end;
5843
    end;
5844
 
5845
    FNeedLoadTexture := True;
5846
  except
5847
    Finalize;
5848
    raise;
5849
  end;
5850
end;
5851
 
5852
procedure TDirect3DTexture2.Load;
5853
const
5854
  MipmapCaps: TDDSCaps2 = (dwCaps: DDSCAPS_TEXTURE or DDSCAPS_MIPMAP);
5855
var
5856
  CurSurface, NextSurface: IDirectDrawSurface4;
5857
  Index: Integer;
5858
  SrcImage: TDXTextureImage;
5859
begin
5860
  if FSurface=nil then
5861
    Initialize;
5862
 
5863
  FNeedLoadTexture := False;
5864
  if FSurface.ISurface.IsLost=DDERR_SURFACELOST then
5865
    FSurface.Restore;
5866
 
5867
  {  Color key setting.  }
5868
  SetColorKey;
5869
 
5870
  {  Image loading into surface.  }
5871
  if FImage<>nil then
5872
  begin
5873
    if FSrcImage is TDIB then
5874
      SetDIB(TDIB(FSrcImage));
5875
 
5876
    CurSurface := FSurface.ISurface4;
5877
    Index := 0;
5878
    while CurSurface<>nil do
5879
    begin
5880
      SrcImage := FImage;
5881
      if Index>0 then
5882
      begin
5883
        if Index-1>=FImage.SubGroupImageCount[DXTextureImageGroupType_Mipmap] then
5884
          Break;
5885
        SrcImage := FImage.SubGroupImages[DXTextureImageGroupType_Mipmap, Index-1];
5886
      end;
5887
 
5888
      LoadSubTexture(CurSurface, SrcImage);
5889
 
5890
      if CurSurface.GetAttachedSurface(MipmapCaps, NextSurface)=0 then
5891
        CurSurface := NextSurface
5892
      else
5893
        CurSurface := nil;
5894
 
5895
      Inc(Index);
5896
    end;
5897
  end else
5898
    DoRestoreSurface;
5899
end;
5900
 
5901
procedure TDirect3DTexture2.SetColorKey;
5902
var
5903
  ck: TDDColorKey;
5904
begin
5905
  FUseColorKey := False;
5906
 
5907
  if (FSurface<>nil) and FTransparent and (FD3DDevDesc.dpcTriCaps.dwTextureCaps and D3DPTEXTURECAPS_TRANSPARENCY<>0) then
5908
  begin
5909
    FillChar(ck, SizeOf(ck), 0);
5910
    if FSurface.SurfaceDesc.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED<>0 then
5911
    begin
5912
      if FTransparentColor shr 24=$01 then
5913
      begin
5914
        {  Palette index  }
5915
        ck.dwColorSpaceLowValue := FTransparentColor and $FF;
5916
      end else
5917
      if FImage<>nil then
5918
      begin
5919
        {  RGB value  }
5920
        ck.dwColorSpaceLowValue := FImage.PaletteIndex(GetRValue(FTransparentColor), GetGValue(FTransparentColor), GetBValue(FTransparentColor));
5921
      end else
5922
        Exit;
5923
    end else
5924
    begin
5925
      if (FImage<>nil) and (FImage.ImageType=DXTextureImageType_PaletteIndexedColor) and (FTransparentColor shr 24=$01) then
5926
      begin
5927
        {  Palette index  }
5928
        ck.dwColorSpaceLowValue :=
5929
          dxtEncodeChannel(dxtMakeChannel(FSurface.SurfaceDesc.ddpfPixelFormat.dwRBitMask, False), FImage.idx_palette[FTransparentColor and $FF].peRed) or
5930
          dxtEncodeChannel(dxtMakeChannel(FSurface.SurfaceDesc.ddpfPixelFormat.dwGBitMask, False), FImage.idx_palette[FTransparentColor and $FF].peGreen) or
5931
          dxtEncodeChannel(dxtMakeChannel(FSurface.SurfaceDesc.ddpfPixelFormat.dwBBitMask, False), FImage.idx_palette[FTransparentColor and $FF].peBlue);
5932
      end else
5933
      if FTransparentColor shr 24=$00 then
5934
      begin
5935
        {  RGB value  }
5936
        ck.dwColorSpaceLowValue :=
5937
          dxtEncodeChannel(dxtMakeChannel(FSurface.SurfaceDesc.ddpfPixelFormat.dwRBitMask, False), GetRValue(FTransparentColor)) or
5938
          dxtEncodeChannel(dxtMakeChannel(FSurface.SurfaceDesc.ddpfPixelFormat.dwGBitMask, False), GetGValue(FTransparentColor)) or
5939
          dxtEncodeChannel(dxtMakeChannel(FSurface.SurfaceDesc.ddpfPixelFormat.dwBBitMask, False), GetBValue(FTransparentColor));
5940
      end else
5941
        Exit;
5942
    end;
5943
 
5944
    ck.dwColorSpaceHighValue := ck.dwColorSpaceLowValue;
5945
    FSurface.ISurface.SetColorKey(DDCKEY_SRCBLT, ck);
5946
 
5947
    FUseColorKey := True;
5948
  end;
5949
end;
5950
 
5951
procedure TDirect3DTexture2.LoadSubTexture(Dest: IDirectDrawSurface4; SrcImage: TDXTextureImage);
5952
const
5953
  Mask1: array[0..7] of DWORD = (1, 2, 4, 8, 16, 32, 64, 128);
5954
  Mask2: array[0..3] of DWORD = (3, 12, 48, 192);
5955
  Mask4: array[0..1] of DWORD = ($0F, $F0);
5956
  Shift1: array[0..7] of DWORD = (0, 1, 2, 3, 4, 5, 6, 7);
5957
  Shift2: array[0..3] of DWORD = (0, 2, 4, 6);
5958
  Shift4: array[0..1] of DWORD = (0, 4);
5959
 
5960
  procedure SetPixel(const ddsd: TDDSurfaceDesc2; x, y: Integer; c: DWORD);
5961
  begin
5962
    case ddsd.ddpfPixelFormat.dwRGBBitCount of
5963
      1 : PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x div 8)^ :=
5964
            (PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x div 8)^ and (not Mask1[x mod 8])) or (c shl Shift1[x mod 8]);
5965
      2 : PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x div 4)^ :=
5966
            (PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x div 4)^ and (not Mask2[x mod 4])) or (c shl Shift2[x mod 4]);
5967
      4 : PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x div 2)^ :=
5968
            (PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x div 2)^ and (not Mask4[x mod 2])) or (c shl Shift4[x mod 2]);
5969
      8 : PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x)^ := c;
5970
      16: PWord(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x*2)^ := c;
5971
      24: begin
5972
            PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x*3)^ := c shr 0;
5973
            PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x*3+1)^ := c shr 8;
5974
            PByte(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x*3+2)^ := c shr 16;
5975
          end;  
5976
      32: PDWORD(Integer(ddsd.lpSurface)+ddsd.lPitch*y+x*4)^ := c;
5977
    end;
5978
  end;
5979
 
5980
  procedure LoadTexture_IndexToIndex;
5981
  var
5982
    ddsd: TDDSurfaceDesc2;
5983
    x, y: Integer;
5984
  begin
5985
    ddsd.dwSize := SizeOf(ddsd);
5986
    if Dest.Lock(nil, ddsd, DDLOCK_WAIT, 0)=0 then
5987
    begin
5988
      try
5989
        if (SrcImage.idx_index.Mask=DWORD(1 shl ddsd.ddpfPixelFormat.dwRGBBitCount)-1) and (SrcImage.idx_alpha.Mask=0) and
5990
          (SrcImage.BitCount=Integer(ddsd.ddpfPixelFormat.dwRGBBitCount)) and (not SrcImage.PackedPixelOrder) then
5991
        begin
5992
          for y:=0 to ddsd.dwHeight-1 do
5993
            Move(SrcImage.ScanLine[y]^, Pointer(Integer(ddsd.lpSurface)+ddsd.lPitch*y)^, (Integer(ddsd.dwWidth)*SrcImage.BitCount+7) div 8);
5994
        end else
5995
        begin
5996
          for y:=0 to ddsd.dwHeight-1 do
5997
          begin
5998
            for x:=0 to ddsd.dwWidth-1 do
5999
              SetPixel(ddsd, x, y, dxtDecodeChannel(SrcImage.idx_index, SrcImage.Pixels[x, y]));
6000
          end;
6001
        end;
6002
      finally
6003
        Dest.UnLock(ddsd.lpSurface);
6004
      end;
6005
    end;
6006
  end;
6007
 
6008
  procedure LoadTexture_IndexToRGB;
6009
  var
6010
    ddsd: TDDSurfaceDesc2;
6011
    x, y: Integer;
6012
    c, cIdx, cA: DWORD;
6013
    dest_red_fmt, dest_green_fmt, dest_blue_fmt, dest_alpha_fmt: TDXTextureImageChannel;
6014
  begin
6015
    ddsd.dwSize := SizeOf(ddsd);
6016
    if Dest.Lock(nil, ddsd, DDLOCK_WAIT, 0)=0 then
6017
    begin
6018
      try
6019
        dest_red_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwRBitMask, False);
6020
        dest_green_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwGBitMask, False);
6021
        dest_blue_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwBBitMask, False);
6022
        dest_alpha_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask, False);
6023
 
6024
        if SrcImage.idx_alpha.mask<>0 then
6025
        begin
6026
          for y:=0 to ddsd.dwHeight-1 do
6027
            for x:=0 to ddsd.dwWidth-1 do
6028
            begin
6029
              c := SrcImage.Pixels[x, y];
6030
              cIdx := dxtDecodeChannel(SrcImage.idx_index, c);
6031
 
6032
              c := dxtEncodeChannel(dest_red_fmt, SrcImage.idx_palette[cIdx].peRed) or
6033
                dxtEncodeChannel(dest_green_fmt, SrcImage.idx_palette[cIdx].peGreen) or
6034
                dxtEncodeChannel(dest_blue_fmt, SrcImage.idx_palette[cIdx].peBlue) or
6035
                dxtEncodeChannel(dest_alpha_fmt, dxtDecodeChannel(SrcImage.idx_alpha, c));
6036
 
6037
              SetPixel(ddsd, x, y, c);
6038
            end;
6039
        end else
6040
        begin
6041
          cA := dxtEncodeChannel(dest_alpha_fmt, 255);
6042
 
6043
          for y:=0 to ddsd.dwHeight-1 do
6044
            for x:=0 to ddsd.dwWidth-1 do
6045
            begin
6046
              c := SrcImage.Pixels[x, y];
6047
              cIdx := dxtDecodeChannel(SrcImage.idx_index, c);
6048
 
6049
              c := dxtEncodeChannel(dest_red_fmt, SrcImage.idx_palette[cIdx].peRed) or
6050
                dxtEncodeChannel(dest_green_fmt, SrcImage.idx_palette[cIdx].peGreen) or
6051
                dxtEncodeChannel(dest_blue_fmt, SrcImage.idx_palette[cIdx].peBlue) or cA;
6052
 
6053
              SetPixel(ddsd, x, y, c);
6054
            end;
6055
        end;
6056
      finally
6057
        Dest.UnLock(ddsd.lpSurface);
6058
      end;
6059
    end;
6060
  end;
6061
 
6062
  procedure LoadTexture_RGBToRGB;
6063
  var
6064
    ddsd: TDDSurfaceDesc2;
6065
    x, y: Integer;
6066
    c, cA: DWORD;
6067
    dest_red_fmt, dest_green_fmt, dest_blue_fmt, dest_alpha_fmt: TDXTextureImageChannel;
6068
  begin
6069
    ddsd.dwSize := SizeOf(ddsd);
6070
    if Dest.Lock(nil, ddsd, DDLOCK_WAIT, 0)=0 then
6071
    begin
6072
      try
6073
        dest_red_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwRBitMask, False);
6074
        dest_green_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwGBitMask, False);
6075
        dest_blue_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwBBitMask, False);
6076
        dest_alpha_fmt := dxtMakeChannel(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask, False);
6077
 
6078
        if (dest_red_fmt.Mask=SrcImage.rgb_red.Mask) and (dest_green_fmt.Mask=SrcImage.rgb_green.Mask) and
6079
          (dest_blue_fmt.Mask=SrcImage.rgb_blue.Mask) and (dest_alpha_fmt.Mask=SrcImage.rgb_alpha.Mask) and
6080
          (Integer(ddsd.ddpfPixelFormat.dwRGBBitCount)=SrcImage.BitCount) and (not SrcImage.PackedPixelOrder) then
6081
        begin                
6082
          for y:=0 to ddsd.dwHeight-1 do
6083
            Move(SrcImage.ScanLine[y]^, Pointer(Integer(ddsd.lpSurface)+ddsd.lPitch*y)^, (Integer(ddsd.dwWidth)*SrcImage.BitCount+7) div 8);
6084
        end else
6085
        if SrcImage.rgb_alpha.mask<>0 then
6086
        begin
6087
          for y:=0 to ddsd.dwHeight-1 do
6088
            for x:=0 to ddsd.dwWidth-1 do
6089
            begin
6090
              c := SrcImage.Pixels[x, y];
6091
 
6092
              c := dxtEncodeChannel(dest_red_fmt, dxtDecodeChannel(SrcImage.rgb_red, c)) or
6093
                dxtEncodeChannel(dest_green_fmt, dxtDecodeChannel(SrcImage.rgb_green, c)) or
6094
                dxtEncodeChannel(dest_blue_fmt, dxtDecodeChannel(SrcImage.rgb_blue, c)) or
6095
                dxtEncodeChannel(dest_alpha_fmt, dxtDecodeChannel(SrcImage.rgb_alpha, c));
6096
 
6097
              SetPixel(ddsd, x, y, c);
6098
            end;
6099
        end else
6100
        begin
6101
          cA := dxtEncodeChannel(dest_alpha_fmt, 255);
6102
 
6103
          for y:=0 to ddsd.dwHeight-1 do
6104
            for x:=0 to ddsd.dwWidth-1 do
6105
            begin
6106
              c := SrcImage.Pixels[x, y];
6107
 
6108
              c := dxtEncodeChannel(dest_red_fmt, dxtDecodeChannel(SrcImage.rgb_red, c)) or
6109
                dxtEncodeChannel(dest_green_fmt, dxtDecodeChannel(SrcImage.rgb_green, c)) or
6110
                dxtEncodeChannel(dest_blue_fmt, dxtDecodeChannel(SrcImage.rgb_blue, c)) or cA;
6111
 
6112
              SetPixel(ddsd, x, y, c);
6113
            end;
6114
        end;
6115
      finally
6116
        Dest.UnLock(ddsd.lpSurface);
6117
      end;
6118
    end;
6119
  end;
6120
 
6121
var
6122
  SurfaceDesc: TDDSurfaceDesc2;
6123
begin
6124
  SurfaceDesc.dwSize := SizeOf(SurfaceDesc);
6125
  Dest.GetSurfaceDesc(SurfaceDesc);
6126
 
6127
  if SurfaceDesc.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED<>0 then
6128
  begin
6129
    case SrcImage.ImageType of
6130
      DXTextureImageType_PaletteIndexedColor: LoadTexture_IndexToIndex;
6131
      DXTextureImageType_RGBColor           : ;
6132
    end;
6133
  end else if SurfaceDesc.ddpfPixelFormat.dwFlags and DDPF_RGB<>0 then
6134
  begin
6135
    case SrcImage.ImageType of
6136
      DXTextureImageType_PaletteIndexedColor: LoadTexture_IndexToRGB;
6137
      DXTextureImageType_RGBColor           : LoadTexture_RGBToRGB;
6138
    end;
6139
  end;
6140
end;
6141
 
6142
{  TDirect3DRMUserVisual  }
6143
 
6144
procedure TDirect3DRMUserVisual_D3DRMOBJECTCALLBACK(lpD3DRMobj: IDirect3DRMObject;
6145
  lpArg: Pointer); CDECL;
6146
begin
6147
  TDirect3DRMUserVisual(lpArg).Free;
6148
end;
6149
 
6150
function TDirect3DRMUserVisual_D3DRMUSERVISUALCALLBACK(lpD3DRMUV: IDirect3DRMUserVisual;
6151
  lpArg: Pointer; lpD3DRMUVreason: TD3DRMUserVisualReason;
6152
  lpD3DRMDev: IDirect3DRMDevice; lpD3DRMview: IDirect3DRMViewport): Integer; CDECL;
6153
begin
6154
  Result := TDirect3DRMUserVisual(lpArg).DoRender(lpD3DRMUVreason, lpD3DRMDev, lpD3DRMview);
6155
end;
6156
 
6157
constructor TDirect3DRMUserVisual.Create(D3DRM: IDirect3DRM);
6158
begin
6159
  inherited Create;
6160
 
6161
  if D3DRM.CreateUserVisual(@TDirect3DRMUserVisual_D3DRMUSERVISUALCALLBACK,
6162
    Self, FUserVisual)<>D3DRM_OK then
6163
    raise EDirect3DRMUserVisualError.CreateFmt(SCannotMade, ['IDirect3DRMUserVisual']);
6164
 
6165
  FUserVisual.AddDestroyCallback(@TDirect3DRMUserVisual_D3DRMOBJECTCALLBACK, Self);
6166
end;
6167
 
6168
destructor TDirect3DRMUserVisual.Destroy;
6169
begin
6170
  if FUserVisual<>nil then
6171
    FUserVisual.DeleteDestroyCallback(@TDirect3DRMUserVisual_D3DRMOBJECTCALLBACK, Self);
6172
  FUserVisual := nil;
6173
  inherited Destroy;
6174
end;
6175
 
6176
function TDirect3DRMUserVisual.DoRender(Reason: TD3DRMUserVisualReason;
6177
  D3DRMDev: IDirect3DRMDevice; D3DRMView: IDirect3DRMViewport): HRESULT;
6178
begin
6179
  Result := 0;
6180
end;
6181
 
6182
{  TPictureCollectionItem  }
6183
 
6184
const
6185
  SurfaceDivWidth = 512;
6186
  SurfaceDivHeight = 512;
6187
 
6188
type
6189
  TPictureCollectionItemPattern = class(TCollectionItem)
6190
  private
6191
    FRect: TRect;
6192
    FSurface: TDirectDrawSurface;
6193
  end;
6194
 
6195
constructor TPictureCollectionItem.Create(Collection: TCollection);
6196
begin
6197
  inherited Create(Collection);
6198
  FPicture := TPicture.Create;
6199
  FPatterns := TCollection.Create(TPictureCollectionItemPattern);
6200
  FSurfaceList := TList.Create;
6201
  FTransparent := True;
6202
end;
6203
 
6204
destructor TPictureCollectionItem.Destroy;
6205
begin
6206
  Finalize;
6207
  FPicture.Free;
6208
  FPatterns.Free;
6209
  FSurfaceList.Free;
6210
  inherited Destroy;
6211
end;
6212
 
6213
procedure TPictureCollectionItem.Assign(Source: TPersistent);
6214
var
6215
  PrevInitialized: Boolean;
6216
begin
6217
  if Source is TPictureCollectionItem then
6218
  begin
6219
    PrevInitialized := Initialized;
6220
    Finalize;
6221
 
6222
    FPatternHeight := TPictureCollectionItem(Source).FPatternHeight;
6223
    FPatternWidth := TPictureCollectionItem(Source).FPatternWidth;
6224
    FSkipHeight := TPictureCollectionItem(Source).FSkipHeight;
6225
    FSkipWidth := TPictureCollectionItem(Source).FSkipWidth;
6226
    FSystemMemory := TPictureCollectionItem(Source).FSystemMemory;
6227
    FTransparent := TPictureCollectionItem(Source).FTransparent;
6228
    FTransparentColor := TPictureCollectionItem(Source).FTransparentColor;
6229
 
6230
    FPicture.Assign(TPictureCollectionItem(Source).FPicture);
6231
 
6232
    if PrevInitialized then
6233
      Restore;
6234
  end else
6235
    inherited Assign(Source);
6236
end;                        
6237
 
6238
procedure TPictureCollectionItem.ClearSurface;
6239
var
6240
  i: Integer;
6241
begin
6242
  FPatterns.Clear;
6243
  for i:=0 to FSurfaceList.Count-1 do
6244
    TDirectDrawSurface(FSurfaceList[i]).Free;
6245
  FSurfaceList.Clear;
6246
end;
6247
 
6248
function TPictureCollectionItem.GetHeight: Integer;
6249
begin
6250
  Result := FPatternHeight;
6251
  if (Result<=0) then
6252
    Result := FPicture.Height;
6253
end;
6254
 
6255
function TPictureCollectionItem.GetPictureCollection: TPictureCollection;
6256
begin
6257
  Result := Collection as TPictureCollection;
6258
end;
6259
 
6260
function TPictureCollectionItem.GetPatternRect(Index: Integer): TRect;
6261
begin
6262
  if (Index>=0) and (index<FPatterns.Count) then
6263
    Result := TPictureCollectionItemPattern(FPatterns.Items[Index]).FRect
6264
  else
6265
    Result := Rect(0, 0, 0, 0);
6266
end;
6267
 
6268
function TPictureCollectionItem.GetPatternSurface(Index: Integer): TDirectDrawSurface;
6269
begin
6270
  if (Index>=0) and (index<FPatterns.Count) then
6271
    Result := TPictureCollectionItemPattern(FPatterns.Items[Index]).FSurface
6272
  else
6273
    Result := nil;
6274
end;
6275
 
6276
function TPictureCollectionItem.GetPatternCount: Integer;
6277
var
6278
  XCount, YCount: Integer;
6279
begin
6280
  if FSurfaceList.Count=0 then
6281
  begin
6282
    XCount := FPicture.Width div (PatternWidth+SkipWidth);
6283
    if FPicture.Width-XCount*(PatternWidth+SkipWidth)=PatternWidth then
6284
     Inc(XCount);
6285
 
6286
    YCount := FPicture.Height div (PatternHeight+SkipHeight);
6287
    if FPicture.Height-YCount*(PatternHeight+SkipHeight)=PatternHeight then
6288
     Inc(YCount);
6289
 
6290
    Result := XCount*YCount;
6291
  end else
6292
    Result := FPatterns.Count;
6293
end;
6294
 
6295
function TPictureCollectionItem.GetWidth: Integer;
6296
begin
6297
  Result := FPatternWidth;
6298
  if (Result<=0) then
6299
    Result := FPicture.Width;
6300
end;
6301
 
6302
procedure TPictureCollectionItem.Draw(Dest: TDirectDrawSurface; X, Y,
6303
  PatternIndex: Integer);            
6304
begin
6305
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6306
  begin
6307
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6308
      Dest.Draw(X, Y, FRect, FSurface, Transparent);
6309
  end;
6310
end;
6311
 
6312
procedure TPictureCollectionItem.StretchDraw(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer);
6313
begin
6314
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6315
  begin
6316
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6317
      Dest.StretchDraw(DestRect, FRect, FSurface, Transparent);
6318
  end;
6319
end;
6320
 
6321
procedure TPictureCollectionItem.DrawAdd(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer;
6322
  Alpha: Integer);
6323
begin
6324
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6325
  begin
6326
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6327
      Dest.DrawAdd(DestRect, FRect, FSurface, Transparent, Alpha);
6328
  end;
6329
end;
6330
 
6331
procedure TPictureCollectionItem.DrawAlpha(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer;
6332
  Alpha: Integer);
6333
begin
6334
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6335
  begin
6336
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6337
      Dest.DrawAlpha(DestRect, FRect, FSurface, Transparent, Alpha);
6338
  end;
6339
end;
6340
 
6341
procedure TPictureCollectionItem.DrawSub(Dest: TDirectDrawSurface; const DestRect: TRect; PatternIndex: Integer;
6342
  Alpha: Integer);
6343
begin
6344
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6345
  begin
6346
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6347
      Dest.DrawSub(DestRect, FRect, FSurface, Transparent, Alpha);
6348
  end;
6349
end;
6350
 
6351
procedure TPictureCollectionItem.DrawRotate(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6352
  CenterX, CenterY: Double; Angle: Integer);
6353
begin
6354
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6355
  begin
6356
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6357
      Dest.DrawRotate(X, Y, Width, Height, FRect, FSurface, CenterX, CenterY, Transparent, Angle);
6358
  end;
6359
end;
6360
 
6361
procedure TPictureCollectionItem.DrawRotateAdd(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6362
  CenterX, CenterY: Double; Angle, Alpha: Integer);
6363
begin
6364
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6365
  begin
6366
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6367
      Dest.DrawRotateAdd(X, Y, Width, Height, FRect, FSurface, CenterX, CenterY, Transparent, Angle, Alpha);
6368
  end;
6369
end;
6370
 
6371
procedure TPictureCollectionItem.DrawRotateAlpha(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6372
  CenterX, CenterY: Double; Angle, Alpha: Integer);
6373
begin
6374
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6375
  begin
6376
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6377
      Dest.DrawRotateAlpha(X, Y, Width, Height, FRect, FSurface, CenterX, CenterY, Transparent, Angle, Alpha);
6378
  end;
6379
end;
6380
 
6381
procedure TPictureCollectionItem.DrawRotateSub(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6382
  CenterX, CenterY: Double; Angle, Alpha: Integer);
6383
begin
6384
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6385
  begin
6386
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6387
      Dest.DrawRotateSub(X, Y, Width, Height, FRect, FSurface, CenterX, CenterY, Transparent, Angle, Alpha);
6388
  end;
6389
end;
6390
 
6391
procedure TPictureCollectionItem.DrawWaveX(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6392
  amp, Len, ph: Integer);
6393
begin
6394
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6395
  begin
6396
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6397
      Dest.DrawWaveX(X, Y, Width, Height, FRect, FSurface, Transparent, amp, Len, ph);
6398
  end;
6399
end;
6400
 
6401
procedure TPictureCollectionItem.DrawWaveXAdd(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6402
  amp, Len, ph, Alpha: Integer);
6403
begin
6404
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6405
  begin
6406
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6407
      Dest.DrawWaveXAdd(X, Y, Width, Height, FRect, FSurface, Transparent, amp, Len, ph, Alpha);
6408
  end;
6409
end;
6410
 
6411
procedure TPictureCollectionItem.DrawWaveXAlpha(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6412
  amp, Len, ph, Alpha: Integer);
6413
begin
6414
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6415
  begin
6416
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6417
      Dest.DrawWaveXAlpha(X, Y, Width, Height, FRect, FSurface, Transparent, amp, Len, ph, Alpha);
6418
  end;
6419
end;
6420
 
6421
procedure TPictureCollectionItem.DrawWaveXSub(Dest: TDirectDrawSurface; X, Y, Width, Height, PatternIndex: Integer;
6422
  amp, Len, ph, Alpha: Integer);
6423
begin
6424
  if FInitialized and (PatternIndex>=0) and (PatternIndex<FPatterns.Count) then
6425
  begin
6426
    with TPictureCollectionItemPattern(FPatterns.Items[PatternIndex]) do
6427
      Dest.DrawWaveXSub(X, Y, Width, Height, FRect, FSurface, Transparent, amp, Len, ph, Alpha);
6428
  end;
6429
end;
6430
 
6431
procedure TPictureCollectionItem.Finalize;
6432
begin
6433
  if FInitialized then
6434
  begin
6435
    FInitialized := False;
6436
    ClearSurface;
6437
  end;
6438
end;
6439
 
6440
procedure TPictureCollectionItem.Initialize;
6441
begin
6442
  Finalize;
6443
  FInitialized := PictureCollection.Initialized;
6444
end;
6445
 
6446
procedure TPictureCollectionItem.Restore;
6447
 
6448
  function AddSurface(const SrcRect: TRect): TDirectDrawSurface;
6449
  begin
6450
    Result := TDirectDrawSurface.Create(PictureCollection.DXDraw.DDraw);
6451
    FSurfaceList.Add(Result);
6452
 
6453
    Result.SystemMemory := FSystemMemory;
6454
    Result.LoadFromGraphicRect(FPicture.Graphic, 0, 0, SrcRect);
6455
    Result.TransparentColor := Result.ColorMatch(FTransparentColor);
6456
  end;
6457
 
6458
var
6459
  x, y, x2, y2: Integer;
6460
  BlockWidth, BlockHeight, BlockXCount, BlockYCount: Integer;
6461
  Width2, Height2: Integer;
6462
begin
6463
  if FPicture.Graphic=nil then Exit;
6464
 
6465
  if not FInitialized then
6466
  begin
6467
    if PictureCollection.Initialized then
6468
      Initialize;
6469
    if not FInitialized then Exit;
6470
  end;
6471
 
6472
  ClearSurface;
6473
 
6474
  Width2 := Width+SkipWidth;
6475
  Height2 := Height+SkipHeight;
6476
 
6477
  if (Width=FPicture.Width) and (Height=FPicture.Height) then
6478
  begin
6479
    {  There is no necessity of division because the number of patterns is one.   }
6480
    with TPictureCollectionItemPattern.Create(FPatterns) do
6481
    begin
6482
      FRect := Bounds(0, 0, FPicture.Width, FPicture.Height);
6483
      FSurface := AddSurface(Bounds(0, 0, FPicture.Width, FPicture.Height));
6484
    end;
6485
  end else if FSystemMemory then
6486
  begin
6487
    {  Load to a system memory.  }
6488
    AddSurface(Bounds(0, 0, FPicture.Width, FPicture.Height));
6489
 
6490
    for y:=0 to (FPicture.Height+SkipHeight) div Height2-1 do
6491
      for x:=0 to (FPicture.Width+SkipWidth) div Width2-1 do
6492
        with TPictureCollectionItemPattern.Create(FPatterns) do
6493
        begin
6494
          FRect := Bounds(x * Width2, y * Height2, Width, Height);
6495
          FSurface := TDirectDrawSurface(FSurfaceList[0]);
6496
        end;
6497
  end else
6498
  begin
6499
    {  Load to a video memory with dividing the image.   }
6500
    BlockWidth := Min(((SurfaceDivWidth+Width2-1) div Width2)*Width2,
6501
      (FPicture.Width+SkipWidth) div Width2*Width2);
6502
    BlockHeight := Min(((SurfaceDivHeight+Height2-1) div Height2)*Height2,
6503
      (FPicture.Height+SkipHeight) div Height2*Height2);
6504
 
6505
    if (BlockWidth=0) or (BlockHeight=0) then Exit;
6506
 
6507
    BlockXCount := (FPicture.Width+BlockWidth-1) div BlockWidth;
6508
    BlockYCount := (FPicture.Height+BlockHeight-1) div BlockHeight;
6509
 
6510
    for y:=0 to BlockYCount-1 do
6511
      for x:=0 to BlockXCount-1 do
6512
      begin
6513
        x2 := Min(BlockWidth, Max(FPicture.Width-x*BlockWidth, 0));
6514
        if x2=0 then x2 := BlockWidth;
6515
 
6516
        y2 := Min(BlockHeight, Max(FPicture.Height-y*BlockHeight, 0));
6517
        if y2=0 then y2 := BlockHeight;
6518
 
6519
        AddSurface(Bounds(x*BlockWidth, y*BlockHeight, x2, y2));
6520
      end;
6521
 
6522
    for y:=0 to (FPicture.Height+SkipHeight) div Height2-1 do
6523
      for x:=0 to (FPicture.Width+SkipWidth) div Width2-1 do
6524
      begin
6525
        x2 := x * Width2;
6526
        y2 := y * Height2;
6527
        with TPictureCollectionItemPattern.Create(FPatterns) do
6528
        begin
6529
          FRect := Bounds(x2-(x2 div BlockWidth*BlockWidth), y2-(y2 div BlockHeight*BlockHeight), Width, Height);
6530
          FSurface := TDirectDrawSurface(FSurfaceList[(x2 div BlockWidth)+((y2 div BlockHeight)*BlockXCount)]);
6531
        end;
6532
      end;
6533
  end;
6534
end;
6535
 
6536
procedure TPictureCollectionItem.SetPicture(Value: TPicture);
6537
begin
6538
  FPicture.Assign(Value);
6539
end;
6540
 
6541
procedure TPictureCollectionItem.SetTransparentColor(Value: TColor);
6542
var
6543
  i: Integer;
6544
  Surface: TDirectDrawSurface;
6545
begin
6546
  if Value<>FTransparentColor then
6547
  begin
6548
    FTransparentColor := Value;
6549
    for i:=0 to FSurfaceList.Count-1 do
6550
    begin
6551
      try
6552
        Surface := TDirectDrawSurface(FSurfaceList[i]);
6553
        Surface.TransparentColor := Surface.ColorMatch(FTransparentColor);
6554
      except
6555
      end;
6556
    end;
6557
  end;
6558
end;
6559
 
6560
{  TPictureCollection  }
6561
 
6562
constructor TPictureCollection.Create(AOwner: TPersistent);
6563
begin
6564
  inherited Create(TPictureCollectionItem);
6565
  FOwner := AOwner;
6566
end;
6567
 
6568
destructor TPictureCollection.Destroy;
6569
begin
6570
  Finalize;
6571
  inherited Destroy;
6572
end;
6573
 
6574
function TPictureCollection.GetItem(Index: Integer): TPictureCollectionItem;
6575
begin
6576
  Result := TPictureCollectionItem(inherited Items[Index]);
6577
end;
6578
 
6579
function TPictureCollection.GetOwner: TPersistent;
6580
begin
6581
  Result := FOwner;
6582
end;
6583
 
6584
function TPictureCollection.Find(const Name: string): TPictureCollectionItem;
6585
var
6586
  i: Integer;
6587
begin
6588
  i := IndexOf(Name);
6589
  if i=-1 then
6590
    raise EPictureCollectionError.CreateFmt(SImageNotFound, [Name]);
6591
  Result := Items[i];
6592
end;
6593
 
6594
procedure TPictureCollection.Finalize;
6595
var
6596
  i: Integer;
6597
begin
6598
  try
6599
    for i:=0 to Count-1 do
6600
      Items[i].Finalize;
6601
  finally
6602
    FDXDraw := nil;
6603
  end;
6604
end;
6605
 
6606
procedure TPictureCollection.Initialize(DXDraw: TCustomDXDraw);
6607
var
6608
  i: Integer;
6609
begin
6610
  Finalize;
6611
  FDXDraw := DXDraw;
6612
 
6613
  if not Initialized then
6614
    raise EPictureCollectionError.CreateFmt(SCannotInitialized, [ClassName]);
6615
 
6616
  for i:=0 to Count-1 do
6617
    Items[i].Initialize;
6618
end;
6619
 
6620
function TPictureCollection.Initialized: Boolean;
6621
begin
6622
  Result := (FDXDraw<>nil) and (FDXDraw.Initialized);
6623
end;
6624
 
6625
procedure TPictureCollection.Restore;
6626
var
6627
  i: Integer;
6628
begin
6629
  for i:=0 to Count-1 do
6630
    Items[i].Restore;
6631
end;
6632
 
6633
procedure TPictureCollection.MakeColorTable;
6634
var
6635
  UseColorTable: array[0..255] of Boolean;
6636
  PaletteCount: Integer;
6637
 
6638
  procedure SetColor(Index: Integer; Col: TRGBQuad);
6639
  begin
6640
    UseColorTable[Index] := True;
6641
    ColorTable[Index] := Col;
6642
    Inc(PaletteCount);
6643
  end;
6644
 
6645
  procedure AddColor(Col: TRGBQuad);
6646
  var
6647
    i: Integer;
6648
  begin
6649
    for i:=0 to 255 do
6650
      if UseColorTable[i] then
6651
        if DWORD(ColorTable[i])=DWORD(Col) then
6652
          Exit;
6653
    for i:=0 to 255 do
6654
      if not UseColorTable[i] then
6655
      begin
6656
        SetColor(i, Col);
6657
        Exit;
6658
      end;
6659
  end;
6660
 
6661
  procedure AddDIB(DIB: TDIB);
6662
  var
6663
    i: Integer;
6664
  begin
6665
    if DIB.BitCount>8 then Exit;
6666
 
6667
    for i:=0 to 255 do
6668
      AddColor(DIB.ColorTable[i]);
6669
  end;
6670
 
6671
  procedure AddGraphic(Graphic: TGraphic);
6672
  var
6673
    i, n: Integer;
6674
    PaletteEntries: TPaletteEntries;
6675
  begin
6676
    if Graphic.Palette<>0 then
6677
    begin
6678
      n := GetPaletteEntries(Graphic.Palette, 0, 256, PaletteEntries);
6679
      for i:=0 to n-1 do
6680
        AddColor(PaletteEntryToRGBQuad(PaletteEntries[i]));
6681
    end;
6682
  end;
6683
 
6684
var
6685
  i: Integer;
6686
begin
6687
  FillChar(UseColorTable, SizeOf(UseColorTable), 0);
6688
  FillChar(ColorTable, SizeOf(ColorTable), 0);
6689
 
6690
  PaletteCount := 0;
6691
 
6692
  {  The system color is included.  }
6693
  SetColor(0, RGBQuad(0, 0, 0));
6694
  SetColor(1, RGBQuad(128, 0, 0));
6695
  SetColor(2, RGBQuad(0, 128, 0));
6696
  SetColor(3, RGBQuad(128, 128, 0));
6697
  SetColor(4, RGBQuad(0, 0, 128));
6698
  SetColor(5, RGBQuad(128, 0, 128));
6699
  SetColor(6, RGBQuad(0, 128, 128));
6700
  SetColor(7, RGBQuad(192, 192, 192));
6701
 
6702
  SetColor(248, RGBQuad(128, 128, 128));
6703
  SetColor(249, RGBQuad(255, 0, 0));
6704
  SetColor(250, RGBQuad(0, 255, 0));
6705
  SetColor(251, RGBQuad(255, 255, 0));
6706
  SetColor(252, RGBQuad(0, 0, 255));
6707
  SetColor(253, RGBQuad(255, 0, 255));
6708
  SetColor(254, RGBQuad(0, 255, 255));
6709
  SetColor(255, RGBQuad(255, 255, 255));
6710
 
6711
  for i:=0 to Count-1 do
6712
    if Items[i].Picture.Graphic<>nil then
6713
    begin
6714
      if Items[i].Picture.Graphic is TDIB then
6715
        AddDIB(TDIB(Items[i].Picture.Graphic))
6716
      else
6717
        AddGraphic(Items[i].Picture.Graphic);
6718
      if PaletteCount=256 then Break;
6719
    end;
6720
end;
6721
 
6722
procedure TPictureCollection.DefineProperties(Filer: TFiler);
6723
begin
6724
  inherited DefineProperties(Filer);
6725
  Filer.DefineBinaryProperty('ColorTable', ReadColorTable, WriteColorTable, True);
6726
end;
6727
 
6728
type
6729
  TPictureCollectionComponent = class(TComponent)
6730
  private
6731
    FList: TPictureCollection;
6732
  published
6733
    property List: TPictureCollection read FList write FList;
6734
  end;
6735
 
6736
procedure TPictureCollection.LoadFromFile(const FileName: string);
6737
var
6738
  Stream: TFileStream;
6739
begin
6740
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
6741
  try
6742
    LoadFromStream(Stream);
6743
  finally
6744
    Stream.Free;
6745
  end;
6746
end;
6747
 
6748
procedure TPictureCollection.LoadFromStream(Stream: TStream);
6749
var
6750
  Component: TPictureCollectionComponent;
6751
begin
6752
  Clear;
6753
  Component := TPictureCollectionComponent.Create(nil);
6754
  try
6755
    Component.FList := Self;
6756
    Stream.ReadComponentRes(Component);
6757
 
6758
    if Initialized then
6759
    begin
6760
      Initialize(FDXDraw);
6761
      Restore;
6762
    end;
6763
  finally
6764
    Component.Free;
6765
  end;
6766
end;
6767
 
6768
procedure TPictureCollection.SaveToFile(const FileName: string);
6769
var
6770
  Stream: TFileStream;
6771
begin
6772
  Stream := TFileStream.Create(FileName, fmCreate);
6773
  try
6774
    SaveToStream(Stream);
6775
  finally
6776
    Stream.Free;
6777
  end;
6778
end;
6779
 
6780
procedure TPictureCollection.SaveToStream(Stream: TStream);
6781
var
6782
  Component: TPictureCollectionComponent;
6783
begin
6784
  Component := TPictureCollectionComponent.Create(nil);
6785
  try
6786
    Component.FList := Self;
6787
    Stream.WriteComponentRes('DelphiXPictureCollection', Component);
6788
  finally
6789
    Component.Free;
6790
  end;
6791
end;
6792
 
6793
procedure TPictureCollection.ReadColorTable(Stream: TStream);
6794
begin
6795
  Stream.ReadBuffer(ColorTable, SizeOf(ColorTable));
6796
end;
6797
 
6798
procedure TPictureCollection.WriteColorTable(Stream: TStream);
6799
begin
6800
  Stream.WriteBuffer(ColorTable, SizeOf(ColorTable));
6801
end;
6802
 
6803
{  TCustomDXImageList  }
6804
 
6805
constructor TCustomDXImageList.Create(AOnwer: TComponent);
6806
begin
6807
  inherited Create(AOnwer);
6808
  FItems := TPictureCollection.Create(Self);
6809
end;
6810
 
6811
destructor TCustomDXImageList.Destroy;
6812
begin
6813
  DXDraw := nil;
6814
  FItems.Free;
6815
  inherited Destroy;
6816
end;
6817
 
6818
procedure TCustomDXImageList.Notification(AComponent: TComponent;
6819
  Operation: TOperation);
6820
begin
6821
  inherited Notification(AComponent, Operation);
6822
  if (Operation=opRemove) and (DXDraw=AComponent) then
6823
    DXDraw := nil;
6824
end;
6825
 
6826
procedure TCustomDXImageList.DXDrawNotifyEvent(Sender: TCustomDXDraw;
6827
  NotifyType: TDXDrawNotifyType);
6828
begin
6829
  case NotifyType of
6830
    dxntDestroying: DXDraw := nil;
6831
    dxntInitialize: FItems.Initialize(Sender);
6832
    dxntFinalize  : FItems.Finalize;
6833
    dxntRestore   : FItems.Restore;
6834
  end;
6835
end;
6836
 
6837
procedure TCustomDXImageList.SetDXDraw(Value: TCustomDXDraw);
6838
begin
6839
  if FDXDraw<>nil then
6840
    FDXDraw.UnRegisterNotifyEvent(DXDrawNotifyEvent);
6841
 
6842
  FDXDraw := Value;
6843
 
6844
  if FDXDraw<>nil then
6845
    FDXDraw.RegisterNotifyEvent(DXDrawNotifyEvent);
6846
end;
6847
 
6848
procedure TCustomDXImageList.SetItems(Value: TPictureCollection);
6849
begin
6850
  FItems.Assign(Value);
6851
end;
6852
 
6853
{  TDirectDrawOverlay  }
6854
 
6855
constructor TDirectDrawOverlay.Create(DDraw: TDirectDraw; TargetSurface: TDirectDrawSurface);
6856
begin
6857
  inherited Create;
6858
  FDDraw := DDraw;
6859
  FTargetSurface := TargetSurface;
6860
  FVisible := True;
6861
end;
6862
 
6863
constructor TDirectDrawOverlay.CreateWindowed(WindowHandle: HWND);
6864
const
6865
  PrimaryDesc: TDDSurfaceDesc = (
6866
      dwSize: SizeOf(PrimaryDesc);
6867
      dwFlags: DDSD_CAPS;
6868
      ddsCaps: (dwCaps: DDSCAPS_PRIMARYSURFACE)
6869
      );
6870
begin
6871
  FDDraw2 := TDirectDraw.CreateEx(nil, False);
6872
  if FDDraw2.IDraw.SetCooperativeLevel(WindowHandle, DDSCL_NORMAL)<>DD_OK then
6873
    raise EDirectDrawOverlayError.CreateFmt(SCannotInitialized, [SOverlay]);
6874
 
6875
  FTargetSurface2 := TDirectDrawSurface.Create(FDDraw2);
6876
  if not FTargetSurface2.CreateSurface(PrimaryDesc) then
6877
    raise EDirectDrawOverlayError.CreateFmt(SCannotInitialized, [SOverlay]);
6878
 
6879
  Create(FDDraw2, FTargetSurface2);
6880
end;
6881
 
6882
destructor TDirectDrawOverlay.Destroy;
6883
begin
6884
  Finalize;
6885
  FTargetSurface2.Free;
6886
  FDDraw2.Free;
6887
  inherited Destroy;
6888
end;
6889
 
6890
procedure TDirectDrawOverlay.Finalize;
6891
begin
6892
  FBackSurface.Free; FBackSurface := nil;
6893
  FSurface.Free; FSurface := nil;
6894
end;
6895
 
6896
procedure TDirectDrawOverlay.Initialize(const SurfaceDesc: TDDSurfaceDesc);
6897
const
6898
  BackBufferCaps: TDDSCaps = (dwCaps: DDSCAPS_BACKBUFFER);
6899
var
6900
  DDSurface: IDirectDrawSurface;
6901
begin
6902
  Finalize;
6903
  try
6904
    FSurface := TDirectDrawSurface.Create(FDDraw);
6905
    if not FSurface.CreateSurface(SurfaceDesc) then
6906
      raise EDirectDrawOverlayError.CreateFmt(SCannotInitialized, [SOverlay]);
6907
 
6908
    FBackSurface := TDirectDrawSurface.Create(FDDraw);
6909
 
6910
    if SurfaceDesc.ddsCaps.dwCaps and DDSCAPS_FLIP<>0 then
6911
    begin
6912
      if FSurface.ISurface.GetAttachedSurface(BackBufferCaps, DDSurface)=DD_OK then
6913
        FBackSurface.IDDSurface := DDSurface;
6914
    end else
6915
      FBackSurface.IDDSurface := FSurface.IDDSurface;
6916
 
6917
    if FVisible then
6918
      SetOverlayRect(FOverlayRect)
6919
    else
6920
      FSurface.ISurface.UpdateOverlay(PRect(nil)^, FTargetSurface.ISurface, PRect(nil)^, DDOVER_HIDE, PDDOverlayFX(nil)^);
6921
  except
6922
    Finalize;
6923
    raise;
6924
  end;
6925
end;
6926
 
6927
procedure TDirectDrawOverlay.Flip;
6928
begin
6929
  if FSurface=nil then Exit;
6930
 
6931
  if FSurface.SurfaceDesc.ddsCaps.dwCaps and DDSCAPS_FLIP<>0 then
6932
    FSurface.ISurface.Flip(nil, DDFLIP_WAIT);
6933
end;
6934
 
6935
procedure TDirectDrawOverlay.SetOverlayColorKey(Value: TColor);
6936
begin
6937
  FOverlayColorKey := Value;
6938
  if FSurface<>nil then
6939
    SetOverlayRect(FOverlayRect);
6940
end;
6941
 
6942
procedure TDirectDrawOverlay.SetOverlayRect(const Value: TRect);
6943
var
6944
  DestRect, SrcRect: TRect;
6945
  XScaleRatio, YScaleRatio: Integer;
6946
  OverlayFX: TDDOverlayFX;
6947
  OverlayFlags: DWORD;
6948
begin
6949
  FOverlayRect := Value;
6950
  if (FSurface<>nil) and FVisible then
6951
  begin
6952
    DestRect := FOverlayRect;
6953
    SrcRect.Left := 0;
6954
    SrcRect.Top := 0;
6955
    SrcRect.Right := FSurface.SurfaceDesc.dwWidth;
6956
    SrcRect.Bottom := FSurface.SurfaceDesc.dwHeight;
6957
 
6958
    OverlayFlags := DDOVER_SHOW;
6959
 
6960
    FillChar(OverlayFX, SizeOf(OverlayFX), 0);
6961
    OverlayFX.dwSize := SizeOf(OverlayFX);
6962
 
6963
    {  Scale rate limitation  }
6964
    XScaleRatio := (DestRect.right - DestRect.left) * 1000 div (SrcRect.right - SrcRect.left);
6965
    YScaleRatio := (DestRect.bottom - DestRect.top) * 1000 div (SrcRect.bottom - SrcRect.top);
6966
 
6967
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_OVERLAYSTRETCH<>0) and
6968
      (FDDraw.DriverCaps.dwMinOverlayStretch<>0) and (XScaleRatio<Integer(FDDraw.DriverCaps.dwMinOverlayStretch)) then
6969
    begin
6970
      DestRect.Right := DestRect.Left + (Integer(FSurface.SurfaceDesc.dwWidth) * (Integer(FDDraw.DriverCaps.dwMinOverlayStretch) + 1)) div 1000;
6971
    end;
6972
 
6973
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_OVERLAYSTRETCH<>0) and
6974
      (FDDraw.DriverCaps.dwMaxOverlayStretch<>0) and (XScaleRatio>Integer(FDDraw.DriverCaps.dwMaxOverlayStretch)) then
6975
    begin
6976
      DestRect.Right := DestRect.Left + (Integer(FSurface.SurfaceDesc.dwWidth) * (Integer(FDDraw.DriverCaps.dwMaxOverlayStretch) + 999)) div 1000;
6977
    end;
6978
 
6979
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_OVERLAYSTRETCH<>0) and
6980
      (FDDraw.DriverCaps.dwMinOverlayStretch<>0) and (YScaleRatio<Integer(FDDraw.DriverCaps.dwMinOverlayStretch)) then
6981
    begin
6982
      DestRect.Bottom := DestRect.Top + (Integer(FSurface.SurfaceDesc.dwHeight) * (Integer(FDDraw.DriverCaps.dwMinOverlayStretch) + 1)) div 1000;
6983
    end;
6984
 
6985
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_OVERLAYSTRETCH<>0) and
6986
      (FDDraw.DriverCaps.dwMaxOverlayStretch<>0) and (YScaleRatio>Integer(FDDraw.DriverCaps.dwMaxOverlayStretch)) then
6987
    begin
6988
      DestRect.Bottom := DestRect.Top + (Integer(FSurface.SurfaceDesc.dwHeight) * (Integer(FDDraw.DriverCaps.dwMaxOverlayStretch) + 999)) div 1000;
6989
    end;
6990
 
6991
    {  Clipping at forwarding destination  }
6992
    XScaleRatio := (DestRect.Right - DestRect.Left) * 1000 div (SrcRect.Right - SrcRect.Left);
6993
    YScaleRatio := (DestRect.Bottom - DestRect.Top) * 1000 div (SrcRect.Bottom - SrcRect.Top);
6994
 
6995
    if DestRect.Top < 0 then
6996
    begin
6997
      SrcRect.Top := -DestRect.Top * 1000 div YScaleRatio;
6998
      DestRect.Top := 0;
6999
    end;
7000
 
7001
    if DestRect.Left < 0 then
7002
    begin
7003
      SrcRect.Left := -DestRect.Left * 1000 div XScaleRatio;
7004
      DestRect.Left := 0;
7005
    end;
7006
 
7007
    if DestRect.Right > Integer(FTargetSurface.SurfaceDesc.dwWidth) then
7008
    begin
7009
      SrcRect.Right := Integer(FSurface.SurfaceDesc.dwWidth) - ((DestRect.Right - Integer(FTargetSurface.SurfaceDesc.dwWidth)) * 1000 div XScaleRatio);
7010
      DestRect.Right := FTargetSurface.SurfaceDesc.dwWidth;
7011
    end;
7012
 
7013
    if DestRect.Bottom > Integer(FTargetSurface.SurfaceDesc.dwHeight) then
7014
    begin
7015
      SrcRect.Bottom := Integer(FSurface.SurfaceDesc.dwHeight) - ((DestRect.Bottom - Integer(FTargetSurface.SurfaceDesc.dwHeight)) * 1000 div YScaleRatio);
7016
      DestRect.Bottom := FTargetSurface.SurfaceDesc.dwHeight;
7017
    end;
7018
 
7019
    {  Forwarding former arrangement  }
7020
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_ALIGNBOUNDARYSRC<>0) and (FDDraw.DriverCaps.dwAlignBoundarySrc<>0) then
7021
    begin
7022
      SrcRect.Left := (SrcRect.Left + Integer(FDDraw.DriverCaps.dwAlignBoundarySrc) div 2) div
7023
        Integer(FDDraw.DriverCaps.dwAlignBoundarySrc)*Integer(FDDraw.DriverCaps.dwAlignBoundarySrc);
7024
    end;
7025
 
7026
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_ALIGNSIZESRC<>0) and (FDDraw.DriverCaps.dwAlignSizeSrc<>0) then
7027
    begin
7028
      SrcRect.Right := SrcRect.Left + (SrcRect.Right - SrcRect.Left + Integer(FDDraw.DriverCaps.dwAlignSizeSrc) div 2) div
7029
        Integer(FDDraw.DriverCaps.dwAlignSizeSrc)*Integer(FDDraw.DriverCaps.dwAlignSizeSrc);
7030
    end;
7031
 
7032
    {  Forwarding destination arrangement  }
7033
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_ALIGNBOUNDARYDEST<>0) and (FDDraw.DriverCaps.dwAlignBoundaryDest<>0) then
7034
    begin
7035
      DestRect.Left := (DestRect.Left + Integer(FDDraw.DriverCaps.dwAlignBoundaryDest) div 2) div
7036
        Integer(FDDraw.DriverCaps.dwAlignBoundaryDest)*Integer(FDDraw.DriverCaps.dwAlignBoundaryDest);
7037
    end;
7038
 
7039
    if (FDDraw.DriverCaps.dwCaps and DDCAPS_ALIGNSIZEDEST<>0) and (FDDraw.DriverCaps.dwAlignSizeDest<>0) then
7040
    begin
7041
      DestRect.Right := DestRect.Left + (DestRect.Right - DestRect.Left) div
7042
        Integer(FDDraw.DriverCaps.dwAlignSizeDest)*Integer(FDDraw.DriverCaps.dwAlignSizeDest);
7043
    end;
7044
 
7045
    {  Color key setting  }
7046
    if FDDraw.DriverCaps.dwCKeyCaps and DDCKEYCAPS_DESTOVERLAY<>0 then
7047
    begin
7048
      OverlayFX.dckDestColorkey.dwColorSpaceLowValue := FTargetSurface.ColorMatch(FOverlayColorKey);
7049
      OverlayFX.dckDestColorkey.dwColorSpaceHighValue := OverlayFX.dckDestColorkey.dwColorSpaceLowValue;
7050
 
7051
      OverlayFlags := OverlayFlags or (DDOVER_KEYDESTOVERRIDE or DDOVER_DDFX);
7052
    end;
7053
 
7054
    FSurface.ISurface.UpdateOverlay(SrcRect, FTargetSurface.ISurface, DestRect, OverlayFlags, OverlayFX);
7055
  end;
7056
end;
7057
 
7058
procedure TDirectDrawOverlay.SetVisible(Value: Boolean);
7059
begin
7060
  FVisible := False;
7061
  if FSurface<>nil then
7062
  begin
7063
    if FVisible then
7064
      SetOverlayRect(FOverlayRect)
7065
    else
7066
      FSurface.ISurface.UpdateOverlay(PRect(nil)^, FTargetSurface.ISurface, PRect(nil)^, DDOVER_HIDE, PDDOverlayFX(nil)^);
7067
  end;
7068
end;
7069
 
7070
initialization
7071
finalization
7072
  DirectDrawDrivers.Free;
7073
end.
7074
 
7075