Compare commits

..

6 Commits

Author SHA1 Message Date
Alibek Omarov
45d52fe242 Remove all vgui limitation because we switch to freevgui here 2026-08-04 02:41:48 +08:00
Andrey Akhmichin
ecda80fb9a Documentation: supported-mod-list.md: update. 2026-07-29 02:43:00 +05:00
Владислав Сухов
9f14c48787 3rdparty: mainui: update 2026-07-27 18:47:53 +04:00
Владислав Сухов
8b15bc9a96 3rdparty: mainui: update 2026-07-26 18:08:54 +05:00
Andrey Akhmichin
e6913c9ce2 Documentation: opensource-mods.md: update. 2026-07-26 08:24:34 +05:00
lewa_j
b4495238d9 3rdparty: gl4es: update from upstream, with msvc build fix 2026-07-25 17:33:13 +03:00
25 changed files with 148 additions and 3636 deletions

3
.gitmodules vendored
View File

@@ -46,3 +46,6 @@
[submodule "3rdparty/mbedtls/mbedtls"]
path = 3rdparty/mbedtls/mbedtls
url = https://github.com/FWGS/mbedtls-releases.git
[submodule "3rdparty/freevgui"]
path = 3rdparty/freevgui
url = https://github.com/FWGS/freevgui.git

1
3rdparty/freevgui vendored Submodule

Submodule 3rdparty/freevgui added at 8bf71dba02

View File

@@ -38,6 +38,9 @@ Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir
## Counter-Life
Available on ModDB - https://www.moddb.com/mods/counter-life/downloads/cl-version-1-source-code
## Crack-Life Anniversary Campaign
Available on ModDB - https://www.moddb.com/mods/crack-life/downloads/crack-life-anniversary-campaign-sdk
## Cthulhu
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK
@@ -85,12 +88,21 @@ Available on ModDB - https://www.moddb.com/mods/half-life-echoes
## Half-Life: Expanded Arsenal
Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal
## Half-Life: Featureful
Branch **featureful** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful
## Half-Life: Field Intensity
Branch **field_intensity_1.7** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/field_intensity_1.7
## Half-Life: Gravgun mod
Branch **gravgun** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/gravgun
## Half-Life: Induction
Version 1.4: Branch **induction** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/induction
## Half-Life: Insecure
Version 1.5 is available on ModDB - https://www.moddb.com/mods/half-life-insecure/downloads/half-life-insecure-map-tools-and-source-code-ver-15
## Half-Life: Invasion
Official github repository - https://github.com/jlecorre/hlinvasion
@@ -109,6 +121,9 @@ Official github repository - https://github.com/Fograin/hl-subsmod-ex
## Half-Life: Rally
Official gitlab repository - https://gitlab.com/hlrally/src
## Half-Life: Reprocessing
Official github repository - https://github.com/EgorYak/ReprocessingSourceCode
## Half-Life: RXT
Available on ModDB - https://www.moddb.com/mods/half-life-rxt/downloads/rxt-source-code-v57
@@ -147,6 +162,9 @@ Mirrored on github (Includes maps and models source files) - https://github.com/
## Ingram Chillin' Mod
Official SourceForge repository - https://sourceforge.net/projects/icm-hl/
## Intense Force
Branch **intense_force** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/intense_force
## Master Sword
Official github repository of Master Sword Classic - https://github.com/BerntA/MasterSwordClassic
@@ -189,6 +207,9 @@ Available in Valve's Half-Life repository - https://github.com/ValveSoftware/hal
## Spirit of Half-Life
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
## The Last Bullet
Official github repository - https://github.com/GT-Project-Cat/The-Last-Bullet-Updated-Code
## The Wastes
Version 1.5: mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-thewastes-sdk
@@ -212,6 +233,19 @@ Download page on official site - http://www.thothie.com/ww/
## Wrong Door
Available on ModDB - https://www.moddb.com/mods/wrong-door/downloads/wrong-door-sdk
## XDM
*This mod is opensource but access to source code is always rebus*
How to get sources of version 3.0.4.3:
Download SFX-archive from ModDB - https://www.moddb.com/mods/xdm/downloads/xdm3043
Extract it.
Open client.dll in HEX-editor and patch header - change `Win!` to `Rar!`
Extract it using unrar - password `iamtheone`
## XashXT
Mirrored on github - https://github.com/a1batross/XashXT_original
@@ -301,7 +335,7 @@ Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
Reverse-engineered code: branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
## Half-Life: Induction
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction
Version 1.0-1.2: Branch **induction_1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction_1.2
## Half-Life: Opposing Force
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
@@ -375,6 +409,9 @@ Branch **aghl** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/
## Bubblemod
Branch **bubblemod** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bubblemod
## Counter-Life
Branch **counter-life** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/counter-life
## Deathmatch Classic
Deathmatch Classic: Adrenaline Gamer Edition - https://github.com/martinwebrant/agmod/tree/master/src/dmc
@@ -388,6 +425,9 @@ Branch **delta_particles** in hlsdk-portable - https://github.com/FWGS/hlsdk-por
## Half-Life: Echoes
Branch **echoes** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/echoes
## Half-Life: Insecure
Branch **insecure** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/insecure
## Half-Life: Invasion
Port to HLSDK 2.4 by malortie - https://github.com/HL1-Mods-Reimplementations-and-Ports/hl-invasion
@@ -423,4 +463,3 @@ Branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tr
## Zombie-X
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x

View File

