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>
12 #include <d3d9types.h>
14 BOOL
IsBackBufferFormat(D3DFORMAT Format
)
16 return ((Format
>= D3DFMT_A8R8G8B8
) && (Format
< D3DFMT_A1R5G5B5
)) ||
17 (IsExtendedFormat(Format
));
20 BOOL
IsExtendedFormat(D3DFORMAT Format
)
22 return (Format
== D3DFMT_A2R10G10B10
);
25 BOOL
IsZBufferFormat(D3DFORMAT Format
)
32 BOOL
IsMultiElementFormat(D3DFORMAT Format
)
34 return (Format
== D3DFMT_MULTI2_ARGB8
);
37 BOOL
IsFourCCFormat(D3DFORMAT Format
)
39 CHAR
* cFormat
= (CHAR
*)&Format
;
40 if (isalnum(cFormat
[0]) &&
41 isalnum(cFormat
[1]) &&
42 isalnum(cFormat
[2]) &&
51 BOOL
IsStencilFormat(D3DFORMAT Format
)
66 DWORD
GetBytesPerPixel(D3DFORMAT Format
)
87 case D3DFMT_A2B10G10R10
:
91 case D3DFMT_A2R10G10B10
:
94 case D3DFMT_A16B16G16R16
:
112 case D3DFMT_X8L8V8U8
:
113 case D3DFMT_Q8W8V8U8
:
115 case D3DFMT_A2W10V10U10
:
119 case D3DFMT_S8_LOCKABLE
:
122 case D3DFMT_D16_LOCKABLE
:
131 case D3DFMT_D32F_LOCKABLE
:
133 case D3DFMT_D32_LOCKABLE
:
140 /* TODO: Handle D3DFMT_VERTEXDATA? */
147 case D3DFMT_Q16W16V16U16
:
155 case D3DFMT_A16B16G16R16F
:
163 case D3DFMT_A32B32G32R32F
:
170 /* Known FourCC formats */
172 case D3DFMT_R8G8_B8G8
:
174 case D3DFMT_G8R8_G8B8
:
186 case D3DFMT_MULTI2_ARGB8
:
194 DWORD
GetPixelStride(D3DFORMAT Format
)
196 DWORD Bpp
= GetBytesPerPixel(Format
);
200 /* TODO: Handle unknown formats here */
206 BOOL
IsSupportedFormatOp(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT DisplayFormat
, DWORD FormatOp
)
208 const DWORD NumFormatOps
= pDriverCaps
->NumSupportedFormatOps
;
211 for (FormatOpIndex
= 0; FormatOpIndex
< NumFormatOps
; FormatOpIndex
++)
213 const LPDDSURFACEDESC pSurfaceDesc
= &pDriverCaps
->pSupportedFormatOps
[FormatOpIndex
];
214 if (pSurfaceDesc
->ddpfPixelFormat
.dwFourCC
== DisplayFormat
&&
215 (pSurfaceDesc
->ddpfPixelFormat
.dwOperations
& FormatOp
) == FormatOp
)
224 HRESULT
CheckDeviceType(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT DisplayFormat
, D3DFORMAT BackBufferFormat
, BOOL Windowed
)
226 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, DisplayFormat
, D3DFORMAT_OP_DISPLAYMODE
| D3DFORMAT_OP_3DACCELERATION
))
228 return D3DERR_NOTAVAILABLE
;
231 if (DisplayFormat
!= BackBufferFormat
)
233 D3DFORMAT AdjustedDisplayFormat
= DisplayFormat
;
235 if (DisplayFormat
== D3DFMT_X8R8G8B8
)
237 DisplayFormat
= D3DFMT_A8R8G8B8
;
239 else if (DisplayFormat
== D3DFMT_X1R5G5B5
)
241 DisplayFormat
= D3DFMT_A1R5G5B5
;
244 if (AdjustedDisplayFormat
== BackBufferFormat
)
246 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, AdjustedDisplayFormat
, D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET
))
248 return D3DERR_NOTAVAILABLE
;
253 else if (FALSE
== Windowed
)
255 return D3DERR_NOTAVAILABLE
;
258 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, BackBufferFormat
, D3DFORMAT_OP_OFFSCREEN_RENDERTARGET
) ||
259 FALSE
== IsSupportedFormatOp(pDriverCaps
, BackBufferFormat
, D3DFORMAT_OP_CONVERT_TO_ARGB
) ||
260 FALSE
== IsSupportedFormatOp(pDriverCaps
, BackBufferFormat
, D3DFORMAT_MEMBEROFGROUP_ARGB
))
262 return D3DERR_NOTAVAILABLE
;
267 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, DisplayFormat
, D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
))
269 return D3DERR_NOTAVAILABLE
;
276 static D3DFORMAT
GetStencilFormat(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT CheckFormat
)
284 if (IsSupportedFormatOp(pDriverCaps
, CheckFormat
- 1, 0))
285 return CheckFormat
- 1;
289 if (IsSupportedFormatOp(pDriverCaps
, CheckFormat
, 0))
292 return D3DFMT_D16_LOCKABLE
;
295 /* StencilFormat same as CheckFormat */
302 static D3DFORMAT
RemoveAlphaChannel(D3DFORMAT CheckFormat
)
306 case D3DFMT_A8R8G8B8
:
307 return D3DFMT_X8R8G8B8
;
309 case D3DFMT_A1R5G5B5
:
310 return D3DFMT_X1R5G5B5
;
312 case D3DFMT_A4R4G4B4
:
313 return D3DFMT_X4R4G4B4
;
315 case D3DFMT_A8B8G8R8
:
316 return D3DFMT_X8B8G8R8
;
319 /* CheckFormat has not relevant alpha channel */
326 HRESULT
CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT AdapterFormat
, DWORD Usage
, D3DRESOURCETYPE RType
, D3DFORMAT CheckFormat
)
328 const DWORD NumFormatOps
= pDriverCaps
->NumSupportedFormatOps
;
329 DWORD NonCompatibleOperations
= 0, MustSupportOperations
= 0;
330 BOOL bSupportedWithAutogen
= FALSE
;
333 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, AdapterFormat
, D3DFORMAT_OP_DISPLAYMODE
| D3DFORMAT_OP_3DACCELERATION
))
335 return D3DERR_NOTAVAILABLE
;
338 /* Check for driver auto generated mip map support if requested */
339 if ((Usage
& (D3DUSAGE_AUTOGENMIPMAP
)) != 0)
343 case D3DRTYPE_TEXTURE
:
344 if ((pDriverCaps
->DriverCaps9
.TextureCaps
& D3DPTEXTURECAPS_MIPMAP
) == 0)
345 return D3DERR_NOTAVAILABLE
;
349 case D3DRTYPE_VOLUME
:
350 case D3DRTYPE_VOLUMETEXTURE
:
351 if ((pDriverCaps
->DriverCaps9
.TextureCaps
& D3DPTEXTURECAPS_MIPVOLUMEMAP
) == 0)
352 return D3DERR_NOTAVAILABLE
;
356 case D3DRTYPE_CUBETEXTURE
:
357 if ((pDriverCaps
->DriverCaps9
.TextureCaps
& D3DPTEXTURECAPS_MIPCUBEMAP
) == 0)
358 return D3DERR_NOTAVAILABLE
;
367 MustSupportOperations
|= D3DFORMAT_OP_AUTOGENMIPMAP
;
370 /* Translate from RType and Usage parameters to FormatOps */
373 case D3DRTYPE_TEXTURE
:
374 MustSupportOperations
|= D3DFORMAT_OP_TEXTURE
;
377 case D3DRTYPE_VOLUME
:
378 case D3DRTYPE_VOLUMETEXTURE
:
379 MustSupportOperations
|= D3DFORMAT_OP_VOLUMETEXTURE
;
382 case D3DRTYPE_CUBETEXTURE
:
383 MustSupportOperations
|= D3DFORMAT_OP_CUBETEXTURE
;
391 if (Usage
== 0 && RType
== D3DRTYPE_SURFACE
)
393 MustSupportOperations
|= D3DFORMAT_OP_OFFSCREENPLAIN
;
396 if ((Usage
& D3DUSAGE_DEPTHSTENCIL
) != 0)
398 MustSupportOperations
|= D3DFORMAT_OP_ZSTENCIL
;
401 if ((Usage
& D3DUSAGE_DMAP
) != 0)
403 MustSupportOperations
|= D3DFORMAT_OP_DMAP
;
406 if ((Usage
& D3DUSAGE_QUERY_LEGACYBUMPMAP
) != 0)
408 MustSupportOperations
|= D3DFORMAT_OP_BUMPMAP
;
411 if ((Usage
& D3DUSAGE_QUERY_SRGBREAD
) != 0)
413 MustSupportOperations
|= D3DFORMAT_OP_SRGBREAD
;
416 if ((Usage
& D3DUSAGE_QUERY_SRGBWRITE
) != 0)
418 MustSupportOperations
|= D3DFORMAT_OP_SRGBWRITE
;
421 if ((Usage
& D3DUSAGE_QUERY_VERTEXTEXTURE
) != 0)
423 MustSupportOperations
|= D3DFORMAT_OP_VERTEXTEXTURE
;
426 CheckFormat
= GetStencilFormat(pDriverCaps
, CheckFormat
);
428 if ((Usage
& D3DUSAGE_RENDERTARGET
) != 0)
430 if (AdapterFormat
== CheckFormat
)
432 MustSupportOperations
|= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
;
436 D3DFORMAT NonAlphaAdapterFormat
;
437 D3DFORMAT NonAlphaCheckFormat
;
439 NonAlphaAdapterFormat
= RemoveAlphaChannel(AdapterFormat
);
440 NonAlphaCheckFormat
= RemoveAlphaChannel(CheckFormat
);
442 if (NonAlphaAdapterFormat
== NonAlphaCheckFormat
&&
443 NonAlphaCheckFormat
!= D3DFMT_UNKNOWN
)
445 MustSupportOperations
|= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET
;
449 MustSupportOperations
|= D3DFORMAT_OP_OFFSCREEN_RENDERTARGET
;
454 if ((Usage
& D3DUSAGE_QUERY_FILTER
) != 0)
456 NonCompatibleOperations
|= D3DFORMAT_OP_OFFSCREENPLAIN
;
459 if ((Usage
& D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
) != 0)
461 NonCompatibleOperations
|= D3DFORMAT_OP_NOALPHABLEND
;
464 if ((Usage
& D3DUSAGE_QUERY_WRAPANDMIP
) != 0)
466 NonCompatibleOperations
|= D3DFORMAT_OP_NOTEXCOORDWRAPNORMIP
;
469 for (FormatOpIndex
= 0; FormatOpIndex
< NumFormatOps
; FormatOpIndex
++)
472 LPDDSURFACEDESC pSurfaceDesc
= &pDriverCaps
->pSupportedFormatOps
[FormatOpIndex
];
474 if (pSurfaceDesc
->ddpfPixelFormat
.dwFourCC
!= CheckFormat
)
477 dwOperations
= pSurfaceDesc
->ddpfPixelFormat
.dwOperations
;
479 if ((dwOperations
& NonCompatibleOperations
) != 0)
482 if ((dwOperations
& MustSupportOperations
) == MustSupportOperations
)
485 if (((dwOperations
& MustSupportOperations
) | D3DFORMAT_OP_AUTOGENMIPMAP
) == MustSupportOperations
)
486 bSupportedWithAutogen
= TRUE
;
489 if (TRUE
== bSupportedWithAutogen
)
490 return D3DOK_NOAUTOGEN
;
492 return D3DERR_NOTAVAILABLE
;
495 HRESULT
CheckDeviceFormatConversion(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT SourceFormat
, D3DFORMAT TargetFormat
)
497 D3DFORMAT NonAlphaSourceFormat
;
498 D3DFORMAT NonAlphaTargetFormat
;
500 NonAlphaSourceFormat
= RemoveAlphaChannel(SourceFormat
);
501 NonAlphaTargetFormat
= RemoveAlphaChannel(TargetFormat
);
503 if (NonAlphaSourceFormat
== NonAlphaTargetFormat
)
508 if (FALSE
== IsFourCCFormat(SourceFormat
))
510 switch (SourceFormat
)
512 case D3DFMT_A8R8G8B8
:
513 case D3DFMT_X8R8G8B8
:
515 case D3DFMT_X1R5G5B5
:
516 case D3DFMT_A1R5G5B5
:
517 case D3DFMT_A2R10G10B10
:
518 /* Do nothing, valid SourceFormat */
522 return D3DERR_NOTAVAILABLE
;
525 else if (pDriverCaps
->DriverCaps9
.DevCaps2
== 0)
530 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, SourceFormat
, D3DFORMAT_OP_CONVERT_TO_ARGB
) ||
531 FALSE
== IsSupportedFormatOp(pDriverCaps
, TargetFormat
, D3DFORMAT_MEMBEROFGROUP_ARGB
))
533 return D3DERR_NOTAVAILABLE
;
539 HRESULT
CheckDepthStencilMatch(LPD3D9_DRIVERCAPS pDriverCaps
, D3DFORMAT AdapterFormat
, D3DFORMAT RenderTargetFormat
, D3DFORMAT DepthStencilFormat
)
541 const DWORD NumFormatOps
= pDriverCaps
->NumSupportedFormatOps
;
542 BOOL bRenderTargetAvailable
= FALSE
;
543 BOOL bDepthStencilAvailable
= FALSE
;
544 BOOL bForceSameDepthStencilBits
= FALSE
;
547 if (FALSE
== IsSupportedFormatOp(pDriverCaps
, AdapterFormat
, D3DFORMAT_OP_DISPLAYMODE
| D3DFORMAT_OP_3DACCELERATION
))
549 return D3DERR_NOTAVAILABLE
;
552 if (DepthStencilFormat
!= D3DFMT_D16_LOCKABLE
&&
553 DepthStencilFormat
!= D3DFMT_D32F_LOCKABLE
)
555 if (TRUE
== IsStencilFormat(DepthStencilFormat
))
557 bForceSameDepthStencilBits
= TRUE
;
561 if (FALSE
== bForceSameDepthStencilBits
&&
562 (DepthStencilFormat
== D3DFMT_D32
|| DepthStencilFormat
== D3DFMT_D24X8
))
564 bForceSameDepthStencilBits
= TRUE
;
567 DepthStencilFormat
= GetStencilFormat(pDriverCaps
, DepthStencilFormat
);
569 /* Observe the multiple conditions */
570 for (FormatIndex
= 0; FormatIndex
< NumFormatOps
&& (bRenderTargetAvailable
== FALSE
|| bDepthStencilAvailable
== FALSE
); FormatIndex
++)
572 const LPDDSURFACEDESC pSurfaceDesc
= &pDriverCaps
->pSupportedFormatOps
[FormatIndex
];
573 const DWORD FourCC
= pSurfaceDesc
->ddpfPixelFormat
.dwFourCC
;
574 const DWORD FormatOperations
= pSurfaceDesc
->ddpfPixelFormat
.dwOperations
;
576 if (FALSE
== bRenderTargetAvailable
&&
577 FourCC
== RenderTargetFormat
&&
578 (FormatOperations
& D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
) != 0)
580 bRenderTargetAvailable
= TRUE
;
583 if (FALSE
== bDepthStencilAvailable
&&
584 FourCC
== DepthStencilFormat
&&
585 (FormatOperations
& D3DFORMAT_OP_ZSTENCIL
) != 0)
587 bDepthStencilAvailable
= TRUE
;
589 if ((FormatOperations
& D3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
) != 0)
591 bForceSameDepthStencilBits
= FALSE
;
596 if (FALSE
== bRenderTargetAvailable
|| FALSE
== bDepthStencilAvailable
)
598 return D3DERR_INVALIDCALL
;
601 if (TRUE
== bForceSameDepthStencilBits
)
603 if (GetPixelStride(RenderTargetFormat
) != GetPixelStride(DepthStencilFormat
))
604 return D3DERR_NOTAVAILABLE
;