Ticket #5877: 0ad_changes-for-e2k.patch

File 0ad_changes-for-e2k.patch, 130.3 KB (added by Ramil Sattarov, 3 years ago)

changes for support of e2k architecture

  • binaries/data/mods/public/gui/credits/texts/programming.json

     
    11{
    22    "Title": "Programming",
    33    "Content": [
    44        {
    55            "Title": "Programming managers",
    66            "List": [
    77                { "nick": "Acumen", "name": "Stuart Walpole" },
    88                { "nick": "Dak Lozar", "name": "Dave Loeser" },
    99                { "nick": "h20", "name": "Daniel Wilhelm" },
    1010                { "nick": "Janwas", "name": "Jan Wassenberg" },
    1111                { "nick": "Raj", "name": "Raj Sharma" }
    1212            ]
    1313        },
    1414        {
    1515            "Subtitle": "Special thanks to",
    1616            "List": [
    1717                { "nick": "leper", "name": "Georg Kilzer" },
    1818                { "nick": "Ykkrosh", "name": "Philip Taylor" }
    1919            ]
    2020        },
    2121        {
    2222            "List": [
    2323                { "nick": "01d55" },
    2424                { "nick": "aBothe", "name": "Alexander Bothe" },
    2525                { "nick": "Acumen", "name": "Stuart Walpole" },
    2626                { "nick": "adrian", "name": "Adrian Boguszewszki" },
    2727                { "name": "Adrian Fatol" },
    2828                { "nick": "AI-Amsterdam" },
    2929                { "nick": "Alan", "name": "Alan Kemp" },
    3030                { "nick": "Alex", "name": "Alexander Yakobovich" },
    3131                { "nick": "alpha123", "name": "Peter P. Cannici" },
    3232                { "nick": "Ampaex", "name": "Antonio Vazquez" },
    3333                { "name": "André Puel" },
    3434                { "nick": "andy5995", "name": "Andy Alt" },
    3535                { "nick": "Angen" },
    3636                { "nick": "Arfrever", "name": "Arfrever Frehtes Taifersar Arahesis" },
    3737                { "nick": "ArnH", "name": "Arno Hemelhof" },
    3838                { "nick": "Aurium", "name": "Aurélio Heckert" },
    3939                { "nick": "badmadblacksad", "name": "Martin F" },
    4040                { "nick": "badosu", "name": "Amadeus Folego" },
    4141                { "nick": "bb", "name": "Bouke Jansen" },
    4242                { "nick": "Ben", "name": "Ben Vinegar" },
    4343                { "nick": "Bird" },
    4444                { "nick": "Blue", "name": "Richard Welsh" },
    4545                { "nick": "bmwiedemann" },
    4646                { "nick": "boeseRaupe", "name": "Michael Kluge" },
    4747                { "nick": "bog_dan_ro", "name": "BogDan Vatra" },
    4848                { "nick": "Bonk", "name": "Christopher Ebbert" },
    4949                { "nick": "Boudica" },
    5050                { "nick": "Caius", "name": "Lars Kemmann" },
    5151                { "nick": "Calefaction", "name": "Matt Holmes" },
    5252                { "nick": "Calvinh", "name": "Carl-Johan Höiby" },
    5353                { "nick": "causative", "name": "Bart Parkis" },
    5454                { "name": "Cédric Houbart" },
    5555                { "nick": "Chakakhan", "name": "Kenny Long" },
    5656                { "nick": "Clockwork-Muse", "name": "Stephen A. Imhoff" },
    5757                { "nick": "Cracker78", "name": "Chad Heim" },
    5858                { "nick": "Crynux", "name": "Stephen J. Fewer" },
    5959                { "nick": "cwprogger" },
    6060                { "nick": "cygal", "name": "Quentin Pradet" },
    6161                { "nick": "Dak Lozar", "name": "Dave Loeser" },
    6262                { "nick": "dalerank", "name": "Sergey Kushnirenko" },
    6363                { "nick": "dan", "name": "Dan Strandberg" },
    6464                { "nick": "DanCar", "name": "Daniel Cardenas" },
    6565                { "nick": "danger89", "name": "Melroy van den Berg" },
    6666                { "name": "Daniel Trevitz" },
    6767                { "nick": "Dariost", "name": "Dario Ostuni" },
    6868                { "nick": "Dave", "name": "David Protasowski" },
    6969                { "nick": "dax", "name": "Dacian Fiordean" },
    7070                { "nick": "deebee", "name": "Deepak Anthony" },
    7171                { "nick": "Deiz" },
    7272                { "nick": "Dietger", "name": "Dietger van Antwerpen" },
    7373                { "nick": "DigitalSeraphim", "name": "Nick Owens" },
    7474                { "nick": "dp304" },
    7575                { "nick": "dpiquet", "name": "Damien Piquet" },
    7676                { "nick": "dumbo" },
    7777                { "nick": "Dunedan", "name": "Daniel Roschka" },
    7878                { "nick": "dvangennip", "name": "Doménique" },
    7979                { "nick": "Echelon9", "name": "Rhys Kidd" },
    8080                { "nick": "echotangoecho" },
    8181                { "nick": "eihrul", "name": "Lee Salzman" },
    8282                { "nick": "elexis", "name": "Alexander Heinsius" },
    8383                { "nick": "EmjeR", "name": "Matthijs de Rijk" },
    8484                { "nick": "EMontana" },
    8585                { "nick": "ericb" },
    8686                { "nick": "evanssthomas", "name": "Evans Thomas" },
    8787                { "nick": "Evulant", "name": "Alexander S." },
    8888                { "nick": "fabio", "name": "Fabio Pedretti" },
    8989                { "nick": "falsevision", "name": "Mahdi Khodadadifard" },
    9090                { "nick": "fatherbushido", "name": "Nicolas Tisserand" },
    9191                { "nick": "fcxSanya", "name": "Alexander Olkhovskiy" },
    9292                { "nick": "FeXoR", "name": "Florian Finke" },
    9393                { "nick": "Fire Giant", "name": "Malte Schwarzkopf" },
    9494                { "name": "Fork AD" },
    9595                { "nick": "fpre", "name": "Frederick Stallmeyer" },
    9696                { "nick": "Freagarach" },
    9797                { "nick": "freenity", "name": "Anton Galitch" },
    9898                { "nick": "Gallaecio", "name": "Adrián Chaves" },
    9999                { "nick": "gbish (aka Iny)", "name": "Grant Bishop" },
    100100                { "nick": "Gee", "name": "Gustav Larsson" },
    101101                { "nick": "Gentz", "name": "Hal Gentz" },
    102102                { "nick": "gerbilOFdoom" },
    103103                { "nick": "godlikeldh" },
    104104                { "nick": "greybeard", "name": "Joe Cocovich" },
    105105                { "nick": "grillaz" },
    106106                { "nick": "Grugnas", "name": "Giuseppe Tranchese" },
    107107                { "nick": "gudo" },
    108108                { "nick": "Guuts", "name": "Matthew Guttag" },
    109109                { "nick": "h20", "name": "Daniel Wilhelm" },
    110110                { "nick": "Hannibal_Barca", "name": "Clive Juhász S." },
    111111                { "nick": "Haommin" },
    112112                { "nick": "happyconcepts", "name": "Ben Bird" },
    113113                { "nick": "historic_bruno", "name": "Ben Brian" },
    114114                { "nick": "idanwin" },
    115115                { "nick": "Imarok", "name": "J. S." },
    116116                { "nick": "Inari" },
    117117                { "nick": "infyquest", "name": "Vijay Kiran Kamuju" },
    118118                { "nick": "irishninja", "name": "Brian Broll" },
    119119                { "nick": "IronNerd", "name": "Matthew McMullan" },
    120120                { "nick": "Itms", "name": "Nicolas Auvray" },
    121121                { "nick": "Jaison", "name": "Marco tom Suden" },
    122122                { "nick": "jammus", "name": "James Scott" },
    123123                { "nick": "Janwas", "name": "Jan Wassenberg" },
    124124                { "nick": "javiergodas", "name": "Javier Godas Vieitez" },
    125125                { "nick": "Jgwman" },
    126126                { "nick": "JonBaer", "name": "Jon Baer" },
    127127                { "nick": "Josh", "name": "Joshua J. Bakita" },
    128128                { "nick": "joskar", "name": "Johnny Oskarsson" },
    129129                { "nick": "jP_wanN", "name": "Jonas Platte" },
    130130                { "nick": "Jubalbarca", "name": "James Baillie" },
    131131                { "nick": "JubJub", "name": "Sebastian Vetter" },
    132132                { "nick": "jurgemaister" },
    133133                { "nick": "kabzerek", "name": "Grzegorz Kabza" },
    134134                { "nick": "Kai", "name": "Kai Chen" },
    135135                { "name": "Kareem Ergawy" },
    136136                { "nick": "kevmo", "name": "Kevin Caffrey" },
    137137                { "nick": "kezz", "name": "Graeme Kerry" },
    138138                { "nick": "kingadami", "name": "Adam Winsor" },
    139139                { "nick": "kingbasil", "name": "Giannis Fafalios" },
    140140                { "nick": "Krinkle", "name": "Timo Tijhof" },
    141141                { "nick": "lafferjm", "name": "Justin Lafferty" },
    142142                { "nick": "LeanderH", "name": "Leander Hemelhof" },
    143143                { "nick": "leper", "name": "Georg Kilzer" },
    144144                { "nick": "Link Mauve", "name": "Emmanuel Gil Peyrot" },
    145145                { "nick": "LittleDev" },
    146146                { "nick": "livingaftermidnight", "name": "Will Dull" },
    147147                { "nick": "Louhike" },
    148148                { "nick": "lsdh" },
    149149                { "nick": "Ludovic", "name": "Ludovic Rousseau" },
    150150                { "nick": "luiko", "name": "Luis Carlos Garcia Barajas" },
    151151                { "nick": "m0l0t0ph", "name": "Christoph Gielisch" },
    152152                { "nick": "madmax", "name": "Abhijit Nandy" },
    153153                { "nick": "madpilot", "name": "Guido Falsi" },
    154154                { "nick": "markcho" },
    155155                { "nick": "MarkT", "name": "Mark Thompson" },
    156156                { "nick": "Markus" },
    157157                { "nick": "Mate-86", "name": "Mate Kovacs" },
    158158                { "nick": "Matei", "name": "Matei Zaharia" },
    159159                { "nick": "MattDoerksen", "name": "Matt Doerksen" },
    160160                { "nick": "mattlott", "name": "Matt Lott" },
    161161                { "nick": "maveric", "name": "Anton Protko" },
    162162                { "nick": "Micnasty", "name": "Travis Gorkin" },
    163163                { "name": "Mikołaj \"Bajter\" Korcz" },
    164164                { "nick": "mimo" },
    165165                { "nick": "mk12", "name": "Mitchell Kember" },
    166166                { "nick": "mmayfield45", "name": "Michael Mayfield" },
    167167                { "nick": "mmoanis", "name": "Mohamed Moanis" },
    168168                { "nick": "Molotov", "name": "Dario Alvarez" },
    169169                { "nick": "mpmoreti", "name": "Marcos Paulo Moreti" },
    170170                { "nick": "mreiland", "name": "Michael Reiland" },
    171171                { "nick": "myconid" },
    172172                { "nick": "nani", "name": "S. N." },
    173173                { "nick": "nd3c3nt", "name": "Gavin Fowler" },
    174174                { "nick": "nephele" },
    175175                { "nick": "Nescio" },
    176176                { "nick": "niektb", "name": "Niek ten Brinke" },
    177177                { "nick": "njm" },
    178178                { "nick": "NoMonkey", "name": "John Mena" },
    179179                { "nick": "norsnor" },
    180180                { "nick": "notpete", "name": "Rich Cross" },
    181181                { "nick": "nwtour" },
    182182                { "nick": "odoaker", "name": "Ágoston Sipos" },
    183183                { "nick": "Offensive ePeen", "name": "Jared Ryan Bills" },
    184184                { "nick": "Ols", "name": "Oliver Whiteman" },
    185185                { "nick": "olsner", "name": "Simon Brenner" },
    186186                { "nick": "OptimusShepard", "name": "Pirmin Stanglmeier" },
    187187                { "nick": "otero" },
    188188                { "nick": "Palaxin", "name": "David A. Freitag" },
    189189                { "name": "Paul Withers" },
    190190                { "nick": "paulobezerr", "name": "Paulo George Gomes Bezerra" },
    191191                { "nick": "pcpa", "name": "Paulo Andrade" },
    192192                { "nick": "Pendingchaos" },
    193193                { "nick": "PeteVasi", "name": "Pete Vasiliauskas" },
    194194                { "nick": "pilino1234" },
    195195                { "nick": "PingvinBetyar", "name": "Schronk Tamás" },
    196196                { "nick": "plugwash", "name": "Peter Michael Green" },
    197197                { "nick": "Polakrity" },
    198198                { "nick": "Poya", "name": "Poya Manouchehri" },
    199199                { "nick": "prefect", "name": "Nicolai Hähnle" },
    200200                { "nick": "Prodigal Son" },
    201201                { "nick": "pstumpf", "name": "Pascal Stumpf" },
    202202                { "nick": "pyrolink", "name": "Andrew Decker" },
    203203                { "nick": "quantumstate", "name": "Jonathan Waller" },
    204204                { "nick": "QuickShot", "name": "Walter Krawec" },
    205205                { "nick": "quonter" },
    206206                { "nick": "qwertz" },
    207207                { "nick": "Radagast" },
    208208                { "nick": "Raj", "name": "Raj Sharma" },
    209209                { "nick": "ramtzok1", "name": "Ram" },
    210210                { "nick": "rapidelectron", "name": "Christian Weihsbach" },
     211                { "nick": "r-a-sattarov", "name": "Ramil Sattarov" },
    211212                { "nick": "RedFox", "name": "Jorma Rebane" },
    212213                { "nick": "RefinedCode" },
    213214                { "nick": "Riemer" },
    214215                { "name": "Rolf Sievers" },
    215216                { "nick": "s0600204", "name": "Matthew Norwood" },
    216217                { "nick": "sacha_vrand", "name": "Sacha Vrand" },
    217218                { "nick": "SafaAlfulaij" },
    218219                { "name": "Samuel Guarnieri" },
    219220                { "nick": "Sandarac" },
    220221                { "nick": "sanderd17", "name": "Sander Deryckere" },
    221222                { "nick": "sathyam", "name": "Sathyam Vellal" },
    222223                { "nick": "sbirmi", "name": "Sharad Birmiwal" },
    223224                { "nick": "sbte", "name": "Sven Baars" },
    224225                { "nick": "scroogie", "name": "André Gemünd" },
    225226                { "nick": "scythetwirler", "name": "Casey X." },
    226227                { "nick": "serveurix" },
    227228                { "nick": "Shane", "name": "Shane Grant" },
    228229                { "nick": "shh" },
    229230                { "nick": "Silk", "name": "Josh Godsiff" },
    230231                { "nick": "silure" },
    231232                { "nick": "Simikolon", "name": "Yannick & Simon" },
    232233                { "nick": "smiley", "name": "M. L." },
    233234                { "nick": "Spahbod", "name": "Omid Davoodi" },
    234235                { "nick": "Stan", "name": "Stanislas Dolcini" },
    235236                { "nick": "Stefan" },
    236237                { "nick": "StefanBruens", "name": "Stefan Brüns" },
    237238                { "nick": "stilz", "name": "Sławomir Zborowski" },
    238239                { "nick": "stwf", "name": "Steven Fuchs" },
    239240                { "nick": "svott", "name": "Sven Ott" },
    240241                { "nick": "t4nk004" },
    241242                { "nick": "tau" },
    242243                { "nick": "tbm", "name": "Martin Michlmayr" },
    243244                { "nick": "Teiresias" },
    244245                { "nick": "temple" },
    245246                { "nick": "texane" },
    246247                { "nick": "thamlett", "name": "Timothy Hamlett" },
    247248                { "nick": "thedrunkyak", "name": "Dan Fuhr" },
    248249                { "nick": "Tobbi" },
    249250                { "nick": "TrinityDeath", "name": "Jethro Lu" },
    250251                { "nick": "triumvir", "name": "Corin Schedler" },
    251252                { "nick": "trompetin17", "name": "Juan Guillermo" },
    252253                { "nick": "user1", "name": "A. C." },
    253254                { "nick": "usey11" },
    254255                { "nick": "vincent_c", "name": "Vincent Cheng" },
    255256                { "nick": "vinhig", "name": "Vincent Higginson" },
    256257                { "nick": "vladislavbelov", "name": "Vladislav Belov" },
    257258                { "nick": "voroskoi" },
    258259                { "nick": "vts", "name": "Jeroen DR" },
    259260                { "nick": "wacko", "name": "Andrew Spiering" },
    260261                { "nick": "WhiteTreePaladin", "name": "Brian Ashley" },
    261262                { "nick": "wraitii", "name": "Lancelot de Ferrière le Vayer" },
    262263                { "nick": "Xentelian", "name": "Mark Strawson" },
    263264                { "nick": "Xienen", "name": "Dayle Flowers" },
    264265                { "nick": "xtizer", "name": "Matt Green" },
    265266                { "nick": "yashi", "name": "Yasushi Shoji" },
    266267                { "nick": "Ykkrosh", "name": "Philip Taylor" },
    267268                { "nick": "Yves" },
    268269                { "nick": "Zeusthor", "name": "Jeffrey Tavares" },
    269270                { "nick": "zoot" },
    270271                { "nick": "zsol", "name": "Zsolt Dollenstein" },
    271272                { "nick": "ztamas", "name": "Tamas Zolnai" },
    272273                { "nick": "Zyi", "name": "Charles De Meulenaer" }
    273274            ]
    274275        }
    275276    ]
    276277}
  • build/premake/premake5.lua

     
    11newoption { trigger = "android", description = "Use non-working Android cross-compiling mode" }
    22newoption { trigger = "atlas", description = "Include Atlas scenario editor projects" }
    33newoption { trigger = "coverage", description = "Enable code coverage data collection (GCC only)" }
    44newoption { trigger = "gles", description = "Use non-working OpenGL ES 2.0 mode" }
    55newoption { trigger = "icc", description = "Use Intel C++ Compiler (Linux only; should use either \"--cc icc\" or --without-pch too, and then set CXX=icpc before calling make)" }
    66newoption { trigger = "jenkins-tests", description = "Configure CxxTest to use the XmlPrinter runner which produces Jenkins-compatible output" }
    77newoption { trigger = "minimal-flags", description = "Only set compiler/linker flags that are really needed. Has no effect on Windows builds" }
    88newoption { trigger = "outpath", description = "Location for generated project files" }
    99newoption { trigger = "with-system-mozjs", description = "Search standard paths for libmozjs60, instead of using bundled copy" }
    1010newoption { trigger = "with-system-nvtt", description = "Search standard paths for nvidia-texture-tools library, instead of using bundled copy" }
    1111newoption { trigger = "without-audio", description = "Disable use of OpenAL/Ogg/Vorbis APIs" }
    1212newoption { trigger = "without-lobby", description = "Disable the use of gloox and the multiplayer lobby" }
    1313newoption { trigger = "without-miniupnpc", description = "Disable use of miniupnpc for port forwarding" }
    1414newoption { trigger = "without-nvtt", description = "Disable use of NVTT" }
    1515newoption { trigger = "without-pch", description = "Disable generation and usage of precompiled headers" }
    1616newoption { trigger = "without-tests", description = "Disable generation of test projects" }
    1717
    1818-- Linux/BSD specific options
    1919newoption { trigger = "prefer-local-libs", description = "Prefer locally built libs. Any local libraries used must also be listed within a file within /etc/ld.so.conf.d so the dynamic linker can find them at runtime." }
    2020
    2121-- OS X specific options
    2222newoption { trigger = "macosx-bundle", description = "Enable OSX bundle, the argument is the bundle identifier string (e.g. com.wildfiregames.0ad)" }
    2323newoption { trigger = "macosx-version-min", description = "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)" }
    2424newoption { trigger = "sysroot", description = "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local" }
    2525
    2626-- Windows specific options
    2727newoption { trigger = "build-shared-glooxwrapper", description = "Rebuild glooxwrapper DLL for Windows. Requires the same compiler version that gloox was built with" }
    2828newoption { trigger = "use-shared-glooxwrapper", description = "Use prebuilt glooxwrapper DLL for Windows" }
    2929newoption { trigger = "large-address-aware", description = "Make the executable large address aware. Do not use for development, in order to spot memory issues easily" }
    3030
    3131-- Install options
    3232newoption { trigger = "bindir", description = "Directory for executables (typically '/usr/games'); default is to be relocatable" }
    3333newoption { trigger = "datadir", description = "Directory for data files (typically '/usr/share/games/0ad'); default is ../data/ relative to executable" }
    3434newoption { trigger = "libdir", description = "Directory for libraries (typically '/usr/lib/games/0ad'); default is ./ relative to executable" }
    3535
    3636-- Root directory of project checkout relative to this .lua file
    3737rootdir = "../.."
    3838
    3939dofile("extern_libs5.lua")
    4040
    4141-- detect compiler for non-Windows
    4242if os.istarget("macosx") then
    4343    cc = "clang"
    4444elseif os.istarget("linux") and _OPTIONS["icc"] then
    4545    cc = "icc"
    4646elseif not os.istarget("windows") then
    4747    cc = os.getenv("CC")
    4848    if cc == nil or cc == "" then
    4949        local hasgcc = os.execute("which gcc > .gccpath")
    5050        local f = io.open(".gccpath", "r")
    5151        local gccpath = f:read("*line")
    5252        f:close()
    5353        os.execute("rm .gccpath")
    5454        if gccpath == nil then
    5555            cc = "clang"
    5656        else
    5757            cc = "gcc"
    5858        end
    5959    end
    6060end
    6161
    6262-- detect CPU architecture (simplistic, currently only supports x86, amd64 and ARM)
    6363arch = "x86"
    6464if _OPTIONS["android"] then
    6565    arch = "arm"
    6666elseif os.istarget("windows") then
    6767    if os.getenv("PROCESSOR_ARCHITECTURE") == "amd64" or os.getenv("PROCESSOR_ARCHITEW6432") == "amd64" then
    6868        arch = "amd64"
    6969    end
    7070else
    7171    arch = os.getenv("HOSTTYPE")
    7272    if arch == "x86_64" or arch == "amd64" then
    7373        arch = "amd64"
    7474    else
    7575        os.execute(cc .. " -dumpmachine > .gccmachine.tmp")
    7676        local f = io.open(".gccmachine.tmp", "r")
    7777        local machine = f:read("*line")
    7878        f:close()
    7979        if string.find(machine, "x86_64") == 1 or string.find(machine, "amd64") == 1 then
    8080            arch = "amd64"
    8181        elseif string.find(machine, "i.86") == 1 then
    8282            arch = "x86"
    8383        elseif string.find(machine, "arm") == 1 then
    8484            arch = "arm"
    8585        elseif string.find(machine, "aarch64") == 1 then
    8686            arch = "aarch64"
     87        elseif string.find(machine, "e2k") == 1 then
     88            arch = "e2k"
    8789        else
    8890            print("WARNING: Cannot determine architecture from GCC, assuming x86")
    8991        end
    9092    end
    9193end
    9294
    9395-- Test whether we need to link libexecinfo.
    9496-- This is mostly the case on musl systems, as well as on BSD systems : only glibc provides the
    9597-- backtrace symbols we require in the libc, for other libcs we use the libexecinfo library.
    9698local link_execinfo = false
    9799if os.istarget("bsd") then
    98100    link_execinfo = true
    99101elseif os.istarget("linux") then
    100102    local _, link_errorCode = os.outputof(cc .. " ./tests/execinfo.c -o /dev/null")
    101103    if link_errorCode ~= 0 then
    102104        link_execinfo = true
    103105    end
    104106end
    105107
    106108-- Set up the Workspace
    107109workspace "pyrogenesis"
    108110targetdir(rootdir.."/binaries/system")
    109111libdirs(rootdir.."/binaries/system")
    110112if not _OPTIONS["outpath"] then
    111113    error("You must specify the 'outpath' parameter")
    112114end
    113115location(_OPTIONS["outpath"])
    114116configurations { "Release", "Debug" }
    115117
    116118source_root = rootdir.."/source/" -- default for most projects - overridden by local in others
    117119
    118120-- Rationale: projects should not have any additional include paths except for
    119121-- those required by external libraries. Instead, we should always write the
    120122-- full relative path, e.g. #include "maths/Vector3d.h". This avoids confusion
    121123-- ("which file is meant?") and avoids enormous include path lists.
    122124
    123125
    124126-- projects: engine static libs, main exe, atlas, atlas frontends, test.
    125127
    126128--------------------------------------------------------------------------------
    127129-- project helper functions
    128130--------------------------------------------------------------------------------
    129131
    130132function project_set_target(project_name)
    131133
    132134    -- Note: On Windows, ".exe" is added on the end, on unices the name is used directly
    133135
    134136    local obj_dir_prefix = _OPTIONS["outpath"].."/obj/"..project_name.."_"
    135137
    136138    filter "Debug"
    137139        objdir(obj_dir_prefix.."Debug")
    138140        targetsuffix("_dbg")
    139141
    140142    filter "Release"
    141143        objdir(obj_dir_prefix.."Release")
    142144
    143145    filter { }
    144146
    145147end
    146148
    147149
    148150function project_set_build_flags()
    149151
    150152    editandcontinue "Off"
    151153
    152154    if not _OPTIONS["minimal-flags"] then
    153155        symbols "On"
    154156    end
    155157
    156158    if cc ~= "icc" and (os.istarget("windows") or not _OPTIONS["minimal-flags"]) then
    157159        -- adds the -Wall compiler flag
    158160        warnings "Extra" -- this causes far too many warnings/remarks on ICC
    159161    end
    160162
    161163    -- disable Windows debug heap, since it makes malloc/free hugely slower when
    162164    -- running inside a debugger
    163165    if os.istarget("windows") then
    164166        debugenvs { "_NO_DEBUG_HEAP=1" }
    165167    end
    166168
    167169    filter "Debug"
    168170        defines { "DEBUG" }
    169171
    170172    filter "Release"
    171173        if os.istarget("windows") or not _OPTIONS["minimal-flags"] then
    172174            optimize "Speed"
    173175        end
    174176        defines { "NDEBUG", "CONFIG_FINAL=1" }
    175177
    176178    filter { }
    177179
    178180    if _OPTIONS["gles"] then
    179181        defines { "CONFIG2_GLES=1" }
    180182    end
    181183
    182184    if _OPTIONS["without-audio"] then
    183185        defines { "CONFIG2_AUDIO=0" }
    184186    end
    185187
    186188    if _OPTIONS["without-nvtt"] then
    187189        defines { "CONFIG2_NVTT=0" }
    188190    end
    189191
    190192    if _OPTIONS["without-lobby"] then
    191193        defines { "CONFIG2_LOBBY=0" }
    192194    end
    193195
    194196    if _OPTIONS["without-miniupnpc"] then
    195197        defines { "CONFIG2_MINIUPNPC=0" }
    196198    end
    197199
    198200    -- required for the lowlevel library. must be set from all projects that use it, otherwise it assumes it is
    199201    -- being used as a DLL (which is currently not the case in 0ad)
    200202    defines { "LIB_STATIC_LINK" }
    201203
    202204    -- Enable C++17 standard.
    203205    filter "action:vs*"
    204206        buildoptions { "/std:c++17" }
    205207    filter "action:not vs*"
    206208        buildoptions { "-std=c++17" }
    207209    filter {}
    208210
    209211    -- various platform-specific build flags
    210212    if os.istarget("windows") then
    211213
    212214        flags { "MultiProcessorCompile" }
    213215
    214216        -- use native wchar_t type (not typedef to unsigned short)
    215217        nativewchar "on"
    216218
    217219    else    -- *nix
    218220
    219221        -- TODO, FIXME: This check is incorrect because it means that some additional flags will be added inside the "else" branch if the
    220222        -- compiler is ICC and minimal-flags is specified (ticket: #2994)
    221223        if cc == "icc" and not _OPTIONS["minimal-flags"] then
    222224            buildoptions {
    223225                "-w1",
    224226                -- "-Wabi",
    225227                -- "-Wp64", -- complains about OBJECT_TO_JSVAL which is annoying
    226228                "-Wpointer-arith",
    227229                "-Wreturn-type",
    228230                -- "-Wshadow",
    229231                "-Wuninitialized",
    230232                "-Wunknown-pragmas",
    231233                "-Wunused-function",
    232234                "-wd1292" -- avoid lots of 'attribute "__nonnull__" ignored'
    233235            }
    234236            filter "Debug"
    235237                buildoptions { "-O0" } -- ICC defaults to -O2
    236238            filter { }
    237239            if os.istarget("macosx") then
    238240                linkoptions { "-multiply_defined","suppress" }
    239241            end
    240242        else
    241243            -- exclude most non-essential build options for minimal-flags
    242244            if not _OPTIONS["minimal-flags"] then
    243245                buildoptions {
    244246                    -- enable most of the standard warnings
    245247                    "-Wno-switch",      -- enumeration value not handled in switch (this is sometimes useful, but results in lots of noise)
    246248                    "-Wno-reorder",     -- order of initialization list in constructors (lots of noise)
    247249                    "-Wno-invalid-offsetof",    -- offsetof on non-POD types (see comment in renderer/PatchRData.cpp)
    248250
    249251                    "-Wextra",
    250252                    "-Wno-missing-field-initializers",  -- (this is common in external headers we can't fix)
    251253
    252254                    -- add some other useful warnings that need to be enabled explicitly
    253255                    "-Wunused-parameter",
    254256                    "-Wredundant-decls",    -- (useful for finding some multiply-included header files)
    255257                    -- "-Wformat=2",        -- (useful sometimes, but a bit noisy, so skip it by default)
    256258                    -- "-Wcast-qual",       -- (useful for checking const-correctness, but a bit noisy, so skip it by default)
    257259                    "-Wnon-virtual-dtor",   -- (sometimes noisy but finds real bugs)
    258260                    "-Wundef",              -- (useful for finding macro name typos)
    259261
    260262                    -- enable security features (stack checking etc) that shouldn't have
    261263                    -- a significant effect on performance and can catch bugs
    262264                    "-fstack-protector-all",
    263265                    "-U_FORTIFY_SOURCE",    -- (avoid redefinition warning if already defined)
    264266                    "-D_FORTIFY_SOURCE=2",
    265267
    266268                    -- always enable strict aliasing (useful in debug builds because of the warnings)
    267269                    "-fstrict-aliasing",
    268270
    269271                    -- don't omit frame pointers (for now), because performance will be impacted
    270272                    -- negatively by the way this breaks profilers more than it will be impacted
    271273                    -- positively by the optimisation
    272274                    "-fno-omit-frame-pointer"
    273275                }
    274276
    275277                if not _OPTIONS["without-pch"] then
    276278                    buildoptions {
    277279                        -- do something (?) so that ccache can handle compilation with PCH enabled
    278280                        -- (ccache 3.1+ also requires CCACHE_SLOPPINESS=time_macros for this to work)
    279281                        "-fpch-preprocess"
    280282                    }
    281283                end
    282284
    283285                if os.istarget("linux") or os.istarget("bsd") then
    284286                    buildoptions { "-fPIC" }
    285287                    linkoptions { "-Wl,--no-undefined", "-Wl,--as-needed", "-Wl,-z,relro" }
    286288                end
    287289
    288290                if arch == "x86" then
    289291                    buildoptions {
    290292                        -- To support intrinsics like __sync_bool_compare_and_swap on x86
    291293                        -- we need to set -march to something that supports them (i686).
    292294                        -- We use pentium3 to also enable other features like mmx and sse,
    293295                        -- while tuning for generic to have good performance on every
    294296                        -- supported CPU.
    295297                        -- Note that all these features are already supported on amd64.
    296298                        "-march=pentium3 -mtune=generic"
    297299                    }
    298300                end
    299301            end
    300302
    301303            if arch == "arm" then
    302304                -- disable warnings about va_list ABI change and use
    303305                -- compile-time flags for futher configuration.
    304306                buildoptions { "-Wno-psabi" }
    305307                if _OPTIONS["android"] then
    306308                    -- Android uses softfp, so we should too.
    307309                    buildoptions { "-mfloat-abi=softfp" }
    308310                end
    309311            end
    310312
    311313            if _OPTIONS["coverage"] then
    312314                buildoptions { "-fprofile-arcs", "-ftest-coverage" }
    313315                links { "gcov" }
    314316            end
    315317
    316318            -- MacOS 10.12 only supports processors with SSE 4.1, so enable that.
    317319            if os.istarget("macosx") then
    318320                buildoptions { "-msse4.1" }
    319321            end
    320322
    321323            -- Check if SDK path should be used
    322324            if _OPTIONS["sysroot"] then
    323325                buildoptions { "-isysroot " .. _OPTIONS["sysroot"] }
    324326                linkoptions { "-Wl,-syslibroot," .. _OPTIONS["sysroot"] }
    325327            end
    326328
    327329            -- On OS X, sometimes we need to specify the minimum API version to use
    328330            if _OPTIONS["macosx-version-min"] then
    329331                buildoptions { "-mmacosx-version-min=" .. _OPTIONS["macosx-version-min"] }
    330332                -- clang and llvm-gcc look at mmacosx-version-min to determine link target
    331333                -- and CRT version, and use it to set the macosx_version_min linker flag
    332334                linkoptions { "-mmacosx-version-min=" .. _OPTIONS["macosx-version-min"] }
    333335            end
    334336
    335337            -- Check if we're building a bundle
    336338            if _OPTIONS["macosx-bundle"] then
    337339                defines { "BUNDLE_IDENTIFIER=" .. _OPTIONS["macosx-bundle"] }
    338340            end
    339341
    340342            -- Only libc++ is supported on MacOS
    341343            if os.istarget("macosx") then
    342344                buildoptions { "-stdlib=libc++" }
    343345                linkoptions { "-stdlib=libc++" }
    344346            end
    345347        end
    346348
    347349        buildoptions {
    348350            -- Hide symbols in dynamic shared objects by default, for efficiency and for equivalence with
    349351            -- Windows - they should be exported explicitly with __attribute__ ((visibility ("default")))
    350352            "-fvisibility=hidden"
    351353        }
    352354
    353355        if _OPTIONS["bindir"] then
    354356            defines { "INSTALLED_BINDIR=" .. _OPTIONS["bindir"] }
    355357        end
    356358        if _OPTIONS["datadir"] then
    357359            defines { "INSTALLED_DATADIR=" .. _OPTIONS["datadir"] }
    358360        end
    359361        if _OPTIONS["libdir"] then
    360362            defines { "INSTALLED_LIBDIR=" .. _OPTIONS["libdir"] }
    361363        end
    362364
    363365        if os.istarget("linux") or os.istarget("bsd") then
    364366            if _OPTIONS["prefer-local-libs"] then
    365367                libdirs { "/usr/local/lib" }
    366368            end
    367369
    368370            -- To use our local shared libraries, they need to be found in the
    369371            -- runtime dynamic linker path. Add their path to -rpath.
    370372            if _OPTIONS["libdir"] then
    371373                linkoptions {"-Wl,-rpath," .. _OPTIONS["libdir"] }
    372374            else
    373375                -- On FreeBSD we need to allow use of $ORIGIN
    374376                if os.istarget("bsd") then
    375377                    linkoptions { "-Wl,-z,origin" }
    376378                end
    377379
    378380                -- Adding the executable path and taking care of correct escaping
    379381                if _ACTION == "gmake" then
    380382                    linkoptions { "-Wl,-rpath,'$$ORIGIN'" }
    381383                elseif _ACTION == "codeblocks" then
    382384                    linkoptions { "-Wl,-R\\\\$$$ORIGIN" }
    383385                end
    384386            end
    385387        end
    386388
    387389    end
    388390end
    389391
    390392-- create a project and set the attributes that are common to all projects.
    391393function project_create(project_name, target_type)
    392394
    393395    project(project_name)
    394396    language "C++"
    395397    kind(target_type)
    396398
    397399    filter "action:vs2017"
    398400        toolset "v141_xp"
    399401    filter {}
    400402
    401403    filter "action:vs*"
    402404        buildoptions "/utf-8"
    403405    filter {}
    404406
    405407    project_set_target(project_name)
    406408    project_set_build_flags()
    407409end
    408410
    409411
    410412-- OSX creates a .app bundle if the project type of the main application is set to "WindowedApp".
    411413-- We don't want this because this bundle would be broken (it lacks all the resources and external dependencies, Info.plist etc...)
    412414-- Windows opens a console in the background if it's set to ConsoleApp, which is not what we want.
    413415-- I didn't check if this setting matters for linux, but WindowedApp works there.
    414416function get_main_project_target_type()
    415417    if _OPTIONS["android"] then
    416418        return "SharedLib"
    417419    elseif os.istarget("macosx") then
    418420        return "ConsoleApp"
    419421    else
    420422        return "WindowedApp"
    421423    end
    422424end
    423425
    424426
    425427-- source_root: rel_source_dirs and rel_include_dirs are relative to this directory
    426428-- rel_source_dirs: A table of subdirectories. All source files in these directories are added.
    427429-- rel_include_dirs: A table of subdirectories to be included.
    428430-- extra_params: table including zero or more of the following:
    429431-- * no_pch: If specified, no precompiled headers are used for this project.
    430432-- * pch_dir: If specified, this directory will be used for precompiled headers instead of the default
    431433--   <source_root>/pch/<projectname>/.
    432434-- * extra_files: table of filenames (relative to source_root) to add to project
    433435-- * extra_links: table of library names to add to link step
    434436function project_add_contents(source_root, rel_source_dirs, rel_include_dirs, extra_params)
    435437
    436438    for i,v in pairs(rel_source_dirs) do
    437439        local prefix = source_root..v.."/"
    438440        files { prefix.."*.cpp", prefix.."*.h", prefix.."*.inl", prefix.."*.js", prefix.."*.asm", prefix.."*.mm" }
    439441    end
    440442
    441443    -- Put the project-specific PCH directory at the start of the
    442444    -- include path, so '#include "precompiled.h"' will look in
    443445    -- there first
    444446    local pch_dir
    445447    if not extra_params["pch_dir"] then
    446448        pch_dir = source_root .. "pch/" .. project().name .. "/"
    447449    else
    448450        pch_dir = extra_params["pch_dir"]
    449451    end
    450452    includedirs { pch_dir }
    451453
    452454    -- Precompiled Headers
    453455    -- rationale: we need one PCH per static lib, since one global header would
    454456    -- increase dependencies. To that end, we can either include them as
    455457    -- "projectdir/precompiled.h", or add "source/PCH/projectdir" to the
    456458    -- include path and put the PCH there. The latter is better because
    457459    -- many projects contain several dirs and it's unclear where there the
    458460    -- PCH should be stored. This way is also a bit easier to use in that
    459461    -- source files always include "precompiled.h".
    460462    -- Notes:
    461463    -- * Visual Assist manages to use the project include path and can
    462464    --   correctly open these files from the IDE.
    463465    -- * precompiled.cpp (needed to "Create" the PCH) also goes in
    464466    --   the abovementioned dir.
    465467    if (not _OPTIONS["without-pch"] and not extra_params["no_pch"]) then
    466468        filter "action:vs*"
    467469            pchheader("precompiled.h")
    468470        filter "action:xcode*"
    469471            pchheader("../"..pch_dir.."precompiled.h")
    470472        filter { "action:not vs*", "action:not xcode*" }
    471473            pchheader(pch_dir.."precompiled.h")
    472474        filter {}
    473475        pchsource(pch_dir.."precompiled.cpp")
    474476        defines { "CONFIG_ENABLE_PCH=1" }
    475477        files { pch_dir.."precompiled.h", pch_dir.."precompiled.cpp" }
    476478    else
    477479        defines { "CONFIG_ENABLE_PCH=0" }
    478480        flags { "NoPCH" }
    479481    end
    480482
    481483    -- next is source root dir, for absolute (nonrelative) includes
    482484    -- (e.g. "lib/precompiled.h")
    483485    includedirs { source_root }
    484486
    485487    for i,v in pairs(rel_include_dirs) do
    486488        includedirs { source_root .. v }
    487489    end
    488490
    489491    if extra_params["extra_files"] then
    490492        for i,v in pairs(extra_params["extra_files"]) do
    491493            -- .rc files are only needed on Windows
    492494            if path.getextension(v) ~= ".rc" or os.istarget("windows") then
    493495                files { source_root .. v }
    494496            end
    495497        end
    496498    end
    497499
    498500    if extra_params["extra_links"] then
    499501        links { extra_params["extra_links"] }
    500502    end
    501503end
    502504
    503505
    504506-- Add command-line options to set up the manifest dependencies for Windows
    505507-- (See lib/sysdep/os/win/manifest.cpp)
    506508function project_add_manifest()
    507509    linkoptions { "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df'\"" }
    508510end
    509511
    510512--------------------------------------------------------------------------------
    511513-- engine static libraries
    512514--------------------------------------------------------------------------------
    513515
    514516-- the engine is split up into several static libraries. this eases separate
    515517-- distribution of those components, reduces dependencies a bit, and can
    516518-- also speed up builds.
    517519-- more to the point, it is necessary to efficiently support a separate
    518520-- test executable that also includes much of the game code.
    519521
    520522-- names of all static libs created. automatically added to the
    521523-- main app project later (see explanation at end of this file)
    522524static_lib_names = {}
    523525static_lib_names_debug = {}
    524526static_lib_names_release = {}
    525527
    526528-- set up one of the static libraries into which the main engine code is split.
    527529-- extra_params:
    528530--  no_default_link: If specified, linking won't be done by default.
    529531--  For the rest of extra_params, see project_add_contents().
    530532-- note: rel_source_dirs and rel_include_dirs are relative to global source_root.
    531533function setup_static_lib_project (project_name, rel_source_dirs, extern_libs, extra_params)
    532534
    533535    local target_type = "StaticLib"
    534536    project_create(project_name, target_type)
    535537    project_add_contents(source_root, rel_source_dirs, {}, extra_params)
    536538    project_add_extern_libs(extern_libs, target_type)
    537539
    538540    if not extra_params["no_default_link"] then
    539541        table.insert(static_lib_names, project_name)
    540542    end
    541543
    542544    -- Deactivate Run Time Type Information. Performance of dynamic_cast is very poor.
    543545    -- The exception to this principle is Atlas UI, which is not a static library.
    544546    rtti "off"
    545547
    546548    if os.istarget("macosx") and _OPTIONS["macosx-version-min"] then
    547549        xcodebuildsettings { MACOSX_DEPLOYMENT_TARGET = _OPTIONS["macosx-version-min"] }
    548550    end
    549551end
    550552
    551553function setup_third_party_static_lib_project (project_name, rel_source_dirs, extern_libs, extra_params)
    552554
    553555    setup_static_lib_project(project_name, rel_source_dirs, extern_libs, extra_params)
    554556    includedirs { source_root .. "third_party/" .. project_name .. "/include/" }
    555557end
    556558
    557559function setup_shared_lib_project (project_name, rel_source_dirs, extern_libs, extra_params)
    558560
    559561    local target_type = "SharedLib"
    560562    project_create(project_name, target_type)
    561563    project_add_contents(source_root, rel_source_dirs, {}, extra_params)
    562564    project_add_extern_libs(extern_libs, target_type)
    563565
    564566    if not extra_params["no_default_link"] then
    565567        table.insert(static_lib_names, project_name)
    566568    end
    567569
    568570    if os.istarget("windows") then
    569571        links { "delayimp" }
    570572    elseif os.istarget("macosx") and _OPTIONS["macosx-version-min"] then
    571573        xcodebuildsettings { MACOSX_DEPLOYMENT_TARGET = _OPTIONS["macosx-version-min"] }
    572574    end
    573575end
    574576
    575577
    576578-- this is where the source tree is chopped up into static libs.
    577579-- can be changed very easily; just copy+paste a new setup_static_lib_project,
    578580-- or remove existing ones. static libs are automagically added to
    579581-- main_exe link step.
    580582function setup_all_libs ()
    581583
    582584    -- relative to global source_root.
    583585    local source_dirs = {}
    584586    -- names of external libraries used (see libraries_dir comment)
    585587    local extern_libs = {}
    586588
    587589
    588590    source_dirs = {
    589591        "network",
    590592    }
    591593    extern_libs = {
    592594        "spidermonkey",
    593595        "enet",
    594596        "boost",    -- dragged in via server->simulation.h->random
    595597        "fmt",
    596598    }
    597599    if not _OPTIONS["without-miniupnpc"] then
    598600        table.insert(extern_libs, "miniupnpc")
    599601    end
    600602    setup_static_lib_project("network", source_dirs, extern_libs, {})
    601603
    602604    source_dirs = {
    603605        "rlinterface",
    604606    }
    605607    extern_libs = {
    606608        "boost", -- dragged in via simulation.h and scriptinterface.h
    607609        "fmt",
    608610        "spidermonkey",
    609611    }
    610612    setup_static_lib_project("rlinterface", source_dirs, extern_libs, { no_pch = 1 })
    611613
    612614    source_dirs = {
    613615        "third_party/tinygettext/src",
    614616    }
    615617    extern_libs = {
    616618        "iconv",
    617619        "boost",
    618620        "fmt",
    619621    }
    620622    setup_third_party_static_lib_project("tinygettext", source_dirs, extern_libs, { } )
    621623
    622624    -- it's an external library and we don't want to modify its source to fix warnings, so we just disable them to avoid noise in the compile output
    623625    filter "action:vs*"
    624626        buildoptions {
    625627            "/wd4127",
    626628            "/wd4309",
    627629            "/wd4800",
    628630            "/wd4100",
    629631            "/wd4996",
    630632            "/wd4099",
    631633            "/wd4503"
    632634        }
    633635    filter {}
    634636
    635637
    636638    if not _OPTIONS["without-lobby"] then
    637639        source_dirs = {
    638640            "lobby",
    639641            "lobby/scripting",
    640642            "i18n",
    641643            "third_party/encryption"
    642644        }
    643645
    644646        extern_libs = {
    645647            "spidermonkey",
    646648            "boost",
    647649            "enet",
    648650            "gloox",
    649651            "icu",
    650652            "iconv",
    651653            "libsodium",
    652654            "tinygettext",
    653655            "fmt",
    654656        }
    655657        setup_static_lib_project("lobby", source_dirs, extern_libs, {})
    656658
    657659        if _OPTIONS["use-shared-glooxwrapper"] and not _OPTIONS["build-shared-glooxwrapper"] then
    658660            table.insert(static_lib_names_debug, "glooxwrapper_dbg")
    659661            table.insert(static_lib_names_release, "glooxwrapper")
    660662        else
    661663            source_dirs = {
    662664                "lobby/glooxwrapper",
    663665            }
    664666            extern_libs = {
    665667                "boost",
    666668                "gloox",
    667669                "fmt",
    668670            }
    669671            if _OPTIONS["build-shared-glooxwrapper"] then
    670672                setup_shared_lib_project("glooxwrapper", source_dirs, extern_libs, {})
    671673            else
    672674                setup_static_lib_project("glooxwrapper", source_dirs, extern_libs, {})
    673675            end
    674676        end
    675677    else
    676678        source_dirs = {
    677679            "lobby/scripting",
    678680            "third_party/encryption"
    679681        }
    680682        extern_libs = {
    681683            "spidermonkey",
    682684            "boost",
    683685            "libsodium",
    684686            "fmt",
    685687        }
    686688        setup_static_lib_project("lobby", source_dirs, extern_libs, {})
    687689        files { source_root.."lobby/Globals.cpp" }
    688690    end
    689691
    690692
    691693    source_dirs = {
    692694        "simulation2",
    693695        "simulation2/components",
    694696        "simulation2/helpers",
    695697        "simulation2/scripting",
    696698        "simulation2/serialization",
    697699        "simulation2/system",
    698700        "simulation2/testcomponents",
    699701    }
    700702    extern_libs = {
    701703        "boost",
    702704        "opengl",
    703705        "spidermonkey",
    704706        "fmt",
    705707    }
    706708    setup_static_lib_project("simulation2", source_dirs, extern_libs, {})
    707709
    708710
    709711    source_dirs = {
    710712        "scriptinterface",
    711713        "scriptinterface/third_party"
    712714    }
    713715    extern_libs = {
    714716        "boost",
    715717        "spidermonkey",
    716718        "valgrind",
    717719        "sdl",
    718720        "fmt",
    719721    }
    720722    setup_static_lib_project("scriptinterface", source_dirs, extern_libs, {})
    721723
    722724
    723725    source_dirs = {
    724726        "ps",
    725727        "ps/scripting",
    726728        "network/scripting",
    727729        "ps/GameSetup",
    728730        "ps/XML",
    729731        "soundmanager",
    730732        "soundmanager/data",
    731733        "soundmanager/items",
    732734        "soundmanager/scripting",
    733735        "maths",
    734736        "maths/scripting",
    735737        "i18n",
    736738        "i18n/scripting",
    737739    }
    738740    extern_libs = {
    739741        "spidermonkey",
    740742        "sdl",  -- key definitions
    741743        "libxml2",
    742744        "opengl",
    743745        "zlib",
    744746        "boost",
    745747        "enet",
    746748        "libcurl",
    747749        "tinygettext",
    748750        "icu",
    749751        "iconv",
    750752        "libsodium",
    751753        "fmt",
    752754    }
    753755
    754756    if not _OPTIONS["without-audio"] then
    755757        table.insert(extern_libs, "openal")
    756758        table.insert(extern_libs, "vorbis")
    757759    end
    758760
    759761    setup_static_lib_project("engine", source_dirs, extern_libs, {})
    760762
    761763
    762764    source_dirs = {
    763765        "graphics",
    764766        "graphics/scripting",
    765767        "renderer",
    766768        "renderer/scripting",
    767769        "third_party/mikktspace",
    768770        "third_party/ogre3d_preprocessor"
    769771    }
    770772    extern_libs = {
    771773        "opengl",
    772774        "sdl",  -- key definitions
    773775        "spidermonkey", -- for graphics/scripting
    774776        "boost",
    775777        "fmt",
    776778    }
    777779    if not _OPTIONS["without-nvtt"] then
    778780        table.insert(extern_libs, "nvtt")
    779781    end
    780782    setup_static_lib_project("graphics", source_dirs, extern_libs, {})
    781783
    782784
    783785    source_dirs = {
    784786        "tools/atlas/GameInterface",
    785787        "tools/atlas/GameInterface/Handlers"
    786788    }
    787789    extern_libs = {
    788790        "boost",
    789791        "sdl",  -- key definitions
    790792        "opengl",
    791793        "spidermonkey",
    792794        "fmt",
    793795    }
    794796    setup_static_lib_project("atlas", source_dirs, extern_libs, {})
    795797
    796798
    797799    source_dirs = {
    798800        "gui",
    799801        "gui/ObjectTypes",
    800802        "gui/ObjectBases",
    801803        "gui/Scripting",
    802804        "gui/SettingTypes",
    803805        "i18n"
    804806    }
    805807    extern_libs = {
    806808        "spidermonkey",
    807809        "sdl",  -- key definitions
    808810        "opengl",
    809811        "boost",
    810812        "enet",
    811813        "tinygettext",
    812814        "icu",
    813815        "iconv",
    814816        "fmt",
    815817    }
    816818    if not _OPTIONS["without-audio"] then
    817819        table.insert(extern_libs, "openal")
    818820    end
    819821    setup_static_lib_project("gui", source_dirs, extern_libs, {})
    820822
    821823
    822824    source_dirs = {
    823825        "lib",
    824826        "lib/adts",
    825827        "lib/allocators",
    826828        "lib/external_libraries",
    827829        "lib/file",
    828830        "lib/file/archive",
    829831        "lib/file/common",
    830832        "lib/file/io",
    831833        "lib/file/vfs",
    832834        "lib/pch",
    833835        "lib/posix",
    834836        "lib/res",
    835837        "lib/res/graphics",
    836838        "lib/sysdep",
    837839        "lib/tex"
    838840    }
    839841    extern_libs = {
    840842        "boost",
    841843        "sdl",
    842844        "openal",
    843845        "opengl",
    844846        "libpng",
    845847        "zlib",
    846848        "valgrind",
    847849        "cxxtest",
    848850        "fmt",
    849851    }
    850852
    851853    -- CPU architecture-specific
    852854    if arch == "amd64" then
    853855        table.insert(source_dirs, "lib/sysdep/arch/amd64");
    854856        table.insert(source_dirs, "lib/sysdep/arch/x86_x64");
    855857    elseif arch == "x86" then
    856858        table.insert(source_dirs, "lib/sysdep/arch/ia32");
    857859        table.insert(source_dirs, "lib/sysdep/arch/x86_x64");
    858860    elseif arch == "arm" then
    859861        table.insert(source_dirs, "lib/sysdep/arch/arm");
    860862    elseif arch == "aarch64" then
    861863        table.insert(source_dirs, "lib/sysdep/arch/aarch64");
     864    elseif arch == "e2k" then
     865        table.insert(source_dirs, "lib/sysdep/arch/e2k");
    862866    end
    863867
    864868    -- OS-specific
    865869    sysdep_dirs = {
    866870        linux = { "lib/sysdep/os/linux", "lib/sysdep/os/unix" },
    867871        -- note: RC file must be added to main_exe project.
    868872        -- note: don't add "lib/sysdep/os/win/aken.cpp" because that must be compiled with the DDK.
    869873        windows = { "lib/sysdep/os/win", "lib/sysdep/os/win/wposix", "lib/sysdep/os/win/whrt" },
    870874        macosx = { "lib/sysdep/os/osx", "lib/sysdep/os/unix" },
    871875        bsd = { "lib/sysdep/os/bsd", "lib/sysdep/os/unix", "lib/sysdep/os/unix/x" },
    872876    }
    873877    for i,v in pairs(sysdep_dirs[os.target()]) do
    874878        table.insert(source_dirs, v);
    875879    end
    876880
    877881    if os.istarget("linux") then
    878882        if _OPTIONS["android"] then
    879883            table.insert(source_dirs, "lib/sysdep/os/android")
    880884        else
    881885            table.insert(source_dirs, "lib/sysdep/os/unix/x")
    882886        end
    883887    end
    884888
    885889    -- On OSX, disable precompiled headers because C++ files and Objective-C++ files are
    886890    -- mixed in this project. To fix that, we would need per-file basis configuration which
    887891    -- is not yet supported by the gmake action in premake. We should look into using gmake2.
    888892    extra_params = {}
    889893    if os.istarget("macosx") then
    890894        extra_params = { no_pch = 1 }
    891895    end
    892896
    893897    -- runtime-library-specific
    894898    if _ACTION == "vs2017" then
    895899        table.insert(source_dirs, "lib/sysdep/rtl/msc");
    896900    else
    897901        table.insert(source_dirs, "lib/sysdep/rtl/gcc");
    898902    end
    899903
    900904    setup_static_lib_project("lowlevel", source_dirs, extern_libs, extra_params)
    901905
    902906
    903907    -- Third-party libraries that are built as part of the main project,
    904908    -- not built externally and then linked
    905909    source_dirs = {
    906910        "third_party/mongoose",
    907911    }
    908912    extern_libs = {
    909913    }
    910914    setup_static_lib_project("mongoose", source_dirs, extern_libs, { no_pch = 1 })
    911915
    912916
    913917    -- CxxTest mock function support
    914918    extern_libs = {
    915919        "boost",
    916920        "cxxtest",
    917921    }
    918922
    919923    -- 'real' implementations, to be linked against the main executable
    920924    -- (files are added manually and not with setup_static_lib_project
    921925    -- because not all files in the directory are included)
    922926    setup_static_lib_project("mocks_real", {}, extern_libs, { no_default_link = 1, no_pch = 1 })
    923927    files { "mocks/*.h", source_root.."mocks/*_real.cpp" }
    924928    -- 'test' implementations, to be linked against the test executable
    925929    setup_static_lib_project("mocks_test", {}, extern_libs, { no_default_link = 1, no_pch = 1 })
    926930    files { source_root.."mocks/*.h", source_root.."mocks/*_test.cpp" }
    927931end
    928932
    929933--------------------------------------------------------------------------------
    930934-- main EXE
    931935--------------------------------------------------------------------------------
    932936
    933937-- used for main EXE as well as test
    934938used_extern_libs = {
    935939    "opengl",
    936940    "sdl",
    937941
    938942    "libpng",
    939943    "zlib",
    940944
    941945    "spidermonkey",
    942946    "libxml2",
    943947
    944948    "boost",
    945949    "cxxtest",
    946950    "comsuppw",
    947951    "enet",
    948952    "libcurl",
    949953    "tinygettext",
    950954    "icu",
    951955    "iconv",
    952956    "libsodium",
    953957    "fmt",
    954958
    955959    "valgrind",
    956960}
    957961
    958962if not os.istarget("windows") and not _OPTIONS["android"] and not os.istarget("macosx") then
    959963    -- X11 should only be linked on *nix
    960964    table.insert(used_extern_libs, "x11")
    961965end
    962966
    963967if not _OPTIONS["without-audio"] then
    964968    table.insert(used_extern_libs, "openal")
    965969    table.insert(used_extern_libs, "vorbis")
    966970end
    967971
    968972if not _OPTIONS["without-nvtt"] then
    969973    table.insert(used_extern_libs, "nvtt")
    970974end
    971975
    972976if not _OPTIONS["without-lobby"] then
    973977    table.insert(used_extern_libs, "gloox")
    974978end
    975979
    976980if not _OPTIONS["without-miniupnpc"] then
    977981    table.insert(used_extern_libs, "miniupnpc")
    978982end
    979983
    980984-- Bundles static libs together with main.cpp and builds game executable.
    981985function setup_main_exe ()
    982986
    983987    local target_type = get_main_project_target_type()
    984988    project_create("pyrogenesis", target_type)
    985989
    986990    filter "system:not macosx"
    987991        linkgroups 'On'
    988992    filter {}
    989993
    990994    links { "mocks_real" }
    991995
    992996    local extra_params = {
    993997        extra_files = { "main.cpp" },
    994998        no_pch = 1
    995999    }
    9961000    project_add_contents(source_root, {}, {}, extra_params)
    9971001    project_add_extern_libs(used_extern_libs, target_type)
    9981002
    9991003    dependson { "Collada" }
    10001004
    10011005    rtti "off"
    10021006
    10031007    -- Platform Specifics
    10041008    if os.istarget("windows") then
    10051009
    10061010        files { source_root.."lib/sysdep/os/win/icon.rc" }
    10071011        -- from "lowlevel" static lib; must be added here to be linked in
    10081012        files { source_root.."lib/sysdep/os/win/error_dialog.rc" }
    10091013
    10101014        linkoptions {
    10111015            -- wraps main thread in a __try block(see wseh.cpp). replace with mainCRTStartup if that's undesired.
    10121016            "/ENTRY:wseh_EntryPoint",
    10131017
    10141018            -- see wstartup.h
    10151019            "/INCLUDE:_wstartup_InitAndRegisterShutdown",
    10161020
    10171021            -- allow manual unload of delay-loaded DLLs
    10181022            "/DELAY:UNLOAD",
    10191023        }
    10201024
    10211025        -- allow the executable to use more than 2GB of RAM.
    10221026        -- this should not be enabled during development, so that memory issues are easily spotted.
    10231027        if _OPTIONS["large-address-aware"] then
    10241028            linkoptions { "/LARGEADDRESSAWARE" }
    10251029        end
    10261030
    10271031        -- see manifest.cpp
    10281032        project_add_manifest()
    10291033
    10301034    elseif os.istarget("linux") or os.istarget("bsd") then
    10311035
    10321036        if not _OPTIONS["android"] and not (os.getversion().description == "OpenBSD") then
    10331037            links { "rt" }
    10341038        end
    10351039
    10361040        if _OPTIONS["android"] then
    10371041            -- NDK's STANDALONE-TOOLCHAIN.html says this is required
    10381042            linkoptions { "-Wl,--fix-cortex-a8" }
    10391043
    10401044            links { "log" }
    10411045        end
    10421046
    10431047        if link_execinfo then
    10441048            links {
    10451049                "execinfo"
    10461050            }
    10471051        end
    10481052
    10491053        if os.istarget("linux") or os.getversion().description == "GNU/kFreeBSD" then
    10501054            links {
    10511055                -- Dynamic libraries (needed for linking for gold)
    10521056                "dl",
    10531057            }
    10541058        end
    10551059
    10561060        -- Threading support
    10571061        buildoptions { "-pthread" }
    10581062        if not _OPTIONS["android"] then
    10591063            linkoptions { "-pthread" }
    10601064        end
    10611065
    10621066        -- For debug_resolve_symbol
    10631067        filter "Debug"
    10641068            linkoptions { "-rdynamic" }
    10651069        filter { }
    10661070
    10671071    elseif os.istarget("macosx") then
    10681072
    10691073        links { "pthread" }
    10701074        links { "ApplicationServices.framework", "Cocoa.framework", "CoreFoundation.framework" }
    10711075        if _OPTIONS["macosx-version-min"] then
    10721076            xcodebuildsettings { MACOSX_DEPLOYMENT_TARGET = _OPTIONS["macosx-version-min"] }
    10731077        end
    10741078    end
    10751079end
    10761080
    10771081
    10781082--------------------------------------------------------------------------------
    10791083-- atlas
    10801084--------------------------------------------------------------------------------
    10811085
    10821086-- setup a typical Atlas component project
    10831087-- extra_params, rel_source_dirs and rel_include_dirs: as in project_add_contents;
    10841088function setup_atlas_project(project_name, target_type, rel_source_dirs, rel_include_dirs, extern_libs, extra_params)
    10851089
    10861090    local source_root = rootdir.."/source/tools/atlas/" .. project_name .. "/"
    10871091    project_create(project_name, target_type)
    10881092
    10891093    -- if not specified, the default for atlas pch files is in the project root.
    10901094    if not extra_params["pch_dir"] then
    10911095        extra_params["pch_dir"] = source_root
    10921096    end
    10931097
    10941098    project_add_contents(source_root, rel_source_dirs, rel_include_dirs, extra_params)
    10951099    project_add_extern_libs(extern_libs, target_type)
    10961100
    10971101    -- Platform Specifics
    10981102    if os.istarget("windows") then
    10991103        -- Link to required libraries
    11001104        links { "winmm", "delayimp" }
    11011105
    11021106    elseif os.istarget("linux") or os.istarget("bsd") then
    11031107        buildoptions { "-rdynamic", "-fPIC" }
    11041108        linkoptions { "-fPIC", "-rdynamic" }
    11051109
    11061110        -- warnings triggered by wxWidgets
    11071111        buildoptions { "-Wno-unused-local-typedefs" }
    11081112
    11091113    elseif os.istarget("macosx") then
    11101114        -- install_name settings aren't really supported yet by premake, but there are plans for the future.
    11111115        -- we currently use this hack to work around some bugs with wrong install_names.
    11121116        if target_type == "SharedLib" then
    11131117            if _OPTIONS["macosx-bundle"] then
    11141118                -- If we're building a bundle, it will be in ../Frameworks
    11151119                filter "Debug"
    11161120                    linkoptions { "-install_name @executable_path/../Frameworks/lib"..project_name.."_dbg.dylib" }
    11171121                filter "Release"
    11181122                    linkoptions { "-install_name @executable_path/../Frameworks/lib"..project_name..".dylib" }
    11191123                filter { }
    11201124            else
    11211125                filter "Debug"
    11221126                    linkoptions { "-install_name @executable_path/lib"..project_name.."_dbg.dylib" }
    11231127                filter "Release"
    11241128                    linkoptions { "-install_name @executable_path/lib"..project_name..".dylib" }
    11251129                filter { }
    11261130            end
    11271131        end
    11281132    end
    11291133
    11301134end
    11311135
    11321136
    11331137-- build all Atlas component projects
    11341138function setup_atlas_projects()
    11351139
    11361140    setup_atlas_project("AtlasObject", "StaticLib",
    11371141    {   -- src
    11381142        ".",
    11391143        "../../../third_party/jsonspirit"
    11401144
    11411145    },{ -- include
    11421146        "../../../third_party/jsonspirit"
    11431147    },{ -- extern_libs
    11441148        "boost",
    11451149        "iconv",
    11461150        "libxml2"
    11471151    },{ -- extra_params
    11481152        no_pch = 1
    11491153    })
    11501154
    11511155    atlas_src = {
    11521156        "ActorEditor",
    11531157        "CustomControls/Buttons",
    11541158        "CustomControls/Canvas",
    11551159        "CustomControls/ColorDialog",
    11561160        "CustomControls/DraggableListCtrl",
    11571161        "CustomControls/EditableListCtrl",
    11581162        "CustomControls/FileHistory",
    11591163        "CustomControls/HighResTimer",
    11601164        "CustomControls/MapDialog",
    11611165        "CustomControls/MapResizeDialog",
    11621166        "CustomControls/SnapSplitterWindow",
    11631167        "CustomControls/VirtualDirTreeCtrl",
    11641168        "CustomControls/Windows",
    11651169        "General",
    11661170        "General/VideoRecorder",
    11671171        "Misc",
    11681172        "ScenarioEditor",
    11691173        "ScenarioEditor/Sections/Common",
    11701174        "ScenarioEditor/Sections/Cinema",
    11711175        "ScenarioEditor/Sections/Environment",
    11721176        "ScenarioEditor/Sections/Map",
    11731177        "ScenarioEditor/Sections/Object",
    11741178        "ScenarioEditor/Sections/Player",
    11751179        "ScenarioEditor/Sections/Terrain",
    11761180        "ScenarioEditor/Tools",
    11771181        "ScenarioEditor/Tools/Common",
    11781182    }
    11791183    atlas_extra_links = {
    11801184        "AtlasObject"
    11811185    }
    11821186
    11831187    atlas_extern_libs = {
    11841188        "boost",
    11851189        "comsuppw",
    11861190        "iconv",
    11871191        "libxml2",
    11881192        "sdl",  -- key definitions
    11891193        "wxwidgets",
    11901194        "zlib",
    11911195    }
    11921196    if not os.istarget("windows") and not os.istarget("macosx") then
    11931197        -- X11 should only be linked on *nix
    11941198        table.insert(atlas_extern_libs, "x11")
    11951199    end
    11961200
    11971201    setup_atlas_project("AtlasUI", "SharedLib", atlas_src,
    11981202    {   -- include
    11991203        "..",
    12001204        "CustomControls",
    12011205        "Misc",
    12021206        "../../../third_party/jsonspirit"
    12031207    },
    12041208    atlas_extern_libs,
    12051209    {   -- extra_params
    12061210        pch_dir = rootdir.."/source/tools/atlas/AtlasUI/Misc/",
    12071211        no_pch = false,
    12081212        extra_links = atlas_extra_links,
    12091213        extra_files = { "Misc/atlas.rc" }
    12101214    })
    12111215end
    12121216
    12131217
    12141218-- Atlas 'frontend' tool-launching projects
    12151219function setup_atlas_frontend_project (project_name)
    12161220
    12171221    local target_type = get_main_project_target_type()
    12181222    project_create(project_name, target_type)
    12191223
    12201224    local source_root = rootdir.."/source/tools/atlas/AtlasFrontends/"
    12211225    files { source_root..project_name..".cpp" }
    12221226
    12231227    if os.istarget("windows") then
    12241228        files { source_root..project_name..".rc" }
    12251229    end
    12261230
    12271231    includedirs { source_root .. ".." }
    12281232
    12291233    -- Platform Specifics
    12301234    if os.istarget("windows") then
    12311235        -- see manifest.cpp
    12321236        project_add_manifest()
    12331237
    12341238    else -- Non-Windows, = Unix
    12351239        links { "AtlasObject" }
    12361240    end
    12371241
    12381242    links { "AtlasUI" }
    12391243
    12401244end
    12411245
    12421246function setup_atlas_frontends()
    12431247    setup_atlas_frontend_project("ActorEditor")
    12441248end
    12451249
    12461250
    12471251--------------------------------------------------------------------------------
    12481252-- collada
    12491253--------------------------------------------------------------------------------
    12501254
    12511255function setup_collada_project(project_name, target_type, rel_source_dirs, rel_include_dirs, extern_libs, extra_params)
    12521256
    12531257    project_create(project_name, target_type)
    12541258    local source_root = source_root.."collada/"
    12551259    extra_params["pch_dir"] = source_root
    12561260    project_add_contents(source_root, rel_source_dirs, rel_include_dirs, extra_params)
    12571261    project_add_extern_libs(extern_libs, target_type)
    12581262
    12591263    -- Platform Specifics
    12601264    if os.istarget("windows") then
    12611265        characterset "MBCS"
    12621266    elseif os.istarget("linux") then
    12631267        defines { "LINUX" }
    12641268
    12651269        links {
    12661270            "dl",
    12671271        }
    12681272
    12691273        -- FCollada is not aliasing-safe, so disallow dangerous optimisations
    12701274        -- (TODO: It'd be nice to fix FCollada, but that looks hard)
    12711275        buildoptions { "-fno-strict-aliasing" }
    12721276
    12731277        buildoptions { "-rdynamic" }
    12741278        linkoptions { "-rdynamic" }
    12751279
    12761280    elseif os.istarget("bsd") then
    12771281        if os.getversion().description == "OpenBSD" then
    12781282            links { "c", }
    12791283        end
    12801284
    12811285        if os.getversion().description == "GNU/kFreeBSD" then
    12821286            links {
    12831287                "dl",
    12841288            }
    12851289        end
    12861290
    12871291        buildoptions { "-fno-strict-aliasing" }
    12881292
    12891293        buildoptions { "-rdynamic" }
    12901294        linkoptions { "-rdynamic" }
    12911295
    12921296    elseif os.istarget("macosx") then
    12931297        -- define MACOS-something?
    12941298
    12951299        -- install_name settings aren't really supported yet by premake, but there are plans for the future.
    12961300        -- we currently use this hack to work around some bugs with wrong install_names.
    12971301        if target_type == "SharedLib" then
    12981302            if _OPTIONS["macosx-bundle"] then
    12991303                -- If we're building a bundle, it will be in ../Frameworks
    13001304                linkoptions { "-install_name @executable_path/../Frameworks/lib"..project_name..".dylib" }
    13011305            else
    13021306                linkoptions { "-install_name @executable_path/lib"..project_name..".dylib" }
    13031307            end
    13041308        end
    13051309
    13061310        buildoptions { "-fno-strict-aliasing" }
    13071311        -- On OSX, fcollada uses a few utility functions from coreservices
    13081312        links { "CoreServices.framework" }
    13091313    end
    13101314
    13111315end
    13121316
    13131317-- build all Collada component projects
    13141318function setup_collada_projects()
    13151319
    13161320    setup_collada_project("Collada", "SharedLib",
    13171321    {   -- src
    13181322        "."
    13191323    },{ -- include
    13201324    },{ -- extern_libs
    13211325        "fcollada",
    13221326        "iconv",
    13231327        "libxml2"
    13241328    },{ -- extra_params
    13251329    })
    13261330
    13271331end
    13281332
    13291333
    13301334--------------------------------------------------------------------------------
    13311335-- tests
    13321336--------------------------------------------------------------------------------
    13331337
    13341338function setup_tests()
    13351339
    13361340    local cxxtest = require "cxxtest"
    13371341
    13381342    if os.istarget("windows") then
    13391343        cxxtest.setpath(rootdir.."/build/bin/cxxtestgen.exe")
    13401344    else
    13411345        cxxtest.setpath(rootdir.."/libraries/source/cxxtest-4.4/bin/cxxtestgen")
    13421346    end
    13431347
    13441348    local runner = "ErrorPrinter"
    13451349    if _OPTIONS["jenkins-tests"] then
    13461350        runner = "XmlPrinter"
    13471351    end
    13481352
    13491353    local includefiles = {
    13501354        -- Precompiled headers - the header is added to all generated .cpp files
    13511355        -- note that the header isn't actually precompiled here, only #included
    13521356        -- so that the build stage can use it as a precompiled header.
    13531357        "precompiled.h",
    13541358        -- This is required to build against SDL 2.0.4 on Windows.
    13551359        "lib/external_libraries/libsdl.h",
    13561360    }
    13571361
    13581362    cxxtest.init(source_root, true, runner, includefiles)
    13591363
    13601364    local target_type = get_main_project_target_type()
    13611365    project_create("test", target_type)
    13621366
    13631367    -- Find header files in 'test' subdirectories
    13641368    local all_files = os.matchfiles(source_root .. "**/tests/*.h")
    13651369    local test_files = {}
    13661370    for i,v in pairs(all_files) do
    13671371        -- Don't include sysdep tests on the wrong sys
    13681372        -- Don't include Atlas tests unless Atlas is being built
    13691373        if not (string.find(v, "/sysdep/os/win/") and not os.istarget("windows")) and
    13701374           not (string.find(v, "/tools/atlas/") and not _OPTIONS["atlas"]) and
    13711375           not (string.find(v, "/sysdep/arch/x86_x64/") and ((arch ~= "amd64") or (arch ~= "x86")))
    13721376        then
    13731377            table.insert(test_files, v)
    13741378        end
    13751379    end
    13761380
    13771381    cxxtest.configure_project(test_files)
    13781382
    13791383    filter "system:not macosx"
    13801384        linkgroups 'On'
    13811385    filter {}
    13821386
    13831387    links { static_lib_names }
    13841388    filter "Debug"
    13851389        links { static_lib_names_debug }
    13861390    filter "Release"
    13871391        links { static_lib_names_release }
    13881392    filter { }
    13891393
    13901394    links { "mocks_test" }
    13911395    if _OPTIONS["atlas"] then
    13921396        links { "AtlasObject" }
    13931397    end
    13941398    extra_params = {
    13951399        extra_files = { "test_setup.cpp" },
    13961400    }
    13971401
    13981402    project_add_contents(source_root, {}, {}, extra_params)
    13991403    project_add_extern_libs(used_extern_libs, target_type)
    14001404
    14011405    dependson { "Collada" }
    14021406
    14031407    rtti "off"
    14041408
    14051409    -- TODO: should fix the duplication between this OS-specific linking
    14061410    -- code, and the similar version in setup_main_exe
    14071411
    14081412    if os.istarget("windows") then
    14091413        -- from "lowlevel" static lib; must be added here to be linked in
    14101414        files { source_root.."lib/sysdep/os/win/error_dialog.rc" }
    14111415
    14121416        -- see wstartup.h
    14131417        linkoptions { "/INCLUDE:_wstartup_InitAndRegisterShutdown" }
    14141418        -- Enables console for the TEST project on Windows
    14151419        linkoptions { "/SUBSYSTEM:CONSOLE" }
    14161420
    14171421        project_add_manifest()
    14181422
    14191423    elseif os.istarget("linux") or os.istarget("bsd") then
    14201424
    14211425        if link_execinfo then
    14221426            links {
    14231427                "execinfo"
    14241428            }
    14251429        end
    14261430        if not _OPTIONS["android"] and not (os.getversion().description == "OpenBSD") then
    14271431            links { "rt" }
    14281432        end
    14291433
    14301434        if _OPTIONS["android"] then
    14311435            -- NDK's STANDALONE-TOOLCHAIN.html says this is required
    14321436            linkoptions { "-Wl,--fix-cortex-a8" }
    14331437        end
    14341438
    14351439        if os.istarget("linux") or os.getversion().description == "GNU/kFreeBSD" then
    14361440            links {
    14371441                -- Dynamic libraries (needed for linking for gold)
    14381442                "dl",
    14391443            }
    14401444        end
    14411445
    14421446        -- Threading support
    14431447        buildoptions { "-pthread" }
    14441448        if not _OPTIONS["android"] then
    14451449            linkoptions { "-pthread" }
    14461450        end
    14471451
    14481452        -- For debug_resolve_symbol
    14491453        filter "Debug"
    14501454            linkoptions { "-rdynamic" }
    14511455        filter { }
    14521456
    14531457        includedirs { source_root .. "pch/test/" }
    14541458
    14551459    elseif os.istarget("macosx") and _OPTIONS["macosx-version-min"] then
    14561460        xcodebuildsettings { MACOSX_DEPLOYMENT_TARGET = _OPTIONS["macosx-version-min"] }
    14571461    end
    14581462end
    14591463
    14601464-- must come first, so that VC sets it as the default project and therefore
    14611465-- allows running via F5 without the "where is the EXE" dialog.
    14621466setup_main_exe()
    14631467
    14641468setup_all_libs()
    14651469
    14661470-- add the static libs to the main EXE project. only now (after
    14671471-- setup_all_libs has run) are the lib names known. cannot move
    14681472-- setup_main_exe to run after setup_all_libs (see comment above).
    14691473-- we also don't want to hardcode the names - that would require more
    14701474-- work when changing the static lib breakdown.
    14711475project("pyrogenesis") -- Set the main project active
    14721476    links { static_lib_names }
    14731477    filter "Debug"
    14741478        links { static_lib_names_debug }
    14751479    filter "Release"
    14761480        links { static_lib_names_release }
    14771481    filter { }
    14781482
    14791483if _OPTIONS["atlas"] then
    14801484    setup_atlas_projects()
    14811485    setup_atlas_frontends()
    14821486end
    14831487
    14841488setup_collada_projects()
    14851489
    14861490if not _OPTIONS["without-tests"] then
    14871491    setup_tests()
    14881492end
  • source/graphics/Color.cpp

     
    1 /* Copyright (C) 2019 Wildfire Games.
     1/* Copyright (C) 2020 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    77 * (at your option) any later version.
    88 *
    99 * 0 A.D. is distributed in the hope that it will be useful,
    1010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1111 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1212 * GNU General Public License for more details.
    1313 *
    1414 * You should have received a copy of the GNU General Public License
    1515 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    1616 */
    1717
    1818#include "precompiled.h"
    1919
    2020#include "graphics/Color.h"
    2121
    2222#include "graphics/SColor.h"
    2323#include "maths/MathUtil.h"
    2424#include "ps/CLogger.h"
    2525#include "ps/CStr.h"
    2626
    2727#if HAVE_SSE
    2828# include <xmmintrin.h>
     29
     30#if ARCH_X86_X64
    2931# include "lib/sysdep/arch/x86_x64/x86_x64.h"
    3032#endif
    3133
     34bool IsSSEEnabled()
     35{
     36#if ARCH_X86_X64
     37    return x86_x64::Cap(x86_x64::CAP_SSE);
     38#elif ARCH_E2K
     39    return true;
     40#else
     41    return false;
     42#endif
     43}
     44#endif // HAVE_SSE
     45
    3246static SColor4ub fallback_ConvertRGBColorTo4ub(const RGBColor& src)
    3347{
    3448    SColor4ub result;
    3549    result.R = Clamp(static_cast<int>(src.X * 255), 0, 255);
    3650    result.G = Clamp(static_cast<int>(src.Y * 255), 0, 255);
    3751    result.B = Clamp(static_cast<int>(src.Z * 255), 0, 255);
    3852    result.A = 255;
    3953    return result;
    4054}
    4155
    4256// on IA32, this is replaced by an SSE assembly version in ia32.cpp
    4357SColor4ub (*ConvertRGBColorTo4ub)(const RGBColor& src) = fallback_ConvertRGBColorTo4ub;
    4458
    4559
    4660// Assembler-optimized function for color conversion
    4761#if HAVE_SSE
    4862static SColor4ub sse_ConvertRGBColorTo4ub(const RGBColor& src)
    4963{
    5064    const __m128 zero = _mm_setzero_ps();
    5165    const __m128 _255 = _mm_set_ss(255.0f);
    5266    __m128 r = _mm_load_ss(&src.X);
    5367    __m128 g = _mm_load_ss(&src.Y);
    5468    __m128 b = _mm_load_ss(&src.Z);
    5569
    5670    // C = min(255, 255*max(C, 0)) ( == Clamp(255*C, 0, 255) )
    5771    r = _mm_max_ss(r, zero);
    5872    g = _mm_max_ss(g, zero);
    5973    b = _mm_max_ss(b, zero);
    6074
    6175    r = _mm_mul_ss(r, _255);
    6276    g = _mm_mul_ss(g, _255);
    6377    b = _mm_mul_ss(b, _255);
    6478
    6579    r = _mm_min_ss(r, _255);
    6680    g = _mm_min_ss(g, _255);
    6781    b = _mm_min_ss(b, _255);
    6882
    6983    // convert to integer and combine channels using bit logic
    7084    int ri = _mm_cvtss_si32(r);
    7185    int gi = _mm_cvtss_si32(g);
    7286    int bi = _mm_cvtss_si32(b);
    7387
    7488    return SColor4ub(ri, gi, bi, 0xFF);
    7589}
    7690#endif
    7791
    7892void ColorActivateFastImpl()
    7993{
    8094#if HAVE_SSE
    81     if (x86_x64::Cap(x86_x64::CAP_SSE))
     95    if (IsSSEEnabled())
    8296    {
    8397        ConvertRGBColorTo4ub = sse_ConvertRGBColorTo4ub;
    8498        return;
    8599    }
    86100#endif
    87101    debug_printf("No SSE available. Slow fallback routines will be used.\n");
    88102}
    89103
    90104/**
    91105 * Important: This function does not modify the value if parsing fails.
    92106 */
    93107bool CColor::ParseString(const CStr8& value, int defaultAlpha)
    94108{
    95109    const size_t NUM_VALS = 4;
    96110    int values[NUM_VALS] = { 0, 0, 0, defaultAlpha };
    97111    std::stringstream stream;
    98112    stream.str(value);
    99113    // Parse each value
    100114    size_t i;
    101115    for (i = 0; i < NUM_VALS; ++i)
    102116    {
    103117        if (stream.eof())
    104118            break;
    105119
    106120        stream >> values[i];
    107121        if ((stream.rdstate() & std::stringstream::failbit) != 0)
    108122        {
    109123            LOGWARNING("Unable to parse CColor parameters. Your input: '%s'", value.c_str());
    110124            return false;
    111125        }
    112126        if (values[i] < 0 || values[i] > 255)
    113127        {
    114128            LOGWARNING("Invalid value (<0 or >255) when parsing CColor parameters. Your input: '%s'", value.c_str());
    115129            return false;
    116130        }
    117131    }
    118132
    119133    if (i < 3)
    120134    {
    121135        LOGWARNING("Not enough parameters when parsing as CColor. Your input: '%s'", value.c_str());
    122136        return false;
    123137    }
    124138    if (!stream.eof())
    125139    {
    126140        LOGWARNING("Too many parameters when parsing as CColor. Your input: '%s'", value.c_str());
    127141        return false;
    128142    }
    129143
    130144    r = values[0] / 255.f;
    131145    g = values[1] / 255.f;
    132146    b = values[2] / 255.f;
    133147    a = values[3] / 255.f;
    134148
    135149    return true;
    136150}
    137151
    138152bool CColor::operator==(const CColor& color) const
    139153{
    140154    return
    141155        r == color.r &&
    142156        g == color.g &&
    143157        b == color.b &&
    144158        a == color.a;
    145159}
  • source/graphics/Color.h

     
    1 /* Copyright (C) 2019 Wildfire Games.
     1/* Copyright (C) 2020 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    77 * (at your option) any later version.
    88 *
    99 * 0 A.D. is distributed in the hope that it will be useful,
    1010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1111 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1212 * GNU General Public License for more details.
    1313 *
    1414 * You should have received a copy of the GNU General Public License
    1515 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    1616 */
    1717
    1818#ifndef INCLUDED_COLOR
    1919#define INCLUDED_COLOR
    2020
    2121#include "graphics/SColor.h"
    2222#include "maths/Vector3D.h"
    2323#include "maths/Vector4D.h"
    2424
     25// Detects CPU SSE Support.
     26bool IsSSEEnabled();
     27
    2528// Simple defines for 3 and 4 component floating point colors - just map to
    2629// corresponding vector types.
    2730typedef CVector3D RGBColor;
    2831typedef CVector4D RGBAColor;
    2932
    3033// Convert float RGB(A) colors to unsigned byte.
    3134// Exposed as function pointer because it is set at init-time to
    3235// one of several implementations depending on CPU caps.
    3336extern SColor4ub (*ConvertRGBColorTo4ub)(const RGBColor& src);
    3437
    3538// call once ia32_Init has run; detects CPU caps and activates the best
    3639// possible codepath.
    3740extern void ColorActivateFastImpl();
    3841
    3942class CStr8;
    4043
    4144struct CColor
    4245{
    4346    CColor() : r(-1.f), g(-1.f), b(-1.f), a(1.f) {}
    4447    CColor(float cr, float cg, float cb, float ca) : r(cr), g(cg), b(cb), a(ca) {}
    4548
    4649    /**
    4750     * Returns whether this has been set to a valid color.
    4851     */
    4952    operator bool() const
    5053    {
    5154        return r >= 0 && g >= 0 && b >= 0 && a >= 0;
    5255    }
    5356
    5457    /**
    5558     * Try to parse @p Value as a color. Returns true on success, false otherwise.
    5659     * Leaves the color unchanged if it failed.
    5760     * @param value Should be "r g b" or "r g b a" where each value is an integer in [0,255].
    5861     * @param defaultAlpha The alpha value that is used if the format of @p Value is "r g b".
    5962     */
    6063    bool ParseString(const CStr8& value, int defaultAlpha = 255);
    6164
    6265    bool operator==(const CColor& color) const;
    6366    bool operator!=(const CColor& color) const
    6467    {
    6568        return !(*this == color);
    6669    }
    6770
    6871    // For passing to glColor[34]fv:
    6972    const float* FloatArray() const { return &r; }
    7073
    7174    // For passing to CRenderer:
    7275    SColor4ub AsSColor4ub() const
    7376    {
    7477        return SColor4ub(
    7578            static_cast<u8>(r * 255.f),
    7679            static_cast<u8>(g * 255.f),
    7780            static_cast<u8>(b * 255.f),
    7881            static_cast<u8>(a * 255.f)
    7982        );
    8083    }
    8184
    8285    float r, g, b, a;
    8386};
    8487
    8588#endif // INCLUDED_COLOR
  • source/lib/byte_order.h

     
    1 /* Copyright (C) 2015 Wildfire Games.
     1/* Copyright (C) 2020 Wildfire Games.
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
    55 * "Software"), to deal in the Software without restriction, including
    66 * without limitation the rights to use, copy, modify, merge, publish,
    77 * distribute, sublicense, and/or sell copies of the Software, and to
    88 * permit persons to whom the Software is furnished to do so, subject to
    99 * the following conditions:
    1010 *
    1111 * The above copyright notice and this permission notice shall be included
    1212 * in all copies or substantial portions of the Software.
    1313 *
    1414 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1515 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1616 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    1717 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    1818 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    1919 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    2020 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    2121 */
    2222
    2323/*
    2424 * byte order (endianness) support routines.
    2525 */
    2626
    2727#ifndef INCLUDED_BYTE_ORDER
    2828#define INCLUDED_BYTE_ORDER
    2929
    3030#include "lib/sysdep/cpu.h"
    3131
    3232// detect byte order via predefined macros.
    3333#ifndef BYTE_ORDER
    3434# define LITTLE_ENDIAN 0x4321
    3535# define BIG_ENDIAN    0x1234
    36 # if ARCH_IA32 || ARCH_IA64 || ARCH_AMD64 || ARCH_ALPHA || ARCH_ARM || ARCH_AARCH64 || ARCH_MIPS || defined(__LITTLE_ENDIAN__)
     36# if ARCH_IA32 || ARCH_IA64 || ARCH_AMD64 || ARCH_ALPHA || ARCH_ARM || ARCH_AARCH64 || ARCH_MIPS || ARCH_E2K || defined(__LITTLE_ENDIAN__)
    3737#  define BYTE_ORDER LITTLE_ENDIAN
    3838# else
    3939#  define BYTE_ORDER BIG_ENDIAN
    4040# endif
    4141#endif
    4242
    4343
    4444/**
    4545 * convert 4 characters to u32 (at compile time) for easy comparison.
    4646 * output is in native byte order; e.g. FOURCC_LE can be used instead.
    4747 **/
    4848#define FOURCC(a,b,c,d) // real definition is below
    4949#undef  FOURCC
    5050
    5151// implementation rationale:
    5252// - can't pass code as string, and use s[0]..s[3], because
    5353//   VC6/7 don't realize the macro is constant
    5454//   (it should be usable as a switch{} expression)
    5555// - the casts are ugly but necessary. u32 is required because u8 << 8 == 0;
    5656//   the additional u8 cast ensures each character is treated as unsigned
    5757//   (otherwise, they'd be promoted to signed int before the u32 cast,
    5858//   which would break things).
    5959
    6060/// big-endian version of FOURCC
    6161#define FOURCC_BE(a,b,c,d) ( ((u32)(u8)a) << 24 | ((u32)(u8)b) << 16 | \
    6262    ((u32)(u8)c) << 8  | ((u32)(u8)d) << 0  )
    6363
    6464/// little-endian version of FOURCC
    6565#define FOURCC_LE(a,b,c,d) ( ((u32)(u8)a) << 0  | ((u32)(u8)b) << 8  | \
    6666    ((u32)(u8)c) << 16 | ((u32)(u8)d) << 24 )
    6767
    6868#if BYTE_ORDER == BIG_ENDIAN
    6969# define FOURCC FOURCC_BE
    7070#else
    7171# define FOURCC FOURCC_LE
    7272#endif
    7373
    7474
    7575#if BYTE_ORDER == BIG_ENDIAN
    7676// convert a little-endian number to/from native byte order.
    7777# define to_le16(x) swap16(x)
    7878# define to_le32(x) swap32(x)
    7979# define to_le64(x) swap64(x)
    8080// convert a big-endian number to/from native byte order.
    8181# define to_be16(x) (x)
    8282# define to_be32(x) (x)
    8383# define to_be64(x) (x)
    8484#else // LITTLE_ENDIAN
    8585// convert a little-endian number to/from native byte order.
    8686# define to_le16(x) (x)
    8787# define to_le32(x) (x)
    8888# define to_le64(x) (x)
    8989// convert a big-endian number to/from native byte order.
    9090# define to_be16(x) swap16(x)
    9191# define to_be32(x) swap32(x)
    9292# define to_be64(x) swap64(x)
    9393#endif
    9494
    9595/// read a little-endian number from memory into native byte order.
    9696LIB_API u16 read_le16(const void* p);
    9797LIB_API u32 read_le32(const void* p);   /// see read_le16
    9898LIB_API u64 read_le64(const void* p);   /// see read_le16
    9999
    100100/// read a big-endian number from memory into native byte order.
    101101LIB_API u16 read_be16(const void* p);
    102102LIB_API u32 read_be32(const void* p);   /// see read_be16
    103103LIB_API u64 read_be64(const void* p);   /// see read_be16
    104104
    105105/// write a little-endian number to memory in native byte order.
    106106LIB_API void write_le16(void* p, u16 x);
    107107LIB_API void write_le32(void* p, u32 x);    /// see write_le16
    108108LIB_API void write_le64(void* p, u64 x);    /// see write_le16
    109109
    110110/// write a big-endian number to memory in native byte order.
    111111LIB_API void write_be16(void* p, u16 x);
    112112LIB_API void write_be32(void* p, u32 x);    /// see write_be16
    113113LIB_API void write_be64(void* p, u64 x);    /// see write_be16
    114114
    115115/**
    116116 * zero-extend \<size\> (truncated to 8) bytes of little-endian data to u64,
    117117 * starting at address \<p\> (need not be aligned).
    118118 **/
    119119LIB_API u64 movzx_le64(const u8* p, size_t size);
    120120LIB_API u64 movzx_be64(const u8* p, size_t size);
    121121
    122122/**
    123123 * sign-extend \<size\> (truncated to 8) bytes of little-endian data to i64,
    124124 * starting at address \<p\> (need not be aligned).
    125125 **/
    126126LIB_API i64 movsx_le64(const u8* p, size_t size);
    127127LIB_API i64 movsx_be64(const u8* p, size_t size);
    128128
    129129
    130130#if ICC_VERSION
    131131#define swap32 _bswap
    132132#define swap64 _bswap64
    133133#elif MSC_VERSION
    134134extern unsigned short _byteswap_ushort(unsigned short);
    135135extern unsigned long _byteswap_ulong(unsigned long);
    136136extern unsigned __int64 _byteswap_uint64(unsigned __int64);
    137137#pragma intrinsic(_byteswap_ushort)
    138138#pragma intrinsic(_byteswap_ulong)
    139139#pragma intrinsic(_byteswap_uint64)
    140140# define swap16 _byteswap_ushort
    141141# define swap32 _byteswap_ulong
    142142# define swap64 _byteswap_uint64
    143143#elif defined(linux)
    144144# include <asm/byteorder.h>
    145145# if defined(__arch__swab16) && !defined(swap16)
    146146#  define swap16 __arch__swab16
    147147# endif
    148148# if defined(__arch__swab32) && !defined(swap32)
    149149#  define swap32 __arch__swab32
    150150# endif
    151151# if defined(__arch__swab64) && !defined(swap64)
    152152#  define swap64 __arch__swab64
    153153# endif
    154154#endif
    155155
    156156#ifndef swap16
    157157LIB_API u16 swap16(const u16 x);
    158158#endif
    159159#ifndef swap32
    160160LIB_API u32 swap32(const u32 x);
    161161#endif
    162162#ifndef swap64
    163163LIB_API u64 swap64(const u64 x);
    164164#endif
    165165
    166166#endif  // #ifndef INCLUDED_BYTE_ORDER
  • source/lib/sysdep/arch/e2k/e2k.cpp

     
     1/* Copyright (C) 2020 Wildfire Games.
     2 *
     3 * Permission is hereby granted, free of charge, to any person obtaining
     4 * a copy of this software and associated documentation files (the
     5 * "Software"), to deal in the Software without restriction, including
     6 * without limitation the rights to use, copy, modify, merge, publish,
     7 * distribute, sublicense, and/or sell copies of the Software, and to
     8 * permit persons to whom the Software is furnished to do so, subject to
     9 * the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included
     12 * in all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 */
     22
     23/**
     24 * Routines specific to E2K (MCST Elbrus 2000)
     25 */
     26
     27#include "precompiled.h"
     28
     29#include "lib/sysdep/cpu.h"
     30
     31intptr_t cpu_AtomicAdd(volatile intptr_t* location, intptr_t increment)
     32{
     33    return __sync_fetch_and_add(location, increment);
     34}
     35
     36bool cpu_CAS(volatile intptr_t* location, intptr_t expected, intptr_t newValue)
     37{
     38    return __sync_bool_compare_and_swap(location, expected, newValue);
     39}
     40
     41bool cpu_CAS64(volatile i64* location, i64 expected, i64 newValue)
     42{
     43    return __sync_bool_compare_and_swap(location, expected, newValue);
     44}
     45
     46const char* cpu_IdentifierString()
     47{
     48    return __builtin_cpu_name();
     49}
  • source/lib/sysdep/arch.h

     
    1 /* Copyright (C) 2015 Wildfire Games.
     1/* Copyright (C) 2020 Wildfire Games.
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
    55 * "Software"), to deal in the Software without restriction, including
    66 * without limitation the rights to use, copy, modify, merge, publish,
    77 * distribute, sublicense, and/or sell copies of the Software, and to
    88 * permit persons to whom the Software is furnished to do so, subject to
    99 * the following conditions:
    1010 *
    1111 * The above copyright notice and this permission notice shall be included
    1212 * in all copies or substantial portions of the Software.
    1313 *
    1414 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1515 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1616 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    1717 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    1818 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    1919 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    2020 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    2121 */
    2222
    2323/*
    2424 * CPU architecture detection.
    2525 */
    2626
    2727#ifndef INCLUDED_ARCH
    2828#define INCLUDED_ARCH
    2929
    3030// detect target CPU architecture via predefined macros
    3131// .. IA-32
    3232#if defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__i386__) || defined(__i386) || defined(i386)
    3333# define ARCH_IA32 1
    3434#else
    3535# define ARCH_IA32 0
    3636#endif
    3737// .. IA-64
    3838#if defined(_M_IA64) || defined(__ia64__)
    3939# define ARCH_IA64 1
    4040#else
    4141# define ARCH_IA64 0
    4242#endif
    4343// .. AMD64
    4444#if defined(_M_X64) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
    4545# define ARCH_AMD64 1
    4646#else
    4747# define ARCH_AMD64 0
    4848#endif
    4949// .. Alpha
    5050#if defined(_M_ALPHA) || defined(__alpha__) || defined(__alpha)
    5151# define ARCH_ALPHA 1
    5252#else
    5353# define ARCH_ALPHA 0
    5454#endif
    5555// .. ARM
    5656#if defined(__arm__)
    5757# define ARCH_ARM 1
    5858#else
    5959# define ARCH_ARM 0
    6060#endif
    6161// .. AArch64 (ARM64)
    6262#if defined(__aarch64__)
    6363# define ARCH_AARCH64 1
    6464#else
    6565# define ARCH_AARCH64 0
    6666#endif
    6767// .. MIPS
    6868#if defined(__MIPS__) || defined(__mips__) || defined(__mips)
    6969# define ARCH_MIPS 1
    7070#else
    7171# define ARCH_MIPS 0
    7272#endif
     73// .. E2K (MCST Elbrus 2000)
     74#if defined(__e2k__)
     75# define ARCH_E2K 1
     76#else
     77# define ARCH_E2K 0
     78#endif
    7379
    7480// ensure exactly one architecture has been detected
    75 #if (ARCH_IA32+ARCH_IA64+ARCH_AMD64+ARCH_ALPHA+ARCH_ARM+ARCH_AARCH64+ARCH_MIPS) != 1
     81#if (ARCH_IA32+ARCH_IA64+ARCH_AMD64+ARCH_ALPHA+ARCH_ARM+ARCH_AARCH64+ARCH_MIPS+ARCH_E2K) != 1
    7682# error "architecture not correctly detected (either none or multiple ARCH_* defined)"
    7783#endif
    7884
    7985// "X86_X64"-specific code requires either IA-32 or AMD64
    8086#define ARCH_X86_X64 (ARCH_IA32|ARCH_AMD64)
    8187
    8288#endif  // #ifndef INCLUDED_ARCH
  • source/lib/sysdep/compiler.h

     
    1 /* Copyright (c) 2019 Wildfire Games.
     1/* Copyright (c) 2020 Wildfire Games.
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
    55 * "Software"), to deal in the Software without restriction, including
    66 * without limitation the rights to use, copy, modify, merge, publish,
    77 * distribute, sublicense, and/or sell copies of the Software, and to
    88 * permit persons to whom the Software is furnished to do so, subject to
    99 * the following conditions:
    1010 *
    1111 * The above copyright notice and this permission notice shall be included
    1212 * in all copies or substantial portions of the Software.
    1313 *
    1414 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1515 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1616 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    1717 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    1818 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    1919 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    2020 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    2121 */
    2222
    2323/*
    2424 * compiler-specific macros and fixes
    2525 */
    2626
    2727#ifndef INCLUDED_COMPILER
    2828#define INCLUDED_COMPILER
    2929
    3030// detect compiler and its version (0 if not present, otherwise
    3131// major*100 + minor). note that more than one *_VERSION may be
    3232// non-zero due to interoperability (e.g. ICC with MSC).
    3333// .. VC
    3434#ifdef _MSC_VER
    3535# define MSC_VERSION _MSC_VER
    3636#else
    3737# define MSC_VERSION 0
    3838#endif
    3939// .. ICC (VC-compatible, GCC-compatible)
    4040#if defined(__INTEL_COMPILER)
    4141# define ICC_VERSION __INTEL_COMPILER
    4242#else
    4343# define ICC_VERSION 0
    4444#endif
    4545// .. LCC (VC-compatible)
    46 #if defined(__LCC__)
     46// LCC-Win32 and MCST LCC compilers define same identifier (__LCC__).
     47// Have been added check of MCST Elbrus 2000 (e2k) architecture.
     48#if defined(__LCC__) && !defined(__e2k__)
    4749# define LCC_VERSION __LCC__
    4850#else
    4951# define LCC_VERSION 0
    5052#endif
     53// .. MCST LCC (eLbrus C/C++ Compiler)
     54#if defined(__LCC__) && defined(__e2k__)
     55# define MCST_LCC_VERSION (__LCC__*100 + __LCC_MINOR__)
     56#else
     57# define MCST_LCC_VERSION 0
     58#endif
    5159// .. GCC
    5260#ifdef __GNUC__
    5361# define GCC_VERSION (__GNUC__*100 + __GNUC_MINOR__)
    5462#else
    5563# define GCC_VERSION 0
    5664#endif
    5765// .. Clang/LLVM (GCC-compatible)
    5866// use Clang's feature checking macros to check for availability of features
    5967// http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
    6068#ifdef __clang__
    6169# define CLANG_VERSION (__clang_major__*100 + __clang_minor__)
    6270#else
    6371# define CLANG_VERSION 0
    6472#endif
    6573
    6674// Clang/LLVM feature check macro compatibility
    6775#ifndef __has_feature
    6876# define __has_feature(x) 0
    6977#endif
    7078
    7179#ifndef __has_cpp_attribute
    7280# define __has_cpp_attribute(x) 0
    7381#endif
    7482
    7583// check if compiling in pure C mode (not C++) with support for C99.
    7684// (this is more convenient than testing __STDC_VERSION__ directly)
    7785//
    7886// note: C99 provides several useful but disjunct bits of functionality.
    7987// unfortunately, most C++ compilers do not offer a complete implementation.
    8088// however, many of these features are likely to be added to C++, and/or are
    8189// already available as extensions. what we'll do is add a HAVE_ macro for
    8290// each feature and test those instead. they are set if HAVE_C99, or also if
    8391// the compiler happens to support something compatible.
    8492//
    8593// rationale: lying about __STDC_VERSION__ via Premake so as to enable support
    8694// for some C99 functions doesn't work. Mac OS X headers would then use the
    8795// restrict keyword, which is never supported by g++ (because that might
    8896// end up breaking valid C++98 programs).
    8997#define HAVE_C99 0
    9098#ifdef __STDC_VERSION__
    9199# if __STDC_VERSION__ >= 199901L
    92100#  undef  HAVE_C99
    93101#  define HAVE_C99 1
    94102# endif
    95103#endif
    96104
    97105// Streaming SIMD Extensions (not supported by all GCC)
    98106// this only ascertains compiler support; use x86_x64::Cap to
    99107// check whether the instructions are supported by the CPU.
    100108#ifndef HAVE_SSE
    101109# if GCC_VERSION && defined(__SSE__)
    102110#  define HAVE_SSE 1
    103111# elif MSC_VERSION  // also includes ICC
    104112#  define HAVE_SSE 1
    105113# else
    106114#  define HAVE_SSE 0
    107115# endif
    108116#endif
    109117
    110118#ifndef HAVE_SSE2
    111119# if GCC_VERSION && defined(__SSE2__)
    112120#  define HAVE_SSE2 1
    113121# elif MSC_VERSION  // also includes ICC
    114122#  define HAVE_SSE2 1
    115123# else
    116124#  define HAVE_SSE2 0
    117125# endif
    118126#endif
    119127
    120128#endif  // #ifndef INCLUDED_COMPILER
  • source/ps/GameSetup/HWDetect.cpp

     
    11/* Copyright (C) 2020 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    77 * (at your option) any later version.
    88 *
    99 * 0 A.D. is distributed in the hope that it will be useful,
    1010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1111 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1212 * GNU General Public License for more details.
    1313 *
    1414 * You should have received a copy of the GNU General Public License
    1515 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    1616 */
    1717
    1818#include "precompiled.h"
    1919
    2020#include "scriptinterface/ScriptInterface.h"
    2121
    2222#include "lib/ogl.h"
    2323#if CONFIG2_AUDIO
    2424#include "lib/snd.h"
    2525#endif
    2626#include "lib/svn_revision.h"
    2727#include "lib/timer.h"
    2828#include "lib/utf8.h"
    2929#include "lib/external_libraries/libsdl.h"
    3030#include "lib/res/graphics/ogl_tex.h"
    3131#include "lib/posix/posix_utsname.h"
    3232#include "lib/sysdep/cpu.h"
    3333#include "lib/sysdep/gfx.h"
    3434#include "lib/sysdep/numa.h"
    3535#include "lib/sysdep/os_cpu.h"
    3636#if ARCH_X86_X64
    3737# include "lib/sysdep/arch/x86_x64/cache.h"
    3838# include "lib/sysdep/arch/x86_x64/topology.h"
    3939#endif
    4040#include "ps/CLogger.h"
    4141#include "ps/ConfigDB.h"
    4242#include "ps/Filesystem.h"
    4343#include "ps/GameSetup/Config.h"
    4444#include "ps/Profile.h"
    4545#include "ps/scripting/JSInterface_ConfigDB.h"
    4646#include "ps/scripting/JSInterface_Debug.h"
    4747#include "ps/UserReport.h"
    4848#include "ps/VideoMode.h"
    4949
    5050// TODO: Support OpenGL platforms which don’t use GLX as well.
    5151#if defined(SDL_VIDEO_DRIVER_X11) && !CONFIG2_GLES
    5252#include <GL/glx.h>
    5353#include <SDL_syswm.h>
    5454
    5555// Define the GLX_MESA_query_renderer macros if built with
    5656// an old Mesa (<10.0) that doesn't provide them
    5757#ifndef GLX_MESA_query_renderer
    5858#define GLX_MESA_query_renderer 1
    5959#define GLX_RENDERER_VENDOR_ID_MESA                      0x8183
    6060#define GLX_RENDERER_DEVICE_ID_MESA                      0x8184
    6161#define GLX_RENDERER_VERSION_MESA                        0x8185
    6262#define GLX_RENDERER_ACCELERATED_MESA                    0x8186
    6363#define GLX_RENDERER_VIDEO_MEMORY_MESA                   0x8187
    6464#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA    0x8188
    6565#define GLX_RENDERER_PREFERRED_PROFILE_MESA              0x8189
    6666#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA    0x818A
    6767#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA    0x818B
    6868#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA      0x818C
    6969#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA     0x818D
    7070#define GLX_RENDERER_ID_MESA                             0x818E
    7171#endif /* GLX_MESA_query_renderer */
    7272
    7373#endif
    7474
    7575static void ReportSDL(const ScriptInterface& scriptInterface, JS::HandleValue settings);
    7676static void ReportGLLimits(const ScriptInterface& scriptInterface, JS::HandleValue settings);
    7777
    7878#if ARCH_X86_X64
    7979void ConvertCaches(const ScriptInterface& scriptInterface, x86_x64::IdxCache idxCache, JS::MutableHandleValue ret)
    8080{
    8181    ScriptRequest rq(scriptInterface);
    8282
    8383    ScriptInterface::CreateArray(rq, ret);
    8484
    8585    for (size_t idxLevel = 0; idxLevel < x86_x64::Cache::maxLevels; ++idxLevel)
    8686    {
    8787        const x86_x64::Cache* pcache = x86_x64::Caches(idxCache+idxLevel);
    8888        if (pcache->m_Type == x86_x64::Cache::kNull || pcache->m_NumEntries == 0)
    8989            continue;
    9090
    9191        JS::RootedValue cache(rq.cx);
    9292
    9393        ScriptInterface::CreateObject(
    9494            rq,
    9595            &cache,
    9696            "type", static_cast<u32>(pcache->m_Type),
    9797            "level", static_cast<u32>(pcache->m_Level),
    9898            "associativity", static_cast<u32>(pcache->m_Associativity),
    9999            "linesize", static_cast<u32>(pcache->m_EntrySize),
    100100            "sharedby", static_cast<u32>(pcache->m_SharedBy),
    101101            "totalsize", static_cast<u32>(pcache->TotalSize()));
    102102
    103103        scriptInterface.SetPropertyInt(ret, idxLevel, cache);
    104104    }
    105105}
    106106
    107107void ConvertTLBs(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret)
    108108{
    109109    ScriptRequest rq(scriptInterface);
    110110
    111111    ScriptInterface::CreateArray(rq, ret);
    112112
    113113    for(size_t i = 0; ; i++)
    114114    {
    115115        const x86_x64::Cache* ptlb = x86_x64::Caches(x86_x64::TLB+i);
    116116        if (!ptlb)
    117117            break;
    118118
    119119        JS::RootedValue tlb(rq.cx);
    120120
    121121        ScriptInterface::CreateObject(
    122122            rq,
    123123            &tlb,
    124124            "type", static_cast<u32>(ptlb->m_Type),
    125125            "level", static_cast<u32>(ptlb->m_Level),
    126126            "associativity", static_cast<u32>(ptlb->m_Associativity),
    127127            "pagesize", static_cast<u32>(ptlb->m_EntrySize),
    128128            "entries", static_cast<u32>(ptlb->m_NumEntries));
    129129
    130130        scriptInterface.SetPropertyInt(ret, i, tlb);
    131131    }
    132132}
    133133#endif
    134134
    135135void SetDisableAudio(ScriptInterface::CmptPrivate* UNUSED(pCmptPrivate), bool disabled)
    136136{
    137137    g_DisableAudio = disabled;
    138138}
    139139
    140140void RunHardwareDetection()
    141141{
    142142    TIMER(L"RunHardwareDetection");
    143143
    144144    ScriptInterface scriptInterface("Engine", "HWDetect", g_ScriptContext);
    145145
    146146    ScriptRequest rq(scriptInterface);
    147147
    148148    JSI_Debug::RegisterScriptFunctions(scriptInterface); // Engine.DisplayErrorDialog
    149149    JSI_ConfigDB::RegisterScriptFunctions(scriptInterface);
    150150
    151151    scriptInterface.RegisterFunction<void, bool, &SetDisableAudio>("SetDisableAudio");
    152152
    153153    // Load the detection script:
    154154
    155155    const wchar_t* scriptName = L"hwdetect/hwdetect.js";
    156156    CVFSFile file;
    157157    if (file.Load(g_VFS, scriptName) != PSRETURN_OK)
    158158    {
    159159        LOGERROR("Failed to load hardware detection script");
    160160        return;
    161161    }
    162162
    163163    std::string code = file.DecodeUTF8(); // assume it's UTF-8
    164164    scriptInterface.LoadScript(scriptName, code);
    165165
    166166    // Collect all the settings we'll pass to the script:
    167167    // (We'll use this same data for the opt-in online reporting system, so it
    168168    // includes some fields that aren't directly useful for the hwdetect script)
    169169
    170170    JS::RootedValue settings(rq.cx);
    171171    ScriptInterface::CreateObject(rq, &settings);
    172172
    173173    scriptInterface.SetProperty(settings, "os_unix", OS_UNIX);
    174174    scriptInterface.SetProperty(settings, "os_bsd", OS_BSD);
    175175    scriptInterface.SetProperty(settings, "os_linux", OS_LINUX);
    176176    scriptInterface.SetProperty(settings, "os_android", OS_ANDROID);
    177177    scriptInterface.SetProperty(settings, "os_macosx", OS_MACOSX);
    178178    scriptInterface.SetProperty(settings, "os_win", OS_WIN);
    179179
    180180    scriptInterface.SetProperty(settings, "arch_ia32", ARCH_IA32);
    181181    scriptInterface.SetProperty(settings, "arch_amd64", ARCH_AMD64);
    182182    scriptInterface.SetProperty(settings, "arch_arm", ARCH_ARM);
    183183    scriptInterface.SetProperty(settings, "arch_aarch64", ARCH_AARCH64);
     184    scriptInterface.SetProperty(settings, "arch_e2k", ARCH_E2K);
    184185
    185186#ifdef NDEBUG
    186187    scriptInterface.SetProperty(settings, "build_debug", 0);
    187188#else
    188189    scriptInterface.SetProperty(settings, "build_debug", 1);
    189190#endif
    190191    scriptInterface.SetProperty(settings, "build_opengles", CONFIG2_GLES);
    191192
    192193    scriptInterface.SetProperty(settings, "build_datetime", std::string(__DATE__ " " __TIME__));
    193194    scriptInterface.SetProperty(settings, "build_revision", std::wstring(svn_revision));
    194195
    195196    scriptInterface.SetProperty(settings, "build_msc", (int)MSC_VERSION);
    196197    scriptInterface.SetProperty(settings, "build_icc", (int)ICC_VERSION);
    197198    scriptInterface.SetProperty(settings, "build_gcc", (int)GCC_VERSION);
    198199    scriptInterface.SetProperty(settings, "build_clang", (int)CLANG_VERSION);
    199200
    200201    scriptInterface.SetProperty(settings, "gfx_card", gfx::CardName());
    201202    scriptInterface.SetProperty(settings, "gfx_drv_ver", gfx::DriverInfo());
    202203#if CONFIG2_AUDIO
    203204    scriptInterface.SetProperty(settings, "snd_card", snd_card);
    204205    scriptInterface.SetProperty(settings, "snd_drv_ver", snd_drv_ver);
    205206#endif
    206207    ReportSDL(scriptInterface, settings);
    207208
    208209    ReportGLLimits(scriptInterface, settings);
    209210
    210211    scriptInterface.SetProperty(settings, "video_desktop_xres", g_VideoMode.GetDesktopXRes());
    211212    scriptInterface.SetProperty(settings, "video_desktop_yres", g_VideoMode.GetDesktopYRes());
    212213    scriptInterface.SetProperty(settings, "video_desktop_bpp", g_VideoMode.GetDesktopBPP());
    213214    scriptInterface.SetProperty(settings, "video_desktop_freq", g_VideoMode.GetDesktopFreq());
    214215
    215216    struct utsname un;
    216217    uname(&un);
    217218    scriptInterface.SetProperty(settings, "uname_sysname", std::string(un.sysname));
    218219    scriptInterface.SetProperty(settings, "uname_release", std::string(un.release));
    219220    scriptInterface.SetProperty(settings, "uname_version", std::string(un.version));
    220221    scriptInterface.SetProperty(settings, "uname_machine", std::string(un.machine));
    221222
    222223#if OS_LINUX
    223224    {
    224225        std::ifstream ifs("/etc/lsb-release");
    225226        if (ifs.good())
    226227        {
    227228            std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
    228229            scriptInterface.SetProperty(settings, "linux_release", str);
    229230        }
    230231    }
    231232#endif
    232233
    233234    scriptInterface.SetProperty(settings, "cpu_identifier", std::string(cpu_IdentifierString()));
    234235    scriptInterface.SetProperty(settings, "cpu_frequency", os_cpu_ClockFrequency());
    235236    scriptInterface.SetProperty(settings, "cpu_pagesize", (u32)os_cpu_PageSize());
    236237    scriptInterface.SetProperty(settings, "cpu_largepagesize", (u32)os_cpu_LargePageSize());
    237238    scriptInterface.SetProperty(settings, "cpu_numprocs", (u32)os_cpu_NumProcessors());
    238239#if ARCH_X86_X64
    239240    scriptInterface.SetProperty(settings, "cpu_numpackages", (u32)topology::NumPackages());
    240241    scriptInterface.SetProperty(settings, "cpu_coresperpackage", (u32)topology::CoresPerPackage());
    241242    scriptInterface.SetProperty(settings, "cpu_logicalpercore", (u32)topology::LogicalPerCore());
    242243    scriptInterface.SetProperty(settings, "cpu_numcaches", (u32)topology::NumCaches());
    243244#endif
    244245
    245246    scriptInterface.SetProperty(settings, "numa_numnodes", (u32)numa_NumNodes());
    246247    scriptInterface.SetProperty(settings, "numa_factor", numa_Factor());
    247248    scriptInterface.SetProperty(settings, "numa_interleaved", numa_IsMemoryInterleaved());
    248249
    249250    scriptInterface.SetProperty(settings, "ram_total", (u32)os_cpu_MemorySize());
    250251    scriptInterface.SetProperty(settings, "ram_total_os", (u32)os_cpu_QueryMemorySize());
    251252
    252253#if ARCH_X86_X64
    253254    scriptInterface.SetProperty(settings, "x86_vendor", (u32)x86_x64::Vendor());
    254255    scriptInterface.SetProperty(settings, "x86_model", (u32)x86_x64::Model());
    255256    scriptInterface.SetProperty(settings, "x86_family", (u32)x86_x64::Family());
    256257
    257258    u32 caps0, caps1, caps2, caps3;
    258259    x86_x64::GetCapBits(&caps0, &caps1, &caps2, &caps3);
    259260    scriptInterface.SetProperty(settings, "x86_caps[0]", caps0);
    260261    scriptInterface.SetProperty(settings, "x86_caps[1]", caps1);
    261262    scriptInterface.SetProperty(settings, "x86_caps[2]", caps2);
    262263    scriptInterface.SetProperty(settings, "x86_caps[3]", caps3);
    263264
    264265    JS::RootedValue tmpVal(rq.cx);
    265266    ConvertCaches(scriptInterface, x86_x64::L1I, &tmpVal);
    266267    scriptInterface.SetProperty(settings, "x86_icaches", tmpVal);
    267268    ConvertCaches(scriptInterface, x86_x64::L1D, &tmpVal);
    268269    scriptInterface.SetProperty(settings, "x86_dcaches", tmpVal);
    269270    ConvertTLBs(scriptInterface, &tmpVal);
    270271    scriptInterface.SetProperty(settings, "x86_tlbs", tmpVal);
    271272#endif
    272273
    273274    scriptInterface.SetProperty(settings, "timer_resolution", timer_Resolution());
    274275   
    275276    // The version should be increased for every meaningful change.
    276277    const int reportVersion = 13;
    277278
    278279    // Send the same data to the reporting system
    279280    g_UserReporter.SubmitReport(
    280281        "hwdetect",
    281282        reportVersion,
    282283        scriptInterface.StringifyJSON(&settings, false),
    283284        scriptInterface.StringifyJSON(&settings, true));
    284285
    285286    // Run the detection script:
    286287    JS::RootedValue global(rq.cx, rq.globalValue());
    287288    scriptInterface.CallFunctionVoid(global, "RunHardwareDetection", settings);
    288289}
    289290
    290291static void ReportSDL(const ScriptInterface& scriptInterface, JS::HandleValue settings)
    291292{
    292293    SDL_version build, runtime;
    293294    SDL_VERSION(&build);
    294295
    295296    char version[16];
    296297    snprintf(version, ARRAY_SIZE(version), "%d.%d.%d", build.major, build.minor, build.patch);
    297298    scriptInterface.SetProperty(settings, "sdl_build_version", version);
    298299
    299300    SDL_GetVersion(&runtime);
    300301    snprintf(version, ARRAY_SIZE(version), "%d.%d.%d", runtime.major, runtime.minor, runtime.patch);
    301302    scriptInterface.SetProperty(settings, "sdl_runtime_version", version);
    302303
    303304    // This is null in atlas (and further the call triggers an assertion).
    304305    const char* backend = g_VideoMode.GetWindow() ? GetSDLSubsystem(g_VideoMode.GetWindow()) : "none";
    305306    scriptInterface.SetProperty(settings, "sdl_video_backend", backend ? backend : "unknown");
    306307}
    307308
    308309static void ReportGLLimits(const ScriptInterface& scriptInterface, JS::HandleValue settings)
    309310{
    310311    const char* errstr = "(error)";
    311312
    312313#define INTEGER(id) do { \
    313314    GLint i = -1; \
    314315    glGetIntegerv(GL_##id, &i); \
    315316    if (ogl_SquelchError(GL_INVALID_ENUM)) \
    316317        scriptInterface.SetProperty(settings, "GL_" #id, errstr); \
    317318    else \
    318319        scriptInterface.SetProperty(settings, "GL_" #id, i); \
    319320    } while (false)
    320321
    321322#define INTEGER2(id) do { \
    322323    GLint i[2] = { -1, -1 }; \
    323324    glGetIntegerv(GL_##id, i); \
    324325    if (ogl_SquelchError(GL_INVALID_ENUM)) { \
    325326        scriptInterface.SetProperty(settings, "GL_" #id "[0]", errstr); \
    326327        scriptInterface.SetProperty(settings, "GL_" #id "[1]", errstr); \
    327328    } else { \
    328329        scriptInterface.SetProperty(settings, "GL_" #id "[0]", i[0]); \
    329330        scriptInterface.SetProperty(settings, "GL_" #id "[1]", i[1]); \
    330331    } \
    331332    } while (false)
    332333
    333334#define FLOAT(id) do { \
    334335    GLfloat f = std::numeric_limits<GLfloat>::quiet_NaN(); \
    335336    glGetFloatv(GL_##id, &f); \
    336337    if (ogl_SquelchError(GL_INVALID_ENUM)) \
    337338        scriptInterface.SetProperty(settings, "GL_" #id, errstr); \
    338339    else \
    339340        scriptInterface.SetProperty(settings, "GL_" #id, f); \
    340341    } while (false)
    341342
    342343#define FLOAT2(id) do { \
    343344    GLfloat f[2] = { std::numeric_limits<GLfloat>::quiet_NaN(), std::numeric_limits<GLfloat>::quiet_NaN() }; \
    344345    glGetFloatv(GL_##id, f); \
    345346    if (ogl_SquelchError(GL_INVALID_ENUM)) { \
    346347        scriptInterface.SetProperty(settings, "GL_" #id "[0]", errstr); \
    347348        scriptInterface.SetProperty(settings, "GL_" #id "[1]", errstr); \
    348349    } else { \
    349350        scriptInterface.SetProperty(settings, "GL_" #id "[0]", f[0]); \
    350351        scriptInterface.SetProperty(settings, "GL_" #id "[1]", f[1]); \
    351352    } \
    352353    } while (false)
    353354
    354355#define STRING(id) do { \
    355356    const char* c = (const char*)glGetString(GL_##id); \
    356357    if (!c) c = ""; \
    357358    if (ogl_SquelchError(GL_INVALID_ENUM)) c = errstr; \
    358359    scriptInterface.SetProperty(settings, "GL_" #id, std::string(c)); \
    359360    }  while (false)
    360361
    361362#define QUERY(target, pname) do { \
    362363    GLint i = -1; \
    363364    pglGetQueryivARB(GL_##target, GL_##pname, &i); \
    364365    if (ogl_SquelchError(GL_INVALID_ENUM)) \
    365366        scriptInterface.SetProperty(settings, "GL_" #target ".GL_" #pname, errstr); \
    366367    else \
    367368        scriptInterface.SetProperty(settings, "GL_" #target ".GL_" #pname, i); \
    368369    } while (false)
    369370
    370371#define VERTEXPROGRAM(id) do { \
    371372    GLint i = -1; \
    372373    pglGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_##id, &i); \
    373374    if (ogl_SquelchError(GL_INVALID_ENUM)) \
    374375        scriptInterface.SetProperty(settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, errstr); \
    375376    else \
    376377        scriptInterface.SetProperty(settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, i); \
    377378    } while (false)
    378379
    379380#define FRAGMENTPROGRAM(id) do { \
    380381    GLint i = -1; \
    381382    pglGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_##id, &i); \
    382383    if (ogl_SquelchError(GL_INVALID_ENUM)) \
    383384        scriptInterface.SetProperty(settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, errstr); \
    384385    else \
    385386        scriptInterface.SetProperty(settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, i); \
    386387    } while (false)
    387388
    388389#define BOOL(id) INTEGER(id)
    389390
    390391    ogl_WarnIfError();
    391392
    392393    // Core OpenGL 1.3:
    393394    // (We don't bother checking extension strings for anything older than 1.3;
    394395    // it'll just produce harmless warnings)
    395396    STRING(VERSION);
    396397    STRING(VENDOR);
    397398    STRING(RENDERER);
    398399    STRING(EXTENSIONS);
    399400#if !CONFIG2_GLES
    400401    INTEGER(MAX_LIGHTS);
    401402    INTEGER(MAX_CLIP_PLANES);
    402403    // Skip MAX_COLOR_MATRIX_STACK_DEPTH (only in imaging subset)
    403404    INTEGER(MAX_MODELVIEW_STACK_DEPTH);
    404405    INTEGER(MAX_PROJECTION_STACK_DEPTH);
    405406    INTEGER(MAX_TEXTURE_STACK_DEPTH);
    406407#endif
    407408    INTEGER(SUBPIXEL_BITS);
    408409#if !CONFIG2_GLES
    409410    INTEGER(MAX_3D_TEXTURE_SIZE);
    410411#endif
    411412    INTEGER(MAX_TEXTURE_SIZE);
    412413    INTEGER(MAX_CUBE_MAP_TEXTURE_SIZE);
    413414#if !CONFIG2_GLES
    414415    INTEGER(MAX_PIXEL_MAP_TABLE);
    415416    INTEGER(MAX_NAME_STACK_DEPTH);
    416417    INTEGER(MAX_LIST_NESTING);
    417418    INTEGER(MAX_EVAL_ORDER);
    418419#endif
    419420    INTEGER2(MAX_VIEWPORT_DIMS);
    420421#if !CONFIG2_GLES
    421422    INTEGER(MAX_ATTRIB_STACK_DEPTH);
    422423    INTEGER(MAX_CLIENT_ATTRIB_STACK_DEPTH);
    423424    INTEGER(AUX_BUFFERS);
    424425    BOOL(RGBA_MODE);
    425426    BOOL(INDEX_MODE);
    426427    BOOL(DOUBLEBUFFER);
    427428    BOOL(STEREO);
    428429#endif
    429430    FLOAT2(ALIASED_POINT_SIZE_RANGE);
    430431#if !CONFIG2_GLES
    431432    FLOAT2(SMOOTH_POINT_SIZE_RANGE);
    432433    FLOAT(SMOOTH_POINT_SIZE_GRANULARITY);
    433434#endif
    434435    FLOAT2(ALIASED_LINE_WIDTH_RANGE);
    435436#if !CONFIG2_GLES
    436437    FLOAT2(SMOOTH_LINE_WIDTH_RANGE);
    437438    FLOAT(SMOOTH_LINE_WIDTH_GRANULARITY);
    438439    // Skip MAX_CONVOLUTION_WIDTH, MAX_CONVOLUTION_HEIGHT (only in imaging subset)
    439440    INTEGER(MAX_ELEMENTS_INDICES);
    440441    INTEGER(MAX_ELEMENTS_VERTICES);
    441442    INTEGER(MAX_TEXTURE_UNITS);
    442443#endif
    443444    INTEGER(SAMPLE_BUFFERS);
    444445    INTEGER(SAMPLES);
    445446    // TODO: compressed texture formats
    446447    INTEGER(RED_BITS);
    447448    INTEGER(GREEN_BITS);
    448449    INTEGER(BLUE_BITS);
    449450    INTEGER(ALPHA_BITS);
    450451#if !CONFIG2_GLES
    451452    INTEGER(INDEX_BITS);
    452453#endif
    453454    INTEGER(DEPTH_BITS);
    454455    INTEGER(STENCIL_BITS);
    455456#if !CONFIG2_GLES
    456457    INTEGER(ACCUM_RED_BITS);
    457458    INTEGER(ACCUM_GREEN_BITS);
    458459    INTEGER(ACCUM_BLUE_BITS);
    459460    INTEGER(ACCUM_ALPHA_BITS);
    460461#endif
    461462
    462463#if !CONFIG2_GLES
    463464
    464465    // Core OpenGL 2.0 (treated as extensions):
    465466
    466467    if (ogl_HaveExtension("GL_EXT_texture_lod_bias"))
    467468    {
    468469        FLOAT(MAX_TEXTURE_LOD_BIAS_EXT);
    469470    }
    470471
    471472    if (ogl_HaveExtension("GL_ARB_occlusion_query"))
    472473    {
    473474        QUERY(SAMPLES_PASSED, QUERY_COUNTER_BITS);
    474475    }
    475476
    476477    if (ogl_HaveExtension("GL_ARB_shading_language_100"))
    477478    {
    478479        STRING(SHADING_LANGUAGE_VERSION_ARB);
    479480    }
    480481
    481482    if (ogl_HaveExtension("GL_ARB_vertex_shader"))
    482483    {
    483484        INTEGER(MAX_VERTEX_ATTRIBS_ARB);
    484485        INTEGER(MAX_VERTEX_UNIFORM_COMPONENTS_ARB);
    485486        INTEGER(MAX_VARYING_FLOATS_ARB);
    486487        INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB);
    487488        INTEGER(MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB);
    488489    }
    489490
    490491    if (ogl_HaveExtension("GL_ARB_fragment_shader"))
    491492    {
    492493        INTEGER(MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB);
    493494    }
    494495
    495496    if (ogl_HaveExtension("GL_ARB_vertex_shader") || ogl_HaveExtension("GL_ARB_fragment_shader") ||
    496497        ogl_HaveExtension("GL_ARB_vertex_program") || ogl_HaveExtension("GL_ARB_fragment_program"))
    497498    {
    498499        INTEGER(MAX_TEXTURE_IMAGE_UNITS_ARB);
    499500        INTEGER(MAX_TEXTURE_COORDS_ARB);
    500501    }
    501502
    502503    if (ogl_HaveExtension("GL_ARB_draw_buffers"))
    503504    {
    504505        INTEGER(MAX_DRAW_BUFFERS_ARB);
    505506    }
    506507
    507508    // Core OpenGL 3.0:
    508509
    509510    if (ogl_HaveExtension("GL_EXT_gpu_shader4"))
    510511    {
    511512        INTEGER(MIN_PROGRAM_TEXEL_OFFSET); // no _EXT version of these in glext.h
    512513        INTEGER(MAX_PROGRAM_TEXEL_OFFSET);
    513514    }
    514515
    515516    if (ogl_HaveExtension("GL_EXT_framebuffer_object"))
    516517    {
    517518        INTEGER(MAX_COLOR_ATTACHMENTS_EXT);
    518519        INTEGER(MAX_RENDERBUFFER_SIZE_EXT);
    519520    }
    520521
    521522    if (ogl_HaveExtension("GL_EXT_framebuffer_multisample"))
    522523    {
    523524        INTEGER(MAX_SAMPLES_EXT);
    524525    }
    525526
    526527    if (ogl_HaveExtension("GL_EXT_texture_array"))
    527528    {
    528529        INTEGER(MAX_ARRAY_TEXTURE_LAYERS_EXT);
    529530    }
    530531
    531532    if (ogl_HaveExtension("GL_EXT_transform_feedback"))
    532533    {
    533534        INTEGER(MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT);
    534535        INTEGER(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT);
    535536        INTEGER(MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT);
    536537    }
    537538
    538539
    539540    // Other interesting extensions:
    540541
    541542    if (ogl_HaveExtension("GL_EXT_timer_query") || ogl_HaveExtension("GL_ARB_timer_query"))
    542543    {
    543544        QUERY(TIME_ELAPSED, QUERY_COUNTER_BITS);
    544545    }
    545546
    546547    if (ogl_HaveExtension("GL_ARB_timer_query"))
    547548    {
    548549        QUERY(TIMESTAMP, QUERY_COUNTER_BITS);
    549550    }
    550551
    551552    if (ogl_HaveExtension("GL_EXT_texture_filter_anisotropic"))
    552553    {
    553554        FLOAT(MAX_TEXTURE_MAX_ANISOTROPY_EXT);
    554555    }
    555556
    556557    if (ogl_HaveExtension("GL_ARB_texture_rectangle"))
    557558    {
    558559        INTEGER(MAX_RECTANGLE_TEXTURE_SIZE_ARB);
    559560    }
    560561
    561562    if (ogl_HaveExtension("GL_ARB_vertex_program") || ogl_HaveExtension("GL_ARB_fragment_program"))
    562563    {
    563564        INTEGER(MAX_PROGRAM_MATRICES_ARB);
    564565        INTEGER(MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB);
    565566    }
    566567
    567568    if (ogl_HaveExtension("GL_ARB_vertex_program"))
    568569    {
    569570        VERTEXPROGRAM(MAX_PROGRAM_ENV_PARAMETERS_ARB);
    570571        VERTEXPROGRAM(MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
    571572        VERTEXPROGRAM(MAX_PROGRAM_INSTRUCTIONS_ARB);
    572573        VERTEXPROGRAM(MAX_PROGRAM_TEMPORARIES_ARB);
    573574        VERTEXPROGRAM(MAX_PROGRAM_PARAMETERS_ARB);
    574575        VERTEXPROGRAM(MAX_PROGRAM_ATTRIBS_ARB);
    575576        VERTEXPROGRAM(MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
    576577        VERTEXPROGRAM(MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
    577578        VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
    578579        VERTEXPROGRAM(MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
    579580        VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
    580581        VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
    581582
    582583        if (ogl_HaveExtension("GL_ARB_fragment_program"))
    583584        {
    584585            // The spec seems to say these should be supported, but
    585586            // Mesa complains about them so let's not bother
    586587            /*
    587588            VERTEXPROGRAM(MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
    588589            VERTEXPROGRAM(MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
    589590            VERTEXPROGRAM(MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
    590591            VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
    591592            VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
    592593            VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
    593594            */
    594595        }
    595596    }
    596597
    597598    if (ogl_HaveExtension("GL_ARB_fragment_program"))
    598599    {
    599600        FRAGMENTPROGRAM(MAX_PROGRAM_ENV_PARAMETERS_ARB);
    600601        FRAGMENTPROGRAM(MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
    601602        FRAGMENTPROGRAM(MAX_PROGRAM_INSTRUCTIONS_ARB);
    602603        FRAGMENTPROGRAM(MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
    603604        FRAGMENTPROGRAM(MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
    604605        FRAGMENTPROGRAM(MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
    605606        FRAGMENTPROGRAM(MAX_PROGRAM_TEMPORARIES_ARB);
    606607        FRAGMENTPROGRAM(MAX_PROGRAM_PARAMETERS_ARB);
    607608        FRAGMENTPROGRAM(MAX_PROGRAM_ATTRIBS_ARB);
    608609        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
    609610        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
    610611        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
    611612        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
    612613        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
    613614        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
    614615        FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
    615616
    616617        if (ogl_HaveExtension("GL_ARB_vertex_program"))
    617618        {
    618619            // The spec seems to say these should be supported, but
    619620            // Intel drivers on Windows complain about them so let's not bother
    620621            /*
    621622            FRAGMENTPROGRAM(MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
    622623            FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
    623624            */
    624625        }
    625626    }
    626627
    627628    if (ogl_HaveExtension("GL_ARB_geometry_shader4"))
    628629    {
    629630        INTEGER(MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB);
    630631        INTEGER(MAX_GEOMETRY_OUTPUT_VERTICES_ARB);
    631632        INTEGER(MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB);
    632633        INTEGER(MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB);
    633634        INTEGER(MAX_GEOMETRY_VARYING_COMPONENTS_ARB);
    634635        INTEGER(MAX_VERTEX_VARYING_COMPONENTS_ARB);
    635636    }
    636637
    637638#else // CONFIG2_GLES
    638639
    639640    // Core OpenGL ES 2.0:
    640641
    641642    STRING(SHADING_LANGUAGE_VERSION);
    642643    INTEGER(MAX_VERTEX_ATTRIBS);
    643644    INTEGER(MAX_VERTEX_UNIFORM_VECTORS);
    644645    INTEGER(MAX_VARYING_VECTORS);
    645646    INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
    646647    INTEGER(MAX_VERTEX_TEXTURE_IMAGE_UNITS);
    647648    INTEGER(MAX_FRAGMENT_UNIFORM_VECTORS);
    648649    INTEGER(MAX_TEXTURE_IMAGE_UNITS);
    649650    INTEGER(MAX_RENDERBUFFER_SIZE);
    650651
    651652#endif // CONFIG2_GLES
    652653
    653654
    654655// TODO: Support OpenGL platforms which don’t use GLX as well.
    655656#if defined(SDL_VIDEO_DRIVER_X11) && !CONFIG2_GLES
    656657
    657658#define GLXQCR_INTEGER(id) do { \
    658659    unsigned int i = UINT_MAX; \
    659660    if (pglXQueryCurrentRendererIntegerMESA(id, &i)) \
    660661        scriptInterface.SetProperty(settings, #id, i); \
    661662    } while (false)
    662663
    663664#define GLXQCR_INTEGER2(id) do { \
    664665    unsigned int i[2] = { UINT_MAX, UINT_MAX }; \
    665666    if (pglXQueryCurrentRendererIntegerMESA(id, i)) { \
    666667        scriptInterface.SetProperty(settings, #id "[0]", i[0]); \
    667668        scriptInterface.SetProperty(settings, #id "[1]", i[1]); \
    668669    } \
    669670    } while (false)
    670671
    671672#define GLXQCR_INTEGER3(id) do { \
    672673    unsigned int i[3] = { UINT_MAX, UINT_MAX, UINT_MAX }; \
    673674    if (pglXQueryCurrentRendererIntegerMESA(id, i)) { \
    674675        scriptInterface.SetProperty(settings, #id "[0]", i[0]); \
    675676        scriptInterface.SetProperty(settings, #id "[1]", i[1]); \
    676677        scriptInterface.SetProperty(settings, #id "[2]", i[2]); \
    677678    } \
    678679    } while (false)
    679680
    680681#define GLXQCR_STRING(id) do { \
    681682    const char* str = pglXQueryCurrentRendererStringMESA(id); \
    682683    if (str) \
    683684        scriptInterface.SetProperty(settings, #id ".string", str); \
    684685    } while (false)
    685686
    686687
    687688    SDL_SysWMinfo wminfo;
    688689    SDL_VERSION(&wminfo.version);
    689690    const int ret = SDL_GetWindowWMInfo(g_VideoMode.GetWindow(), &wminfo);
    690691    if (ret && wminfo.subsystem == SDL_SYSWM_X11)
    691692    {
    692693        Display* dpy = wminfo.info.x11.display;
    693694        int scrnum = DefaultScreen(dpy);
    694695
    695696        const char* glxexts = glXQueryExtensionsString(dpy, scrnum);
    696697
    697698        scriptInterface.SetProperty(settings, "glx_extensions", glxexts);
    698699
    699700        if (strstr(glxexts, "GLX_MESA_query_renderer") && pglXQueryCurrentRendererIntegerMESA && pglXQueryCurrentRendererStringMESA)
    700701        {
    701702            GLXQCR_INTEGER(GLX_RENDERER_VENDOR_ID_MESA);
    702703            GLXQCR_INTEGER(GLX_RENDERER_DEVICE_ID_MESA);
    703704            GLXQCR_INTEGER3(GLX_RENDERER_VERSION_MESA);
    704705            GLXQCR_INTEGER(GLX_RENDERER_ACCELERATED_MESA);
    705706            GLXQCR_INTEGER(GLX_RENDERER_VIDEO_MEMORY_MESA);
    706707            GLXQCR_INTEGER(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA);
    707708            GLXQCR_INTEGER(GLX_RENDERER_PREFERRED_PROFILE_MESA);
    708709            GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA);
    709710            GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA);
    710711            GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA);
    711712            GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA);
    712713            GLXQCR_STRING(GLX_RENDERER_VENDOR_ID_MESA);
    713714            GLXQCR_STRING(GLX_RENDERER_DEVICE_ID_MESA);
    714715        }
    715716    }
    716717#endif // SDL_VIDEO_DRIVER_X11
    717718
    718719}
  • source/renderer/ModelRenderer.cpp

     
    11/* Copyright (C) 2020 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    77 * (at your option) any later version.
    88 *
    99 * 0 A.D. is distributed in the hope that it will be useful,
    1010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1111 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1212 * GNU General Public License for more details.
    1313 *
    1414 * You should have received a copy of the GNU General Public License
    1515 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    1616 */
    1717
    1818#include "precompiled.h"
    1919
    2020#include "graphics/Color.h"
    2121#include "graphics/LightEnv.h"
    2222#include "graphics/Material.h"
    2323#include "graphics/Model.h"
    2424#include "graphics/ModelDef.h"
    2525#include "graphics/ShaderManager.h"
    2626#include "graphics/TextureManager.h"
    2727#include "lib/allocators/allocator_adapters.h"
    2828#include "lib/allocators/arena.h"
    2929#include "lib/hash.h"
    3030#include "lib/ogl.h"
    3131#include "maths/Vector3D.h"
    3232#include "maths/Vector4D.h"
    3333#include "ps/CLogger.h"
    3434#include "ps/Profile.h"
    3535#include "renderer/MikktspaceWrap.h"
    3636#include "renderer/ModelRenderer.h"
    3737#include "renderer/ModelVertexRenderer.h"
    3838#include "renderer/Renderer.h"
    3939#include "renderer/RenderModifiers.h"
    4040#include "renderer/SkyManager.h"
    4141#include "renderer/TimeManager.h"
    4242#include "renderer/WaterManager.h"
    4343
    44 #if ARCH_X86_X64
    45 # include "lib/sysdep/arch/x86_x64/x86_x64.h"
    46 #endif
    47 
    4844///////////////////////////////////////////////////////////////////////////////////////////////
    4945// ModelRenderer implementation
    5046
    51 #if ARCH_X86_X64
     47#if HAVE_SSE
    5248static bool g_EnableSSE = false;
    5349#endif
    5450
    5551void ModelRenderer::Init()
    5652{
    57 #if ARCH_X86_X64
    58     if (x86_x64::Cap(x86_x64::CAP_SSE))
     53#if HAVE_SSE
     54    if (IsSSEEnabled())
    5955        g_EnableSSE = true;
    6056#endif
    6157}
    6258
    6359// Helper function to copy object-space position and normal vectors into arrays.
    6460void ModelRenderer::CopyPositionAndNormals(
    6561        const CModelDefPtr& mdef,
    6662        const VertexArrayIterator<CVector3D>& Position,
    6763        const VertexArrayIterator<CVector3D>& Normal)
    6864{
    6965    size_t numVertices = mdef->GetNumVertices();
    7066    SModelVertex* vertices = mdef->GetVertices();
    7167
    7268    for (size_t j = 0; j < numVertices; ++j)
    7369    {
    7470        Position[j] = vertices[j].m_Coords;
    7571        Normal[j] = vertices[j].m_Norm;
    7672    }
    7773}
    7874
    7975// Helper function to transform position and normal vectors into world-space.
    8076void ModelRenderer::BuildPositionAndNormals(
    8177        CModel* model,
    8278        const VertexArrayIterator<CVector3D>& Position,
    8379        const VertexArrayIterator<CVector3D>& Normal)
    8480{
    8581    CModelDefPtr mdef = model->GetModelDef();
    8682    size_t numVertices = mdef->GetNumVertices();
    8783    SModelVertex* vertices = mdef->GetVertices();
    8884
    8985    if (model->IsSkinned())
    9086    {
    9187        // boned model - calculate skinned vertex positions/normals
    9288
    9389        // Avoid the noisy warnings that occur inside SkinPoint/SkinNormal in
    9490        // some broken situations
    9591        if (numVertices && vertices[0].m_Blend.m_Bone[0] == 0xff)
    9692        {
    9793            LOGERROR("Model %s is boned with unboned animation", mdef->GetName().string8());
    9894            return;
    9995        }
    10096
    10197#if HAVE_SSE
    10298        if (g_EnableSSE)
    10399        {
    104100            CModelDef::SkinPointsAndNormals_SSE(numVertices, Position, Normal, vertices, mdef->GetBlendIndices(), model->GetAnimatedBoneMatrices());
    105101        }
    106102        else
    107103#endif
    108104        {
    109105            CModelDef::SkinPointsAndNormals(numVertices, Position, Normal, vertices, mdef->GetBlendIndices(), model->GetAnimatedBoneMatrices());
    110106        }
    111107    }
    112108    else
    113109    {
    114110        PROFILE("software transform");
    115111        // just copy regular positions, transform normals to world space
    116112        const CMatrix3D& transform = model->GetTransform();
    117113        const CMatrix3D& invtransform = model->GetInvTransform();
    118114        for (size_t j = 0; j < numVertices; ++j)
    119115        {
    120116            transform.Transform(vertices[j].m_Coords, Position[j]);
    121117            invtransform.RotateTransposed(vertices[j].m_Norm, Normal[j]);
    122118        }
    123119    }
    124120}
    125121
    126122
    127123// Helper function for lighting
    128124void ModelRenderer::BuildColor4ub(
    129125        CModel* model,
    130126        const VertexArrayIterator<CVector3D>& Normal,
    131127        const VertexArrayIterator<SColor4ub>& Color)
    132128{
    133129    PROFILE("lighting vertices");
    134130
    135131    CModelDefPtr mdef = model->GetModelDef();
    136132    size_t numVertices = mdef->GetNumVertices();
    137133    const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
    138134    CColor shadingColor = model->GetShadingColor();
    139135
    140136    for (size_t j = 0; j < numVertices; ++j)
    141137    {
    142138        RGBColor tempcolor = lightEnv.EvaluateUnitScaled(Normal[j]);
    143139        tempcolor.X *= shadingColor.r;
    144140        tempcolor.Y *= shadingColor.g;
    145141        tempcolor.Z *= shadingColor.b;
    146142        Color[j] = ConvertRGBColorTo4ub(tempcolor);
    147143    }
    148144}
    149145
    150146
    151147void ModelRenderer::GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning)
    152148{
    153149    MikkTSpace ms(mdef, newVertices, gpuSkinning);
    154150    ms.Generate();
    155151}
    156152
    157153
    158154// Copy UV coordinates
    159155void ModelRenderer::BuildUV(
    160156        const CModelDefPtr& mdef,
    161157        const VertexArrayIterator<float[2]>& UV,
    162158        int UVset)
    163159{
    164160    size_t numVertices = mdef->GetNumVertices();
    165161    SModelVertex* vertices = mdef->GetVertices();
    166162
    167163    for (size_t j = 0; j < numVertices; ++j)
    168164    {
    169165        UV[j][0] = vertices[j].m_UVs[UVset * 2];
    170166        UV[j][1] = 1.0 - vertices[j].m_UVs[UVset * 2 + 1];
    171167    }
    172168}
    173169
    174170
    175171// Build default indices array.
    176172void ModelRenderer::BuildIndices(
    177173        const CModelDefPtr& mdef,
    178174        const VertexArrayIterator<u16>& Indices)
    179175{
    180176    size_t idxidx = 0;
    181177    SModelFace* faces = mdef->GetFaces();
    182178
    183179    for (size_t j = 0; j < mdef->GetNumFaces(); ++j)
    184180    {
    185181        SModelFace& face = faces[j];
    186182        Indices[idxidx++] = face.m_Verts[0];
    187183        Indices[idxidx++] = face.m_Verts[1];
    188184        Indices[idxidx++] = face.m_Verts[2];
    189185    }
    190186}
    191187
    192188
    193189
    194190///////////////////////////////////////////////////////////////////////////////////////////////
    195191// ShaderModelRenderer implementation
    196192
    197193
    198194/**
    199195 * Internal data of the ShaderModelRenderer.
    200196 *
    201197 * Separated into the source file to increase implementation hiding (and to
    202198 * avoid some causes of recompiles).
    203199 */
    204200struct ShaderModelRenderer::ShaderModelRendererInternals
    205201{
    206202    ShaderModelRendererInternals(ShaderModelRenderer* r) : m_Renderer(r) { }
    207203
    208204    /// Back-link to "our" renderer
    209205    ShaderModelRenderer* m_Renderer;
    210206
    211207    /// ModelVertexRenderer used for vertex transformations
    212208    ModelVertexRendererPtr vertexRenderer;
    213209
    214210    /// List of submitted models for rendering in this frame
    215211    std::vector<CModel*> submissions[CRenderer::CULL_MAX];
    216212};
    217213
    218214
    219215// Construction/Destruction
    220216ShaderModelRenderer::ShaderModelRenderer(ModelVertexRendererPtr vertexrenderer)
    221217{
    222218    m = new ShaderModelRendererInternals(this);
    223219    m->vertexRenderer = vertexrenderer;
    224220}
    225221
    226222ShaderModelRenderer::~ShaderModelRenderer()
    227223{
    228224    delete m;
    229225}
    230226
    231227// Submit one model.
    232228void ShaderModelRenderer::Submit(int cullGroup, CModel* model)
    233229{
    234230    CModelRData* rdata = (CModelRData*)model->GetRenderData();
    235231
    236232    // Ensure model data is valid
    237233    const void* key = m->vertexRenderer.get();
    238234    if (!rdata || rdata->GetKey() != key)
    239235    {
    240236        rdata = m->vertexRenderer->CreateModelData(key, model);
    241237        model->SetRenderData(rdata);
    242238        model->SetDirty(~0u);
    243239    }
    244240
    245241    m->submissions[cullGroup].push_back(model);
    246242}
    247243
    248244
    249245// Call update for all submitted models and enter the rendering phase
    250246void ShaderModelRenderer::PrepareModels()
    251247{
    252248    for (int cullGroup = 0; cullGroup < CRenderer::CULL_MAX; ++cullGroup)
    253249    {
    254250        for (size_t i = 0; i < m->submissions[cullGroup].size(); ++i)
    255251        {
    256252            CModel* model = m->submissions[cullGroup][i];
    257253
    258254            model->ValidatePosition();
    259255
    260256            CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
    261257            ENSURE(rdata->GetKey() == m->vertexRenderer.get());
    262258
    263259            m->vertexRenderer->UpdateModelData(model, rdata, rdata->m_UpdateFlags);
    264260            rdata->m_UpdateFlags = 0;
    265261        }
    266262    }
    267263}
    268264
    269265
    270266// Clear the submissions list
    271267void ShaderModelRenderer::EndFrame()
    272268{
    273269    for (int cullGroup = 0; cullGroup < CRenderer::CULL_MAX; ++cullGroup)
    274270        m->submissions[cullGroup].clear();
    275271}
    276272
    277273
    278274// Helper structs for ShaderModelRenderer::Render():
    279275
    280276struct SMRSortByDistItem
    281277{
    282278    size_t techIdx;
    283279    CModel* model;
    284280    float dist;
    285281};
    286282
    287283struct SMRBatchModel
    288284{
    289285    bool operator()(CModel* a, CModel* b)
    290286    {
    291287        if (a->GetModelDef() < b->GetModelDef())
    292288            return true;
    293289        if (b->GetModelDef() < a->GetModelDef())
    294290            return false;
    295291
    296292        if (a->GetMaterial().GetDiffuseTexture() < b->GetMaterial().GetDiffuseTexture())
    297293            return true;
    298294        if (b->GetMaterial().GetDiffuseTexture() < a->GetMaterial().GetDiffuseTexture())
    299295            return false;
    300296
    301297        return a->GetMaterial().GetStaticUniforms() < b->GetMaterial().GetStaticUniforms();
    302298    }
    303299};
    304300
    305301struct SMRCompareSortByDistItem
    306302{
    307303    bool operator()(const SMRSortByDistItem& a, const SMRSortByDistItem& b)
    308304    {
    309305        // Prefer items with greater distance, so we draw back-to-front
    310306        return (a.dist > b.dist);
    311307
    312308        // (Distances will almost always be distinct, so we don't need to bother
    313309        // tie-breaking on modeldef/texture/etc)
    314310    }
    315311};
    316312
    317313struct SMRMaterialBucketKey
    318314{
    319315    SMRMaterialBucketKey(CStrIntern effect, const CShaderDefines& defines)
    320316        : effect(effect), defines(defines) { }
    321317
    322318    CStrIntern effect;
    323319    CShaderDefines defines;
    324320
    325321    bool operator==(const SMRMaterialBucketKey& b) const
    326322    {
    327323        return (effect == b.effect && defines == b.defines);
    328324    }
    329325
    330326private:
    331327    SMRMaterialBucketKey& operator=(const SMRMaterialBucketKey&);
    332328};
    333329
    334330struct SMRMaterialBucketKeyHash
    335331{
    336332    size_t operator()(const SMRMaterialBucketKey& key) const
    337333    {
    338334        size_t hash = 0;
    339335        hash_combine(hash, key.effect.GetHash());
    340336        hash_combine(hash, key.defines.GetHash());
    341337        return hash;
    342338    }
    343339};
    344340
    345341struct SMRTechBucket
    346342{
    347343    CShaderTechniquePtr tech;
    348344    CModel** models;
    349345    size_t numModels;
    350346
    351347    // Model list is stored as pointers, not as a std::vector,
    352348    // so that sorting lists of this struct is fast
    353349};
    354350
    355351struct SMRCompareTechBucket
    356352{
    357353    bool operator()(const SMRTechBucket& a, const SMRTechBucket& b)
    358354    {
    359355        return a.tech < b.tech;
    360356    }
    361357};
    362358
    363359void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags)
    364360{
    365361    if (m->submissions[cullGroup].empty())
    366362        return;
    367363
    368364    CMatrix3D worldToCam;
    369365    g_Renderer.GetViewCamera().GetOrientation().GetInverse(worldToCam);
    370366
    371367    /*
    372368     * Rendering approach:
    373369     *
    374370     * m->submissions contains the list of CModels to render.
    375371     *
    376372     * The data we need to render a model is:
    377373     *  - CShaderTechnique
    378374     *  - CTexture
    379375     *  - CShaderUniforms
    380376     *  - CModelDef (mesh data)
    381377     *  - CModel (model instance data)
    382378     *
    383379     * For efficient rendering, we need to batch the draw calls to minimise state changes.
    384380     * (Uniform and texture changes are assumed to be cheaper than binding new mesh data,
    385381     * and shader changes are assumed to be most expensive.)
    386382     * First, group all models that share a technique to render them together.
    387383     * Within those groups, sub-group by CModelDef.
    388384     * Within those sub-groups, sub-sub-group by CTexture.
    389385     * Within those sub-sub-groups, sub-sub-sub-group by CShaderUniforms.
    390386     *
    391387     * Alpha-blended models have to be sorted by distance from camera,
    392388     * then we can batch as long as the order is preserved.
    393389     * Non-alpha-blended models can be arbitrarily reordered to maximise batching.
    394390     *
    395391     * For each model, the CShaderTechnique is derived from:
    396392     *  - The current global 'context' defines
    397393     *  - The CModel's material's defines
    398394     *  - The CModel's material's shader effect name
    399395     *
    400396     * There are a smallish number of materials, and a smaller number of techniques.
    401397     *
    402398     * To minimise technique lookups, we first group models by material,
    403399     * in 'materialBuckets' (a hash table).
    404400     *
    405401     * For each material bucket we then look up the appropriate shader technique.
    406402     * If the technique requires sort-by-distance, the model is added to the
    407403     * 'sortByDistItems' list with its computed distance.
    408404     * Otherwise, the bucket's list of models is sorted by modeldef+texture+uniforms,
    409405     * then the technique and model list is added to 'techBuckets'.
    410406     *
    411407     * 'techBuckets' is then sorted by technique, to improve batching when multiple
    412408     * materials map onto the same technique.
    413409     *
    414410     * (Note that this isn't perfect batching: we don't sort across models in
    415411     * multiple buckets that share a technique. In practice that shouldn't reduce
    416412     * batching much (we rarely have one mesh used with multiple materials),
    417413     * and it saves on copying and lets us sort smaller lists.)
    418414     *
    419415     * Extra tech buckets are added for the sorted-by-distance models without reordering.
    420416     * Finally we render by looping over each tech bucket, then looping over the model
    421417     * list in each, rebinding the GL state whenever it changes.
    422418     */
    423419
    424420    Allocators::DynamicArena arena(256 * KiB);
    425421    using ModelListAllocator = ProxyAllocator<CModel*, Allocators::DynamicArena>;
    426422    using ModelList_t = std::vector<CModel*, ModelListAllocator>;
    427423    using MaterialBuckets_t = std::unordered_map<
    428424        SMRMaterialBucketKey,
    429425        ModelList_t,
    430426        SMRMaterialBucketKeyHash,
    431427        std::equal_to<SMRMaterialBucketKey>,
    432428        ProxyAllocator<
    433429            std::pair<const SMRMaterialBucketKey, ModelList_t>,
    434430            Allocators::DynamicArena> >;
    435431
    436432    MaterialBuckets_t materialBuckets((MaterialBuckets_t::allocator_type(arena)));
    437433
    438434    {
    439435        PROFILE3("bucketing by material");
    440436
    441437        for (size_t i = 0; i < m->submissions[cullGroup].size(); ++i)
    442438        {
    443439            CModel* model = m->submissions[cullGroup][i];
    444440
    445441            uint32_t condFlags = 0;
    446442
    447443            const CShaderConditionalDefines& condefs = model->GetMaterial().GetConditionalDefines();
    448444            for (size_t j = 0; j < condefs.GetSize(); ++j)
    449445            {
    450446                const CShaderConditionalDefines::CondDefine& item = condefs.GetItem(j);
    451447                int type = item.m_CondType;
    452448                switch (type)
    453449                {
    454450                    case DCOND_DISTANCE:
    455451                    {
    456452                        CVector3D modelpos = model->GetTransform().GetTranslation();
    457453                        float dist = worldToCam.Transform(modelpos).Z;
    458454
    459455                        float dmin = item.m_CondArgs[0];
    460456                        float dmax = item.m_CondArgs[1];
    461457
    462458                        if ((dmin < 0 || dist >= dmin) && (dmax < 0 || dist < dmax))
    463459                            condFlags |= (1 << j);
    464460
    465461                        break;
    466462                    }
    467463                }
    468464            }
    469465
    470466            CShaderDefines defs = model->GetMaterial().GetShaderDefines(condFlags);
    471467            SMRMaterialBucketKey key(model->GetMaterial().GetShaderEffect(), defs);
    472468
    473469            MaterialBuckets_t::iterator it = materialBuckets.find(key);
    474470            if (it == materialBuckets.end())
    475471            {
    476472                std::pair<MaterialBuckets_t::iterator, bool> inserted = materialBuckets.insert(
    477473                    std::make_pair(key, ModelList_t(ModelList_t::allocator_type(arena))));
    478474                inserted.first->second.reserve(32);
    479475                inserted.first->second.push_back(model);
    480476            }
    481477            else
    482478            {
    483479                it->second.push_back(model);
    484480            }
    485481        }
    486482    }
    487483
    488484    typedef ProxyAllocator<SMRSortByDistItem, Allocators::DynamicArena> SortByDistItemsAllocator;
    489485    std::vector<SMRSortByDistItem, SortByDistItemsAllocator> sortByDistItems((SortByDistItemsAllocator(arena)));
    490486
    491487    typedef ProxyAllocator<CShaderTechniquePtr, Allocators::DynamicArena> SortByTechItemsAllocator;
    492488    std::vector<CShaderTechniquePtr, SortByTechItemsAllocator> sortByDistTechs((SortByTechItemsAllocator(arena)));
    493489        // indexed by sortByDistItems[i].techIdx
    494490        // (which stores indexes instead of CShaderTechniquePtr directly
    495491        // to avoid the shared_ptr copy cost when sorting; maybe it'd be better
    496492        // if we just stored raw CShaderTechnique* and assumed the shader manager
    497493        // will keep it alive long enough)
    498494
    499495    typedef ProxyAllocator<SMRTechBucket, Allocators::DynamicArena> TechBucketsAllocator;
    500496    std::vector<SMRTechBucket, TechBucketsAllocator> techBuckets((TechBucketsAllocator(arena)));
    501497
    502498    {
    503499        PROFILE3("processing material buckets");
    504500        for (MaterialBuckets_t::iterator it = materialBuckets.begin(); it != materialBuckets.end(); ++it)
    505501        {
    506502            CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(it->first.effect, context, it->first.defines);
    507503
    508504            // Skip invalid techniques (e.g. from data file errors)
    509505            if (!tech)
    510506                continue;
    511507
    512508            if (tech->GetSortByDistance())
    513509            {
    514510                // Add the tech into a vector so we can index it
    515511                // (There might be duplicates in this list, but that doesn't really matter)
    516512                if (sortByDistTechs.empty() || sortByDistTechs.back() != tech)
    517513                    sortByDistTechs.push_back(tech);
    518514                size_t techIdx = sortByDistTechs.size() - 1;
    519515
    520516                // Add each model into sortByDistItems
    521517                for (size_t i = 0; i < it->second.size(); ++i)
    522518                {
    523519                    SMRSortByDistItem itemWithDist;
    524520                    itemWithDist.techIdx = techIdx;
    525521
    526522                    CModel* model = it->second[i];
    527523                    itemWithDist.model = model;
    528524
    529525                    CVector3D modelpos = model->GetTransform().GetTranslation();
    530526                    itemWithDist.dist = worldToCam.Transform(modelpos).Z;
    531527
    532528                    sortByDistItems.push_back(itemWithDist);
    533529                }
    534530            }
    535531            else
    536532            {
    537533                // Sort model list by modeldef+texture, for batching
    538534                // TODO: This only sorts by base texture. While this is an OK approximation
    539535                // for most cases (as related samplers are usually used together), it would be better
    540536                // to take all the samplers into account when sorting here.
    541537                std::sort(it->second.begin(), it->second.end(), SMRBatchModel());
    542538
    543539                // Add a tech bucket pointing at this model list
    544540                SMRTechBucket techBucket = { tech, &it->second[0], it->second.size() };
    545541                techBuckets.push_back(techBucket);
    546542            }
    547543        }
    548544    }
    549545
    550546    {
    551547        PROFILE3("sorting tech buckets");
    552548        // Sort by technique, for better batching
    553549        std::sort(techBuckets.begin(), techBuckets.end(), SMRCompareTechBucket());
    554550    }
    555551
    556552    // List of models corresponding to sortByDistItems[i].model
    557553    // (This exists primarily because techBuckets wants a CModel**;
    558554    // we could avoid the cost of copying into this list by adding
    559555    // a stride length into techBuckets and not requiring contiguous CModel*s)
    560556    std::vector<CModel*, ModelListAllocator> sortByDistModels((ModelListAllocator(arena)));
    561557
    562558    if (!sortByDistItems.empty())
    563559    {
    564560        {
    565561            PROFILE3("sorting items by dist");
    566562            std::sort(sortByDistItems.begin(), sortByDistItems.end(), SMRCompareSortByDistItem());
    567563        }
    568564
    569565        {
    570566            PROFILE3("batching dist-sorted items");
    571567
    572568            sortByDistModels.reserve(sortByDistItems.size());
    573569
    574570            // Find runs of distance-sorted models that share a technique,
    575571            // and create a new tech bucket for each run
    576572
    577573            size_t start = 0; // start of current run
    578574            size_t currentTechIdx = sortByDistItems[start].techIdx;
    579575
    580576            for (size_t end = 0; end < sortByDistItems.size(); ++end)
    581577            {
    582578                sortByDistModels.push_back(sortByDistItems[end].model);
    583579
    584580                size_t techIdx = sortByDistItems[end].techIdx;
    585581                if (techIdx != currentTechIdx)
    586582                {
    587583                    // Start of a new run - push the old run into a new tech bucket
    588584                    SMRTechBucket techBucket = { sortByDistTechs[currentTechIdx], &sortByDistModels[start], end - start };
    589585                    techBuckets.push_back(techBucket);
    590586                    start = end;
    591587                    currentTechIdx = techIdx;
    592588                }
    593589            }
    594590
    595591            // Add the tech bucket for the final run
    596592            SMRTechBucket techBucket = { sortByDistTechs[currentTechIdx], &sortByDistModels[start], sortByDistItems.size() - start };
    597593            techBuckets.push_back(techBucket);
    598594        }
    599595    }
    600596
    601597    {
    602598        PROFILE3("rendering bucketed submissions");
    603599
    604600        size_t idxTechStart = 0;
    605601
    606602        // This vector keeps track of texture changes during rendering. It is kept outside the
    607603        // loops to avoid excessive reallocations. The token allocation of 64 elements
    608604        // should be plenty, though it is reallocated below (at a cost) if necessary.
    609605        typedef ProxyAllocator<CTexture*, Allocators::DynamicArena> TextureListAllocator;
    610606        std::vector<CTexture*, TextureListAllocator> currentTexs((TextureListAllocator(arena)));
    611607        currentTexs.reserve(64);
    612608
    613609        // texBindings holds the identifier bindings in the shader, which can no longer be defined
    614610        // statically in the ShaderRenderModifier class. texBindingNames uses interned strings to
    615611        // keep track of when bindings need to be reevaluated.
    616612        typedef ProxyAllocator<CShaderProgram::Binding, Allocators::DynamicArena> BindingListAllocator;
    617613        std::vector<CShaderProgram::Binding, BindingListAllocator> texBindings((BindingListAllocator(arena)));
    618614        texBindings.reserve(64);
    619615
    620616        typedef ProxyAllocator<CStrIntern, Allocators::DynamicArena> BindingNamesListAllocator;
    621617        std::vector<CStrIntern, BindingNamesListAllocator> texBindingNames((BindingNamesListAllocator(arena)));
    622618        texBindingNames.reserve(64);
    623619
    624620        while (idxTechStart < techBuckets.size())
    625621        {
    626622            CShaderTechniquePtr currentTech = techBuckets[idxTechStart].tech;
    627623
    628624            // Find runs [idxTechStart, idxTechEnd) in techBuckets of the same technique
    629625            size_t idxTechEnd;
    630626            for (idxTechEnd = idxTechStart + 1; idxTechEnd < techBuckets.size(); ++idxTechEnd)
    631627            {
    632628                if (techBuckets[idxTechEnd].tech != currentTech)
    633629                    break;
    634630            }
    635631
    636632            // For each of the technique's passes, render all the models in this run
    637633            for (int pass = 0; pass < currentTech->GetNumPasses(); ++pass)
    638634            {
    639635                currentTech->BeginPass(pass);
    640636
    641637                const CShaderProgramPtr& shader = currentTech->GetShader(pass);
    642638                int streamflags = shader->GetStreamFlags();
    643639
    644640                modifier->BeginPass(shader);
    645641
    646642                m->vertexRenderer->BeginPass(streamflags);
    647643
    648644                // When the shader technique changes, textures need to be
    649645                // rebound, so ensure there are no remnants from the last pass.
    650646                // (the vector size is set to 0, but memory is not freed)
    651647                currentTexs.clear();
    652648                texBindings.clear();
    653649                texBindingNames.clear();
    654650
    655651                CModelDef* currentModeldef = NULL;
    656652                CShaderUniforms currentStaticUniforms;
    657653
    658654                for (size_t idx = idxTechStart; idx < idxTechEnd; ++idx)
    659655                {
    660656                    CModel** models = techBuckets[idx].models;
    661657                    size_t numModels = techBuckets[idx].numModels;
    662658                    for (size_t i = 0; i < numModels; ++i)
    663659                    {
    664660                        CModel* model = models[i];
    665661
    666662                        if (flags && !(model->GetFlags() & flags))
    667663                            continue;
    668664
    669665                        const CMaterial::SamplersVector& samplers = model->GetMaterial().GetSamplers();
    670666                        size_t samplersNum = samplers.size();
    671667
    672668                        // make sure the vectors are the right virtual sizes, and also
    673669                        // reallocate if there are more samplers than expected.
    674670                        if (currentTexs.size() != samplersNum)
    675671                        {
    676672                            currentTexs.resize(samplersNum, NULL);
    677673                            texBindings.resize(samplersNum, CShaderProgram::Binding());
    678674                            texBindingNames.resize(samplersNum, CStrIntern());
    679675
    680676                            // ensure they are definitely empty
    681677                            std::fill(texBindings.begin(), texBindings.end(), CShaderProgram::Binding());
    682678                            std::fill(currentTexs.begin(), currentTexs.end(), (CTexture*)NULL);
    683679                            std::fill(texBindingNames.begin(), texBindingNames.end(), CStrIntern());
    684680                        }
    685681
    686682                        // bind the samplers to the shader
    687683                        for (size_t s = 0; s < samplersNum; ++s)
    688684                        {
    689685                            const CMaterial::TextureSampler& samp = samplers[s];
    690686
    691687                            // check that the handles are current
    692688                            // and reevaluate them if necessary
    693689                            if (texBindingNames[s] != samp.Name || !texBindings[s].Active())
    694690                            {
    695691                                texBindings[s] = shader->GetTextureBinding(samp.Name);
    696692                                texBindingNames[s] = samp.Name;
    697693                            }
    698694
    699695                            // same with the actual sampler bindings
    700696                            CTexture* newTex = samp.Sampler.get();
    701697                            if (texBindings[s].Active() && newTex != currentTexs[s])
    702698                            {
    703699                                shader->BindTexture(texBindings[s], newTex->GetHandle());
    704700                                currentTexs[s] = newTex;
    705701                            }
    706702                        }
    707703
    708704                        // Bind modeldef when it changes
    709705                        CModelDef* newModeldef = model->GetModelDef().get();
    710706                        if (newModeldef != currentModeldef)
    711707                        {
    712708                            currentModeldef = newModeldef;
    713709                            m->vertexRenderer->PrepareModelDef(shader, streamflags, *currentModeldef);
    714710                        }
    715711
    716712                        // Bind all uniforms when any change
    717713                        CShaderUniforms newStaticUniforms = model->GetMaterial().GetStaticUniforms();
    718714                        if (newStaticUniforms != currentStaticUniforms)
    719715                        {
    720716                            currentStaticUniforms = newStaticUniforms;
    721717                            currentStaticUniforms.BindUniforms(shader);
    722718                        }
    723719
    724720                        const CShaderRenderQueries& renderQueries = model->GetMaterial().GetRenderQueries();
    725721
    726722                        for (size_t q = 0; q < renderQueries.GetSize(); ++q)
    727723                        {
    728724                            CShaderRenderQueries::RenderQuery rq = renderQueries.GetItem(q);
    729725                            if (rq.first == RQUERY_TIME)
    730726                            {
    731727                                CShaderProgram::Binding binding = shader->GetUniformBinding(rq.second);
    732728                                if (binding.Active())
    733729                                {
    734730                                    double time = g_Renderer.GetTimeManager().GetGlobalTime();
    735731                                    shader->Uniform(binding, time, 0.0f, 0.0f, 0.0f);
    736732                                }
    737733                            }
    738734                            else if (rq.first == RQUERY_WATER_TEX)
    739735                            {
    740736                                WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    741737                                double time = WaterMgr->m_WaterTexTimer;
    742738                                double period = 1.6;
    743739                                int curTex = static_cast<int>(time * 60.0 / period) % 60;
    744740
    745741                                if (WaterMgr->m_RenderWater && WaterMgr->WillRenderFancyWater())
    746742                                    shader->BindTexture(str_waterTex, WaterMgr->m_NormalMap[curTex]);
    747743                                else
    748744                                    shader->BindTexture(str_waterTex, g_Renderer.GetTextureManager().GetErrorTexture());
    749745                            }
    750746                            else if (rq.first == RQUERY_SKY_CUBE)
    751747                            {
    752748                                shader->BindTexture(str_skyCube, g_Renderer.GetSkyManager()->GetSkyCube());
    753749                            }
    754750                        }
    755751
    756752                        modifier->PrepareModel(shader, model);
    757753
    758754                        CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
    759755                        ENSURE(rdata->GetKey() == m->vertexRenderer.get());
    760756
    761757                        m->vertexRenderer->RenderModel(shader, streamflags, model, rdata);
    762758                    }
    763759                }
    764760
    765761                m->vertexRenderer->EndPass(streamflags);
    766762
    767763                currentTech->EndPass(pass);
    768764            }
    769765
    770766            idxTechStart = idxTechEnd;
    771767        }
    772768    }
    773769}