@@ -892,6 +892,8 @@ Currently, fresh Xash3D FWGS builds for Android, PS Vita and Nintendo Switch use
## List of games and mods with custom gamedll
For mods from this category - first of all place mod folder beside **valve** folder.
NOTE: Precompiled libraries for some mods from this category may be already available for your platform in [hlsdk-mega-build](https://github.com/FWGS/hlsdk-mega-build) and this mods may be launch on Android out-of-the-box.
1. **[Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)**
To run this mod on specific platforms you may be need to compile libraries from **redemption** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
@@ -950,7 +952,11 @@ This mod already supports x86 Linux.
Support for other platforms may be available later.
14. **[Counter Strike 1.6](https://store.steampowered.com/app/10/CounterStrike/)**
14. **[Counter-Life](https://www.moddb.com/mods/counter-life)**
To run this mod on specific platforms you may be need to compile libraries from **counter-life** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
15. **[Counter Strike 1.6](https://store.steampowered.com/app/10/CounterStrike/)**
On x86 you may be need to compile client part.
@@ -962,57 +968,65 @@ Client: https://github.com/Velaron/cs16-client/
Server: https://github.com/rehlds/ReGameDLL_CS
15. **[Crack-Life](https://www.moddb.com/mods/crack-life/downloads/crack-life)**
16. **[Crack-Life](https://www.moddb.com/mods/crack-life/downloads/crack-life)**
To run this mod on specific platforms you may be need to compile libraries from **cracklife** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
16. **[Crack-Life: Campaign Mode](https://www.moddb.com/mods/crack-life/downloads/crack-life-campaign-mode)**
17. **[Crack-Life: Campaign Mode](https://www.moddb.com/mods/crack-life/downloads/crack-life-campaign-mode)**
To run this mod on specific platforms you may be need to compile libraries from **clcampaign** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
17. **[Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)**
18. **[Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)**
Steam version already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
18. **[Delta Particles](https://www.moddb.com/mods/half-life-delta)**
19. **[Delta Particles](https://www.moddb.com/mods/half-life-delta)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
To run this mod on specific platforms you may be need to compile libraries from **delta_particles** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
19. **[Escape from the Darkness](https://www.moddb.com/mods/escape-from-the-darkness)**
20. **[Escape from the Darkness](https://www.moddb.com/mods/escape-from-the-darkness)**
To run this mod on specific platforms you may be need to compile libraries from **eftd** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
20. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
21. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
21. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
22. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
To run this mod on specific platforms you may be need to compile libraries from **bshift** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
22. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
23. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
Currently, you can compile mod libraries for x86 Linux from **decay-pc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Support for other platforms may be available later.
23. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
24. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
To run this mod on specific platforms you may be need to compile libraries from **echoes** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
24. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
25. [Half-Life: Featureful](https://freeslave.github.io/halflife-featureful/)
*It's modding SDK*
This mod already supports x86 Linux.
Support for other platforms may be available later.
To run this mod on specific platforms you may be need to compile libraries from **featureful** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
25. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
26. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
This mod already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **field_intensity_1.7** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
27. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
*Support temporary abandoned*
@@ -1022,163 +1036,183 @@ Currently, MSVC is not supported, use MinGW if you need build for Windows.
Mod files: [1](http://mittorn.fwgs.ru/coop-entpatches/), [2](http://mittorn.fwgs.ru/ggm/), [3](https://github.com/nillerusr/gravgun-extras).
26. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
28. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
To run this mod on specific platforms you may be need to compile libraries from **induction_1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
27. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
29. **[Half-Life: Induction 1.4](https://www.moddb.com/mods/half-life-induction)**
This mod supports x86 Linux.
This mod already supports x86 Linux.
Support for other platforms may be available later.
To run this mod on specific platforms you may be need to compile libraries from **induction** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
28. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
30. **[Half-Life: Insecure](https://www.moddb.com/mods/half-life-insecure)**
To run this mod on specific platforms you may be need to compile libraries from **insecure** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
31. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
This mod already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **intense_force** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
29. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
32. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
This mod supports x86 Linux.
Support for other platforms may be available later.
33. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
Steam version already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **opfor** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
30. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
34. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
To run this mod on specific platforms you may be need to compile libraries from **sci** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
31. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
35. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
To run this mod on specific platforms you may be need to compile libraries from **topdown** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
32. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
36. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
To run this mod on specific platforms you may be need to compile libraries from **hl_urbicide** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
33. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
37. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
To run this mod on specific platforms you may be need to compile libraries from **visitors** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
34. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
38. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
35. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
39. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
To run this mod on specific platforms you may be need to compile libraries from **half-screwed** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
36. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
40. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
To run this mod on specific platforms you may be need to compile libraries from **half-secret** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
37. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
41. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
38. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
42. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
To run this mod on specific platforms you may be need to compile libraries from **noffice** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
39. **[Paranoia](https://www.moddb.com/mods/paranoia)**
43. **[Paranoia](https://www.moddb.com/mods/paranoia)**
*Support temporary abandoned*
[Source code](https://github.com/FWGS/paranoia_toolkit).
40. **[Poke646](https://poke646.com/)**
44. **[Poke646](https://poke646.com/)**
To run this mod on specific platforms you may be need to compile libraries from **poke646** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
41. **[Poke646: Vendetta](https://poke646.com/)**
45. **[Poke646: Vendetta](https://poke646.com/)**
To run this mod on specific platforms you may be need to compile libraries from **poke646_vendetta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
42. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
46. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
*It's modding SDK*
[Source code](https://github.com/SNMetamorph/PrimeXT)
43. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
47. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
*Support was fully abandoned due Quake Wrapper release.*
[Actual source code](https://github.com/FWGS/quakeremake)
44. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
48. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
To run this mod on specific platforms you may be need to compile libraries from **rebellion** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
45. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
49. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
46. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
50. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
47. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
51. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
48. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
52. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
To run this mod on specific platforms you may be need to compile libraries from **sewer_beta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
49. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
53. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
*It's modding SDK*
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
50. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
54. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
To run this mod on specific platforms you may be need to compile libraries from **halloween** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
51. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
55. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
This mod already supports x86 Linux.
Currently, only source code of [client part](https://github.com/Velaron/tf15-client) is available.
52. **[The Gate](https://www.moddb.com/mods/the-gate)**
56. **[The Gate](https://www.moddb.com/mods/the-gate)**
To run this mod on specific platforms you may be need to compile libraries from **thegate** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
53. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
57. **[The Last Bullet](https://www.moddb.com/mods/the-last-bullet-update)**
To run this mod on specific platforms you may be need to compile libraries from **fwgs** branch of [The-Last-Bullet-Updated-Code](https://github.com/GT-Project-Cat/The-Last-Bullet-Updated-Code).
58. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
To run this mod on specific platforms you may be need to compile libraries from **theyhunger** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
54. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
59. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
55. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
60. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
To run this mod on specific platforms you may be need to compile libraries from **tot** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
56. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
61. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
*It's modding SDK*
*Support was fully abandoned due PrimeXT development*
[Source code](https://github.com/FWGS/XashXT-FWGS/)
57. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
62. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
58. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
63. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Don't forget to enable XENWARRIOR build option!!!
59. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
64. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
To run this mod on specific platforms you may be need to compile libraries from **zombie-x** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).

View File

@@ -706,9 +706,6 @@ static void R_CollectRendererNames( void )
#if XASH_REF_GLES3COMPAT_ENABLED
"gles3compat",
#endif
#if XASH_REF_DX2_ENABLED
"dx2",
#endif
#if XASH_REF_SOFT_ENABLED
"soft",
#endif
@@ -732,9 +729,6 @@ static void R_CollectRendererNames( void )
#if XASH_REF_GLES3COMPAT_ENABLED
"GLES3 (gl2_shim)",
#endif
#if XASH_REF_DX2_ENABLED
"DirectX 2",
#endif
#if XASH_REF_SOFT_ENABLED
"Software",
#endif

View File

@@ -28,7 +28,7 @@ typedef struct
{
void *context; // handle to GL rendering context
ref_safegl_context_t safe;
ref_graphic_apis_t type;
qboolean software;
} glwstate_t;
extern glwstate_t glw_state;

View File

@@ -285,7 +285,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
if( window_mode != WINDOW_MODE_WINDOWED )
SetBits( flags, SDL_FULLSCREEN|SDL_HWSURFACE );
if( glw_state.type == REF_GL )
if( !glw_state.software )
SetBits( flags, SDL_OPENGL );
if( !VID_CreateWindowWithSafeGL( wndname, 0, 0, width, height, flags ))
@@ -381,10 +381,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
refState.desktopBitsPixel = 16;
glw_state.type = type;
switch( type )
{
case REF_SOFTWARE:
glw_state.software = true;
break;
case REF_GL:
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
@@ -399,8 +399,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
return false;
}
break;
case REF_D3D:
break;
default:
Host_Error( "Can't initialize unknown context type %d!\n", type );
break;
@@ -419,7 +417,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
ref.dllFuncs.GL_InitExtensions();
break;
case REF_SOFTWARE:
case REF_D3D:
default:
break;
}

View File

@@ -359,7 +359,7 @@ void GL_UpdateSwapInterval( void )
{
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
if( glw_state.context && SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
if( SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ));
}
}
@@ -386,7 +386,7 @@ static void VID_GetWindowSizeInPixels( SDL_Window *window, SDL_Renderer *rendere
#if SDL_VERSION_ATLEAST( 2, 26, 0 )
SDL_GetWindowSizeInPixels( window, w, h );
#else
if( glw_state.type != REF_GL )
if( glw_state.software )
SDL_GetRendererOutputSize( renderer, w, h );
else
SDL_GL_GetDrawableSize( window, w, h );
@@ -669,7 +669,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
SetBits( flags, SDL_WINDOW_ALLOW_HIGHDPI );
#endif // !XASH_WIN32
if( glw_state.type == REF_GL )
if( !glw_state.software )
SetBits( flags, SDL_WINDOW_OPENGL );
if( vid_maximized.value )
@@ -681,7 +681,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
if( !host.hWnd )
{
err = (glw_state.type == REF_GL) ? rserr_invalid_context : rserr_unknown;
err = glw_state.software ? rserr_unknown : rserr_invalid_context;
goto cleanup;
}
@@ -698,7 +698,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
SDL_ShowWindow( host.hWnd );
SDL_RaiseWindow( host.hWnd );
if( glw_state.type == REF_SOFTWARE )
if( glw_state.software )
{
char cmd[64];
@@ -720,7 +720,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
Con_Printf( "SDL_Renderer %s initialized\n", info.name );
}
}
else if( glw_state.type == REF_GL )
else
{
glw_state.context = SDL_GL_CreateContext( host.hWnd );
@@ -917,10 +917,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
SDL_SetHint( SDL_HINT_VIDEO_X11_XRANDR, "1" );
SDL_SetHint( SDL_HINT_VIDEO_X11_XVIDMODE, "1" );
glw_state.type = type;
switch( type )
{
case REF_SOFTWARE:
glw_state.software = true;
break;
case REF_GL:
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
@@ -935,8 +935,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
return false;
}
break;
case REF_D3D:
break;
default:
Host_Error( "Can't initialize unknown context type %d!\n", type );
break;
@@ -952,7 +950,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
ref.dllFuncs.GL_InitExtensions();
break;
case REF_SOFTWARE:
case REF_D3D:
default:
break;
}

View File

@@ -113,7 +113,7 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height,
SDL_Rect rect = { SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, input_width, input_height };
Uint32 flags = SDL_WINDOW_RESIZABLE;
if( glw_state.type == REF_GL )
if( !glw_state.software )
SetBits( flags, SDL_WINDOW_OPENGL );
// probe true fullscreen first, if it fails, try borderless next
@@ -168,12 +168,12 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height,
VID_SetWindowIcon( host.hWnd );
if( glw_state.type == REF_SOFTWARE )
if( glw_state.software )
{
// no support yet
return false;
}
else if ( glw_state.type == REF_GL )
else
{
glw_state.context = SDL_GL_CreateContext( host.hWnd );
@@ -337,10 +337,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
if( Sys_CheckParm( "-egl" ))
Con_Printf( S_WARN "%s: -egl option is deprecated\n", __func__ );
glw_state.type = type;
switch( type )
{
case REF_SOFTWARE:
glw_state.software = true;
break;
case REF_GL:
{
@@ -357,8 +357,6 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
break;
}
case REF_D3D:
break;
default:
Host_Error( "Can't initialize unknown context type %d!\n", type );
break;

View File

@@ -1,19 +0,0 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "windows.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@@ -1,481 +0,0 @@
/*
r_context.c -- dx2 renderer context
Copyright (C) 2023-2024 a1batross
Copyright (C) 2025-2026 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#define INITGUID
#include "r_local.h"
#include "xash3d_mathlib.h"
#include "crtlib.h"
#include "r_studioint.h"
//#pragma comment(lib, "ddraw.lib")
//TODO COM_GetProcAddress
static void R_SimpleStub( void )
{
;
}
static void R_SimpleStubInt( int unused )
{
;
}
static void R_SimpleStubUInt( unsigned int unused )
{
;
}
static const char *R_GetConfigName( void )
{
return "ref_dx2";
}
static qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y )
{
qboolean ret = true;
tr.rotation = rotate;
if( offset_x || offset_y )
{
gEngfuncs.Con_Printf("offset transform not supported\n");
ret = false;
}
if( scale_x != 1.0f || scale_y != 1.0f )
{
gEngfuncs.Con_Printf("scale transform not supported\n");
ret = false;
}
return ret;
}
void GL_BackendStartFrame( void )
{
}
void GL_BackendEndFrame( void )
{
}
void GL_SetRenderMode( int mode )
{
dxc.renderMode = mode;
}
static void R_ProcessEntData( qboolean allocate, cl_entity_t *entities, unsigned int max_entities )
{
if (!allocate)
{
tr.draw_list->num_solid_entities = 0;
tr.draw_list->num_trans_entities = 0;
tr.draw_list->num_beam_entities = 0;
tr.max_entities = 0;
tr.entities = NULL;
}
else
{
tr.max_entities = max_entities;
tr.entities = entities;
}
if (gEngfuncs.drawFuncs->R_ProcessEntData)
gEngfuncs.drawFuncs->R_ProcessEntData(allocate);
}
static void R_SetupSky( int *skytextures )
{
;
}
static qboolean VID_ScreenShot( const char *filename, int shot_type )
{
return false;
}
static qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot )
{
return false;
}
static colorVec R_LightPoint( const float *p )
{
colorVec c = { 0 };
return c;
}
static void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale )
{
;
}
static int R_CreateDecalList( struct decallist_s *pList )
{
return 0;
}
static float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc, double time )
{
return 0.0f;
}
static void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles )
{
;
}
static qboolean R_StudioFillAPI( struct engine_studio_api_s *api, struct r_studio_interface_s *pDefaultDraw )
{
return false;
}
static r_studio_interface_t *pStudioDraw;
static void R_StudioSetDrawInterface( struct r_studio_interface_s *pDraw )
{
pStudioDraw = pDraw;
}
static void R_SetSkyCloudsTextures( int solidskyTexture, int alphaskyTexture )
{
;
}
static void CL_RunLightStyles( lightstyle_t *ls )
{
}
static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buffer, size_t buffersize )
{
gEngfuncs.Con_Printf("Mod_ProcessRenderData(%p(%s), %d, %p, %zu)\n", mod, mod->name, create, buffer, buffersize);
return true;
}
static void Mod_StudioLoadTextures( model_t *mod, void *data )
{
;
}
static void CL_DrawParticles( double frametime, particle_t *particles, float partsize )
{
;
}
static void CL_DrawTracers( double frametime, particle_t *tracers )
{
;
}
static void CL_DrawBeams( int fTrans, BEAM *beams )
{
;
}
static intptr_t RefGetParm( int parm, int arg )
{
dx_texture_t *glt;
switch (parm)
{
case PARM_TEX_WIDTH:
glt = R_GetTexture(arg);
return glt->width;
case PARM_TEX_HEIGHT:
glt = R_GetTexture(arg);
return glt->height;
case PARM_TEX_SRC_WIDTH:
glt = R_GetTexture(arg);
return glt->srcWidth;
case PARM_TEX_SRC_HEIGHT:
glt = R_GetTexture(arg);
return glt->srcHeight;
case PARM_TEX_GLFORMAT:
glt = R_GetTexture(arg);
return 0;
case PARM_TEX_ENCODE:
glt = R_GetTexture(arg);
return 0;
case PARM_TEX_MIPCOUNT:
glt = R_GetTexture(arg);
return glt->numMips;
case PARM_TEX_DEPTH:
glt = R_GetTexture(arg);
return 1;
#if 0
case PARM_TEX_SKYBOX:
Assert(arg >= 0 && arg < 6);
return tr.skyboxTextures[arg];
#endif
case PARM_TEX_SKYTEXNUM:
return tr.skytexturenum;
#if 0
case PARM_TEX_LIGHTMAP:
arg = bound(0, arg, MAX_LIGHTMAPS - 1);
return tr.lightmapTextures[arg];
#endif
case PARM_TEX_TARGET:
glt = R_GetTexture(arg);
return 0;
case PARM_TEX_TEXNUM:
glt = R_GetTexture(arg);
return arg;
case PARM_TEX_FLAGS:
glt = R_GetTexture(arg);
return glt->flags;
#if 0
case PARM_TEX_MEMORY:
return GL_TexMemory();
case PARM_ACTIVE_TMU:
return glState.activeTMU;
#endif
case PARM_LIGHTSTYLEVALUE:
arg = bound(0, arg, MAX_LIGHTSTYLES - 1);
return g_lightstylevalue[arg];
#if 0
case PARM_MAX_IMAGE_UNITS:
return GL_MaxTextureUnits();
case PARM_REBUILD_GAMMA:
return glConfig.softwareGammaUpdate;
case PARM_GL_CONTEXT_TYPE:
return glConfig.context;
case PARM_GLES_WRAPPER:
return glConfig.wrapper;
#endif
case PARM_STENCIL_ACTIVE:
return 0;//No stencil in dx2
case PARM_TEX_FILTERING:
return 0;
#if 0
if (arg < 0)
return gl_texture_nearest.value == 0.0f;
return GL_TextureFilteringEnabled(R_GetTexture(arg));
#endif
case PARM_GET_STUDIO_HDR:
//return (intptr_t)R_StudioGetHeader();
return 0;
default:
return (*gEngfuncs.EngineGetParm)(parm, arg);
}
return 0;
}
void GL_Bind( int tmu, unsigned int texnum )
{
const dx_texture_t *texture;
// missed or invalid texture?
if( texnum <= 0 || texnum >= MAX_TEXTURES )
{
if( texnum != 0 )
gEngfuncs.Con_DPrintf( S_ERROR "%s: invalid texturenum %d\n", __func__, texnum );
texnum = tr.defaultTexture;
}
texture = R_GetTexture( texnum );
//if( dxc.currentTexture == texture->d3dHandle )
// return;
dxc.currentTexture = texture->d3dHandle;
}
static qboolean R_SpeedsMessage( char *out, size_t size )
{
return false;
}
static void R_NewMap( void )
{
tr.worldmodel = gp_cl->models[1];
// clear out efrags in case the level hasn't been reloaded
for( int i = 0; i < tr.worldmodel->numleafs; i++ )
tr.worldmodel->leafs[i+1].efrags = NULL;
tr.skytexturenum = -1;
// clearing texture chains
for( int i = 0; i < tr.worldmodel->numtextures; i++ )
{
if( !tr.worldmodel->textures[i] )
continue;
texture_t *tx = tr.worldmodel->textures[i];
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 ))
tr.skytexturenum = i;
tx->texturechain = NULL;
}
GL_BuildLightmaps();
if( gEngfuncs.drawFuncs->R_NewMap != NULL )
gEngfuncs.drawFuncs->R_NewMap();
}
static void Color4f( float r, float g, float b, float a )
{
Vector4Set(dxc.currentColor, r, g, b, a);
}
static void Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
{
Vector4Set(dxc.currentColor, r/255.f, g/255.f, b/255.f, a/255.f);
}
static void Vertex3fv( const float *worldPnt )
{
;
}
static void Vertex3f( float x, float y, float z )
{
;
}
static void CullFace( TRICULLSTYLE mode )
{
;
}
static void VGUI_SetupDrawing( qboolean rect )
{
;
}
static void R_FillRenderAPI( render_api_t *api )
{
;
}
static void R_FillTriAPI( triangleapi_t *api )
{
;
}
const ref_interface_t gReffuncs =
{
.R_Init = R_Init,
.R_Shutdown = R_Shutdown,
.R_GetConfigName = R_GetConfigName,
.R_SetDisplayTransform = R_SetDisplayTransform,
.GL_SetupAttributes = GL_SetupAttributes,
.GL_InitExtensions = GL_InitExtensions,
.GL_ClearExtensions = GL_ClearExtensions,
.R_GammaChanged = R_GammaChanged,
.R_BeginFrame = R_BeginFrame,
.R_RenderScene = R_RenderScene,
.R_EndFrame = R_EndFrame,
.R_PushScene = R_SimpleStub,
.R_PopScene = R_SimpleStub,
.GL_BackendStartFrame = GL_BackendStartFrame,
.GL_BackendEndFrame = GL_BackendEndFrame,
.R_ClearScreen = R_SimpleStub,
.R_AllowFog = R_AllowFog,
.GL_SetRenderMode = GL_SetRenderMode,
.R_AddEntity = R_AddEntity,
.R_ProcessEntData = R_ProcessEntData,
.R_ShowTextures = R_ShowTextures,
.R_GetTextureOriginalBuffer = R_GetTextureOriginalBuffer,
.GL_LoadTextureFromBuffer = GL_LoadTextureFromBuffer,
.GL_ProcessTexture = GL_ProcessTexture,
.R_SetupSky = R_SetupSky,
.R_Set2DMode = R_Set2DMode,
.R_DrawStretchPic = R_DrawStretchPic,
.FillRGBA = FillRGBA,
.WorldToScreen = WorldToScreen,
.VID_ScreenShot = VID_ScreenShot,
.VID_CubemapShot = VID_CubemapShot,
.R_LightPoint = R_LightPoint,
.R_DecalShoot = R_DecalShoot,
.R_DecalRemoveAll = R_SimpleStubInt,
.R_CreateDecalList = R_CreateDecalList,
.R_ClearAllDecals = R_SimpleStub,
.R_StudioEstimateFrame = R_StudioEstimateFrame,
.R_StudioLerpMovement = R_StudioLerpMovement,
.R_StudioFillAPI = R_StudioFillAPI,
.R_StudioSetDrawInterface = R_StudioSetDrawInterface,
.R_SetSkyCloudsTextures = R_SetSkyCloudsTextures,
.GL_SubdivideSurface = GL_SubdivideSurface,
.CL_RunLightStyles = CL_RunLightStyles,
.Mod_ProcessRenderData = Mod_ProcessRenderData,
.Mod_StudioLoadTextures = Mod_StudioLoadTextures,
.CL_DrawParticles = CL_DrawParticles,
.CL_DrawTracers = CL_DrawTracers,
.CL_DrawBeams = CL_DrawBeams,
.RefGetParm = RefGetParm,
.R_GetDetailScaleForTexture = R_GetDetailScaleForTexture,
.R_SetDetailScaleForTexture = R_SetDetailScaleForTexture,
.GL_CreateTexture = GL_CreateTexture,
.GL_FindTexture = GL_FindTexture,
.GL_TextureName = GL_TextureName,
.GL_TextureData = GL_TextureData,
.GL_LoadTexture = GL_LoadTexture,
.GL_FreeTexture = GL_FreeTexture,
.R_OverrideTextureSourceSize = R_OverrideTextureSourceSize,
.GL_UpdateTexture = GL_UpdateTexture,
.GL_Bind = GL_Bind,
.GL_RenderFrame = R_RenderFrame,
.GL_OrthoBounds = GL_OrthoBounds,
.R_SpeedsMessage = R_SpeedsMessage,
.Mod_GetCurrentVis = Mod_GetCurrentVis,
.R_NewMap = R_NewMap,
.R_ClearScene = R_ClearScene,
.TriRenderMode = R_SimpleStubInt,
.Begin = R_SimpleStubInt,
.End = R_SimpleStub,
.Color4f = Color4f,
.Color4ub = Color4ub,
.Vertex3fv = Vertex3fv,
.Vertex3f = Vertex3f,
.CullFace = CullFace,
.R_FillRenderAPI = R_FillRenderAPI,
.R_FillTriAPI = R_FillTriAPI,
.VGUI_SetupDrawing = VGUI_SetupDrawing,
};

View File

@@ -1,559 +0,0 @@
/*
r_d3d.c -- dx2 renderer d3d related code
Copyright (C) 2025-2026 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "r_local.h"
#include "xash3d_mathlib.h"
CVAR_DEFINE_AUTO( r_novis, "0", 0, "ignore vis information (perfomance test)" );
CVAR_DEFINE_AUTO( r_nocull, "0", 0, "ignore frustrum culling (perfomance test)" );
CVAR_DEFINE_AUTO( r_lockpvs, "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" );
CVAR_DEFINE_AUTO( r_lockfrustum, "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
dx_globals_t tr;
dx_context_t dxc;
const char *dxResultToStr( HRESULT r )
{
if( r == DD_OK )
return "DD_OK";
if( r == DDERR_INVALIDPARAMS )
return "DDERR_INVALIDPARAMS";
if( r == DDERR_INVALIDOBJECT )
return "DDERR_INVALIDOBJECT";
if( r == DDERR_UNSUPPORTED )
return "DDERR_UNSUPPORTED";
if( r == DDERR_NOCOOPERATIVELEVELSET )
return "DDERR_NOCOOPERATIVELEVELSET";
if( r == DDERR_INVALIDCAPS )
return "DDERR_INVALIDCAPS";
if( r == DDERR_INCOMPATIBLEPRIMARY )
return "DDERR_INCOMPATIBLEPRIMARY";
if( r == DDERR_NOEXCLUSIVEMODE )
return "DDERR_NOEXCLUSIVEMODE";
if( r == DDERR_NOFLIPHW )
return "DDERR_NOFLIPHW";
if( r == DDERR_OUTOFVIDEOMEMORY )
return "DDERR_OUTOFVIDEOMEMORY";
if( r == DDERR_PRIMARYSURFACEALREADYEXISTS )
return "DDERR_PRIMARYSURFACEALREADYEXISTS";
if( r == DDERR_UNSUPPORTEDMODE )
return "DDERR_UNSUPPORTEDMODE";
if( r == DDERR_NOTFOUND )
return "DDERR_NOTFOUND";
if( r == DDERR_INVALIDRECT )
return "DDERR_INVALIDRECT";
if( r == D3DERR_VIEWPORTDATANOTSET )
return "D3DERR_VIEWPORTDATANOTSET";
if( r == D3DERR_VIEWPORTHASNODEVICE )
return "D3DERR_VIEWPORTHASNODEVICE";
if( r == D3DERR_SURFACENOTINVIDMEM )
return "D3DERR_SURFACENOTINVIDMEM";
return "UNKNOWN";
}
static qboolean DD_CreatePrimarySurface( void )
{
DDSURFACEDESC ddsd = { 0 };
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsPrimary, NULL));
printf("IDirectDraw::CreateSurface(PRIMARY) %p\n", dxc.pddsPrimary);
if (!dxc.pddsPrimary)
return false;
DXCheck(IDirectDraw_CreateClipper(dxc.pdd, 0, &dxc.pddClipper, NULL));
gEngfuncs.Con_Printf("IDirectDraw::CreateClipper %p\n", dxc.pddClipper);
if (!dxc.pddClipper)
return false;
DXCheck(IDirectDrawClipper_SetHWnd(dxc.pddClipper, 0, dxc.window));
DXCheck(IDirectDrawSurface_SetClipper(dxc.pddsPrimary, dxc.pddClipper));
return true;
}
static qboolean DD_CreateBackSurface( void )
{
DDCAPS ddcaps =
{
.dwSize = sizeof(ddcaps)
};
DDCAPS helcaps =
{
.dwSize = sizeof(helcaps)
};
DXCheck(IDirectDraw_GetCaps(dxc.pdd, &ddcaps, &helcaps));
gEngfuncs.Con_Printf("IDirectDraw::GetCaps\n");
gEngfuncs.Con_Printf("ZBUFFER: %s\n", (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) ? "- ^2enabled" : "- ^1failed");
if (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
gEngfuncs.Con_Printf("ZBufferBitDepths: 0x%X\n", ddcaps.dwZBufferBitDepths);
if (helcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
gEngfuncs.Con_Printf("HEL ZBufferBitDepths: 0x%X\n", helcaps.dwZBufferBitDepths);
DDSURFACEDESC ddsd = { 0 };
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth = dxc.windowWidth;
ddsd.dwHeight = dxc.windowHeight;
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsBack, NULL));
gEngfuncs.Con_Printf("IDirectDraw::CreateSurface(BACK) %p\n", dxc.pddsBack);
if (!dxc.pddsBack)
return false;
DXCheck(IDirectDraw_CreateClipper(dxc.pdd, 0, &dxc.pddBackClipper, NULL));
gEngfuncs.Con_Printf("IDirectDraw::CreateClipper(BACK) %p\n", dxc.pddBackClipper);
if (!dxc.pddBackClipper)
return false;
struct region_t
{
RGNDATAHEADER rdh;
RECT rect;
} region;
region.rdh.dwSize = sizeof(region.rdh);
region.rdh.iType = RDH_RECTANGLES;
region.rdh.nCount = 1;
region.rdh.nRgnSize = sizeof(RECT);
region.rdh.rcBound.left = 0;
region.rdh.rcBound.top = 0;
region.rdh.rcBound.right = dxc.windowWidth;
region.rdh.rcBound.bottom = dxc.windowHeight;
memcpy(&region.rect, &region.rdh.rcBound, sizeof(region.rdh.rcBound));
DXCheck(IDirectDrawClipper_SetClipList(dxc.pddBackClipper, (RGNDATA *)&region, 0));
DXCheck(IDirectDrawSurface_SetClipper(dxc.pddsBack, dxc.pddBackClipper));
int bitDepths = ddcaps.dwZBufferBitDepths;
if (!bitDepths)
bitDepths = helcaps.dwZBufferBitDepths;
if( (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && bitDepths )
{
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth = dxc.windowWidth;
ddsd.dwHeight = dxc.windowHeight;
ddsd.dwZBufferBitDepth = 16;
if(bitDepths & DDBD_16 )
ddsd.dwZBufferBitDepth = 16;
else if(bitDepths & DDBD_24 )
ddsd.dwZBufferBitDepth = 24;
else if(bitDepths & DDBD_32 )
ddsd.dwZBufferBitDepth = 32;
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsZBuffer, NULL));
gEngfuncs.Con_Printf("IDirectDraw::CreateSurface(ZBUFFER %dbit) %p\n", ddsd.dwZBufferBitDepth, dxc.pddsZBuffer);
if( !dxc.pddsZBuffer )
return false;
DXCheck(IDirectDrawSurface_AddAttachedSurface(dxc.pddsBack, dxc.pddsZBuffer));
}
return true;
}
static qboolean D3D_Init( void )
{
DXCheck(IDirectDraw_QueryInterface(dxc.pdd, &IID_IDirect3D, (void**)&dxc.pd3d));
gEngfuncs.Con_Printf("IDirectDraw::QueryInterface(IID_IDirect3D) %p\n", dxc.pd3d);
if( !dxc.pd3d )
return false;
DXCheck(IDirect3D_CreateViewport(dxc.pd3d, &dxc.viewport, NULL));
gEngfuncs.Con_Printf("IDirect3D::CreateViewport %p\n", dxc.viewport);
if( !dxc.viewport )
return false;
return true;
}
static qboolean D3D_InitDevice( void )
{
if( !dxc.pd3d )
return false;
D3DFINDDEVICESEARCH search = { 0 };
memset(&search, 0, sizeof(search));
search.dwSize = sizeof(search);
search.dwFlags = D3DFDS_COLORMODEL;
search.dcmColorModel = D3DCOLOR_RGB;
#if 0
search.dwFlags |= D3DFDS_HARDWARE;
search.bHardware = FALSE;
#endif
D3DFINDDEVICERESULT result = { 0 };
memset(&result, 0, sizeof(result));
result.dwSize = sizeof(result);
DXCheck(IDirect3D_FindDevice(dxc.pd3d, &search, &result));
DXCheck(IDirectDrawSurface_QueryInterface(dxc.pddsBack, &result.guid, (void**)&dxc.pd3dd));
gEngfuncs.Con_Printf("IDirectDrawSurface::QueryInterface(IDirect3DDevice) %p\n", dxc.pd3dd);
gEngfuncs.Con_Printf("DeviceZBufferBitDepth: 0x%X\n", result.ddHwDesc.dwDeviceZBufferBitDepth);
gEngfuncs.Con_Printf("SW DeviceZBufferBitDepth: 0x%X\n", result.ddSwDesc.dwDeviceZBufferBitDepth);
if( !dxc.pd3dd )
return false;
D3DDEVICEDESC d3ddesc =
{
.dwSize = sizeof(d3ddesc)
};
D3DDEVICEDESC held3ddesc =
{
.dwSize = sizeof(held3ddesc)
};
DXCheck(IDirect3DDevice_GetCaps(dxc.pd3dd, &d3ddesc, &held3ddesc));
gEngfuncs.Con_Printf("IDirect3DDevice::GetCaps\n");
gEngfuncs.Con_Printf("DeviceZBufferBitDepth: 0x%X\n", result.ddHwDesc.dwDeviceZBufferBitDepth);
gEngfuncs.Con_Printf("HEL DeviceZBufferBitDepth: 0x%X\n", result.ddSwDesc.dwDeviceZBufferBitDepth);
D3DEXECUTEBUFFERDESC ebd = { 0 };
memset(&ebd, 0, sizeof(ebd));
ebd.dwSize = sizeof(ebd);
ebd.dwFlags = D3DDEB_BUFSIZE;
ebd.dwBufferSize = 1024 * 64;
DXCheck(IDirect3DDevice_CreateExecuteBuffer(dxc.pd3dd, &ebd, &dxc.pd3deb, NULL));
gEngfuncs.Con_Printf("IDirect3DDevice::CreateExecuteBuffer %p\n", dxc.pd3deb);
if (!dxc.pd3deb)
return false;
if (!dxc.viewport)
return false;
DXCheck(IDirect3DDevice_AddViewport(dxc.pd3dd, dxc.viewport));
DDSURFACEDESC desc = { 0 };
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
DXCheck(IDirectDrawSurface_GetSurfaceDesc(dxc.pddsBack, &desc));
D3DVIEWPORT viewport = { 0 };
viewport.dwSize = sizeof(viewport);
viewport.dwX = 0;
viewport.dwY = 0;
viewport.dwWidth = desc.dwWidth;
viewport.dwHeight = desc.dwHeight;
viewport.dvScaleX = 0.5 * viewport.dwWidth;
viewport.dvScaleY = 0.5f * viewport.dwHeight;
viewport.dvMaxX = 1;
viewport.dvMaxY = 1;
viewport.dvMinZ = 0;
viewport.dvMaxZ = 1;
DXCheck(IDirect3DViewport_SetViewport(dxc.viewport, &viewport));
DXCheck(IDirect3DDevice_CreateMatrix(dxc.pd3dd, &dxc.mtxWorld));
DXCheck(IDirect3DDevice_CreateMatrix(dxc.pd3dd, &dxc.mtxProjection));
//set transform state
{
d3dEBContext_t ebc = { 0 };
if (!D3D_StartExecuteBuffer(&ebc))
return false;
void *cur = ebc.data;
D3D_PutInstruction(&cur, D3DOP_STATETRANSFORM, sizeof(D3DSTATE), 2);
D3D_PutTransformState(&cur, D3DTRANSFORMSTATE_WORLD, dxc.mtxWorld);
D3D_PutTransformState(&cur, D3DTRANSFORMSTATE_PROJECTION, dxc.mtxProjection);
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, FALSE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, FALSE);
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
ebc.vertCount = 0;
ebc.insOffset = 0;
ebc.insLength = ((char *)cur - (char *)ebc.data);
if (!D3D_EndExecuteBuffer(&ebc))
return false;
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
D3D_ReleaseExecuteBuffer(&ebc);
}
return true;
}
qboolean R_Init( void )
{
memset(&dxc, 0, sizeof(dxc));
gEngfuncs.Cvar_RegisterVariable( &r_novis );
gEngfuncs.Cvar_RegisterVariable( &r_nocull );
gEngfuncs.Cvar_RegisterVariable( &r_lockpvs );
gEngfuncs.Cvar_RegisterVariable( &r_lockfrustum );
// init draw stack
tr.draw_list = &tr.draw_stack[0];
tr.draw_stack_pos = 0;
r_temppool = Mem_AllocPool("Render Zone");
// create the window
if (!gEngfuncs.R_Init_Video(REF_D3D))
{
Mem_FreePool(&r_temppool);
return false;
}
void *handle = NULL;
ref_window_type_t wt = gEngfuncs.R_GetWindowHandle( &handle, REF_WINDOW_TYPE_WIN32 );
gEngfuncs.Con_Printf( "R_Init: WindowHandle %p type %d\n", handle, wt );
if (wt != REF_WINDOW_TYPE_WIN32 || !handle)
{
Mem_FreePool(&r_temppool);
return false;
}
dxc.window = (HWND)handle;
RECT dstRect = { 0 };
GetClientRect(dxc.window, &dstRect);
dxc.windowWidth = dstRect.right - dstRect.left;
dxc.windowHeight = dstRect.bottom - dstRect.top;
DXCheck(DirectDrawCreate(NULL, &dxc.pdd, NULL));
gEngfuncs.Con_Reportf("DirectDrawCreate %p\n", dxc.pdd);
if (!dxc.pdd)
{
Mem_FreePool(&r_temppool);
return false;
}
DXCheck(IDirectDraw_SetCooperativeLevel(dxc.pdd, dxc.window, DDSCL_NORMAL));
if (!DD_CreatePrimarySurface())
{
Mem_FreePool(&r_temppool);
return false;
}
if (!DD_CreateBackSurface())
{
Mem_FreePool(&r_temppool);
return false;
}
if (!D3D_Init())
{
Mem_FreePool(&r_temppool);
return false;
}
if (!D3D_InitDevice())
{
Mem_FreePool(&r_temppool);
return false;
}
// see R_ProcessEntData for tr.entities initialization
tr.world = (struct world_static_s *)ENGINE_GET_PARM( PARM_GET_WORLD_PTR );
tr.viewent = (cl_entity_t *)ENGINE_GET_PARM( PARM_GET_VIEWENT_PTR );
dxc.renderMode = kRenderNormal;
Vector4Set(dxc.currentColor, 1, 1, 1, 1);
R_InitImages();
return true;
}
void R_Shutdown( void )
{
gEngfuncs.Con_Printf("ref: R_Shutdown()\n");
Mem_FreePool(&r_temppool);
gEngfuncs.R_Free_Video();
}
void D3D_Resize( int width, int height )
{
dxc.windowWidth = width;
dxc.windowHeight = height;
if( dxc.pd3deb )
IDirect3DExecuteBuffer_Release(dxc.pd3deb);
dxc.pd3deb = NULL;
if( dxc.pd3dd )
IDirect3DDevice_Release(dxc.pd3dd);
dxc.pd3dd = NULL;
if( dxc.pddsBack )
IDirectDrawSurface_Release(dxc.pddsBack);
dxc.pddsBack = NULL;
if( dxc.pddsZBuffer )
IDirectDrawSurface_Release(dxc.pddsZBuffer);
dxc.pddsZBuffer = NULL;
if( dxc.pddBackClipper )
IDirectDrawClipper_Release(dxc.pddBackClipper);
dxc.pddBackClipper = NULL;
if( DD_CreateBackSurface() )
{
if( D3D_InitDevice() )
{
}
}
}
void GL_SetupAttributes( int safegl )
{
;
}
void GL_InitExtensions( void )
{
tr.framecount = tr.visframecount = 1;
}
void GL_ClearExtensions( void )
{
;
}
#define DX2_CREATE_EB 0
qboolean D3D_StartExecuteBuffer( d3dEBContext_t *ctx )
{
#if DX2_CREATE_EB
ctx->pd3deb = NULL;
D3DEXECUTEBUFFERDESC ebd = { 0 };
memset(&ebd, 0, sizeof(ebd));
ebd.dwSize = sizeof(ebd);
ebd.dwFlags = D3DDEB_BUFSIZE;
ebd.dwBufferSize = 512;
DXCheck(IDirect3DDevice_CreateExecuteBuffer(dxc.pd3dd, &ebd, &ctx->pd3deb, NULL));
#else
ctx->pd3deb = dxc.pd3deb;
#endif
if (!ctx->pd3deb)
return false;
D3DEXECUTEBUFFERDESC ebDesc = { 0 };
memset(&ebDesc, 0, sizeof(ebDesc));
ebDesc.dwSize = sizeof(ebDesc);
ebDesc.dwFlags = D3DDEB_LPDATA;
HRESULT r = D3D_OK;
DXCheckRet(r, IDirect3DExecuteBuffer_Lock(ctx->pd3deb, &ebDesc));
if (r != D3D_OK)
return false;
//gEngfuncs.Con_Printf("IDirect3DExecuteBuffer_Lock size %lu data %p\n", ebDesc.dwBufferSize, ebDesc.lpData);
ctx->bufferSize = ebDesc.dwBufferSize;
ctx->data = ebDesc.lpData;
return true;
}
qboolean D3D_EndExecuteBuffer( d3dEBContext_t *ctx )
{
HRESULT r = D3D_OK;
DXCheckRet(r, IDirect3DExecuteBuffer_Unlock(ctx->pd3deb));
if( r != D3D_OK )
return false;
D3DEXECUTEDATA exData = { 0 };
memset(&exData, 0, sizeof(exData));
exData.dwSize = sizeof(exData);
exData.dwVertexCount = ctx->vertCount;
exData.dwVertexOffset = 0;
exData.dwInstructionOffset = ctx->insOffset;
exData.dwInstructionLength = ctx->insLength;
DXCheckRet(r, IDirect3DExecuteBuffer_SetExecuteData(ctx->pd3deb, &exData));
return r == D3D_OK;
}
void D3D_ReleaseExecuteBuffer( d3dEBContext_t *ctx )
{
#if DX2_CREATE_EB
if( ctx->pd3deb && ctx->pd3deb != dxc.pd3deb )
IDirect3DExecuteBuffer_Release( ctx->pd3deb );
#endif
}
void D3D_SetVertTL( D3DTLVERTEX* v, float x, float y, float z, float w, float tu, float tv )
{
v->sx = x;
v->sy = y;
v->sz = z;
v->rhw = w;
//v->color = RGBA_MAKE(250, 10, 10, 255);
v->tu = tu;
v->tv = tv;
}
void D3D_SetTri( D3DTRIANGLE *t, int v1, int v2, int v3 )
{
t->v1 = v1;
t->v2 = v2;
t->v3 = v3;
t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
}
void D3D_PutInstruction( void **dst, BYTE opcode, BYTE size, WORD count )
{
D3DINSTRUCTION* inst = (D3DINSTRUCTION*)*dst;
inst->bOpcode = opcode;
inst->bSize = size;
inst->wCount = count;
*dst = (void*)(((D3DINSTRUCTION*)*dst) + 1);
}
void D3D_PutProcessVertices( void** dst, DWORD flags, WORD start, WORD count )
{
D3D_PutInstruction(dst, D3DOP_PROCESSVERTICES, sizeof(D3DPROCESSVERTICES), 1);
D3DPROCESSVERTICES* pv = (D3DPROCESSVERTICES*)*dst;
pv->dwFlags = flags;
pv->wStart = start;
pv->wDest = start;
pv->dwCount = count;
pv->dwReserved = 0;
*dst = (void*)(((D3DPROCESSVERTICES*)*dst) + 1);
}
void D3D_PutRenderState( void** dst, D3DRENDERSTATETYPE type, DWORD arg )
{
D3DSTATE* s = (D3DSTATE*)*dst;
s->drstRenderStateType = type;
s->dwArg[0] = arg;
*dst = (void*)(((D3DSTATE*)*dst) + 1);
}
void D3D_PutTransformState( void** dst, D3DTRANSFORMSTATETYPE type, DWORD arg )
{
D3DSTATE* s = (D3DSTATE*)*dst;
s->dtstTransformStateType = type;
s->dwArg[0] = arg;
*dst = (void*)(((D3DSTATE*)*dst) + 1);
}

View File

@@ -1,204 +0,0 @@
/*
r_draw.c -- dx2 2D drawing
Copyright (C) 2025-2026 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "r_local.h"
#include "xash3d_mathlib.h"
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
{
if (texnum <= 0 || texnum >= MAX_TEXTURES)
return;
dx_texture_t *tex = R_GetTexture(texnum);
if (!tex->dds)
return;
#if 0
RECT dstRect = { x, y, x + w, y + h };
RECT srcRect = { s1 * tex->width, t1 * tex->height, s2 * tex->width, t2 * tex->height};
if (dxc.renderMode == kRenderNormal)
{
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, tex->dds, &srcRect, DDBLT_WAIT, NULL));
}
else
{
DDCOLORKEY ddck;
ddck.dwColorSpaceLowValue = 0;
ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
DXCheck(IDirectDrawSurface_SetColorKey(tex->dds, DDCKEY_SRCBLT, &ddck));
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, tex->dds, &srcRect, DDBLT_WAIT | DDBLT_KEYSRC, NULL));
}
#else
if (!dxc.pd3dd)
return;
d3dEBContext_t ebc = { 0 };
{
if( !D3D_StartExecuteBuffer( &ebc ))
return;
void *cur = ebc.data;
const int vertCount = 4;
D3DTLVERTEX* verts = (D3DTLVERTEX*)cur;
// fix for half coordinate pixel centers in d3d compared to gl
x -= 0.5;
y -= 0.5;
#define VecToD3DCOLOR(v) D3DRGBA(v[0], v[1], v[2], v[3])
verts[0].color = VecToD3DCOLOR(dxc.currentColor);
D3D_SetVertTL(verts, x, y, 0.5, 1, s1, t1);
verts[1].color = verts[0].color;
D3D_SetVertTL(verts + 1, x + w, y, 0.5, 1, s2, t1);
verts[2].color = verts[0].color;
D3D_SetVertTL(verts + 2, x + w, y + h, 0.5, 1, s2, t2);
verts[3].color = verts[0].color;
D3D_SetVertTL(verts + 3, x, y + h, 0.5, 1, s1, t2);
cur = (void*)(((D3DTLVERTEX*)cur) + vertCount);
void* insStart = cur;
D3D_PutProcessVertices(&cur, D3DPROCESSVERTICES_COPY | D3DPROCESSVERTICES_UPDATEEXTENTS, 0, vertCount);
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 3);
// TODO disable when == tr.whiteTexture
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREHANDLE, tex->d3dHandle);
//D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL);
if (dxc.renderMode == kRenderTransAlpha)
{
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
}
else if (dxc.renderMode == kRenderGlow ||
dxc.renderMode == kRenderTransAdd)
{
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, TRUE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
D3D_PutRenderState(&cur, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
D3D_PutRenderState(&cur, D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
}
else if (dxc.renderMode == kRenderTransColor || dxc.renderMode == kRenderTransTexture)
{
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, TRUE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
D3D_PutRenderState(&cur, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
D3D_PutRenderState(&cur, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
}
else// if (dxc.renderMode == kRenderNormal)
{
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
}
// align
if (((ULONG)cur) & 7) {
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0);
}
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 2);
D3DTRIANGLE* tris = (D3DTRIANGLE*)cur;
D3D_SetTri(tris, 0, 1, 2);
D3D_SetTri(tris + 1, 0, 2, 3);
cur = (void*)(((D3DTRIANGLE*)cur) + 2);
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
ebc.vertCount = 4;
ebc.insOffset = ((char*)insStart - (char*)ebc.data);
ebc.insLength = ((char*)cur - (char*)insStart);
if( !D3D_EndExecuteBuffer( &ebc ))
return;
}
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
D3D_ReleaseExecuteBuffer( &ebc );
#endif
}
void FillRGBA( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a )
{
#if 0
RECT dstRect = { x, y, x + w, y + h };
DDBLTFX bltFx = { 0 };
bltFx.dwSize = sizeof(bltFx);
bltFx.dwFillColor = RGBA_MAKE(r, g, b, a);
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &bltFx));
#else
// TODO Restore after?
GL_SetRenderMode( (rendermode == kRenderTransAdd) ? rendermode : kRenderTransColor);
Vector4Set( dxc.currentColor, r / 255.f, g / 255.f, b / 255.f, a / 255.f );
R_DrawStretchPic( x, y, w, h, 0, 0, 0, 0, tr.whiteTexture );
#endif
}
void R_Set2DMode( qboolean enable )
{
if( enable && dxc.in2DMode )
return;
dxc.in2DMode = enable;
d3dEBContext_t ebc = { 0 };
if( !D3D_StartExecuteBuffer( &ebc ))
return;
void *cur = ebc.data;
if( enable )
{
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 4);
D3D_PutRenderState(&cur, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, FALSE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, FALSE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
Vector4Set( dxc.currentColor, 1.0f, 1.0f, 1.0f, 1.0f );
RI.currententity = NULL;
RI.currentmodel = NULL;
}
else
{
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 3);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, TRUE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, TRUE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
}
ebc.vertCount = 0;
ebc.insOffset = 0;
ebc.insLength = ((char *)cur - (char *)ebc.data);
if (!D3D_EndExecuteBuffer(&ebc))
return;
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
D3D_ReleaseExecuteBuffer(&ebc);
}

View File

@@ -1,185 +0,0 @@
/*
r_frustum.c - frustum test implementation
Copyright (C) 2016 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "r_local.h"
#include "xash3d_mathlib.h"
static void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
{
Assert( side >= 0 && side < FRUSTUM_PLANES );
out->planes[side].type = PlaneTypeForNormal( vecNormal );
out->planes[side].signbits = SignbitsForPlane( vecNormal );
VectorCopy( vecNormal, out->planes[side].normal );
out->planes[side].dist = flDist;
SetBits( out->clipFlags, BIT( side ));
}
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY )
{
float xs, xc;
vec3_t farpoint, nearpoint;
vec3_t normal, iforward;
// horizontal fov used for left and right planes
SinCos( DEG2RAD( flFovX ) * 0.5f, &xs, &xc );
// setup left plane
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vright, normal );
GL_FrustumSetPlane( out, FRUSTUM_LEFT, normal, DotProduct( RI.cullorigin, normal ));
// setup right plane
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vright, normal );
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, normal, DotProduct( RI.cullorigin, normal ));
// vertical fov used for top and bottom planes
SinCos( DEG2RAD( flFovY ) * 0.5f, &xs, &xc );
VectorNegate( RI.cull_vforward, iforward );
// setup bottom plane
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vup, normal );
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, normal, DotProduct( RI.cullorigin, normal ));
// setup top plane
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vup, normal );
GL_FrustumSetPlane( out, FRUSTUM_TOP, normal, DotProduct( RI.cullorigin, normal ));
// setup far plane
VectorMA( RI.cullorigin, flZFar, RI.cull_vforward, farpoint );
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, DotProduct( iforward, farpoint ));
// no need to setup backplane for general view.
if( flZNear == 0.0f ) return;
// setup near plane
VectorMA( RI.cullorigin, flZNear, RI.cull_vforward, nearpoint );
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, DotProduct( RI.cull_vforward, nearpoint ));
}
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar )
{
vec3_t iforward, iright, iup;
// setup the near and far planes
float orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward );
VectorNegate( RI.cull_vforward, iforward );
// because quake ortho is inverted and far and near should be swaped
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, -flZNear - orgOffset );
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, flZFar + orgOffset );
// setup left and right planes
orgOffset = DotProduct( RI.cullorigin, RI.cull_vright );
VectorNegate( RI.cull_vright, iright );
GL_FrustumSetPlane( out, FRUSTUM_LEFT, RI.cull_vright, xLeft + orgOffset );
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, iright, -xRight - orgOffset );
// setup top and buttom planes
orgOffset = DotProduct( RI.cullorigin, RI.cull_vup );
VectorNegate( RI.cull_vup, iup );
GL_FrustumSetPlane( out, FRUSTUM_TOP, RI.cull_vup, yTop + orgOffset );
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, iup, -yBottom - orgOffset );
}
// cull methods
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags )
{
int iClipFlags;
int i, bit;
if( r_nocull.value )
return false;
if( userClipFlags != 0 )
iClipFlags = userClipFlags;
else iClipFlags = out->clipFlags;
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
{
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
if( !FBitSet( iClipFlags, bit ))
continue;
switch( p->signbits )
{
case 0:
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 1:
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 2:
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 3:
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 4:
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
case 5:
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
case 6:
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
case 7:
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
default:
return false;
}
}
return false;
}
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t center, float radius, int userClipFlags )
{
int iClipFlags;
int i, bit;
if( r_nocull.value )
return false;
if( userClipFlags != 0 )
iClipFlags = userClipFlags;
else iClipFlags = out->clipFlags;
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
{
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
if( !FBitSet( iClipFlags, bit ))
continue;
if( DotProduct( center, p->normal ) - p->dist <= -radius )
return true;
}
return false;
}

View File

@@ -1,41 +0,0 @@
/*
r_frustum.h - frustum test implementation
Copyright (C) 2016 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef GL_FRUSTUM_H
#define GL_FRUSTUM_H
// don't change this order
#define FRUSTUM_LEFT 0
#define FRUSTUM_RIGHT 1
#define FRUSTUM_BOTTOM 2
#define FRUSTUM_TOP 3
#define FRUSTUM_FAR 4
#define FRUSTUM_NEAR 5
#define FRUSTUM_PLANES 6
typedef struct gl_frustum_s
{
mplane_t planes[FRUSTUM_PLANES];
unsigned int clipFlags;
} gl_frustum_t;
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY );
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar );
// cull methods
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags );
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t centre, float radius, int userClipFlags );
#endif//GL_FRUSTUM_H

View File

@@ -1,622 +0,0 @@
/*
r_context.c -- dx2 renderer texture uploading and processing
Copyright (C) 2010 Uncle Mike
Copyright (C) 2025 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "r_local.h"
#include "xash3d_mathlib.h"
#include "crtlib.h"
#include "crclib.h"
static dx_texture_t dx_textures[MAX_TEXTURES];
static dx_texture_t *dx_texturesHashTable[TEXTURES_HASH_SIZE];
static uint dx_numTextures;
void R_InitImages( void )
{
memset(dx_textures, 0, sizeof(dx_textures));
memset(dx_texturesHashTable, 0, sizeof(dx_texturesHashTable));
dx_numTextures = 0;
// create unused 0-entry
Q_strncpy(dx_textures->name, "*unused*", sizeof(dx_textures->name));
dx_textures->hashValue = COM_HashKey(dx_textures->name, TEXTURES_HASH_SIZE);
dx_textures->nextHash = dx_texturesHashTable[dx_textures->hashValue];
dx_texturesHashTable[dx_textures->hashValue] = dx_textures;
dx_numTextures = 1;
}
dx_texture_t *R_GetTexture( unsigned int texnum )
{
Assert(texnum < MAX_TEXTURES);
return &dx_textures[texnum];
}
void R_ShowTextures( void )
{
}
const byte *R_GetTextureOriginalBuffer( unsigned int idx )
{
return NULL;
}
static qboolean GL_CheckTexName( const char *name )
{
int len;
if( COM_StringEmptyOrNULL( name ))
return false;
len = Q_strlen( name );
// because multi-layered textures can exceed name string
if( len >= sizeof( dx_textures->name ))
{
gEngfuncs.Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, len );
return false;
}
return true;
}
static dx_texture_t *GL_TextureForName( const char *name )
{
dx_texture_t *tex;
uint hash;
// find the texture in array
hash = COM_HashKey(name, TEXTURES_HASH_SIZE);
for (tex = dx_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash)
{
if (!Q_stricmp(tex->name, name))
return tex;
}
return NULL;
}
static dx_texture_t *GL_AllocTexture( const char *name, texFlags_t flags )
{
dx_texture_t *tex = NULL;
// find a free texture_t slot
uint i;
//skip 0
for (i = 1; i < MAX_TEXTURES; i++)
{
if (dx_textures[i].used)
continue;
tex = &dx_textures[i];
break;
}
if (tex == NULL)
{
gEngfuncs.Host_Error("%s: MAX_TEXTURES limit exceeds\n", __func__);
return NULL;
}
// copy initial params
Q_strncpy(tex->name, name, sizeof(tex->name));
tex->used = 1;
tex->flags = flags;
// increase counter
dx_numTextures = Q_max((tex - dx_textures) + 1, dx_numTextures);
// add to hash table
tex->hashValue = COM_HashKey(name, TEXTURES_HASH_SIZE);
tex->nextHash = dx_texturesHashTable[tex->hashValue];
dx_texturesHashTable[tex->hashValue] = tex;
return tex;
}
static void GL_ProcessImage( dx_texture_t *tex, rgbdata_t *pic )
{
uint img_flags = 0;
// force upload texture as RGB or RGBA (detail textures requires this)
if (tex->flags & TF_FORCE_COLOR) pic->flags |= IMAGE_HAS_COLOR;
if (pic->flags & IMAGE_HAS_ALPHA) tex->flags |= TF_HAS_ALPHA;
if (ImageCompressed(pic->type))
{
if (!pic->numMips)
tex->flags |= TF_NOMIPMAP; // disable mipmapping by user request
// clear all the unsupported flags
tex->flags &= ~TF_KEEP_SOURCE;
}
else
{
// copy flag about luma pixels
if (pic->flags & IMAGE_HAS_LUMA)
tex->flags |= TF_HAS_LUMA;
if (pic->flags & IMAGE_QUAKEPAL)
tex->flags |= TF_QUAKEPAL;
// create luma texture from quake texture
if (tex->flags & TF_MAKELUMA)
{
img_flags |= IMAGE_MAKE_LUMA;
tex->flags &= ~TF_MAKELUMA;
}
if (!FBitSet(tex->flags, TF_IMG_UPLOADED) && FBitSet(tex->flags, TF_KEEP_SOURCE))
tex->original = gEngfuncs.FS_CopyImage(pic); // because current pic will be expanded to rgba
// we need to expand image into RGBA buffer
if (pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32)
img_flags |= IMAGE_FORCE_RGBA;
// processing image before uploading (force to rgba, make luma etc)
if (pic->buffer) gEngfuncs.Image_Process(&pic, 0, 0, img_flags, 0);
if (FBitSet(tex->flags, TF_LUMINANCE))
ClearBits(pic->flags, IMAGE_HAS_COLOR);
}
}
static int GL_CalcMipmapCount( dx_texture_t *tex, qboolean haveBuffer )
{
int width, height;
int mipcount;
Assert(tex != NULL);
//TEMP
return 1;
if (!haveBuffer)
return 1;
// generate mip-levels by user request
if (FBitSet(tex->flags, TF_NOMIPMAP))
return 1;
// mip-maps can't exceeds 16
for (mipcount = 0; mipcount < 16; mipcount++)
{
width = Q_max(1, (tex->width >> mipcount));
height = Q_max(1, (tex->height >> mipcount));
if (width == 1 && height == 1)
break;
}
return mipcount + 1;
}
static void GL_TextureImageRAW( dx_texture_t *tex, int width, int height, int type, const char *data )
{
if (!data)
return;
DDSURFACEDESC ddsd = {};
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_LPSURFACE;
DXCheck(IDirectDrawSurface_Lock(tex->dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL));
int pitch = ddsd.lPitch;
if (!pitch)
pitch = ddsd.dwWidth * 4;
char *dst = (char *)ddsd.lpSurface;
for (int j = 0; j < (int)ddsd.dwHeight; j++)
{
//RGBA to BGRA
if (type == PF_RGBA_32)
{
for (int i = 0; i < ddsd.dwWidth; i++)
{
dst[i * 4 + 0] = data[i * 4 + 2];
dst[i * 4 + 1] = data[i * 4 + 1];
dst[i * 4 + 2] = data[i * 4 + 0];
dst[i * 4 + 3] = data[i * 4 + 3];
}
}
else if (type == PF_BGRA_32)
{
memcpy(dst, data, ddsd.dwWidth * 4);
}
dst += pitch;
data += ddsd.dwWidth * 4;
}
DXCheck(IDirectDrawSurface_Unlock(tex->dds, ddsd.lpSurface));
}
static qboolean GL_UploadTexture( dx_texture_t *tex, rgbdata_t *pic )
{
byte *buf, *data;
size_t size;
uint width, height;
uint j;
qboolean normalMap;
const byte *bufend;
// dedicated server
if (!dxc.window)
return true;
Assert(pic != NULL);
Assert(tex != NULL);
qboolean supported = true;
if (FBitSet(pic->flags, IMAGE_CUBEMAP))
supported = false;
else if (FBitSet(pic->flags, IMAGE_MULTILAYER) && pic->depth >= 1)
supported = false;
else if (pic->width > 1 && pic->height > 1 && pic->depth > 1)
supported = false;
else if (FBitSet(tex->flags, TF_RECTANGLE))
supported = false;
else if (FBitSet(tex->flags, TF_MULTISAMPLE))
supported = false;
// make sure what target is correct
if (!supported)
{
gEngfuncs.Con_DPrintf(S_ERROR "%s: %s is not supported\n", __func__, tex->name);
return false;
}
//if (pic->type == PF_BC6H_SIGNED || pic->type == PF_BC6H_UNSIGNED || pic->type == PF_BC7_UNORM || pic->type == PF_BC7_SRGB)
if (ImageCompressed(pic->type))
{
gEngfuncs.Con_DPrintf(S_ERROR "%s: compressed textures are not supported\n", __func__);
return false;
}
// store original sizes
tex->srcWidth = pic->width;
tex->srcHeight = pic->height;
// set the texture dimensions
{
int step = 0;// (int)gl_round_down.value;
int scaled_width, scaled_height;
for (scaled_width = 1; scaled_width < pic->width; scaled_width <<= 1);
if (step > 0 && pic->width < scaled_width && (step == 1 || (scaled_width - pic->width) > (scaled_width >> step)))
scaled_width >>= 1;
for (scaled_height = 1; scaled_height < pic->height; scaled_height <<= 1);
if (step > 0 && pic->height < scaled_height && (step == 1 || (scaled_height - pic->height) > (scaled_height >> step)))
scaled_height >>= 1;
tex->width = Q_max(1, scaled_width);
tex->height = Q_max(1, scaled_height);
}
DDSURFACEDESC ddsd = {};
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
//if (pic->numMips > 1)
// ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
ddsd.dwWidth = tex->width;
ddsd.dwHeight = tex->height;
#if 1
//BGRA8
ddsd.dwFlags |= DDSD_PIXELFORMAT;
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
if(FBitSet(pic->flags, IMAGE_HAS_ALPHA))
ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
ddsd.ddpfPixelFormat.dwBBitMask = 0xFF;
ddsd.ddpfPixelFormat.dwGBitMask = 0xFF00;
ddsd.ddpfPixelFormat.dwRBitMask = 0xFF0000;
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
#endif
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &tex->dds, NULL));
DXCheck(IDirectDrawSurface_QueryInterface(tex->dds, &IID_IDirect3DTexture, (void**)&tex->d3dTex));
DXCheck(IDirect3DTexture_GetHandle(tex->d3dTex, dxc.pd3dd, &tex->d3dHandle));
tex->fogParams[0] = pic->fogParams[0];
tex->fogParams[1] = pic->fogParams[1];
tex->fogParams[2] = pic->fogParams[2];
tex->fogParams[3] = pic->fogParams[3];
buf = pic->buffer;
bufend = pic->buffer + pic->size; // total image size include all the layers, cube sides, mipmaps
normalMap = FBitSet(tex->flags, TF_NORMALMAP) ? true : false;
if (Q_max(1, pic->numMips) > 1) // not-compressed DDS
{
//TEMP
j = 0;
//for (j = 0; j < Q_max(1, pic->numMips); j++)
{
// track the buffer bounds
if (buf != NULL && buf >= bufend)
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
width = Q_max(1, (tex->width >> j));
height = Q_max(1, (tex->height >> j));
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
GL_TextureImageRAW(tex, width, height, pic->type, buf);
buf += size; // move pointer
tex->numMips++;
}
}
else // RGBA32
{
// track the buffer bounds
if (buf != NULL && buf >= bufend)
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
int mipCount = GL_CalcMipmapCount(tex, (buf != NULL));
// NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides
if (((pic->width != tex->width) || (pic->height != tex->height)))
data = GL_ResampleTexture(buf, pic->width, pic->height, tex->width, tex->height, normalMap);
else data = buf;
//if (!ImageCompressed(pic->type) && !FBitSet(tex->flags, TF_NOMIPMAP) && FBitSet(pic->flags, IMAGE_ONEBIT_ALPHA))
// data = GL_ApplyFilter(data, tex->width, tex->height);
// mips will be auto-generated if desired
for (j = 0; j < mipCount; j++)
{
width = Q_max(1, (tex->width >> j));
height = Q_max(1, (tex->height >> j));
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
GL_TextureImageRAW(tex, width, height, pic->type, data);
//if (mipCount > 1)
// GL_BuildMipMap(data, width, height, tex->depth, tex->flags);
tex->numMips++;
}
}
SetBits(tex->flags, TF_IMG_UPLOADED); // done
return true;
}
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update )
{
dx_texture_t *tex;
if (!GL_CheckTexName(name))
return 0;
// see if already loaded
if ((tex = GL_TextureForName(name)) && !update)
return (tex - dx_textures);
// couldn't loading image
if (!pic) return 0;
if (update)
{
if (tex == NULL)
gEngfuncs.Host_Error("%s: couldn't find texture %s for update\n", __func__, name);
SetBits(tex->flags, flags);
}
else
{
// allocate the new one
tex = GL_AllocTexture(name, flags);
}
GL_ProcessImage(tex, pic);
if (!GL_UploadTexture(tex, pic))
{
memset(tex, 0, sizeof(dx_texture_t));
return 0;
}
return (tex - dx_textures);
}
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags )
{
qboolean update = FBitSet( flags, TF_UPDATE ) ? true : false;
int datasize = 1;
rgbdata_t r_empty;
if( FBitSet( flags, TF_ARB_16BIT ))
datasize = 2;
else if( FBitSet( flags, TF_ARB_FLOAT ))
datasize = 4;
ClearBits( flags, TF_UPDATE );
memset( &r_empty, 0, sizeof( r_empty ));
r_empty.width = width;
r_empty.height = height;
r_empty.type = PF_RGBA_32;
r_empty.size = r_empty.width * r_empty.height * datasize * 4;
r_empty.buffer = (byte *)buffer;
// clear invalid combinations
ClearBits( flags, TF_TEXTURE_3D );
// if image not luminance and not alphacontrast it will have color
if( !FBitSet( flags, TF_LUMINANCE ) && !FBitSet( flags, TF_ALPHACONTRAST ))
SetBits( r_empty.flags, IMAGE_HAS_COLOR );
if( FBitSet( flags, TF_HAS_ALPHA ))
SetBits( r_empty.flags, IMAGE_HAS_ALPHA );
if( FBitSet( flags, TF_CUBEMAP ))
{
// no cubemaps in dx2
return 0;
}
int texnum = GL_LoadTextureFromBuffer( name, &r_empty, flags, update );
if( !Q_strcmp( name, REF_DEFAULT_TEXTURE ))
tr.defaultTexture = texnum;
else if( !Q_strcmp( name, REF_PARTICLE_TEXTURE ))
tr.particleTexture = texnum;
else if( !Q_strcmp( name, REF_WHITE_TEXTURE ))
tr.whiteTexture = texnum;
else if( !Q_strcmp( name, REF_GRAY_TEXTURE ))
tr.grayTexture = texnum;
else if( !Q_strcmp( name, REF_BLACK_TEXTURE ))
tr.blackTexture = texnum;
return texnum;
}
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
{
;
}
void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale )
{
*xScale = *yScale = 1.0f;
}
void R_SetDetailScaleForTexture( int texture, float xScale, float yScale )
{
;
}
int GL_FindTexture( const char *name )
{
gEngfuncs.Con_Printf("GL_FindTexture(%s)\n", name);
return 0;
}
const char *GL_TextureName( unsigned int texnum )
{
return NULL;
}
const byte *GL_TextureData( unsigned int texnum )
{
return NULL;
}
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
{
dx_texture_t *tex;
rgbdata_t *pic;
uint picFlags = 0;
if (!GL_CheckTexName(name))
return 0;
// see if already loaded
if ((tex = GL_TextureForName(name)))
return (tex - dx_textures);
gEngfuncs.Con_Printf("GL_LoadTexture(%s, %p, %zu, %X)\n", name, buf, size, flags);
if (FBitSet(flags, TF_NOFLIP_TGA))
SetBits(picFlags, IL_DONTFLIP_TGA);
if (FBitSet(flags, TF_KEEP_SOURCE) && !FBitSet(flags, TF_EXPAND_SOURCE))
SetBits(picFlags, IL_KEEP_8BIT);
// set some image flags
gEngfuncs.Image_SetForceFlags(picFlags);
pic = gEngfuncs.FS_LoadImage(name, buf, size);
if (!pic) return 0; // couldn't loading image
// allocate the new one
tex = GL_AllocTexture(name, flags);
GL_ProcessImage(tex, pic);
if (!GL_UploadTexture(tex, pic))
{
memset(tex, 0, sizeof(dx_texture_t));
gEngfuncs.FS_FreeImage(pic); // release source texture
return 0;
}
//GL_ApplyTextureParams(tex); // update texture filter, wrap etc
gEngfuncs.FS_FreeImage(pic); // release source texture
// NOTE: always return texnum as index in array or engine will stop work !!!
return tex - dx_textures;
}
void GL_FreeTexture( unsigned int texnum )
{
if (texnum <= 0 || texnum >= MAX_TEXTURES)
return;
gEngfuncs.Con_Printf("GL_FreeTexture(%d) %s\n", texnum, dx_textures[texnum].name);
dx_texture_t* tex = R_GetTexture(texnum);
if (!tex->dds)
return;
// debug
if (!tex->name[0])
{
gEngfuncs.Con_Printf(S_ERROR "%s: trying to free unnamed texture with handle %X\n", __func__, tex->d3dHandle);
return;
}
// remove from hash table
dx_texture_t **prev = &dx_texturesHashTable[tex->hashValue];
while (1)
{
dx_texture_t *cur = *prev;
if (!cur) break;
if (cur == tex)
{
*prev = cur->nextHash;
break;
}
prev = &cur->nextHash;
}
// TODO invalidate texture state
// release source
if (tex->original)
gEngfuncs.FS_FreeImage(tex->original);
if (tex->d3dTex)
IDirect3DTexture_Release(tex->d3dTex);
if (tex->dds)
IDirectDrawSurface_Release(tex->dds);
memset(tex, 0, sizeof(*tex));
}
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight )
{
}
void GL_UpdateTexture( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt )
{
;
}

View File

@@ -1,319 +0,0 @@
/*
r_local.h - renderer local declarations
Copyright (C) 2010 Uncle Mike
Copyright (C) 2025-2026 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#pragma once
#include "ref_common.h"
#include "ref_api.h"
#include "r_frustum.h"
#include "ref_params.h"
#include "mod_local.h"
#include "com_strings.h"
#include "pmove.h"
#define DIRECTDRAW_VERSION 0x0200
#define DIRECT3D_VERSION 0x0500//D3DCOLORMODEL bug
#include <ddraw.h>
#include <d3d.h>
#define MAX_TEXTURES 8192
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
#define MAX_DRAW_STACK 2 // normal view and menu view
#define CULL_VISIBLE 0 // not culled
#define CULL_BACKSIDE 1 // backside of transparent wall
#define CULL_FRUSTUM 2 // culled by frustum
#define CULL_VISFRAME 3 // culled by PVS
#define CULL_OTHER 4 // culled by other reason
typedef struct dx_texture_s
{
char name[256]; // game path, including extension (can be store image programs)
word srcWidth; // keep unscaled sizes
word srcHeight;
word width; // upload width\height
word height;
byte numMips; // mipmap count
int used;
texFlags_t flags;
rgba_t fogParams; // some water textures
// contain info about underwater fog
rgbdata_t *original; // keep original image
#if 0
word depth; // texture depth or count of layers for 2D_ARRAY
GLuint target; // glTarget
GLuint texnum; // gl texture binding
GLint format; // uploaded format
// debug info
size_t size; // upload size for debug targets
// detail textures stuff
float xscale;
float yscale;
#endif
IDirectDrawSurface *dds;
IDirect3DTexture *d3dTex;
D3DTEXTUREHANDLE d3dHandle;
uint hashValue;
struct dx_texture_s *nextHash;
} dx_texture_t;
typedef struct d3dEBContext_s
{
IDirect3DExecuteBuffer *pd3deb;
DWORD bufferSize;
void *data;
DWORD vertCount;
DWORD insOffset;
DWORD insLength;
} d3dEBContext_t;
typedef struct
{
ref_viewpass_t rvp;
cl_entity_t *currententity;
model_t *currentmodel;
cl_entity_t *currentbeam; // same as above but for beams
gl_frustum_t frustum;
mleaf_t *viewleaf;
mleaf_t *oldviewleaf;
vec3_t vforward;
vec3_t vright;
vec3_t vup;
vec3_t cullorigin;
vec3_t cull_vforward;
vec3_t cull_vright;
vec3_t cull_vup;
float farClip;
qboolean fogCustom;
qboolean fogEnabled;
qboolean fogSkybox;
vec4_t fogColor;
float fogDensity;
float fogStart;
float fogEnd;
int cached_contents; // in water
int cached_waterlevel; // was in water
float skyMins[2][SKYBOX_MAX_SIDES];
float skyMaxs[2][SKYBOX_MAX_SIDES];
matrix4x4 objectMatrix; // currententity matrix
matrix4x4 worldviewMatrix; // modelview for world
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
matrix4x4 projectionMatrix;
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
byte visbytes[( MAX_MAP_LEAFS + 7 ) / 8];// actual PVS for current frame
float viewplanedist;
mplane_t clipPlane;
} ref_instance_t;
typedef struct
{
cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes
cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes
cl_entity_t *beam_entities[MAX_VISIBLE_PACKET];
uint num_solid_entities;
uint num_trans_entities;
uint num_beam_entities;
} draw_list_t;
typedef struct
{
int defaultTexture; // use for bad textures
int particleTexture;
int whiteTexture;
int grayTexture;
int blackTexture;
int skytexturenum; // index into model_t::textures
// entity lists
draw_list_t draw_stack[MAX_DRAW_STACK];
int draw_stack_pos;
draw_list_t *draw_list;
// matrix states
qboolean modelviewIdentity;
int visframecount; // PVS frame
int dlightframecount; // dynamic light frame
int realframecount; // not including viewpasses
int framecount;
qboolean fCustomRendering;
qboolean fResetVis;
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
float blend; // global blend value
// cull info
vec3_t modelorg; // relative to viewpoint
// get from engine
model_t *worldmodel;
world_static_t *world;
cl_entity_t *entities;
cl_entity_t *viewent;
uint max_entities;
ref_screen_rotation_t rotation;
} dx_globals_t;
struct dx_context_s
{
HWND window;
int windowWidth;
int windowHeight;
IDirectDraw *pdd;
IDirectDrawSurface *pddsPrimary;
IDirectDrawSurface *pddsBack;
IDirectDrawSurface *pddsZBuffer;
IDirectDrawClipper *pddClipper;
IDirectDrawClipper *pddBackClipper;
IDirect3D *pd3d;
IDirect3DDevice *pd3dd;
IDirect3DExecuteBuffer *pd3deb;
IDirect3DViewport *viewport;
D3DMATRIXHANDLE mtxWorld;
D3DMATRIXHANDLE mtxProjection;
qboolean in2DMode;
int renderMode;
vec4_t currentColor;
D3DTEXTUREHANDLE currentTexture;
D3DTEXTUREHANDLE lastBoundTexture;
};
typedef struct dx_context_s dx_context_t;
extern ref_instance_t RI;
extern dx_globals_t tr;
extern dx_context_t dxc;
static inline cl_entity_t *CL_GetEntityByIndex( int index )
{
if( unlikely( index < 0 || index >= tr.max_entities || !tr.entities ))
return NULL;
return &tr.entities[index];
}
static inline model_t *CL_ModelHandle( int index )
{
if( unlikely( index < 0 || index >= gp_cl->nummodels ))
return NULL;
return gp_cl->models[index];
}
const char *dxResultToStr( HRESULT r );
#define DXCheckRet(DST, CALL) \
(DST) = (CALL);\
if ((DST) != DD_OK)\
gEngfuncs.Con_Printf( S_ERROR "%s():%s:%d: DirectX error %X(%d 0x%X %d) %s at \"" #CALL "\"\n", __FUNCTION__, __FILE__, __LINE__, (DST), ( (DST) >> 31 ) & 1, ( (DST) >> 16 ) & 0x7FFF, (DST) & 0xFFFF, dxResultToStr( r ));
#define DXCheck(CALL) \
{\
HRESULT r = DD_OK;\
DXCheckRet(r, CALL)\
}
void GL_SetRenderMode( int mode );
void GL_Bind( int tmu, unsigned int texnum );
// r_d3d.c
qboolean R_Init( void );
void R_Shutdown( void );
void GL_SetupAttributes( int safegl );
void GL_InitExtensions( void );
void GL_ClearExtensions( void );
void D3D_Resize( int width, int height );
qboolean D3D_StartExecuteBuffer( d3dEBContext_t *ctx );
qboolean D3D_EndExecuteBuffer( d3dEBContext_t *ctx );
void D3D_ReleaseExecuteBuffer( d3dEBContext_t *ctx );
void D3D_SetVertTL( D3DTLVERTEX *v, float x, float y, float z, float w, float tu, float tv );
void D3D_SetTri( D3DTRIANGLE *t, int v1, int v2, int v3 );
void D3D_PutInstruction( void **dst, BYTE opcode, BYTE size, WORD count );
void D3D_PutProcessVertices( void **dst, DWORD flags, WORD start, WORD count );
void D3D_PutRenderState( void **dst, D3DRENDERSTATETYPE type, DWORD arg );
void D3D_PutTransformState( void **dst, D3DTRANSFORMSTATETYPE type, DWORD arg );
// r_main.c
void R_GammaChanged( qboolean do_reset_gamma );
void R_BeginFrame( qboolean clearScene );
void R_RenderScene( void );
void R_EndFrame( void );
void R_AllowFog( qboolean allowed );
void R_RenderFrame( const struct ref_viewpass_s *rvp );
qboolean R_AddEntity( struct cl_entity_s *clent, int type );
void R_ClearScene( void );
int WorldToScreen( const vec3_t world, vec3_t screen );
void R_LoadIdentity( void );
void R_SetupD3D( qboolean set_state );
// r_draw.c
void R_Set2DMode( qboolean enable );
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum );
void FillRGBA( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a );
// r_image.c
void R_InitImages( void );
dx_texture_t *R_GetTexture( unsigned int texnum );
void R_ShowTextures( void );
const byte *R_GetTextureOriginalBuffer( unsigned int idx );
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale );
void R_SetDetailScaleForTexture( int texture, float xScale, float yScale );
int GL_FindTexture( const char *name );
const char *GL_TextureName( unsigned int texnum );
const byte *GL_TextureData( unsigned int texnum );
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
void GL_FreeTexture( unsigned int texnum );
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight );
void GL_UpdateTexture( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt );
// r_surf.c
void GL_SubdivideSurface( model_t *mod, msurface_t *fa );
void GL_OrthoBounds( const float *mins, const float *maxs );
byte *Mod_GetCurrentVis( void );
void R_DrawWorld( void );
void R_MarkLeaves( void );
void GL_BuildLightmaps( void );
extern convar_t r_novis;
extern convar_t r_nocull;
extern convar_t r_lockpvs;
extern convar_t r_lockfrustum;

View File

@@ -1,380 +0,0 @@
/*
r_main.c -- dx2 renderer main loop
Copyright (C) 2010 Uncle Mike
Copyright (C) 2025-2026 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "r_local.h"
#include "ref_params.h"
#include "xash3d_mathlib.h"
ref_instance_t RI;
static void R_Clear( int bitMask )
{
int bits = D3DCLEAR_ZBUFFER;
//bits &= bitMask;
D3DRECT rect = {
.x1 = 0,
.y1 = 0,
.x2 = dxc.windowWidth,
.y2 = dxc.windowHeight,
};
DXCheck(IDirect3DViewport_Clear(dxc.viewport, 1, &rect, bits));
}
static float R_GetFarClip( void )
{
if( tr.worldmodel && FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) )
return gp_movevars->zmax * 1.73f;
return 2048.0f;
}
void R_SetupFrustum( void )
{
// build the transformation matrix for the given view angles
AngleVectors( RI.rvp.viewangles, RI.vforward, RI.vright, RI.vup );
if( !r_lockfrustum.value )
{
VectorCopy( RI.rvp.vieworigin, RI.cullorigin );
VectorCopy( RI.vforward, RI.cull_vforward );
VectorCopy( RI.vright, RI.cull_vright );
VectorCopy( RI.vup, RI.cull_vup );
}
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
{
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
}
else
{
GL_FrustumInitProj( &RI.frustum, 0.0f, R_GetFarClip(), RI.rvp.fov_x, RI.rvp.fov_y ); // NOTE: we ignore nearplane here (mirrors only)
}
}
static void R_SetupProjectionMatrix( matrix4x4 m )
{
float xMin, xMax, yMin, yMax, zNear, zFar;
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
{
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
Matrix4x4_CreateOrtho( m, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
return;
}
RI.farClip = R_GetFarClip();
zNear = 4.0f;
zFar = Q_max( 256.0f, RI.farClip );
yMax = zNear * tan( RI.rvp.fov_y * M_PI_F / 360.0f );
yMin = -yMax;
xMax = zNear * tan( RI.rvp.fov_x * M_PI_F / 360.0f );
xMin = -xMax;
if( tr.rotation & 1 )
{
Matrix4x4_CreateProjection( m, yMax, yMin, xMax, xMin, zNear, zFar );
}
else
{
Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar );
}
}
/*
=============
R_SetupModelviewMatrix
=============
*/
static void R_SetupModelviewMatrix( matrix4x4 m )
{
Matrix4x4_CreateModelview( m );
if( tr.rotation & 1 )
{
Matrix4x4_ConcatRotate( m, anglemod( -RI.rvp.viewangles[2] + 90 ), 1, 0, 0 );
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[0], 0, 1, 0 );
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[1], 0, 0, 1 );
}
else
{
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[2], 1, 0, 0 );
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[0], 0, 1, 0 );
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[1], 0, 0, 1 );
}
Matrix4x4_ConcatTranslate( m, -RI.rvp.vieworigin[0], -RI.rvp.vieworigin[1], -RI.rvp.vieworigin[2] );
}
void R_LoadIdentity( void )
{
if( tr.modelviewIdentity ) return;
Matrix4x4_LoadIdentity( RI.objectMatrix );
Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix );
//TODO GL_LoadMatrix( MODELVIEW, RI.modelviewMatrix );
tr.modelviewIdentity = true;
}
void R_GammaChanged( qboolean do_reset_gamma )
{
if( do_reset_gamma )
{
// paranoia cubemap rendering
if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
gEngfuncs.drawFuncs->GL_BuildLightmaps( );
}
else
{
//GL_RebuildLightmaps();
}
}
void R_BeginFrame( qboolean clearScene )
{
if(( gl_clear->value || ENGINE_GET_PARM( PARM_DEV_OVERVIEW )) &&
clearScene && ENGINE_GET_PARM( PARM_CONNSTATE ) != ca_cinematic )
{
D3DRECT rect = {
.x1 = 0,
.y1 = 0,
.x2 = dxc.windowWidth,
.y2 = dxc.windowHeight,
};
DXCheck(IDirect3DViewport_Clear(dxc.viewport, 1, &rect, D3DCLEAR_TARGET));
}
R_Set2DMode( true );
gEngfuncs.CL_ExtraUpdate();
}
static void R_DrawEntitiesOnList( void )
{
}
void R_RenderScene( void )
{
if( !tr.worldmodel && FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) )
gEngfuncs.Host_Error("%s: NULL worldmodel\n", __func__);
// frametime is valid only for normal pass
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ))
tr.frametime = gp_cl->time - gp_cl->oldtime;
else tr.frametime = 0.0;
// begin a new frame
tr.framecount++;
tr.dlightframecount = R_PushDlights( tr.worldmodel, tr.framecount );
R_SetupFrustum();
#if 0
R_SetupFrame();
#endif
R_SetupD3D(true);
R_Clear(~0);
R_MarkLeaves();
#if 0
R_DrawFog();
if( FBitSet( RI.rvp.flags, RF_DRAW_WORLD ))
R_AnimateRipples();
R_CheckGLFog();
#endif
R_DrawWorld();
// R_CheckFog();
gEngfuncs.CL_ExtraUpdate(); // don't let sound get messed up if going slow
R_DrawEntitiesOnList();
// R_DrawWaterSurfaces();
}
void R_EndFrame( void )
{
if (!dxc.window)
return;
R_Set2DMode( false );
//swap
if (dxc.pddsBack)
{
RECT dstRect = { 0 };
POINT point = { 0,0 };
ClientToScreen(dxc.window, &point);
GetClientRect(dxc.window, &dstRect);
OffsetRect(&dstRect, point.x, point.y);
RECT srcRect = { 0,0,dxc.windowWidth,dxc.windowHeight };
DXCheck(IDirectDrawSurface_Blt(dxc.pddsPrimary, &dstRect, dxc.pddsBack, &srcRect, DDBLT_WAIT, NULL));
}
//resize
RECT rect = { 0 };
GetClientRect(dxc.window, &rect);
int w = rect.right - rect.left;
int h = rect.bottom - rect.top;
if (w != dxc.windowWidth || h != dxc.windowHeight)
{
D3D_Resize(w, h);
}
}
void R_AllowFog( qboolean allowed )
{
}
static void R_SetupRefParams( const ref_viewpass_t *rvp )
{
RI.rvp = *rvp;
RI.farClip = 0;
}
void R_RenderFrame( const ref_viewpass_t *rvp )
{
if( r_norefresh->value )
return;
// setup the initial render params
R_SetupRefParams( rvp );
// completely override rendering
if( gEngfuncs.drawFuncs->GL_RenderFrame != NULL )
{
tr.fCustomRendering = true;
if( gEngfuncs.drawFuncs->GL_RenderFrame( rvp ))
{
R_GatherPlayerLight( tr.viewent );
tr.realframecount++;
tr.fResetVis = true;
return;
}
}
tr.fCustomRendering = false;
#if 0
if( !FBitSet( RI.rvp.flags, RF_ONLY_CLIENTDRAW ))
R_RunViewmodelEvents();
#endif
tr.realframecount++; // right called after viewmodel events
R_RenderScene();
}
qboolean R_AddEntity( struct cl_entity_s *clent, int type )
{
return true;
}
void R_ClearScene( void )
{
tr.draw_list->num_solid_entities = 0;
tr.draw_list->num_trans_entities = 0;
tr.draw_list->num_beam_entities = 0;
// clear the scene befor start new frame
if (gEngfuncs.drawFuncs->R_ClearScene != NULL)
gEngfuncs.drawFuncs->R_ClearScene();
}
int WorldToScreen( const vec3_t world, vec3_t screen )
{
VectorClear( screen );
return 0;
}
void R_SetupD3D( qboolean set_state )
{
R_SetupModelviewMatrix( RI.worldviewMatrix );
R_SetupProjectionMatrix( RI.projectionMatrix );
Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix );
if( !set_state ) return;
D3DVIEWPORT viewport = { 0 };
viewport.dwSize = sizeof(viewport);
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ))
{
int x, x2, y, y2;
// set up viewport (main, playersetup)
x = floor( RI.rvp.viewport[0] * gpGlobals->width / gpGlobals->width );
x2 = ceil( (RI.rvp.viewport[0] + RI.rvp.viewport[2]) * gpGlobals->width / gpGlobals->width );
y = floor( gpGlobals->height - RI.rvp.viewport[1] * gpGlobals->height / gpGlobals->height );
y2 = ceil( gpGlobals->height - (RI.rvp.viewport[1] + RI.rvp.viewport[3]) * gpGlobals->height / gpGlobals->height );
if( tr.rotation & 1 )
{
viewport.dwX = y2;
viewport.dwY = x;
viewport.dwWidth = y - y2;
viewport.dwHeight = x2 - x;
}
else
{
viewport.dwX = x;
viewport.dwY = y2;
viewport.dwWidth = x2 - x;
viewport.dwHeight = y - y2;
}
}
else
{
// envpass, mirrorpass
viewport.dwX = RI.rvp.viewport[0];
viewport.dwY = RI.rvp.viewport[1];
viewport.dwWidth = RI.rvp.viewport[2];
viewport.dwHeight = RI.rvp.viewport[3];
}
viewport.dvScaleX = 0.5f * viewport.dwWidth;
viewport.dvScaleY = 0.5f * viewport.dwHeight;
viewport.dvMaxX = 1;//calc for partial views
viewport.dvMaxY = 1;
viewport.dvMinZ = 0;
viewport.dvMaxZ = 1;
DXCheck(IDirect3DViewport_SetViewport(dxc.viewport, &viewport));
{
float dest[16];
Matrix4x4_ToArrayFloatGL(RI.projectionMatrix, dest);
DXCheck(IDirect3DDevice_SetMatrix(dxc.pd3dd, dxc.mtxProjection, (D3DMATRIX *)&dest));
Matrix4x4_ToArrayFloatGL(RI.worldviewMatrix, dest);
DXCheck(IDirect3DDevice_SetMatrix(dxc.pd3dd, dxc.mtxWorld, (D3DMATRIX *)&dest));
}
}

View File

@@ -1,625 +0,0 @@
/*
r_surf.c - surface-related refresh code
Copyright (C) 2025-2026 lewa_j
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "r_local.h"
#include "xash3d_mathlib.h"
void GL_OrthoBounds( const float *mins, const float *maxs )
{
;
}
byte *Mod_GetCurrentVis( void )
{
return NULL;
}
void R_LightmapCoord( const vec3_t v, const msurface_t *surf, const float sample_size, vec2_t coords )
{
const mextrasurf_t *info = surf->info;
float s, t;
#define BLOCK_SIZE 256
s = DotProduct( v, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0];
s += surf->light_s * sample_size;
s += sample_size * 0.5f;
s /= BLOCK_SIZE * sample_size;
t = DotProduct( v, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1];
t += surf->light_t * sample_size;
t += sample_size * 0.5f;
t /= BLOCK_SIZE * sample_size;
#undef BLOCK_SIZE
Vector2Set( coords, s, t );
}
static void R_TextureCoord( const vec3_t v, const msurface_t *surf, vec2_t coords )
{
const mtexinfo_t *info = surf->texinfo;
float s, t;
s = DotProduct( v, info->vecs[0] );
t = DotProduct( v, info->vecs[1] );
if( !FBitSet( surf->flags, SURF_DRAWTURB ))
{
s = ( s + info->vecs[0][3] ) / info->texture->width;
t = ( t + info->vecs[1][3] ) / info->texture->height;
}
Vector2Set( coords, s, t );
}
static void R_GetEdgePosition( const model_t *mod, const msurface_t *fa, int i, vec3_t vec )
{
const int lindex = mod->surfedges[fa->firstedge + i];
if( FBitSet( mod->flags, MODEL_QBSP2 ))
{
const medge32_t *pedges = mod->edges32;
if( lindex > 0 )
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
else
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
}
else
{
const medge16_t *pedges = mod->edges16;
if( lindex > 0 )
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
else
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
}
}
void GL_SubdivideSurface( model_t *mod, msurface_t *fa )
{
;
}
/*
================
GL_BuildPolygonFromSurface
================
*/
static int GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
{
int i, lnumverts, nColinElim = 0;
float sample_size;
texture_t *tex;
dx_texture_t *dxt;
glpoly2_t *poly;
if( !mod || !fa->texinfo || !fa->texinfo->texture )
return nColinElim; // bad polygon ?
if( FBitSet( fa->flags, SURF_CONVEYOR ) && fa->texinfo->texture->gl_texturenum != 0 )
{
dxt = R_GetTexture( fa->texinfo->texture->gl_texturenum );
tex = fa->texinfo->texture;
Assert( dxt != NULL && tex != NULL );
// update conveyor widths for keep properly speed of scrolling
dxt->srcWidth = tex->width;
dxt->srcHeight = tex->height;
}
sample_size = gEngfuncs.Mod_SampleSizeForFace( fa );
// reconstruct the polygon
lnumverts = fa->numedges;
// detach if already created, reconstruct again
poly = fa->polys;
fa->polys = NULL;
// quake simple models (healthkits etc) need to be reconstructed their polys because LM coords has changed after the map change
poly = Mem_Realloc( mod->mempool, poly, sizeof( glpoly2_t ) + lnumverts * VERTEXSIZE * sizeof( float ));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
for( i = 0; i < lnumverts; i++ )
{
R_GetEdgePosition( mod, fa, i, poly->verts[i] );
R_TextureCoord( poly->verts[i], fa, &poly->verts[i][3] );
R_LightmapCoord( poly->verts[i], fa, sample_size, &poly->verts[i][5] );
}
// TODO or not TODO gl_keeptjunctions?
poly->numverts = lnumverts;
return nColinElim;
}
/*
===============
R_TextureAnimation
Returns the proper texture for a given time and surface
===============
*/
static texture_t *R_TextureAnimation( msurface_t *s )
{
texture_t *base = s->texinfo->texture;
// TODO
return base;
}
static void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
{
float *v;
float sOffset, sy;
float tOffset, cy;
cl_entity_t *e = RI.currententity;
int i, hasScale = false;
if( !p ) return;
{
sOffset = tOffset = 0.0f;
}
if( xScale != 0.0f && yScale != 0.0f )
hasScale = true;
d3dEBContext_t ebc = { 0 };
if( !D3D_StartExecuteBuffer( &ebc ))
return;
void *cur = ebc.data;
D3DLVERTEX* verts = (D3DLVERTEX*)cur;
for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE )
{
D3DLVERTEX *dv = verts + i;
if( hasScale )
{
dv->tu = ( v[3] + sOffset ) * xScale;
dv->tv = ( v[4] + tOffset ) * yScale;
}
else
{
dv->tu = v[3] + sOffset;
dv->tv = v[4] + tOffset;
}
dv->x = v[0];
dv->y = v[1];
dv->z = v[2];
dv->color = 0xFFFFFFFF;
}
cur = (void*)(((D3DTLVERTEX*)cur) + p->numverts);
void* insStart = cur;
D3D_PutProcessVertices(&cur, D3DPROCESSVERTICES_TRANSFORM | D3DPROCESSVERTICES_UPDATEEXTENTS, 0, p->numverts);
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 4);
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREHANDLE, dxc.currentTexture);
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL);
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
// align
if (((ULONG)cur) & 7) {
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0);
}
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), p->numverts - 2);
for (i = 0; i < p->numverts; i++)
{
D3D_SetTri(cur, 0, i + 1, i + 2);
cur = (void*)(((D3DTRIANGLE*)cur) + 1);
}
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
ebc.vertCount = p->numverts;
ebc.insOffset = ((char*)insStart - (char*)ebc.data);
ebc.insLength = ((char*)cur - (char*)insStart);
if( !D3D_EndExecuteBuffer( &ebc ))
return;
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
D3D_ReleaseExecuteBuffer( &ebc );
//
//if( FBitSet( p->flags, SURF_DRAWTILED ))
// GL_SetupFogColorForSurfaces();
}
static void R_RenderBrushPoly( msurface_t *fa, int cull_type )
{
texture_t *t;
//r_stats.c_world_polys++;
if( fa->flags & SURF_DRAWSKY )
return; // already handled
t = R_TextureAnimation( fa );
GL_Bind( XASH_TEXTURE0, t->gl_texturenum );
DrawGLPoly( fa->polys, 0.0f, 0.0f );
}
static void R_DrawTextureChains( void )
{
int i;
msurface_t *s;
texture_t *t;
// make sure what color is reset
Vector4Set( dxc.currentColor, 1, 1, 1, 1 );
R_LoadIdentity(); // set identity matrix
//GL_SetupFogColorForSurfaces();
// restore worldmodel
RI.currententity = CL_GetEntityByIndex( 0 );
RI.currentmodel = RI.currententity->model;
for( i = 0; i < tr.worldmodel->numtextures; i++ )
{
t = tr.worldmodel->textures[i];
if( !t ) continue;
s = t->texturechain;
if( !s || ( i == tr.skytexturenum ))
continue;
for( ; s != NULL; s = s->texturechain )
R_RenderBrushPoly( s, CULL_VISIBLE );
t->texturechain = NULL;
}
}
/*
=================
R_CullSurface
cull invisible surfaces
=================
*/
static int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags )
{
cl_entity_t *e = RI.currententity;
if( !surf || !surf->texinfo || !surf->texinfo->texture )
return CULL_OTHER;
//TODO
return CULL_VISIBLE;
}
static void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
{
int i, clipped;
msurface_t *surf, **mark;
mleaf_t *pleaf;
int c, side;
float dot;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0:
if( node->contents == CONTENTS_SOLID )
return; // hit a solid leaf
if( node->visframe != tr.visframecount )
return;
if( clipflags && !r_nocull.value )
{
for( i = 0; i < 6; i++ )
{
const mplane_t *p = &RI.frustum.planes[i];
if( !FBitSet( clipflags, BIT( i )))
continue;
clipped = BoxOnPlaneSide( node->minmaxs, node->minmaxs + 3, p );
if( clipped == 2 ) return;
if( clipped == 1 ) ClearBits( clipflags, BIT( i ));
}
}
// if a leaf node, draw stuff
if( node->contents < 0 )
{
pleaf = (mleaf_t *)node;
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
if( c )
{
do
{
(*mark)->visframe = tr.framecount;
mark++;
} while( --c );
}
// deal with model fragments in this leaf
if( pleaf->efrags )
gEngfuncs.R_StoreEfrags( &pleaf->efrags, tr.realframecount );
// r_stats.c_world_leafs++;
return;
}
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
dot = PlaneDiff( tr.modelorg, node->plane );
side = (dot >= 0.0f) ? 0 : 1;
// recurse down the children, front side first
node_children( children, node, tr.worldmodel );
R_RecursiveWorldNode( children[side], clipflags );
firstsurface = node_firstsurface( node, tr.worldmodel );
numsurfaces = node_numsurfaces( node, tr.worldmodel );
// draw stuff
for( c = numsurfaces, surf = tr.worldmodel->surfaces + firstsurface; c; c--, surf++ )
{
if( R_CullSurface( surf, &RI.frustum, clipflags ))
continue;
if( surf->flags & SURF_DRAWSKY )
{
#if 0
// make sky chain to right clip the skybox
surf->texturechain = skychain;
skychain = surf;
#endif
}
else
{
surf->texturechain = surf->texinfo->texture->texturechain;
surf->texinfo->texture->texturechain = surf;
}
}
// recurse down the back side
node = children[!side];
goto loc0;
}
void R_DrawWorld( void )
{
double start, end;
// paranoia issues: when gl_renderer is "0" we need have something valid for currententity
// to prevent crashing until HeadShield drawing.
RI.currententity = CL_GetEntityByIndex( 0 );
if( !RI.currententity )
return;
RI.currentmodel = RI.currententity->model;
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) || FBitSet( RI.rvp.flags, RF_ONLY_CLIENTDRAW ))
return;
VectorCopy( RI.cullorigin, tr.modelorg );
//memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces ));
//memset( fullbright_surfaces, 0, sizeof( fullbright_surfaces ));
//memset( detail_surfaces, 0, sizeof( detail_surfaces ));
//gl_lms.dynamic_surfaces = NULL;
tr.blend = 1.0f;
//R_ClearSkyBox ();
start = gEngfuncs.pfnTime();
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
{
//R_DrawWorldTopView( tr.worldmodel->nodes, RI.frustum.clipFlags );
}
else R_RecursiveWorldNode( tr.worldmodel->nodes, RI.frustum.clipFlags );
end = gEngfuncs.pfnTime();
//r_stats.t_world_node = end - start;
start = gEngfuncs.pfnTime();
R_DrawTextureChains();
end = gEngfuncs.pfnTime();
//r_stats.t_world_draw = end - start;
//tr.num_draw_decals = 0;
//skychain = NULL;
gEngfuncs.R_DrawWorldHull();
}
/*
===============
R_MarkLeaves
Mark the leaves and nodes that are in the PVS for the current leaf
===============
*/
void R_MarkLeaves( void )
{
qboolean novis = false;
qboolean force = false;
mleaf_t *leaf = NULL;
mnode_t *node;
vec3_t test;
int i;
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) ) return;
if( FBitSet( r_novis.flags, FCVAR_CHANGED ) || tr.fResetVis )
{
// force recalc viewleaf
ClearBits( r_novis.flags, FCVAR_CHANGED );
tr.fResetVis = false;
RI.viewleaf = NULL;
}
VectorCopy( RI.rvp.vieworigin, test );
if( RI.viewleaf != NULL )
{
// merge two leafs that can be a crossed-line contents
if( RI.viewleaf->contents == CONTENTS_EMPTY )
VectorSet( test, RI.rvp.vieworigin[0], RI.rvp.vieworigin[1], RI.rvp.vieworigin[2] - 16.0f );
else
VectorSet( test, RI.rvp.vieworigin[0], RI.rvp.vieworigin[1], RI.rvp.vieworigin[2] + 16.0f );
leaf = gEngfuncs.Mod_PointInLeaf( test, tr.worldmodel->nodes, tr.worldmodel );
if(( leaf->contents != CONTENTS_SOLID ) && ( RI.viewleaf != leaf ))
force = true;
}
if( RI.viewleaf == RI.oldviewleaf && RI.viewleaf != NULL && !force )
return;
// development aid to let you run around
// and see exactly where the pvs ends
if( r_lockpvs.value ) return;
RI.oldviewleaf = RI.viewleaf;
tr.visframecount++;
if( r_novis.value || FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ) || !RI.viewleaf || !tr.worldmodel->visdata )
novis = true;
gEngfuncs.R_FatPVS( RI.rvp.vieworigin, r_pvs_radius->value, RI.visbytes, false, novis );
if( force && !novis )
gEngfuncs.R_FatPVS( test, r_pvs_radius->value, RI.visbytes, true, novis );
for( i = 0; i < tr.worldmodel->numleafs; i++ )
{
if( CHECKVISBIT( RI.visbytes, i ))
{
node = (mnode_t *)&tr.worldmodel->leafs[i+1];
do
{
if( node->visframe == tr.visframecount )
break;
node->visframe = tr.visframecount;
node = node->parent;
} while( node );
}
}
}
/*
==================
GL_BuildLightmaps
Builds the lightmap texture
with all the surfaces from all brush models
==================
*/
void GL_BuildLightmaps( void )
{
int i, j, nColinElim = 0;
model_t *m;
#if 0
// release old lightmaps
for( i = 0; i < MAX_LIGHTMAPS; i++ )
{
if( !tr.lightmapTextures[i] ) break;
GL_FreeTexture( tr.lightmapTextures[i] );
}
memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
#endif
memset( &RI, 0, sizeof( RI ));
#if 0
// update the lightmap blocksize
if( FBitSet( gp_host->features, ENGINE_LARGE_LIGHTMAPS ) || tr.world->version == QBSP2_VERSION || r_large_lightmaps.value )
tr.block_size = BLOCK_SIZE_MAX;
else tr.block_size = BLOCK_SIZE_DEFAULT;
skychain = NULL;
#endif
tr.framecount = tr.visframecount = 1; // no dlight cache
//gl_lms.current_lightmap_texture = 0;
tr.modelviewIdentity = false;
tr.realframecount = 1;
#if 0
// setup the texture for dlights
R_InitDlightTexture();
// setup all the lightstyles
CL_RunLightStyles((lightstyle_t *)ENGINE_GET_PARM( PARM_GET_LIGHTSTYLES_PTR ));
LM_InitBlock();
#endif
for( i = 0; i < gp_cl->nummodels; i++ )
{
if(( m = CL_ModelHandle( i + 1 )) == NULL )
continue;
if( m->name[0] == '*' || m->type != mod_brush )
continue;
for( j = 0; j < m->numsurfaces; j++ )
{
// clearing all decal chains
m->surfaces[j].pdecals = NULL;
m->surfaces[j].visframe = 0;
//GL_CreateSurfaceLightmap( m->surfaces + j, m );
if( m->surfaces[j].flags & SURF_DRAWTURB )
continue;
nColinElim += GL_BuildPolygonFromSurface( m, m->surfaces + j );
}
// clearing visframe
for( j = 0; j < m->numleafs; j++ )
m->leafs[j+1].visframe = 0;
for( j = 0; j < m->numnodes; j++ )
m->nodes[j].visframe = 0;
}
//LM_UploadBlock( false );
if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
{
// build lightmaps on the client-side
gEngfuncs.drawFuncs->GL_BuildLightmaps( );
}
}

View File

@@ -1,18 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
# mittorn, 2018
def options(opt):
pass
def configure(conf):
pass
def build(bld):
bld.shlib(
source = ['r_context.c', 'r_image.c', 'r_d3d.c', 'r_main.c', 'r_draw.c', 'r_surf.c', 'r_frustum.c'],
target = 'ref_dx2',
defines = 'REF_DLL',
use = 'ref_common engine_includes sdk_includes werror public USER32 DDRAW',
install_path = bld.env.LIBDIR
)

View File

@@ -1,97 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
# mittorn, 2018
from waflib.Configure import conf
from waflib import Logs
import os
VGUI_SUPPORTED_OS = ['win32', 'darwin', 'linux']
VGUI_FRAGMENT = '''#include <VGUI.h>
int main() { return 0; }'''
def options(opt):
grp = opt.add_option_group('VGUI options')
vgui_dev_path = os.path.join(opt.path.path_from(opt.root), 'vgui-dev')
grp.add_option('--vgui', action = 'store', dest = 'VGUI_DEV', default=vgui_dev_path,
help = 'path to vgui-dev repo [default: %(default)s]')
grp.add_option('--enable-unsupported-vgui', action = 'store_true', dest = 'ENABLE_UNSUPPORTED_VGUI', default=False,
help = 'ignore all checks and allow link against anything [default: %(default)s]')
grp.add_option('--skip-vgui-sanity-check', action = 'store_false', dest = 'VGUI_SANITY_CHECK', default=True,
help = 'skip checking VGUI sanity [default: %(default)s]' )
return
@conf
def check_vgui(conf):
if not conf.options.ENABLE_UNSUPPORTED_VGUI:
conf.start_msg('Does this architecture support VGUI?')
if conf.env.DEST_CPU != 'x86':
conf.end_msg('no')
Logs.warn('vgui is not supported on this CPU: ' + str(conf.env.DEST_CPU))
return False
else: conf.end_msg('yes')
conf.start_msg('Does this OS support VGUI?')
if conf.env.DEST_OS not in VGUI_SUPPORTED_OS:
conf.end_msg('no')
Logs.warn('vgui is not supported on this OS: ' + str(conf.env.DEST_OS))
return False
else: conf.end_msg('yes')
conf.start_msg('Does this toolchain able to link VGUI?')
if conf.env.DEST_OS == 'win32' and conf.env.COMPILER_CXX != 'msvc':
conf.end_msg('no')
# we have ABI incompatibility ONLY on MinGW
Logs.warn('vgui can\'t be linked with MinGW')
return False
else: conf.end_msg('yes')
conf.start_msg('Configuring VGUI by provided path')
vgui_dev = conf.options.VGUI_DEV
libpath = os.path.abspath(os.path.join(vgui_dev, 'lib'))
if conf.env.DEST_OS == 'win32':
conf.env.LIB_VGUI = ['vgui']
libpath = os.path.join(libpath, 'win32_vc6')
if conf.env.DEST_CPU != 'x86':
# for 32-bit x86 it's expected to be under win32_vc6
# for others, it's expected to be under win32_vc6 subdirectory matching CPU arch (x86_64 for 64-bit CPUs)
libpath = os.path.join(libpath, conf.env.DEST_CPU)
conf.env.LIBPATH_VGUI = [libpath]
elif conf.env.DEST_OS == 'linux':
conf.env.LIB_VGUI = [':vgui.so']
if conf.env.DEST_CPU != 'x86':
libpath = os.path.join(libpath, conf.env.DEST_CPU)
conf.env.LIBPATH_VGUI = [libpath]
elif conf.env.DEST_OS == 'darwin':
if conf.env.DEST_CPU != 'x86':
conf.env.LDFLAGS_VGUI = [os.path.join(libpath, conf.env.DEST_CPU, 'vgui.dylib')]
else:
conf.env.LDFLAGS_VGUI = [os.path.join(libpath, 'vgui.dylib')]
else:
# TODO: figure out what to do here
conf.env.LIB_VGUI = ['vgui']
conf.env.LIBPATH_VGUI = [os.path.join(libpath, conf.env.DEST_OS, conf.env.DEST_CPU)]
conf.env.INCLUDES_VGUI = [os.path.abspath(os.path.join(vgui_dev, 'include'))]
conf.env.HAVE_VGUI = 1
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env.LIB_VGUI, conf.env.LIBPATH_VGUI, conf.env.INCLUDES_VGUI))
if conf.env.HAVE_VGUI and conf.options.VGUI_SANITY_CHECK:
try:
conf.check_cxx(fragment=VGUI_FRAGMENT,
msg = 'Checking for library VGUI sanity',
use = 'VGUI',
execute = False)
except conf.errors.ConfigurationError:
conf.fatal("Can't compile simple program. Check your path to vgui-dev repository.")
return True

View File

@@ -118,7 +118,6 @@ SUBDIRS = [
Subproject('ref/common', lambda x: x.env.CLIENT),
Subproject('ref/gl', lambda x: x.env.CLIENT and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES or x.env.GLES3COMPAT)),
Subproject('ref/soft', lambda x: x.env.CLIENT and x.env.SOFT),
Subproject('ref/dx2', lambda x: x.env.CLIENT and x.env.DX2),
Subproject('ref/null', lambda x: x.env.CLIENT and x.env.NULL),
Subproject('3rdparty/bzip2', lambda x: x.env.CLIENT and not x.env.HAVE_SYSTEM_BZ2),
Subproject('3rdparty/mbedtls'),
@@ -128,6 +127,7 @@ SUBDIRS = [
Subproject('3rdparty/opusfile', lambda x: x.env.CLIENT and not x.env.HAVE_SYSTEM_OPUSFILE),
Subproject('3rdparty/maintui', lambda x: x.env.CLIENT and x.env.TUI),
Subproject('3rdparty/mainui', lambda x: x.env.CLIENT and x.env.DEST_OS != 'android'),
Subproject('3rdparty/freevgui', lambda x: x.env.CLIENT),
Subproject('3rdparty/vgui_support', lambda x: x.env.CLIENT),
Subproject('3rdparty/MultiEmulator',lambda x: x.env.CLIENT),
# Subproject('3rdparty/freevgui', lambda x: x.env.CLIENT),
@@ -152,7 +152,6 @@ REFDLLS = [
RefDll('gl4es', False),
RefDll('gles3compat', False, 'GLES3COMPAT'),
RefDll('null', False),
RefDll('dx2', False),
]
def options(opt):
@@ -497,7 +496,7 @@ def configure(conf):
# Don't check them more than once, to save time
# Usually, they are always available
# but we need them in uselib
a = [ 'user32', 'shell32', 'gdi32', 'advapi32', 'dbghelp', 'psapi', 'ws2_32', 'bcrypt', 'ddraw' ]
a = [ 'user32', 'shell32', 'gdi32', 'advapi32', 'dbghelp', 'psapi', 'ws2_32', 'bcrypt' ]
if conf.env.COMPILER_CC == 'msvc':
for i in a:
conf.start_msg('Checking for MSVC library')