2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS ReactX
4 * FILE: dll/directx/d3d9/format.c
5 * PURPOSE: d3d9.dll D3DFORMAT helper functions
6 * PROGRAMERS: Gregor Brunmar <gregor (dot) brunmar (at) home (dot) se>
13 BOOL
IsBackBufferFormat(D3DFORMAT Format
)
15 return ((Format
>= D3DFMT_A8R8G8B8
) && (Format
< D3DFMT_A1R5G5B5
)) ||
16 (IsExtendedFormat(Format
));
19 BOOL
IsExtendedFormat(D3DFORMAT Format
)
21 return (Format
== D3DFMT_A2R10G10B10
);
24 BOOL
IsZBufferFormat(D3DFORMAT Format
)
31 BOOL
IsMultiElementFormat(D3DFORMAT Format
)
33 return (Format
== D3DFMT_MULTI2_ARGB8
);
36 BOOL
IsFourCCFormat(D3DFORMAT Format
)
38 CHAR
* cFormat
= (CHAR
*)&Format
;
39 if (isalnum(cFormat
[0]) &&
40 isalnum(cFormat
[1]) &&
41 isalnum(cFormat
[2]) &&
50 BOOL
IsStencilFormat(D3DFORMAT Format
)
65 DWORD
GetBytesPerPixel(D3DFORMAT Format
)
86 case D3DFMT_A2B10G10R10
:
90 case D3DFMT_A2R10G10B10
:
93 case D3DFMT_A16B16G16R16
:
111 case D3DFMT_X8L8V8U8
:
112 case D3DFMT_Q8W8V8U8
:
114 case D3DFMT_A2W10V10U10
:
118 case D3DFMT_S8_LOCKABLE
:
121 case D3DFMT_D16_LOCKABLE
:
130 case D3DFMT_D32F_LOCKABLE
:
132 case D3DFMT_D32_LOCKABLE
:
139 /* TODO: Handle D3DFMT_VERTEXDATA? */
146 case D3DFMT_Q16W16V16U16
:
154 case D3DFMT_A16B16G16R16F
:
162 case D3DFMT_A32B32G32R32F
:
169 /* Known FourCC formats */
171 case D3DFMT_R8G8_B8G8
:
173 case D3DFMT_G8R8_G8B8
:
185 case D3DFMT_MULTI2_ARGB8
:
193 DWORD
GetPixelStride(D3DFORMAT Format
)
195 DWORD Bpp
= GetBytesPerPixel(Format
);
199 /* TODO: Handle unknown formats here */
205 BOOL
IsSupportedFormatOp(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT DisplayFormat
, DWORD FormatOp
)
207 const DWORD NumFormatOps
= pDriverCaps
->NumSupportedFormatOps
;
210 for (FormatOpIndex
= 0; FormatOpIndex
< NumFormatOps
; FormatOpIndex
++)
212 const LPDDSURFACEDESC pSurfaceDesc
= &pDriverCaps
->pSupportedFormatOps
[FormatOpIndex
];
213 if (pSurfaceDesc
->ddpfPixelFormat
.dwFourCC
== DisplayFormat
&&
214 (pSurfaceDesc
->ddpfPixelFormat
.dwOperations
& FormatOp
) == FormatOp
)
223 HRESULT
CheckDeviceType(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT DisplayFormat
, D3DFORMAT BackBufferFormat
, BOOL Windowed
)
225 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, DisplayFormat
, D3DFORMAT_OP_DISPLAYMODE
| D3DFORMAT_OP_3DACCELERATION
))
227 return D3DERR_NOTAVAILABLE
;
230 if (DisplayFormat
!= BackBufferFormat
)
232 D3DFORMAT AdjustedDisplayFormat
= DisplayFormat
;
234 if (DisplayFormat
== D3DFMT_X8R8G8B8
)
236 DisplayFormat
= D3DFMT_A8R8G8B8
;
238 else if (DisplayFormat
== D3DFMT_X1R5G5B5
)
240 DisplayFormat
= D3DFMT_A1R5G5B5
;
243 if (AdjustedDisplayFormat
== BackBufferFormat
)
245 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, AdjustedDisplayFormat
, D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET
))
247 return D3DERR_NOTAVAILABLE
;
252 else if (FALSE
== Windowed
)
254 return D3DERR_NOTAVAILABLE
;
257 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, BackBufferFormat
, D3DFORMAT_OP_OFFSCREEN_RENDERTARGET
) ||
258 FALSE
== IsSupportedFormatOp(pDriverCaps
, BackBufferFormat
, D3DFORMAT_OP_CONVERT_TO_ARGB
) ||
259 FALSE
== IsSupportedFormatOp(pDriverCaps
, BackBufferFormat
, D3DFORMAT_MEMBEROFGROUP_ARGB
))
261 return D3DERR_NOTAVAILABLE
;
266 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, DisplayFormat
, D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
))
268 return D3DERR_NOTAVAILABLE
;
275 static D3DFORMAT
GetStencilFormat(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT CheckFormat
)
283 if (IsSupportedFormatOp(pDriverCaps
, CheckFormat
- 1, 0))
284 return CheckFormat
- 1;
288 if (IsSupportedFormatOp(pDriverCaps
, CheckFormat
, 0))
291 return D3DFMT_D16_LOCKABLE
;
294 /* StencilFormat same as CheckFormat */
301 static D3DFORMAT
RemoveAlphaChannel(D3DFORMAT CheckFormat
)
305 case D3DFMT_A8R8G8B8
:
306 return D3DFMT_X8R8G8B8
;
308 case D3DFMT_A1R5G5B5
:
309 return D3DFMT_X1R5G5B5
;
311 case D3DFMT_A4R4G4B4
:
312 return D3DFMT_X4R4G4B4
;
314 case D3DFMT_A8B8G8R8
:
315 return D3DFMT_X8B8G8R8
;
318 /* CheckFormat has not relevant alpha channel */
325 HRESULT
CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT AdapterFormat
, DWORD Usage
, D3DRESOURCETYPE RType
, D3DFORMAT CheckFormat
)
327 const DWORD NumFormatOps
= pDriverCaps
->NumSupportedFormatOps
;
328 DWORD NonCompatibleOperations
= 0, MustSupportOperations
= 0;
329 BOOL bSupportedWithAutogen
= FALSE
;
332 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, AdapterFormat
, D3DFORMAT_OP_DISPLAYMODE
| D3DFORMAT_OP_3DACCELERATION
))
334 return D3DERR_NOTAVAILABLE
;
337 /* Check for driver auto generated mip map support if requested */
338 if ((Usage
& (D3DUSAGE_AUTOGENMIPMAP
)) != 0)
342 case D3DRTYPE_TEXTURE
:
343 if ((pDriverCaps
->DriverCaps9
.TextureCaps
& D3DPTEXTURECAPS_MIPMAP
) == 0)
344 return D3DERR_NOTAVAILABLE
;
348 case D3DRTYPE_VOLUME
:
349 case D3DRTYPE_VOLUMETEXTURE
:
350 if ((pDriverCaps
->DriverCaps9
.TextureCaps
& D3DPTEXTURECAPS_MIPVOLUMEMAP
) == 0)
351 return D3DERR_NOTAVAILABLE
;
355 case D3DRTYPE_CUBETEXTURE
:
356 if ((pDriverCaps
->DriverCaps9
.TextureCaps
& D3DPTEXTURECAPS_MIPCUBEMAP
) == 0)
357 return D3DERR_NOTAVAILABLE
;
366 MustSupportOperations
|= D3DFORMAT_OP_AUTOGENMIPMAP
;
369 /* Translate from RType and Usage parameters to FormatOps */
372 case D3DRTYPE_TEXTURE
:
373 MustSupportOperations
|= D3DFORMAT_OP_TEXTURE
;
376 case D3DRTYPE_VOLUME
:
377 case D3DRTYPE_VOLUMETEXTURE
:
378 MustSupportOperations
|= D3DFORMAT_OP_VOLUMETEXTURE
;
381 case D3DRTYPE_CUBETEXTURE
:
382 MustSupportOperations
|= D3DFORMAT_OP_CUBETEXTURE
;
390 if (Usage
== 0 && RType
== D3DRTYPE_SURFACE
)
392 MustSupportOperations
|= D3DFORMAT_OP_OFFSCREENPLAIN
;
395 if ((Usage
& D3DUSAGE_DEPTHSTENCIL
) != 0)
397 MustSupportOperations
|= D3DFORMAT_OP_ZSTENCIL
;
400 if ((Usage
& D3DUSAGE_DMAP
) != 0)
402 MustSupportOperations
|= D3DFORMAT_OP_DMAP
;
405 if ((Usage
& D3DUSAGE_QUERY_LEGACYBUMPMAP
) != 0)
407 MustSupportOperations
|= D3DFORMAT_OP_BUMPMAP
;
410 if ((Usage
& D3DUSAGE_QUERY_SRGBREAD
) != 0)
412 MustSupportOperations
|= D3DFORMAT_OP_SRGBREAD
;
415 if ((Usage
& D3DUSAGE_QUERY_SRGBWRITE
) != 0)
417 MustSupportOperations
|= D3DFORMAT_OP_SRGBWRITE
;
420 if ((Usage
& D3DUSAGE_QUERY_VERTEXTEXTURE
) != 0)
422 MustSupportOperations
|= D3DFORMAT_OP_VERTEXTEXTURE
;
425 CheckFormat
= GetStencilFormat(pDriverCaps
, CheckFormat
);
427 if ((Usage
& D3DUSAGE_RENDERTARGET
) != 0)
429 if (AdapterFormat
== CheckFormat
)
431 MustSupportOperations
|= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
;
435 D3DFORMAT NonAlphaAdapterFormat
;
436 D3DFORMAT NonAlphaCheckFormat
;
438 NonAlphaAdapterFormat
= RemoveAlphaChannel(AdapterFormat
);
439 NonAlphaCheckFormat
= RemoveAlphaChannel(CheckFormat
);
441 if (NonAlphaAdapterFormat
== NonAlphaCheckFormat
&&
442 NonAlphaCheckFormat
!= D3DFMT_UNKNOWN
)
444 MustSupportOperations
|= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET
;
448 MustSupportOperations
|= D3DFORMAT_OP_OFFSCREEN_RENDERTARGET
;
453 if ((Usage
& D3DUSAGE_QUERY_FILTER
) != 0)
455 NonCompatibleOperations
|= D3DFORMAT_OP_OFFSCREENPLAIN
;
458 if ((Usage
& D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
) != 0)
460 NonCompatibleOperations
|= D3DFORMAT_OP_NOALPHABLEND
;
463 if ((Usage
& D3DUSAGE_QUERY_WRAPANDMIP
) != 0)
465 NonCompatibleOperations
|= D3DFORMAT_OP_NOTEXCOORDWRAPNORMIP
;
468 for (FormatOpIndex
= 0; FormatOpIndex
< NumFormatOps
; FormatOpIndex
++)
471 LPDDSURFACEDESC pSurfaceDesc
= &pDriverCaps
->pSupportedFormatOps
[FormatOpIndex
];
473 if (pSurfaceDesc
->ddpfPixelFormat
.dwFourCC
!= CheckFormat
)
476 dwOperations
= pSurfaceDesc
->ddpfPixelFormat
.dwOperations
;
478 if ((dwOperations
& NonCompatibleOperations
) != 0)
481 if ((dwOperations
& MustSupportOperations
) == MustSupportOperations
)
484 if (((dwOperations
& MustSupportOperations
) | D3DFORMAT_OP_AUTOGENMIPMAP
) == MustSupportOperations
)
485 bSupportedWithAutogen
= TRUE
;
488 if (TRUE
== bSupportedWithAutogen
)
489 return D3DOK_NOAUTOGEN
;
491 return D3DERR_NOTAVAILABLE
;
494 HRESULT
CheckDeviceFormatConversion(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT SourceFormat
, D3DFORMAT TargetFormat
)
496 D3DFORMAT NonAlphaSourceFormat
;
497 D3DFORMAT NonAlphaTargetFormat
;
499 NonAlphaSourceFormat
= RemoveAlphaChannel(SourceFormat
);
500 NonAlphaTargetFormat
= RemoveAlphaChannel(TargetFormat
);
502 if (NonAlphaSourceFormat
== NonAlphaTargetFormat
)
507 if (FALSE
== IsFourCCFormat(SourceFormat
))
509 switch (SourceFormat
)
511 case D3DFMT_A8R8G8B8
:
512 case D3DFMT_X8R8G8B8
:
514 case D3DFMT_X1R5G5B5
:
515 case D3DFMT_A1R5G5B5
:
516 case D3DFMT_A2R10G10B10
:
517 /* Do nothing, valid SourceFormat */
521 return D3DERR_NOTAVAILABLE
;
524 else if (pDriverCaps
->DriverCaps9
.DevCaps2
== 0)
529 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, SourceFormat
, D3DFORMAT_OP_CONVERT_TO_ARGB
) ||
530 FALSE
== IsSupportedFormatOp(pDriverCaps
, TargetFormat
, D3DFORMAT_MEMBEROFGROUP_ARGB
))
532 return D3DERR_NOTAVAILABLE
;
538 HRESULT
CheckDepthStencilMatch(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT AdapterFormat
, D3DFORMAT RenderTargetFormat
, D3DFORMAT DepthStencilFormat
)
540 const DWORD NumFormatOps
= pDriverCaps
->NumSupportedFormatOps
;
541 BOOL bRenderTargetAvailable
= FALSE
;
542 BOOL bDepthStencilAvailable
= FALSE
;
543 BOOL bForceSameDepthStencilBits
= FALSE
;
546 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, AdapterFormat
, D3DFORMAT_OP_DISPLAYMODE
| D3DFORMAT_OP_3DACCELERATION
))
548 return D3DERR_NOTAVAILABLE
;
551 if (DepthStencilFormat
!= D3DFMT_D16_LOCKABLE
&&
552 DepthStencilFormat
!= D3DFMT_D32F_LOCKABLE
)
554 if (TRUE
== IsStencilFormat(DepthStencilFormat
))
556 bForceSameDepthStencilBits
= TRUE
;
560 if (FALSE
== bForceSameDepthStencilBits
&&
561 (DepthStencilFormat
== D3DFMT_D32
|| DepthStencilFormat
== D3DFMT_D24X8
))
563 bForceSameDepthStencilBits
= TRUE
;
566 DepthStencilFormat
= GetStencilFormat(pDriverCaps
, DepthStencilFormat
);
568 /* Observe the multiple conditions */
569 for (FormatIndex
= 0; FormatIndex
< NumFormatOps
&& (bRenderTargetAvailable
== FALSE
|| bDepthStencilAvailable
== FALSE
); FormatIndex
++)
571 const LPDDSURFACEDESC pSurfaceDesc
= &pDriverCaps
->pSupportedFormatOps
[FormatIndex
];
572 const DWORD FourCC
= pSurfaceDesc
->ddpfPixelFormat
.dwFourCC
;
573 const DWORD FormatOperations
= pSurfaceDesc
->ddpfPixelFormat
.dwOperations
;
575 if (FALSE
== bRenderTargetAvailable
&&
576 FourCC
== RenderTargetFormat
&&
577 (FormatOperations
& D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
) != 0)
579 bRenderTargetAvailable
= TRUE
;
582 if (FALSE
== bDepthStencilAvailable
&&
583 FourCC
== DepthStencilFormat
&&
584 (FormatOperations
& D3DFORMAT_OP_ZSTENCIL
) != 0)
586 bDepthStencilAvailable
= TRUE
;
588 if ((FormatOperations
& D3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
) != 0)
590 bForceSameDepthStencilBits
= FALSE
;
595 if (FALSE
== bRenderTargetAvailable
|| FALSE
== bDepthStencilAvailable
)
597 return D3DERR_INVALIDCALL
;
600 if (TRUE
== bForceSameDepthStencilBits
)
602 if (GetPixelStride(RenderTargetFormat
) != GetPixelStride(DepthStencilFormat
))
603 return D3DERR_NOTAVAILABLE
;