Merge branch 'DRTVWR-546' of ssh://bitbucket.org/lindenlab/viewer into DRTVWR-546
commit
e0ea20a3c9
372
autobuild.xml
372
autobuild.xml
|
|
@ -76,9 +76,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9b8bcc3be6dbe40a04c9c81c313f70dc</string>
|
||||
<string>b6357ef3a0ec37877a5831820f25094e</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/68333/658209/apr_suite-1.4.5.548882-darwin64-548882.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80557/759704/apr_suite-1.4.5.558565-darwin64-558565.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -112,9 +112,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>6bdf460c18ee004b41a46afc80041a92</string>
|
||||
<string>cb48ac069440f6dcd564cfa9fd02a4c2</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/68334/658225/apr_suite-1.4.5.548882-windows-548882.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80556/759710/apr_suite-1.4.5.558565-windows-558565.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -124,16 +124,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>83104bfa4dabb77cd70d185e38a95b49</string>
|
||||
<string>646dc3828d9c39fb1e77c4eec44ed739</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/68332/658215/apr_suite-1.4.5.548882-windows64-548882.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80555/759709/apr_suite-1.4.5.558565-windows64-558565.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.4.5.548882</string>
|
||||
<string>1.4.5.558565</string>
|
||||
</map>
|
||||
<key>boost</key>
|
||||
<map>
|
||||
|
|
@ -166,9 +166,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>3cc73623c9a976b4f8346a3837f7a916</string>
|
||||
<string>35cc090d942b85c9126ceac9912d52d6</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64088/601256/boost-1.72-darwin64-545361.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78585/744021/boost-1.72-darwin64-557045.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -202,9 +202,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7d4b2511976449e9a4ec7be41dc8310f</string>
|
||||
<string>9aa4ce32df5f5e36124c990e2d77b885</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64092/601270/boost-1.72-windows-545361.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78586/743982/boost-1.72-windows-557045.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -214,9 +214,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>4ad8df0700745201cddf6b71d7b0949f</string>
|
||||
<string>a79511c9d8b956767ebaa405155d4238</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64091/601265/boost-1.72-windows64-545361.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78584/743961/boost-1.72-windows64-557045.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -308,9 +308,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>02e6a8207dcdaf243dcb6da19b8c3534</string>
|
||||
<string>1d063cf1783e7788f17486c234adb1db</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64099/601302/colladadom-2.3.545362-darwin64-545362.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78635/744249/colladadom-2.3.557064-darwin64-557064.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -344,9 +344,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>8a02a10fc69c8f504dc5335644db184a</string>
|
||||
<string>e78ecf919eee01567556787c3a358d15</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64104/601313/colladadom-2.3.545362-windows-545362.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78637/744269/colladadom-2.3.557064-windows-557064.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -356,16 +356,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>742180324fca7ab92b6a61a36aab4f9d</string>
|
||||
<string>7e63a212c8909a25236138422fe01298</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64103/601314/colladadom-2.3.545362-windows64-545362.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78636/744273/colladadom-2.3.557064-windows64-557064.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.3.545362</string>
|
||||
<string>2.3.557064</string>
|
||||
</map>
|
||||
<key>curl</key>
|
||||
<map>
|
||||
|
|
@ -398,9 +398,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f5ae57117a6518d11f49ccfbfbe0969d</string>
|
||||
<string>13f74f43a6363ec998569f731fd869c5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64131/601402/curl-7.54.1.545369-darwin64-545369.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82637/774617/curl-7.54.1.560191-darwin64-560191.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -434,11 +434,11 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2796ae7b09e730a55ac03f74ed669520</string>
|
||||
<string>0df99bd685dc3561ca8ea347b2921987</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64130/601396/curl-7.54.1.545369-windows-545369.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82639/774610/curl-7.54.1.560191-windows-560191.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -448,16 +448,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>a8f96e5cdb8128b23d49ff4c3f2233a4</string>
|
||||
<string>50db2a9e6b74ec4b0c38b1ea8f135735</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64129/601382/curl-7.54.1.545369-windows64-545369.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82638/774608/curl-7.54.1.560191-windows64-560191.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>7.54.1.545369</string>
|
||||
<string>7.54.1.560191</string>
|
||||
</map>
|
||||
<key>db</key>
|
||||
<map>
|
||||
|
|
@ -580,9 +580,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>49fff41e17e06cdf9eb0c737d20df52f</string>
|
||||
<string>45dedb5b09995cd794304150e94fcf21</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/83411/779825/dullahan-1.12.2.202106220202_91.1.21_g9dd45fe_chromium-91.0.4472.114-darwin64-560751.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87950/806969/dullahan-1.12.2.202109170444_91.1.21_g9dd45fe_chromium-91.0.4472.114-darwin64-563968.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -592,9 +592,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f51f324d50a2461cda273e84fa65e0ad</string>
|
||||
<string>d0fd9d7086699da4bb5ccc935622a717</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/83413/779836/dullahan-1.12.2.202106220213_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows-560751.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/88276/809277/dullahan-1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows-563968.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -604,16 +604,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>d3df46f6592715c75df2bf520c1ad68b</string>
|
||||
<string>7e8c3ccd420ff5aef24ff72d609ba394</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/83412/779840/dullahan-1.12.2.202106220213_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows64-560751.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/88275/809281/dullahan-1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows64-563968.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.12.2.202106220213_91.1.21_g9dd45fe_chromium-91.0.4472.114</string>
|
||||
<string>1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114</string>
|
||||
</map>
|
||||
<key>elfio</key>
|
||||
<map>
|
||||
|
|
@ -670,9 +670,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>3656b7f7b655cb267fd94f089d2e145c</string>
|
||||
<string>f4e80e0dfcab713a3da90cd8f7f23e7b</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54860/510198/expat-2.1.1.538990-darwin64-538990.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76341/727265/expat-2.1.1.555519-darwin64-555519.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -706,9 +706,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c509f8afa1e02f4c16232cce7f6855f8</string>
|
||||
<string>cd4fe03473076c324d80ae3bd91a85bb</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55056/512080/expat-2.1.1.538990-windows-538990.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76343/727273/expat-2.1.1.555519-windows-555519.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -718,16 +718,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>aba97cfdf44c04dbfcac89c7cb472580</string>
|
||||
<string>d2d74d73b914150982b1883a3b96e60b</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55054/512068/expat-2.1.1.538990-windows64-538990.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76344/727279/expat-2.1.1.555519-windows64-555519.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.1.1.538990</string>
|
||||
<string>2.1.1.555519</string>
|
||||
</map>
|
||||
<key>fmodstudio</key>
|
||||
<map>
|
||||
|
|
@ -748,9 +748,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>89c37441a806ed80c0102d380eec6fd0</string>
|
||||
<string>d5528538e67c710387ae0c061a90cb23</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65400/612632/fmodstudio-2.00.11.546392-darwin64-546392.tar.bz2</string>
|
||||
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76868/730756/fmodstudio-2.01.07.555883-darwin64-555883.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -784,9 +784,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>0f44323b0d03b7d0d8a17eec83e103ce</string>
|
||||
<string>a2bb6eaf51f933993b26a5fe7503a761</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65401/612647/fmodstudio-2.00.11.546392-windows-546392.tar.bz2</string>
|
||||
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76869/730763/fmodstudio-2.01.07.555883-windows-555883.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -796,16 +796,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>462d28eacf731a5d36ab031e7071c32a</string>
|
||||
<string>138d07dd516a9ad5b9787192fe6134dd</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65402/612648/fmodstudio-2.00.11.546392-windows64-546392.tar.bz2</string>
|
||||
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76867/730751/fmodstudio-2.01.07.555883-windows64-555883.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.00.11.546392</string>
|
||||
<string>2.01.07.555883</string>
|
||||
</map>
|
||||
<key>fontconfig</key>
|
||||
<map>
|
||||
|
|
@ -880,9 +880,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>81a2e9aca3e33c4eecf0081854540b07</string>
|
||||
<string>3a478d6c8a10d49d9161ef864394b03c</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56309/526711/freetype-2.4.4.539865-darwin64-539865.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78592/744013/freetype-2.4.4.557047-darwin64-557047.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -916,9 +916,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>1d1c7b60f71a5152ced60bee87f5bba8</string>
|
||||
<string>7ee200d6b5fa282c7f973ade5615aa86</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56312/526734/freetype-2.4.4.539865-windows-539865.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78594/744011/freetype-2.4.4.557047-windows-557047.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -928,16 +928,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>53e78d4a607e959637e98a82a3cf5bea</string>
|
||||
<string>69307aaba16ac71531c9c4d930ace993</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56310/526723/freetype-2.4.4.539865-windows64-539865.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78593/744010/freetype-2.4.4.557047-windows64-557047.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.4.4.539865</string>
|
||||
<string>2.4.4.557047</string>
|
||||
</map>
|
||||
<key>glext</key>
|
||||
<map>
|
||||
|
|
@ -1078,9 +1078,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>343913fe1434da228c2210c23d2e3a1a</string>
|
||||
<string>a9eaa005ff9d387f946283fbcb69b3c8</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54850/510134/glod-1.0pre3.538980-darwin64-538980.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76353/727324/glod-1.0pre3.555522-darwin64-555522.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -1139,97 +1139,7 @@
|
|||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.0pre3.538980</string>
|
||||
</map>
|
||||
<key>google_breakpad</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 2006, Google Inc.</string>
|
||||
<key>description</key>
|
||||
<string>Breakpad is a crossplatform library for capturing crash callstacks and runtime data.</string>
|
||||
<key>license</key>
|
||||
<string>bsd</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/google_breakpad.txt</string>
|
||||
<key>name</key>
|
||||
<string>google_breakpad</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>171b39db6d0702535b41fad5b476e39d</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/google-breakpad_3p-update-google-breakpad/rev/298033/arch/Darwin/installer/google_breakpad-1413.298033-darwin-298033.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin</string>
|
||||
</map>
|
||||
<key>darwin64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>ca33f234aae399b9e704e262f7e15d35</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56338/526869/google_breakpad-1413.539880-darwin64-539880.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>352e673897e8f36f8470150b8ace6ce9</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-google-breakpad/rev/314225/arch/Linux/installer/google_breakpad-1413.314225-linux-314225.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>6bddcc1ac470dd5eab459220102df9e9</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1835/4114/google_breakpad-1413.501824-linux64-501824.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>bfee0438617f57f02f7e8515a801cb20</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56359/526982/google_breakpad-1413.539880-windows-539880.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>6f983e754bb3046f065806b510b408c5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56358/526975/google_breakpad-1413.539880-windows64-539880.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1413.539880</string>
|
||||
<string>1.0pre3.555522</string>
|
||||
</map>
|
||||
<key>googlemock</key>
|
||||
<map>
|
||||
|
|
@ -1262,9 +1172,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f9831360ced94943ab9dfb3fbf5256d3</string>
|
||||
<string>19e925604bc1a91efb4b130e1edd8bf2</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64101/601290/googlemock-1.7.0.545363-darwin64-545363.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78620/744140/googlemock-1.7.0.557057-darwin64-557057.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -1298,9 +1208,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>8149e46b4f7abb3ac284415cfe1366e1</string>
|
||||
<string>eed7b41d0d1f41b24f315349ef78c728</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64102/601296/googlemock-1.7.0.545363-windows-545363.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78622/744148/googlemock-1.7.0.557057-windows-557057.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -1310,16 +1220,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f3851eba809ead2810d702041569d36d</string>
|
||||
<string>a6ad6fe722d2fe4e8137495af3f374c9</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64100/601284/googlemock-1.7.0.545363-windows64-545363.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78621/744152/googlemock-1.7.0.557057-windows64-557057.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.7.0.545363</string>
|
||||
<string>1.7.0.557057</string>
|
||||
</map>
|
||||
<key>gstreamer</key>
|
||||
<map>
|
||||
|
|
@ -1792,9 +1702,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c327e6d6573fc0a808677de47f08acd9</string>
|
||||
<string>2021ea3a19b81c82993e733709683303</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54844/510092/libhunspell-1.3.2.538974-darwin64-538974.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76371/727419/libhunspell-1.3.2.555528-darwin64-555528.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -1828,9 +1738,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>ec22ec25160bcfd2a74f1c7bc8ff6133</string>
|
||||
<string>2253ec09136cc7c208481030d78d9dd7</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54986/511824/libhunspell-1.3.2.538974-windows-538974.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76369/727412/libhunspell-1.3.2.555528-windows-555528.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -1840,16 +1750,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f470c6f3f7b0559e95e76467b808de10</string>
|
||||
<string>858d1708f6b3a74738a3d57a5387e20f</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54985/511817/libhunspell-1.3.2.538974-windows64-538974.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76370/727413/libhunspell-1.3.2.555528-windows64-555528.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.3.2.538974</string>
|
||||
<string>1.3.2.555528</string>
|
||||
</map>
|
||||
<key>libndofdev</key>
|
||||
<map>
|
||||
|
|
@ -1882,9 +1792,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>bf765dfe0b928ef3c531cd9618fee89b</string>
|
||||
<string>a487fff84208a45844602c4a1f68c974</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54843/510085/libndofdev-0.1.538973-darwin64-538973.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76356/727333/libndofdev-0.1.555523-darwin64-555523.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -1894,9 +1804,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>8abb7d216535009f6c0a7e43b0734b1e</string>
|
||||
<string>4c839555bf0ed9ae60ffc3f8a7c96f9b</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54984/511810/libndofdev-0.1.538973-windows-538973.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76354/727340/libndofdev-0.1.555523-windows-555523.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -1906,16 +1816,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9da7aed5a914174dcb2be12ecd4a656f</string>
|
||||
<string>cbc033ae3b034b992b59f6de1034247c</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54983/511803/libndofdev-0.1.538973-windows64-538973.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76355/727341/libndofdev-0.1.555523-windows64-555523.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>0.1.538973</string>
|
||||
<string>0.1.555523</string>
|
||||
</map>
|
||||
<key>libpng</key>
|
||||
<map>
|
||||
|
|
@ -1948,9 +1858,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>0932b19bb6a8e2641706afd13d92951d</string>
|
||||
<string>2a41acc3116ce19a443873216cb882ad</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56313/526740/libpng-1.6.8.539868-darwin64-539868.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78587/743948/libpng-1.6.8.557046-darwin64-557046.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -1984,9 +1894,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f498782698428888113b64a7505c8f7f</string>
|
||||
<string>b935b440947f63c69700bdcf5095a8e1</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56319/526770/libpng-1.6.8.539868-windows-539868.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78591/743970/libpng-1.6.8.557046-windows-557046.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -1996,16 +1906,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f8ac4f690a2925418866bccf6eba3cf4</string>
|
||||
<string>d1cc8354ac4e877eefedf16b1be3aac6</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56317/526762/libpng-1.6.8.539868-windows64-539868.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78589/743991/libpng-1.6.8.557046-windows64-557046.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.6.8.539868</string>
|
||||
<string>1.6.8.557046</string>
|
||||
</map>
|
||||
<key>libuuid</key>
|
||||
<map>
|
||||
|
|
@ -2080,9 +1990,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>0706b9c3889d767af9f5105d9ffa9b51</string>
|
||||
<string>6677173bbbb0ea32369b5e9b6c9aa641</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56327/526819/libxml2-2.9.4.539866-darwin64-539866.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78631/744225/libxml2-2.9.4.557062-darwin64-557062.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2116,9 +2026,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>1b7b979a8387fbb0f278dc681558b9ef</string>
|
||||
<string>ad6a596fbf0e83a21d95762da78437bc</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56316/526755/libxml2-2.9.4.539866-windows-539866.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78633/744239/libxml2-2.9.4.557062-windows-557062.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -2128,16 +2038,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>4f8ff97d6a9ab350306b62eec8adc810</string>
|
||||
<string>6b5bb230684ecf28386d7c91c47bb6e1</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56314/526748/libxml2-2.9.4.539866-windows64-539866.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78634/744240/libxml2-2.9.4.557062-windows64-557062.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.9.4.539866</string>
|
||||
<string>2.9.4.557062</string>
|
||||
</map>
|
||||
<key>llappearance_utility</key>
|
||||
<map>
|
||||
|
|
@ -2414,9 +2324,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>937ce1a2158c0cfff37f5989f5b24aba</string>
|
||||
<string>e4f784d8a035c51921a1562ca7a1bab6</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64066/601156/nghttp2-1.40.0.545354-darwin64-545354.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76357/727350/nghttp2-1.40.0.555524-darwin64-555524.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2450,9 +2360,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>138b881bdf37dff4e626e022a50dd11f</string>
|
||||
<string>af05aa2994c9845308fecd094b7b2d25</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64069/601181/nghttp2-1.40.0.545354-windows-545354.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76359/727360/nghttp2-1.40.0.555524-windows-555524.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -2462,9 +2372,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c23c6480c7cbea60a2bd26e257adc0a7</string>
|
||||
<string>5a55cede40eef16b9d1e47c418a2b77a</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/64068/601177/nghttp2-1.40.0.545354-windows64-545354.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76358/727359/nghttp2-1.40.0.555524-windows64-555524.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -2473,7 +2383,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>1.40.0.545354</string>
|
||||
<string>1.40.0.555524</string>
|
||||
</map>
|
||||
<key>nvapi</key>
|
||||
<map>
|
||||
|
|
@ -2828,9 +2738,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>18aef0c8fc471b6539addbdc019aea25</string>
|
||||
<string>5503e4928bcdb0a29685b3242c4a409b</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56325/526804/openssl-1.0.2l.539874-darwin64-539874.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82619/774464/openssl-1.1.1l.560177-darwin64-560177.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2864,9 +2774,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2b2f61313b1cbd2893c1ba5bf15061fa</string>
|
||||
<string>d2153f20dc2d35c609b876a9f019a748</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56328/526826/openssl-1.0.2l.539874-windows-539874.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82623/774521/openssl-1.1.1l.560177-windows-560177.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -2876,16 +2786,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>59aae854155bc7119e0dca25e65828c0</string>
|
||||
<string>f40b8622ba38084b0962e273988d748f</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/56326/526811/openssl-1.0.2l.539874-windows64-539874.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82624/774520/openssl-1.1.1l.560177-windows64-560177.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.0.2l.539874</string>
|
||||
<string>1.1.1l.560177</string>
|
||||
</map>
|
||||
<key>pcre</key>
|
||||
<map>
|
||||
|
|
@ -3008,9 +2918,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>321a8542e7b693fbe8e44ebface06087</string>
|
||||
<string>6ce3cbaed968a69fb7a2cca80220874d</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55966/524403/slvoice-4.10.0000.32327.5fc3fe7c.539691-darwin64-539691.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80380/758537/slvoice-4.10.0000.32327.5fc3fe7c.558436-darwin64-558436.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3044,9 +2954,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>fb1a57a1cf5e38a3d51b32307b93ffba</string>
|
||||
<string>2eb38c5eff4d0f18fbb89d0c30c4f0a4</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55968/524423/slvoice-4.10.0000.32327.5fc3fe7c.539691-windows-539691.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80382/758550/slvoice-4.10.0000.32327.5fc3fe7c.558436-windows-558436.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3056,16 +2966,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>81df970eb0c97d415d7bd12049c82042</string>
|
||||
<string>9ee8f3cbc5369c598a998c61961ed16d</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55967/524409/slvoice-4.10.0000.32327.5fc3fe7c.539691-windows64-539691.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80381/758551/slvoice-4.10.0000.32327.5fc3fe7c.558436-windows64-558436.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>4.10.0000.32327.5fc3fe7c.539691</string>
|
||||
<string>4.10.0000.32327.5fc3fe7c.558436</string>
|
||||
</map>
|
||||
<key>tracy</key>
|
||||
<map>
|
||||
|
|
@ -3192,9 +3102,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>60f008c5fd31641ad4e61ac751ce15d1</string>
|
||||
<string>c42575ac8997de979eadb082c33a578e</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/75748/723495/uriparser-0.9.4-darwin64-555117.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81322/765512/uriparser-0.9.4-darwin64-559132.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3228,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>00aff37a6f5e1fe08456702d28706cf6</string>
|
||||
<string>901b1063556fc6b2575e745eef2bf744</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/75751/723507/uriparser-0.9.4-windows-555117.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81323/765528/uriparser-0.9.4-windows-559132.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3240,9 +3150,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>ff27a91f3941c7bef5e1613a064cb048</string>
|
||||
<string>962c01d553f286c430102998129fb0d6</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/75750/723506/uriparser-0.9.4-windows64-555117.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81324/765527/uriparser-0.9.4-windows64-559132.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -3326,9 +3236,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>5e553a4358203f283c74744aed2fcd8c</string>
|
||||
<string>b639d0035f4a8c9b4973be428a1b7e61</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54836/510036/vlc_bin-2.2.8.538966-darwin64-538966.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69569/671323/vlc_bin-3.0.9.549888-darwin64-549888.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3350,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>ca84b7c5f86e702fb35727eed8f0c8c4</string>
|
||||
<string>4f50b0c47daa081dd4fcb83763d5b0b2</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54958/511725/vlc_bin-2.2.8.538966-windows-538966.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69567/671314/vlc_bin-3.0.9.549888-windows-549888.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3362,16 +3272,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>93cd88d90cb8aedbed5cd90ff9262409</string>
|
||||
<string>c2f8c01fb6c261b72beb07f0c4cd423f</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54954/511718/vlc_bin-2.2.8.538966-windows64-538966.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69568/671315/vlc_bin-3.0.9.549888-windows64-549888.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.2.8.538966</string>
|
||||
<string>3.0.9.549888</string>
|
||||
</map>
|
||||
<key>xmlrpc-epi</key>
|
||||
<map>
|
||||
|
|
@ -3404,9 +3314,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>99ea1808ee9f5b55029daa9fdef86776</string>
|
||||
<string>922a0dea32266897ed1911200438e1e1</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55063/512104/xmlrpc_epi-0.54.1.539072-darwin64-539072.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76372/727426/xmlrpc_epi-0.54.1.555529-darwin64-555529.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3440,9 +3350,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>94643b7cebb449f049fa9e32ae682bcd</string>
|
||||
<string>34b847e6b280048465fe7c6ce67fe05c</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55138/512288/xmlrpc_epi-0.54.1.539072-windows-539072.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76374/727436/xmlrpc_epi-0.54.1.555529-windows-555529.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3452,16 +3362,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c409de1974a879291ce7daaf52348d85</string>
|
||||
<string>8fbe7c4ea22bb7f23a93c73884ebb34c</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55137/512279/xmlrpc_epi-0.54.1.539072-windows64-539072.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76373/727435/xmlrpc_epi-0.54.1.555529-windows64-555529.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>0.54.1.539072</string>
|
||||
<string>0.54.1.555529</string>
|
||||
</map>
|
||||
<key>zlib</key>
|
||||
<map>
|
||||
|
|
@ -3494,9 +3404,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9785bda5b4d3b41bf391b33d0da78c9e</string>
|
||||
<string>9181bc8229f1a8e480d2a40a2744ec28</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54858/510190/zlib-1.2.8.538988-darwin64-538988.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78578/743913/zlib-1.2.11.557041-darwin64-557041.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3532,9 +3442,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>ebdb07d4aaa5312005a8773f625032a4</string>
|
||||
<string>8308cbd2ea0fe290541698b0f63482e2</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55048/512031/zlib-1.2.8.538988-windows-538988.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78579/743926/zlib-1.2.11.557041-windows-557041.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3544,16 +3454,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>0ac95f3dece7d575ba45cf5728f53eea</string>
|
||||
<string>36bdc34f67d3ad3c57125dc1b16a3129</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55047/512024/zlib-1.2.8.538988-windows64-538988.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78577/743920/zlib-1.2.11.557041-windows64-557041.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.2.8.538988</string>
|
||||
<string>1.2.11.557041</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>package_description</key>
|
||||
|
|
|
|||
46
build.sh
46
build.sh
|
|
@ -16,6 +16,29 @@
|
|||
# * The special style in which python is invoked is intentional to permit
|
||||
# use of a native python install on windows - which requires paths in DOS form
|
||||
|
||||
retry_cmd()
|
||||
{
|
||||
max_attempts="$1"; shift
|
||||
initial_wait="$1"; shift
|
||||
attempt_num=1
|
||||
echo "trying" "$@"
|
||||
until "$@"
|
||||
do
|
||||
if ((attempt_num==max_attempts))
|
||||
then
|
||||
echo "Last attempt $attempt_num failed"
|
||||
return 1
|
||||
else
|
||||
wait_time=$(($attempt_num*$initial_wait))
|
||||
echo "Attempt $attempt_num failed. Trying again in $wait_time seconds..."
|
||||
sleep $wait_time
|
||||
attempt_num=$(($attempt_num+1))
|
||||
fi
|
||||
done
|
||||
echo "succeeded"
|
||||
return 0
|
||||
}
|
||||
|
||||
build_dir_Darwin()
|
||||
{
|
||||
echo build-darwin-x86_64
|
||||
|
|
@ -132,7 +155,11 @@ pre_build()
|
|||
fi
|
||||
set -x
|
||||
|
||||
"$autobuild" configure --quiet -c $variant -- \
|
||||
# honor autobuild_configure_parameters same as sling-buildscripts
|
||||
eval_autobuild_configure_parameters=$(eval $(echo echo $autobuild_configure_parameters))
|
||||
|
||||
"$autobuild" configure --quiet -c $variant \
|
||||
${eval_autobuild_configure_parameters:---} \
|
||||
-DPACKAGE:BOOL=ON \
|
||||
-DHAVOK:BOOL="$HAVOK" \
|
||||
-DRELEASE_CRASH_REPORTING:BOOL="$RELEASE_CRASH_REPORTING" \
|
||||
|
|
@ -182,7 +209,11 @@ build()
|
|||
if $build_viewer
|
||||
then
|
||||
begin_section "autobuild $variant"
|
||||
"$autobuild" build --no-configure -c $variant || fatal "failed building $variant"
|
||||
# honor autobuild_build_parameters same as sling-buildscripts
|
||||
eval_autobuild_build_parameters=$(eval $(echo echo $autobuild_build_parameters))
|
||||
"$autobuild" build --no-configure -c $variant \
|
||||
$eval_autobuild_build_parameters \
|
||||
|| fatal "failed building $variant"
|
||||
echo true >"$build_dir"/build_ok
|
||||
end_section "autobuild $variant"
|
||||
|
||||
|
|
@ -447,7 +478,7 @@ then
|
|||
succeeded=$build_coverity
|
||||
else
|
||||
# Upload base package.
|
||||
python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
|
||||
|| fatal "Upload of installer failed"
|
||||
wait_for_codeticket
|
||||
|
||||
|
|
@ -457,7 +488,7 @@ then
|
|||
package=$(installer_$arch "$package_id")
|
||||
if [ x"$package" != x ]
|
||||
then
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
|
||||
|| fatal "Upload of installer $package_id failed"
|
||||
wait_for_codeticket
|
||||
else
|
||||
|
|
@ -471,7 +502,7 @@ then
|
|||
if [ "${RELEASE_CRASH_REPORTING:-}" != "OFF" ]
|
||||
then
|
||||
# Upload crash reporter file
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \
|
||||
|| fatal "Upload of symbolfile failed"
|
||||
wait_for_codeticket
|
||||
fi
|
||||
|
|
@ -481,10 +512,7 @@ then
|
|||
if [ -r "$build_dir/llphysicsextensions_package" ]
|
||||
then
|
||||
llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
|
||||
# This next upload is a frequent failure; see if giving the last one some time helps
|
||||
# JJ is making changes to Codeticket that we hope will eliminate this failure soon
|
||||
sleep 300
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
|
||||
|| fatal "Upload of physics extensions package failed"
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -95,17 +95,6 @@ if (USE_BUGSPLAT)
|
|||
endif (BUGSPLAT_DB)
|
||||
else (USE_BUGSPLAT)
|
||||
message(STATUS "Not building with BugSplat")
|
||||
if (LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
|
||||
add_dependencies(viewer linux-crash-logger-strip-target)
|
||||
elseif (DARWIN)
|
||||
add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
|
||||
add_dependencies(viewer mac-crash-logger)
|
||||
elseif (WINDOWS)
|
||||
add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
|
||||
# add_dependencies(viewer windows-setup windows-crash-logger)
|
||||
add_dependencies(viewer windows-crash-logger)
|
||||
endif (LINUX)
|
||||
endif (USE_BUGSPLAT)
|
||||
|
||||
add_subdirectory(${VIEWER_PREFIX}newview)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ elseif (DARWIN)
|
|||
message(FATAL_ERROR "AppKit not found")
|
||||
endif()
|
||||
|
||||
FIND_LIBRARY(CEF_LIBRARY "Chromium Embedded Framework" ${ARCH_PREBUILT_DIRS_RELEASE})
|
||||
set(CEF_LIBRARY "'${ARCH_PREBUILT_DIRS_RELEASE}/Chromium\ Embedded\ Framework.framework'")
|
||||
if (NOT CEF_LIBRARY)
|
||||
message(FATAL_ERROR "CEF not found")
|
||||
endif()
|
||||
|
|
@ -33,7 +33,7 @@ elseif (DARWIN)
|
|||
${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a
|
||||
${APPKIT_LIBRARY}
|
||||
${CEF_LIBRARY}
|
||||
"-F ${CEF_LIBRARY}"
|
||||
)
|
||||
|
||||
elseif (LINUX)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ set(cmake_SOURCE_FILES
|
|||
FindAutobuild.cmake
|
||||
FindBerkeleyDB.cmake
|
||||
FindGLH.cmake
|
||||
FindGoogleBreakpad.cmake
|
||||
FindHUNSPELL.cmake
|
||||
FindJsonCpp.cmake
|
||||
FindNDOF.cmake
|
||||
|
|
@ -43,7 +42,6 @@ set(cmake_SOURCE_FILES
|
|||
GLH.cmake
|
||||
GLOD.cmake
|
||||
## GStreamer010Plugin.cmake
|
||||
GoogleBreakpad.cmake
|
||||
GoogleMock.cmake
|
||||
Havok.cmake
|
||||
Hunspell.cmake
|
||||
|
|
|
|||
|
|
@ -56,14 +56,21 @@ if(WINDOWS)
|
|||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
ssleay32.dll
|
||||
libeay32.dll
|
||||
nghttp2.dll
|
||||
glod.dll
|
||||
libhunspell.dll
|
||||
uriparser.dll
|
||||
)
|
||||
|
||||
# OpenSSL
|
||||
if(ADDRESS_SIZE EQUAL 64)
|
||||
set(release_files ${release_files} libcrypto-1_1-x64.dll)
|
||||
set(release_files ${release_files} libssl-1_1-x64.dll)
|
||||
else(ADDRESS_SIZE EQUAL 64)
|
||||
set(release_files ${release_files} libcrypto-1_1.dll)
|
||||
set(release_files ${release_files} libssl-1_1.dll)
|
||||
endif(ADDRESS_SIZE EQUAL 64)
|
||||
|
||||
# Filenames are different for 32/64 bit BugSplat file and we don't
|
||||
# have any control over them so need to branch.
|
||||
if (USE_BUGSPLAT)
|
||||
|
|
@ -160,7 +167,6 @@ elseif(DARWIN)
|
|||
libapr-1.dylib
|
||||
libaprutil-1.0.dylib
|
||||
libaprutil-1.dylib
|
||||
libexception_handler.dylib
|
||||
${EXPAT_COPY}
|
||||
libGLOD.dylib
|
||||
libhunspell-1.3.0.dylib
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# - Find Google BreakPad
|
||||
# Find the Google BreakPad includes and library
|
||||
# This module defines
|
||||
# BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR, where to find exception_handler.h, etc.
|
||||
# BREAKPAD_EXCEPTION_HANDLER_LIBRARIES, the libraries needed to use Google BreakPad.
|
||||
# BREAKPAD_EXCEPTION_HANDLER_FOUND, If false, do not try to use Google BreakPad.
|
||||
# also defined, but not for general use are
|
||||
# BREAKPAD_EXCEPTION_HANDLER_LIBRARY, where to find the Google BreakPad library.
|
||||
|
||||
FIND_PATH(BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR google_breakpad/exception_handler.h)
|
||||
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} breakpad_client)
|
||||
FIND_LIBRARY(BREAKPAD_EXCEPTION_HANDLER_LIBRARY
|
||||
NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES}
|
||||
)
|
||||
|
||||
IF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES ${BREAKPAD_EXCEPTION_HANDLER_LIBRARY})
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "YES")
|
||||
ELSE (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "NO")
|
||||
ENDIF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
|
||||
|
||||
|
||||
IF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
|
||||
IF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Google BreakPad: ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}")
|
||||
ENDIF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
|
||||
ELSE (BREAKPAD_EXCEPTION_HANDLER_FOUND)
|
||||
IF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Google BreakPad library")
|
||||
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
|
||||
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
BREAKPAD_EXCEPTION_HANDLER_LIBRARY
|
||||
BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR
|
||||
)
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON)
|
||||
include(FindGoogleBreakpad)
|
||||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(google_breakpad)
|
||||
if (DARWIN)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler)
|
||||
endif (DARWIN)
|
||||
if (LINUX)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client)
|
||||
endif (LINUX)
|
||||
if (WINDOWS)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client crash_generation_server common)
|
||||
endif (WINDOWS)
|
||||
# yes, this does look dumb, no, it's not incorrect
|
||||
#
|
||||
set(BREAKPAD_INCLUDE_DIRECTORIES "${LIBS_PREBUILT_DIR}/include/google_breakpad" "${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad")
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ if (USESYSTEMLIBS)
|
|||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(openssl)
|
||||
if (WINDOWS)
|
||||
set(OPENSSL_LIBRARIES ssleay32 libeay32)
|
||||
set(OPENSSL_LIBRARIES libssl libcrypto)
|
||||
else (WINDOWS)
|
||||
set(OPENSSL_LIBRARIES ssl crypto)
|
||||
endif (WINDOWS)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
euclid 5/29/2020
|
||||
euclid 7/23/2020
|
||||
euclid 4/29/2021
|
||||
euclid 4/29/2021
|
||||
euclid 10/5/2021 DRTVWR-546
|
||||
|
|
|
|||
|
|
@ -42,9 +42,11 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// class LLEditingMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLEditingMotion :
|
||||
public LLMotion
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
// Constructor
|
||||
LLEditingMotion(const LLUUID &id);
|
||||
|
|
@ -108,6 +110,13 @@ public:
|
|||
//-------------------------------------------------------------------------
|
||||
// joint states to be animated
|
||||
//-------------------------------------------------------------------------
|
||||
LL_ALIGN_16(LLJoint mParentJoint);
|
||||
LL_ALIGN_16(LLJoint mShoulderJoint);
|
||||
LL_ALIGN_16(LLJoint mElbowJoint);
|
||||
LL_ALIGN_16(LLJoint mWristJoint);
|
||||
LL_ALIGN_16(LLJoint mTarget);
|
||||
LLJointSolverRP3 mIKSolver;
|
||||
|
||||
LLCharacter *mCharacter;
|
||||
LLVector3 mWristOffset;
|
||||
|
||||
|
|
@ -117,17 +126,10 @@ public:
|
|||
LLPointer<LLJointState> mWristState;
|
||||
LLPointer<LLJointState> mTorsoState;
|
||||
|
||||
LLJoint mParentJoint;
|
||||
LLJoint mShoulderJoint;
|
||||
LLJoint mElbowJoint;
|
||||
LLJoint mWristJoint;
|
||||
LLJoint mTarget;
|
||||
LLJointSolverRP3 mIKSolver;
|
||||
|
||||
static S32 sHandPose;
|
||||
static S32 sHandPosePriority;
|
||||
LLVector3 mLastSelectPt;
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#endif // LL_LLKEYFRAMEMOTION_H
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,10 @@ inline bool operator!=(const LLVector3OverrideMap& a, const LLVector3OverrideMap
|
|||
//-----------------------------------------------------------------------------
|
||||
// class LLJoint
|
||||
//-----------------------------------------------------------------------------
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLJoint
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
// priority levels, from highest to lowest
|
||||
enum JointPriority
|
||||
|
|
@ -115,17 +117,17 @@ public:
|
|||
SUPPORT_EXTENDED
|
||||
};
|
||||
protected:
|
||||
std::string mName;
|
||||
// explicit transformation members
|
||||
LL_ALIGN_16(LLMatrix4a mWorldMatrix);
|
||||
LLXformMatrix mXform;
|
||||
|
||||
std::string mName;
|
||||
|
||||
SupportCategory mSupport;
|
||||
|
||||
// parent joint
|
||||
LLJoint *mParent;
|
||||
|
||||
// explicit transformation members
|
||||
LLXformMatrix mXform;
|
||||
LLMatrix4a mWorldMatrix;
|
||||
|
||||
LLVector3 mDefaultPosition;
|
||||
LLVector3 mDefaultScale;
|
||||
|
||||
|
|
@ -300,6 +302,6 @@ public:
|
|||
// These are used in checks of whether a pos/scale override is considered significant.
|
||||
bool aboveJointPosThreshold(const LLVector3& pos) const;
|
||||
bool aboveJointScaleThreshold(const LLVector3& scale) const;
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
#endif // LL_LLJOINT_H
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,11 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// class LLKeyframeStandMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLKeyframeStandMotion :
|
||||
public LLKeyframeMotion
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
// Constructor
|
||||
LLKeyframeStandMotion(const LLUUID &id);
|
||||
|
|
@ -69,6 +71,18 @@ public:
|
|||
//-------------------------------------------------------------------------
|
||||
// Member Data
|
||||
//-------------------------------------------------------------------------
|
||||
LLJoint mPelvisJoint;
|
||||
|
||||
LLJoint mHipLeftJoint;
|
||||
LLJoint mKneeLeftJoint;
|
||||
LLJoint mAnkleLeftJoint;
|
||||
LLJoint mTargetLeft;
|
||||
|
||||
LLJoint mHipRightJoint;
|
||||
LLJoint mKneeRightJoint;
|
||||
LLJoint mAnkleRightJoint;
|
||||
LLJoint mTargetRight;
|
||||
|
||||
LLCharacter *mCharacter;
|
||||
|
||||
BOOL mFlipFeet;
|
||||
|
|
@ -83,18 +97,6 @@ public:
|
|||
LLPointer<LLJointState> mKneeRightState;
|
||||
LLPointer<LLJointState> mAnkleRightState;
|
||||
|
||||
LLJoint mPelvisJoint;
|
||||
|
||||
LLJoint mHipLeftJoint;
|
||||
LLJoint mKneeLeftJoint;
|
||||
LLJoint mAnkleLeftJoint;
|
||||
LLJoint mTargetLeft;
|
||||
|
||||
LLJoint mHipRightJoint;
|
||||
LLJoint mKneeRightJoint;
|
||||
LLJoint mAnkleRightJoint;
|
||||
LLJoint mTargetRight;
|
||||
|
||||
LLJointSolverRP3 mIKLeft;
|
||||
LLJointSolverRP3 mIKRight;
|
||||
|
||||
|
|
@ -110,7 +112,7 @@ public:
|
|||
BOOL mTrackAnkles;
|
||||
|
||||
S32 mFrameNum;
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#endif // LL_LLKEYFRAMESTANDMOTION_H
|
||||
|
||||
|
|
|
|||
|
|
@ -80,8 +80,10 @@ public:
|
|||
|
||||
const S32 JSB_NUM_JOINT_STATES = 6;
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLJointStateBlender
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
protected:
|
||||
LLPointer<LLJointState> mJointStates[JSB_NUM_JOINT_STATES];
|
||||
S32 mPriorities[JSB_NUM_JOINT_STATES];
|
||||
|
|
@ -96,8 +98,8 @@ public:
|
|||
void resetCachedJoint();
|
||||
|
||||
public:
|
||||
LLJoint mJointCache;
|
||||
};
|
||||
LL_ALIGN_16(LLJoint mJointCache);
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
class LLMotion;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ include(Linking)
|
|||
include(Boost)
|
||||
include(LLSharedLibs)
|
||||
include(JsonCpp)
|
||||
include(GoogleBreakpad)
|
||||
include(Copy3rdPartyLibs)
|
||||
include(ZLIB)
|
||||
include(URIPARSER)
|
||||
|
|
@ -20,7 +19,6 @@ include_directories(
|
|||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${JSONCPP_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
${BREAKPAD_INCLUDE_DIRECTORIES}
|
||||
${URIPARSER_INCLUDE_DIRS}
|
||||
${TRACY_INCLUDE_DIR}
|
||||
)
|
||||
|
|
@ -123,12 +121,14 @@ set(llcommon_SOURCE_FILES
|
|||
llworkerthread.cpp
|
||||
timing.cpp
|
||||
u64.cpp
|
||||
workqueue.cpp
|
||||
StackWalker.cpp
|
||||
)
|
||||
|
||||
set(llcommon_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
chrono.h
|
||||
ctype_workaround.h
|
||||
fix_macros.h
|
||||
indra_constants.h
|
||||
|
|
@ -256,8 +256,11 @@ set(llcommon_HEADER_FILES
|
|||
lockstatic.h
|
||||
stdtypes.h
|
||||
stringize.h
|
||||
threadsafeschedule.h
|
||||
timer.h
|
||||
tuple.h
|
||||
u64.h
|
||||
workqueue.h
|
||||
StackWalker.h
|
||||
)
|
||||
|
||||
|
|
@ -291,7 +294,6 @@ endif(LLCOMMON_LINK_SHARED)
|
|||
|
||||
target_link_libraries(
|
||||
llcommon
|
||||
${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}
|
||||
${APRUTIL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${EXPAT_LIBRARIES}
|
||||
|
|
@ -362,6 +364,9 @@ if (LL_TESTS)
|
|||
LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(threadsafeschedule "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(tuple "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(workqueue "" "${test_libs}")
|
||||
|
||||
## llexception_test.cpp isn't a regression test, and doesn't need to be run
|
||||
## every build. It's to help a developer make implementation choices about
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* @file chrono.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-05
|
||||
* @brief supplement <chrono> with utility functions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_CHRONO_H)
|
||||
#define LL_CHRONO_H
|
||||
|
||||
#include <chrono>
|
||||
#include <type_traits> // std::enable_if
|
||||
|
||||
namespace LL
|
||||
{
|
||||
|
||||
// time_point_cast() is derived from https://stackoverflow.com/a/35293183
|
||||
// without the iteration: we think errors in the ~1 microsecond range are
|
||||
// probably acceptable.
|
||||
|
||||
// This variant is for the optimal case when the source and dest use the same
|
||||
// clock: that case is handled by std::chrono.
|
||||
template <typename DestTimePoint, typename SrcTimePoint,
|
||||
typename std::enable_if<std::is_same<typename DestTimePoint::clock,
|
||||
typename SrcTimePoint::clock>::value,
|
||||
bool>::type = true>
|
||||
DestTimePoint time_point_cast(const SrcTimePoint& time)
|
||||
{
|
||||
return std::chrono::time_point_cast<typename DestTimePoint::duration>(time);
|
||||
}
|
||||
|
||||
// This variant is for when the source and dest use different clocks -- see
|
||||
// the linked StackOverflow answer, also Howard Hinnant's, for more context.
|
||||
template <typename DestTimePoint, typename SrcTimePoint,
|
||||
typename std::enable_if<! std::is_same<typename DestTimePoint::clock,
|
||||
typename SrcTimePoint::clock>::value,
|
||||
bool>::type = true>
|
||||
DestTimePoint time_point_cast(const SrcTimePoint& time)
|
||||
{
|
||||
// The basic idea is that we must adjust the passed time_point by the
|
||||
// difference between the clocks' epochs. But since time_point doesn't
|
||||
// expose its epoch, we fall back on what each of them thinks is now().
|
||||
// However, since we necessarily make sequential calls to those now()
|
||||
// functions, the answers differ not only by the cycles spent executing
|
||||
// those calls, but by potential OS interruptions between them. Try to
|
||||
// reduce that error by capturing the source clock time both before and
|
||||
// after the dest clock, and splitting the difference. Of course an
|
||||
// interruption between two of these now() calls without a comparable
|
||||
// interruption between the other two will skew the result, but better is
|
||||
// more expensive.
|
||||
const auto src_before = typename SrcTimePoint::clock::now();
|
||||
const auto dest_now = typename DestTimePoint::clock::now();
|
||||
const auto src_after = typename SrcTimePoint::clock::now();
|
||||
const auto src_diff = src_after - src_before;
|
||||
const auto src_now = src_before + src_diff / 2;
|
||||
return dest_now + (time - src_now);
|
||||
}
|
||||
|
||||
} // namespace LL
|
||||
|
||||
#endif /* ! defined(LL_CHRONO_H) */
|
||||
|
|
@ -46,7 +46,6 @@
|
|||
#include "llstl.h" // for DeletePointer()
|
||||
#include "llstring.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "google_breakpad/exception_handler.h"
|
||||
#include "stringize.h"
|
||||
#include "llcleanup.h"
|
||||
#include "llevents.h"
|
||||
|
|
@ -62,12 +61,6 @@
|
|||
|
||||
LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop);
|
||||
BOOL ConsoleCtrlHandler(DWORD fdwCtrlType);
|
||||
bool windows_post_minidump_callback(const wchar_t* dump_path,
|
||||
const wchar_t* minidump_id,
|
||||
void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
MDRawAssertionInfo* assertion,
|
||||
bool succeeded);
|
||||
#else
|
||||
# include <signal.h>
|
||||
# include <unistd.h> // for fork()
|
||||
|
|
@ -146,8 +139,6 @@ void LLApp::commonCtor()
|
|||
|
||||
// Set the application to this instance.
|
||||
sApplication = this;
|
||||
|
||||
mExceptionHandler = 0;
|
||||
|
||||
// initialize the buffer to write the minidump filename to
|
||||
// (this is used to avoid allocating memory in the crash handler)
|
||||
|
|
@ -177,8 +168,6 @@ LLApp::~LLApp()
|
|||
delete mThreadErrorp;
|
||||
mThreadErrorp = NULL;
|
||||
}
|
||||
|
||||
if(mExceptionHandler != 0) delete mExceptionHandler;
|
||||
|
||||
SUBSYSTEM_CLEANUP_DBG(LLCommon);
|
||||
}
|
||||
|
|
@ -394,139 +383,18 @@ void LLApp::setupErrorHandling(bool second_instance)
|
|||
|
||||
#if LL_WINDOWS
|
||||
|
||||
#if LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT)
|
||||
EnableCrashingOnCrashes();
|
||||
|
||||
// This sets a callback to handle w32 signals to the console window.
|
||||
// The viewer shouldn't be affected, sicne its a windowed app.
|
||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE);
|
||||
|
||||
// Install the Google Breakpad crash handler for Windows
|
||||
if(mExceptionHandler == 0)
|
||||
{
|
||||
if ( second_instance ) //BUG-5707 Firing teleport from a web browser causes second
|
||||
{
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
L"C:\\Temp\\",
|
||||
0, //No filter
|
||||
windows_post_minidump_callback,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL); //No custom client info.
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "adding breakpad exception handler" << LL_ENDL;
|
||||
|
||||
std::wstring wpipe_name;
|
||||
wpipe_name = mCrashReportPipeStr + wstringize(getPid());
|
||||
|
||||
const std::wstring wdump_path(utf8str_to_utf16str(mDumpPath));
|
||||
|
||||
int retries = 30;
|
||||
for (; retries > 0; --retries)
|
||||
{
|
||||
if (mExceptionHandler != 0) delete mExceptionHandler;
|
||||
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
wdump_path,
|
||||
NULL, //No filter
|
||||
windows_post_minidump_callback,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
MiniDumpNormal, //Generate a 'normal' minidump.
|
||||
wpipe_name.c_str(),
|
||||
NULL); //No custom client info.
|
||||
if (mExceptionHandler->IsOutOfProcess())
|
||||
{
|
||||
LL_INFOS("CRASHREPORT") << "Successfully attached to Out of Process exception handler." << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler. " << retries << " retries remaining." << LL_ENDL;
|
||||
::Sleep(100); //Wait a tick and try again.
|
||||
}
|
||||
}
|
||||
|
||||
if (retries == 0) LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (mExceptionHandler)
|
||||
{
|
||||
mExceptionHandler->set_handle_debug_exceptions(true);
|
||||
}
|
||||
}
|
||||
#endif // LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT)
|
||||
#else // ! LL_WINDOWS
|
||||
|
||||
#if defined(LL_BUGSPLAT)
|
||||
// Don't install our own signal handlers -- BugSplat needs to hook them,
|
||||
// or it's completely ineffectual.
|
||||
bool installHandler = false;
|
||||
|
||||
#else // ! LL_BUGSPLAT
|
||||
//
|
||||
// Start up signal handling.
|
||||
//
|
||||
// There are two different classes of signals. Synchronous signals are delivered to a specific
|
||||
// thread, asynchronous signals can be delivered to any thread (in theory)
|
||||
//
|
||||
setup_signals();
|
||||
|
||||
// Add google breakpad exception handler configured for Darwin/Linux.
|
||||
bool installHandler = true;
|
||||
#if ! defined(LL_BUGSPLAT)
|
||||
//
|
||||
// Start up signal handling.
|
||||
//
|
||||
// There are two different classes of signals. Synchronous signals are delivered to a specific
|
||||
// thread, asynchronous signals can be delivered to any thread (in theory)
|
||||
//
|
||||
setup_signals();
|
||||
#endif // ! LL_BUGSPLAT
|
||||
|
||||
#if LL_DARWIN
|
||||
// For the special case of Darwin, we do not want to install the handler if
|
||||
// the process is being debugged as the app will exit with value ABRT (6) if
|
||||
// we do. Unfortunately, the code below which performs that test relies on
|
||||
// the structure kinfo_proc which has been tagged by apple as an unstable
|
||||
// API. We disable this test for shipping versions to avoid conflicts with
|
||||
// future releases of Darwin. This test is really only needed for developers
|
||||
// starting the app from a debugger anyway.
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
int mib[4];
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = getpid();
|
||||
|
||||
struct kinfo_proc info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
size_t size = sizeof(info);
|
||||
int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
|
||||
if((result == 0) || (errno == ENOMEM))
|
||||
{
|
||||
// P_TRACED flag is set, so this process is being debugged; do not install
|
||||
// the handler
|
||||
if(info.kp_proc.p_flag & P_TRACED) installHandler = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to discover if the process is being debugged; default to
|
||||
// installing the handler.
|
||||
installHandler = true;
|
||||
}
|
||||
#endif // ! LL_RELEASE_FOR_DOWNLOAD
|
||||
|
||||
if(installHandler && (mExceptionHandler == 0))
|
||||
{
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, 0, &unix_post_minidump_callback, 0, true, 0);
|
||||
}
|
||||
#elif LL_LINUX
|
||||
if(installHandler && (mExceptionHandler == 0))
|
||||
{
|
||||
if (mDumpPath.empty())
|
||||
{
|
||||
mDumpPath = "/tmp";
|
||||
}
|
||||
google_breakpad::MinidumpDescriptor desc(mDumpPath);
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1);
|
||||
}
|
||||
#endif // LL_LINUX
|
||||
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
#ifdef LL_BUGSPLAT
|
||||
|
|
@ -614,31 +482,6 @@ void LLApp::setError()
|
|||
setStatus(APP_STATUS_ERROR);
|
||||
}
|
||||
|
||||
void LLApp::setMiniDumpDir(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
mDumpPath = "/tmp";
|
||||
}
|
||||
else
|
||||
{
|
||||
mDumpPath = path;
|
||||
}
|
||||
|
||||
if(mExceptionHandler == 0) return;
|
||||
#ifdef LL_WINDOWS
|
||||
std::wstring buffer(utf8str_to_utf16str(mDumpPath));
|
||||
if (buffer.size() > MAX_MINDUMP_PATH_LENGTH) buffer.resize(MAX_MINDUMP_PATH_LENGTH);
|
||||
mExceptionHandler->set_dump_path(buffer);
|
||||
#elif LL_LINUX
|
||||
//google_breakpad::MinidumpDescriptor desc("/tmp"); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
|
||||
google_breakpad::MinidumpDescriptor desc(mDumpPath); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
|
||||
mExceptionHandler->set_minidump_descriptor(desc);
|
||||
#else
|
||||
mExceptionHandler->set_dump_path(mDumpPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLApp::setDebugFileNames(const std::string &path)
|
||||
{
|
||||
mStaticDebugFileName = path + "static_debug_info.log";
|
||||
|
|
@ -647,8 +490,6 @@ void LLApp::setDebugFileNames(const std::string &path)
|
|||
|
||||
void LLApp::writeMiniDump()
|
||||
{
|
||||
if(mExceptionHandler == 0) return;
|
||||
mExceptionHandler->WriteMinidump();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -705,13 +546,6 @@ bool LLApp::isExiting()
|
|||
|
||||
void LLApp::disableCrashlogger()
|
||||
{
|
||||
// Disable Breakpad exception handler.
|
||||
if (mExceptionHandler != 0)
|
||||
{
|
||||
delete mExceptionHandler;
|
||||
mExceptionHandler = 0;
|
||||
}
|
||||
|
||||
sDisableCrashlogger = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1105,64 +939,3 @@ bool unix_post_minidump_callback(const char *dump_dir,
|
|||
}
|
||||
#endif // !WINDOWS
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
bool windows_post_minidump_callback(const wchar_t* dump_path,
|
||||
const wchar_t* minidump_id,
|
||||
void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
MDRawAssertionInfo* assertion,
|
||||
bool succeeded)
|
||||
{
|
||||
char * path = LLApp::instance()->getMiniDumpFilename();
|
||||
S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
|
||||
size_t bytesUsed;
|
||||
|
||||
LL_INFOS("MINIDUMPCALLBACK") << "Dump file was generated." << LL_ENDL;
|
||||
bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining));
|
||||
remaining -= bytesUsed;
|
||||
path += bytesUsed;
|
||||
if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\')
|
||||
{
|
||||
*path++ = '\\';
|
||||
--remaining;
|
||||
}
|
||||
if(remaining > 0)
|
||||
{
|
||||
bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining));
|
||||
remaining -= bytesUsed;
|
||||
path += bytesUsed;
|
||||
}
|
||||
if(remaining > 0)
|
||||
{
|
||||
strncpy(path, ".dmp", remaining);
|
||||
}
|
||||
|
||||
LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
|
||||
// *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
|
||||
//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
|
||||
// *TODO: Translate the signals/exceptions into cross-platform stuff
|
||||
// Windows implementation
|
||||
LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL;
|
||||
|
||||
if (LLApp::isError())
|
||||
{
|
||||
LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Flag status to error, so thread_error starts its work
|
||||
LLApp::setError();
|
||||
|
||||
// Block in the exception handler until the app has stopped
|
||||
// This is pretty sketchy, but appears to work just fine
|
||||
while (!LLApp::isStopped())
|
||||
{
|
||||
ms_sleep(10);
|
||||
}
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,10 +49,6 @@ void clear_signals();
|
|||
|
||||
#endif
|
||||
|
||||
namespace google_breakpad {
|
||||
class ExceptionHandler; // See exception_handler.h
|
||||
}
|
||||
|
||||
class LL_COMMON_API LLApp
|
||||
{
|
||||
friend class LLErrorThread;
|
||||
|
|
@ -236,7 +232,6 @@ public:
|
|||
static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
|
||||
|
||||
// change the directory where Breakpad minidump files are written to
|
||||
void setMiniDumpDir(const std::string &path);
|
||||
void setDebugFileNames(const std::string &path);
|
||||
|
||||
// Return the Google Breakpad minidump filename after a crash.
|
||||
|
|
@ -316,9 +311,6 @@ private:
|
|||
private:
|
||||
// the static application instance if it was created.
|
||||
static LLApp* sApplication;
|
||||
|
||||
google_breakpad::ExceptionHandler * mExceptionHandler;
|
||||
|
||||
|
||||
#if !LL_WINDOWS
|
||||
friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
|
||||
|
|
|
|||
|
|
@ -34,14 +34,13 @@
|
|||
#include "llcleanup.h"
|
||||
|
||||
#if (TRACY_ENABLE)
|
||||
// Override new/delet for tracy memory profiling
|
||||
// Override new/delete for tracy memory profiling
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
auto ptr = (malloc) (size);
|
||||
if (!ptr)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
return nullptr;
|
||||
}
|
||||
TracyAlloc(ptr, size);
|
||||
return ptr;
|
||||
|
|
@ -62,7 +61,7 @@ void operator delete(void *ptr) noexcept
|
|||
|
||||
void *tracy_aligned_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
auto ptr = (_aligned_malloc) (size, alignment);
|
||||
auto ptr = ll_aligned_malloc_fallback(size, alignment);
|
||||
if (ptr) TracyAlloc(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
|
@ -70,7 +69,7 @@ void *tracy_aligned_malloc(size_t size, size_t alignment)
|
|||
void tracy_aligned_free(void *memblock)
|
||||
{
|
||||
TracyFree(memblock);
|
||||
(_aligned_free)(memblock);
|
||||
ll_aligned_free_fallback(memblock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ private:
|
|||
LLCoros::Mutex mMutex;
|
||||
// Use LLCoros::ConditionVariable for the same reason.
|
||||
LLCoros::ConditionVariable mCond;
|
||||
using LockType = LLCoros::LockType;
|
||||
using cv_status = LLCoros::cv_status;
|
||||
|
||||
public:
|
||||
/// LLCond can be explicitly initialized with a specific value for mData if
|
||||
|
|
@ -65,10 +67,14 @@ public:
|
|||
LLCond(const LLCond&) = delete;
|
||||
LLCond& operator=(const LLCond&) = delete;
|
||||
|
||||
/// get() returns a const reference to the stored DATA. The only way to
|
||||
/// get a non-const reference -- to modify the stored DATA -- is via
|
||||
/// update_one() or update_all().
|
||||
const value_type& get() const { return mData; }
|
||||
/// get() returns the stored DATA by value -- so to use get(), DATA must
|
||||
/// be copyable. The only way to get a non-const reference -- to modify
|
||||
/// the stored DATA -- is via update_one() or update_all().
|
||||
value_type get()
|
||||
{
|
||||
LockType lk(mMutex);
|
||||
return mData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass update_one() an invocable accepting non-const (DATA&). The
|
||||
|
|
@ -83,7 +89,7 @@ public:
|
|||
void update_one(MODIFY modify)
|
||||
{
|
||||
{ // scope of lock can/should end before notify_one()
|
||||
LLCoros::LockType lk(mMutex);
|
||||
LockType lk(mMutex);
|
||||
modify(mData);
|
||||
}
|
||||
mCond.notify_one();
|
||||
|
|
@ -102,7 +108,7 @@ public:
|
|||
void update_all(MODIFY modify)
|
||||
{
|
||||
{ // scope of lock can/should end before notify_all()
|
||||
LLCoros::LockType lk(mMutex);
|
||||
LockType lk(mMutex);
|
||||
modify(mData);
|
||||
}
|
||||
mCond.notify_all();
|
||||
|
|
@ -118,7 +124,7 @@ public:
|
|||
template <typename Pred>
|
||||
void wait(Pred pred)
|
||||
{
|
||||
LLCoros::LockType lk(mMutex);
|
||||
LockType lk(mMutex);
|
||||
// We must iterate explicitly since the predicate accepted by
|
||||
// condition_variable::wait() requires a different signature:
|
||||
// condition_variable::wait() calls its predicate with no arguments.
|
||||
|
|
@ -205,14 +211,14 @@ private:
|
|||
template <typename Clock, typename Duration, typename Pred>
|
||||
bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, Pred pred)
|
||||
{
|
||||
LLCoros::LockType lk(mMutex);
|
||||
LockType lk(mMutex);
|
||||
// We advise the caller to pass a predicate accepting (const DATA&).
|
||||
// But what if they instead pass a predicate accepting non-const
|
||||
// (DATA&)? Such a predicate could modify mData, which would be Bad.
|
||||
// Forbid that.
|
||||
while (! pred(const_cast<const value_type&>(mData)))
|
||||
{
|
||||
if (LLCoros::cv_status::timeout == mCond.wait_until(lk, timeout_time))
|
||||
if (cv_status::timeout == mCond.wait_until(lk, timeout_time))
|
||||
{
|
||||
// It's possible that wait_until() timed out AND the predicate
|
||||
// became true more or less simultaneously. Even though
|
||||
|
|
|
|||
|
|
@ -83,13 +83,34 @@ class LLInstanceTracker
|
|||
typedef llthread::LockStatic<StaticData> LockStatic;
|
||||
|
||||
public:
|
||||
using ptr_t = std::shared_ptr<T>;
|
||||
using weak_t = std::weak_ptr<T>;
|
||||
|
||||
/**
|
||||
* Storing a dumb T* somewhere external is a bad idea, since
|
||||
* LLInstanceTracker subclasses are explicitly destroyed rather than
|
||||
* managed by smart pointers. It's legal to declare stack instances of an
|
||||
* LLInstanceTracker subclass. But it's reasonable to store a
|
||||
* std::weak_ptr<T>, which will become invalid when the T instance is
|
||||
* destroyed.
|
||||
*/
|
||||
weak_t getWeak()
|
||||
{
|
||||
return mSelf;
|
||||
}
|
||||
|
||||
static S32 instanceCount()
|
||||
{
|
||||
return LockStatic()->mMap.size();
|
||||
}
|
||||
|
||||
// snapshot of std::pair<const KEY, std::shared_ptr<T>> pairs
|
||||
class snapshot
|
||||
{
|
||||
// It's very important that what we store in this snapshot are
|
||||
// weak_ptrs, NOT shared_ptrs. That's how we discover whether any
|
||||
// instance has been deleted during the lifespan of a snapshot.
|
||||
typedef std::vector<std::pair<const KEY, std::weak_ptr<T>>> VectorType;
|
||||
typedef std::vector<std::pair<const KEY, weak_t>> VectorType;
|
||||
// Dereferencing our iterator produces a std::shared_ptr for each
|
||||
// instance that still exists. Since we store weak_ptrs, that involves
|
||||
// two chained transformations:
|
||||
|
|
@ -98,7 +119,7 @@ public:
|
|||
// It is very important that we filter lazily, that is, during
|
||||
// traversal. Any one of our stored weak_ptrs might expire during
|
||||
// traversal.
|
||||
typedef std::pair<const KEY, std::shared_ptr<T>> strong_pair;
|
||||
typedef std::pair<const KEY, ptr_t> strong_pair;
|
||||
// Note for future reference: nat has not yet had any luck (up to
|
||||
// Boost 1.67) trying to use boost::transform_iterator with a hand-
|
||||
// coded functor, only with actual functions. In my experience, an
|
||||
|
|
@ -202,17 +223,12 @@ public:
|
|||
iterator end() { return iterator(snapshot::end(), key_getter); }
|
||||
};
|
||||
|
||||
static T* getInstance(const KEY& k)
|
||||
static ptr_t getInstance(const KEY& k)
|
||||
{
|
||||
LockStatic lock;
|
||||
const InstanceMap& map(lock->mMap);
|
||||
typename InstanceMap::const_iterator found = map.find(k);
|
||||
return (found == map.end()) ? NULL : found->second.get();
|
||||
}
|
||||
|
||||
static S32 instanceCount()
|
||||
{
|
||||
return LockStatic()->mMap.size();
|
||||
return (found == map.end()) ? NULL : found->second;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -222,7 +238,9 @@ protected:
|
|||
// shared_ptr, so give it a no-op deleter. We store shared_ptrs in our
|
||||
// InstanceMap specifically so snapshot can store weak_ptrs so we can
|
||||
// detect deletions during traversals.
|
||||
std::shared_ptr<T> ptr(static_cast<T*>(this), [](T*){});
|
||||
ptr_t ptr(static_cast<T*>(this), [](T*){});
|
||||
// save corresponding weak_ptr for future reference
|
||||
mSelf = ptr;
|
||||
LockStatic lock;
|
||||
add_(lock, key, ptr);
|
||||
}
|
||||
|
|
@ -257,7 +275,7 @@ private:
|
|||
static std::string report(const char* key) { return report(std::string(key)); }
|
||||
|
||||
// caller must instantiate LockStatic
|
||||
void add_(LockStatic& lock, const KEY& key, const std::shared_ptr<T>& ptr)
|
||||
void add_(LockStatic& lock, const KEY& key, const ptr_t& ptr)
|
||||
{
|
||||
mInstanceKey = key;
|
||||
InstanceMap& map = lock->mMap;
|
||||
|
|
@ -281,7 +299,7 @@ private:
|
|||
break;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<T> remove_(LockStatic& lock)
|
||||
ptr_t remove_(LockStatic& lock)
|
||||
{
|
||||
InstanceMap& map = lock->mMap;
|
||||
typename InstanceMap::iterator iter = map.find(mInstanceKey);
|
||||
|
|
@ -295,6 +313,9 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
// Storing a weak_ptr to self is a bit like deriving from
|
||||
// std::enable_shared_from_this(), except more explicit.
|
||||
weak_t mSelf;
|
||||
KEY mInstanceKey;
|
||||
};
|
||||
|
||||
|
|
@ -326,6 +347,9 @@ class LLInstanceTracker<T, void, KEY_COLLISION_BEHAVIOR>
|
|||
typedef llthread::LockStatic<StaticData> LockStatic;
|
||||
|
||||
public:
|
||||
using ptr_t = std::shared_ptr<T>;
|
||||
using weak_t = std::weak_ptr<T>;
|
||||
|
||||
/**
|
||||
* Storing a dumb T* somewhere external is a bad idea, since
|
||||
* LLInstanceTracker subclasses are explicitly destroyed rather than
|
||||
|
|
@ -334,12 +358,15 @@ public:
|
|||
* std::weak_ptr<T>, which will become invalid when the T instance is
|
||||
* destroyed.
|
||||
*/
|
||||
std::weak_ptr<T> getWeak()
|
||||
weak_t getWeak()
|
||||
{
|
||||
return mSelf;
|
||||
}
|
||||
|
||||
static S32 instanceCount() { return LockStatic()->mSet.size(); }
|
||||
static S32 instanceCount()
|
||||
{
|
||||
return LockStatic()->mSet.size();
|
||||
}
|
||||
|
||||
// snapshot of std::shared_ptr<T> pointers
|
||||
class snapshot
|
||||
|
|
@ -347,7 +374,7 @@ public:
|
|||
// It's very important that what we store in this snapshot are
|
||||
// weak_ptrs, NOT shared_ptrs. That's how we discover whether any
|
||||
// instance has been deleted during the lifespan of a snapshot.
|
||||
typedef std::vector<std::weak_ptr<T>> VectorType;
|
||||
typedef std::vector<weak_t> VectorType;
|
||||
// Dereferencing our iterator produces a std::shared_ptr for each
|
||||
// instance that still exists. Since we store weak_ptrs, that involves
|
||||
// two chained transformations:
|
||||
|
|
@ -453,7 +480,7 @@ protected:
|
|||
private:
|
||||
// Storing a weak_ptr to self is a bit like deriving from
|
||||
// std::enable_shared_from_this(), except more explicit.
|
||||
std::weak_ptr<T> mSelf;
|
||||
weak_t mSelf;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ void LLLeapListener::getAPI(const LLSD& request) const
|
|||
{
|
||||
Response reply(LLSD(), request);
|
||||
|
||||
LLEventAPI* found = LLEventAPI::getInstance(request["api"]);
|
||||
auto found = LLEventAPI::getInstance(request["api"]);
|
||||
if (found)
|
||||
{
|
||||
reply["name"] = found->getName();
|
||||
|
|
|
|||
|
|
@ -101,6 +101,19 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
|
|||
|
||||
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
|
||||
|
||||
#define LL_ALIGN_NEW \
|
||||
public: \
|
||||
void* operator new(size_t size) \
|
||||
{ \
|
||||
return ll_aligned_malloc_16(size); \
|
||||
} \
|
||||
\
|
||||
void operator delete(void* ptr) \
|
||||
{ \
|
||||
ll_aligned_free_16(ptr); \
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file llthreadsafequeue.h
|
||||
* @brief Base classes for thread, mutex and condition handling.
|
||||
* @brief Queue protected with mutexes for cross-thread use
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
|
|
@ -27,16 +27,19 @@
|
|||
#ifndef LL_LLTHREADSAFEQUEUE_H
|
||||
#define LL_LLTHREADSAFEQUEUE_H
|
||||
|
||||
#include "llexception.h"
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include "mutex.h"
|
||||
#include "llcoros.h"
|
||||
#include LLCOROS_MUTEX_HEADER
|
||||
#include <boost/fiber/timed_mutex.hpp>
|
||||
#include LLCOROS_CONDVAR_HEADER
|
||||
#include "llexception.h"
|
||||
#include "mutex.h"
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
/*****************************************************************************
|
||||
* LLThreadSafeQueue
|
||||
*****************************************************************************/
|
||||
//
|
||||
// A general queue exception.
|
||||
//
|
||||
|
|
@ -66,70 +69,111 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Implements a thread safe FIFO.
|
||||
//
|
||||
template<typename ElementT>
|
||||
/**
|
||||
* Implements a thread safe FIFO.
|
||||
*/
|
||||
// Let the default std::queue default to underlying std::deque. Override if
|
||||
// desired.
|
||||
template<typename ElementT, typename QueueT=std::queue<ElementT>>
|
||||
class LLThreadSafeQueue
|
||||
{
|
||||
public:
|
||||
typedef ElementT value_type;
|
||||
|
||||
// If the pool is set to NULL one will be allocated and managed by this
|
||||
// queue.
|
||||
|
||||
// Limiting the number of pending items prevents unbounded growth of the
|
||||
// underlying queue.
|
||||
LLThreadSafeQueue(U32 capacity = 1024);
|
||||
|
||||
// Add an element to the front of queue (will block if the queue has
|
||||
virtual ~LLThreadSafeQueue() {}
|
||||
|
||||
// Add an element to the queue (will block if the queue has
|
||||
// reached capacity).
|
||||
//
|
||||
// This call will raise an interrupt error if the queue is closed while
|
||||
// the caller is blocked.
|
||||
void pushFront(ElementT const & element);
|
||||
|
||||
// Try to add an element to the front of queue without blocking. Returns
|
||||
// true only if the element was actually added.
|
||||
bool tryPushFront(ElementT const & element);
|
||||
template <typename T>
|
||||
void push(T&& element);
|
||||
// legacy name
|
||||
void pushFront(ElementT const & element) { return push(element); }
|
||||
|
||||
// Try to add an element to the front of queue, blocking if full but with
|
||||
// timeout. Returns true if the element was added.
|
||||
// Try to add an element to the queue without blocking. Returns
|
||||
// true only if the element was actually added.
|
||||
template <typename T>
|
||||
bool tryPush(T&& element);
|
||||
// legacy name
|
||||
bool tryPushFront(ElementT const & element) { return tryPush(element); }
|
||||
|
||||
// Try to add an element to the queue, blocking if full but with timeout
|
||||
// after specified duration. Returns true if the element was added.
|
||||
// There are potentially two different timeouts involved: how long to try
|
||||
// to lock the mutex, versus how long to wait for the queue to stop being
|
||||
// full. Careful settings for each timeout might be orders of magnitude
|
||||
// apart. However, this method conflates them.
|
||||
template <typename Rep, typename Period, typename T>
|
||||
bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout,
|
||||
T&& element);
|
||||
// legacy name
|
||||
template <typename Rep, typename Period>
|
||||
bool tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout,
|
||||
ElementT const & element);
|
||||
ElementT const & element) { return tryPushFor(timeout, element); }
|
||||
|
||||
// Pop the element at the end of the queue (will block if the queue is
|
||||
// Try to add an element to the queue, blocking if full but with
|
||||
// timeout at specified time_point. Returns true if the element was added.
|
||||
template <typename Clock, typename Duration, typename T>
|
||||
bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
T&& element);
|
||||
// no legacy name because this is a newer method
|
||||
|
||||
// Pop the element at the head of the queue (will block if the queue is
|
||||
// empty).
|
||||
//
|
||||
// This call will raise an interrupt error if the queue is closed while
|
||||
// the caller is blocked.
|
||||
ElementT popBack(void);
|
||||
|
||||
// Pop an element from the end of the queue if there is one available.
|
||||
ElementT pop(void);
|
||||
// legacy name
|
||||
ElementT popBack(void) { return pop(); }
|
||||
|
||||
// Pop an element from the head of the queue if there is one available.
|
||||
// Returns true only if an element was popped.
|
||||
bool tryPopBack(ElementT & element);
|
||||
|
||||
bool tryPop(ElementT & element);
|
||||
// legacy name
|
||||
bool tryPopBack(ElementT & element) { return tryPop(element); }
|
||||
|
||||
// Pop the element at the head of the queue, blocking if empty, with
|
||||
// timeout after specified duration. Returns true if an element was popped.
|
||||
template <typename Rep, typename Period>
|
||||
bool tryPopFor(const std::chrono::duration<Rep, Period>& timeout, ElementT& element);
|
||||
// no legacy name because this is a newer method
|
||||
|
||||
// Pop the element at the head of the queue, blocking if empty, with
|
||||
// timeout at specified time_point. Returns true if an element was popped.
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
ElementT& element);
|
||||
// no legacy name because this is a newer method
|
||||
|
||||
// Returns the size of the queue.
|
||||
size_t size();
|
||||
|
||||
//Returns the capacity of the queue.
|
||||
U32 capacity() { return mCapacity; }
|
||||
|
||||
// closes the queue:
|
||||
// - every subsequent pushFront() call will throw LLThreadSafeQueueInterrupt
|
||||
// - every subsequent tryPushFront() call will return false
|
||||
// - popBack() calls will return normally until the queue is drained, then
|
||||
// every subsequent popBack() will throw LLThreadSafeQueueInterrupt
|
||||
// - tryPopBack() calls will return normally until the queue is drained,
|
||||
// then every subsequent tryPopBack() call will return false
|
||||
// - every subsequent push() call will throw LLThreadSafeQueueInterrupt
|
||||
// - every subsequent tryPush() call will return false
|
||||
// - pop() calls will return normally until the queue is drained, then
|
||||
// every subsequent pop() will throw LLThreadSafeQueueInterrupt
|
||||
// - tryPop() calls will return normally until the queue is drained,
|
||||
// then every subsequent tryPop() call will return false
|
||||
void close();
|
||||
|
||||
// detect closed state
|
||||
// producer end: are we prevented from pushing any additional items?
|
||||
bool isClosed();
|
||||
// inverse of isClosed()
|
||||
explicit operator bool();
|
||||
// consumer end: are we done, is the queue entirely drained?
|
||||
bool done();
|
||||
|
||||
private:
|
||||
std::deque< ElementT > mStorage;
|
||||
protected:
|
||||
typedef QueueT queue_type;
|
||||
QueueT mStorage;
|
||||
U32 mCapacity;
|
||||
bool mClosed;
|
||||
|
||||
|
|
@ -137,37 +181,152 @@ private:
|
|||
typedef std::unique_lock<decltype(mLock)> lock_t;
|
||||
boost::fibers::condition_variable_any mCapacityCond;
|
||||
boost::fibers::condition_variable_any mEmptyCond;
|
||||
|
||||
enum pop_result { EMPTY, DONE, WAITING, POPPED };
|
||||
// implementation logic, suitable for passing to tryLockUntil()
|
||||
template <typename Clock, typename Duration>
|
||||
pop_result tryPopUntil_(lock_t& lock,
|
||||
const std::chrono::time_point<Clock, Duration>& until,
|
||||
ElementT& element);
|
||||
// if we're able to lock immediately, do so and run the passed callable,
|
||||
// which must accept lock_t& and return bool
|
||||
template <typename CALLABLE>
|
||||
bool tryLock(CALLABLE&& callable);
|
||||
// if we're able to lock before the passed time_point, do so and run the
|
||||
// passed callable, which must accept lock_t& and return bool
|
||||
template <typename Clock, typename Duration, typename CALLABLE>
|
||||
bool tryLockUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
CALLABLE&& callable);
|
||||
// while lock is locked, really push the passed element, if we can
|
||||
template <typename T>
|
||||
bool push_(lock_t& lock, T&& element);
|
||||
// while lock is locked, really pop the head element, if we can
|
||||
pop_result pop_(lock_t& lock, ElementT& element);
|
||||
// Is the current head element ready to pop? We say yes; subclass can
|
||||
// override as needed.
|
||||
virtual bool canPop(const ElementT& head) const { return true; }
|
||||
};
|
||||
|
||||
// LLThreadSafeQueue
|
||||
//-----------------------------------------------------------------------------
|
||||
/*****************************************************************************
|
||||
* PriorityQueueAdapter
|
||||
*****************************************************************************/
|
||||
namespace LL
|
||||
{
|
||||
/**
|
||||
* std::priority_queue's API is almost like std::queue, intentionally of
|
||||
* course, but you must access the element about to pop() as top() rather
|
||||
* than as front(). Make an adapter for use with LLThreadSafeQueue.
|
||||
*/
|
||||
template <typename T, typename Container=std::vector<T>,
|
||||
typename Compare=std::less<typename Container::value_type>>
|
||||
class PriorityQueueAdapter
|
||||
{
|
||||
public:
|
||||
// publish all the same types
|
||||
typedef std::priority_queue<T, Container, Compare> queue_type;
|
||||
typedef typename queue_type::container_type container_type;
|
||||
typedef typename queue_type::value_compare value_compare;
|
||||
typedef typename queue_type::value_type value_type;
|
||||
typedef typename queue_type::size_type size_type;
|
||||
typedef typename queue_type::reference reference;
|
||||
typedef typename queue_type::const_reference const_reference;
|
||||
|
||||
template<typename ElementT>
|
||||
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(U32 capacity) :
|
||||
// Although std::queue defines both const and non-const front()
|
||||
// methods, std::priority_queue defines only const top().
|
||||
const_reference front() const { return mQ.top(); }
|
||||
// std::priority_queue has no equivalent to back(), so it's good that
|
||||
// LLThreadSafeQueue doesn't use it.
|
||||
|
||||
// All the rest of these merely forward to the corresponding
|
||||
// queue_type methods.
|
||||
bool empty() const { return mQ.empty(); }
|
||||
size_type size() const { return mQ.size(); }
|
||||
void push(const value_type& value) { mQ.push(value); }
|
||||
void push(value_type&& value) { mQ.push(std::move(value)); }
|
||||
template <typename... Args>
|
||||
void emplace(Args&&... args) { mQ.emplace(std::forward<Args>(args)...); }
|
||||
void pop() { mQ.pop(); }
|
||||
|
||||
private:
|
||||
queue_type mQ;
|
||||
};
|
||||
} // namespace LL
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* LLThreadSafeQueue implementation
|
||||
*****************************************************************************/
|
||||
template<typename ElementT, typename QueueT>
|
||||
LLThreadSafeQueue<ElementT, QueueT>::LLThreadSafeQueue(U32 capacity) :
|
||||
mCapacity(capacity),
|
||||
mClosed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
|
||||
// if we're able to lock immediately, do so and run the passed callable, which
|
||||
// must accept lock_t& and return bool
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename CALLABLE>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryLock(CALLABLE&& callable)
|
||||
{
|
||||
lock_t lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock())
|
||||
return false;
|
||||
|
||||
return std::forward<CALLABLE>(callable)(lock1);
|
||||
}
|
||||
|
||||
|
||||
// if we're able to lock before the passed time_point, do so and run the
|
||||
// passed callable, which must accept lock_t& and return bool
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename Clock, typename Duration, typename CALLABLE>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryLockUntil(
|
||||
const std::chrono::time_point<Clock, Duration>& until,
|
||||
CALLABLE&& callable)
|
||||
{
|
||||
lock_t lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock_until(until))
|
||||
return false;
|
||||
|
||||
return std::forward<CALLABLE>(callable)(lock1);
|
||||
}
|
||||
|
||||
|
||||
// while lock is locked, really push the passed element, if we can
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename T>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::push_(lock_t& lock, T&& element)
|
||||
{
|
||||
if (mStorage.size() >= mCapacity)
|
||||
return false;
|
||||
|
||||
mStorage.push(std::forward<T>(element));
|
||||
lock.unlock();
|
||||
// now that we've pushed, if somebody's been waiting to pop, signal them
|
||||
mEmptyCond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename ElementT, typename QueueT>
|
||||
template<typename T>
|
||||
void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element)
|
||||
{
|
||||
lock_t lock1(mLock);
|
||||
while (true)
|
||||
{
|
||||
// On the producer side, it doesn't matter whether the queue has been
|
||||
// drained or not: the moment either end calls close(), further push()
|
||||
// operations will fail.
|
||||
if (mClosed)
|
||||
{
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
}
|
||||
|
||||
if (mStorage.size() < mCapacity)
|
||||
{
|
||||
mStorage.push_front(element);
|
||||
lock1.unlock();
|
||||
mEmptyCond.notify_one();
|
||||
if (push_(lock1, std::forward<T>(element)))
|
||||
return;
|
||||
}
|
||||
|
||||
// Storage Full. Wait for signal.
|
||||
mCapacityCond.wait(lock1);
|
||||
|
|
@ -175,39 +334,184 @@ void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
|
|||
}
|
||||
|
||||
|
||||
template <typename ElementT>
|
||||
template <typename Rep, typename Period>
|
||||
bool LLThreadSafeQueue<ElementT>::tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout,
|
||||
ElementT const & element)
|
||||
template<typename ElementT, typename QueueT>
|
||||
template<typename T>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryPush(T&& element)
|
||||
{
|
||||
return tryLock(
|
||||
[this, element=std::move(element)](lock_t& lock)
|
||||
{
|
||||
if (mClosed)
|
||||
return false;
|
||||
return push_(lock, std::move(element));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename Rep, typename Period, typename T>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryPushFor(
|
||||
const std::chrono::duration<Rep, Period>& timeout,
|
||||
T&& element)
|
||||
{
|
||||
// Convert duration to time_point: passing the same timeout duration to
|
||||
// each of multiple calls is wrong.
|
||||
auto endpoint = std::chrono::steady_clock::now() + timeout;
|
||||
return tryPushUntil(std::chrono::steady_clock::now() + timeout,
|
||||
std::forward<T>(element));
|
||||
}
|
||||
|
||||
lock_t lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock_until(endpoint))
|
||||
return false;
|
||||
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename Clock, typename Duration, typename T>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryPushUntil(
|
||||
const std::chrono::time_point<Clock, Duration>& until,
|
||||
T&& element)
|
||||
{
|
||||
return tryLockUntil(
|
||||
until,
|
||||
[this, until, element=std::move(element)](lock_t& lock)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (mClosed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (push_(lock, std::move(element)))
|
||||
return true;
|
||||
|
||||
// Storage Full. Wait for signal.
|
||||
if (LLCoros::cv_status::timeout == mCapacityCond.wait_until(lock, until))
|
||||
{
|
||||
// timed out -- formally we might recheck both conditions above
|
||||
return false;
|
||||
}
|
||||
// If we didn't time out, we were notified for some reason. Loop back
|
||||
// to check.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// while lock is locked, really pop the head element, if we can
|
||||
template <typename ElementT, typename QueueT>
|
||||
typename LLThreadSafeQueue<ElementT, QueueT>::pop_result
|
||||
LLThreadSafeQueue<ElementT, QueueT>::pop_(lock_t& lock, ElementT& element)
|
||||
{
|
||||
// If mStorage is empty, there's no head element.
|
||||
if (mStorage.empty())
|
||||
return mClosed? DONE : EMPTY;
|
||||
|
||||
// If there's a head element, pass it to canPop() to see if it's ready to pop.
|
||||
if (! canPop(mStorage.front()))
|
||||
return WAITING;
|
||||
|
||||
// std::queue::front() is the element about to pop()
|
||||
element = mStorage.front();
|
||||
mStorage.pop();
|
||||
lock.unlock();
|
||||
// now that we've popped, if somebody's been waiting to push, signal them
|
||||
mCapacityCond.notify_one();
|
||||
return POPPED;
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT, typename QueueT>
|
||||
ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void)
|
||||
{
|
||||
lock_t lock1(mLock);
|
||||
ElementT value;
|
||||
while (true)
|
||||
{
|
||||
if (mClosed)
|
||||
// On the consumer side, we always try to pop before checking mClosed
|
||||
// so we can finish draining the queue.
|
||||
pop_result popped = pop_(lock1, value);
|
||||
if (popped == POPPED)
|
||||
return std::move(value);
|
||||
|
||||
// Once the queue is DONE, there will never be any more coming.
|
||||
if (popped == DONE)
|
||||
{
|
||||
return false;
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
}
|
||||
|
||||
if (mStorage.size() < mCapacity)
|
||||
// If we didn't pop because WAITING, i.e. canPop() returned false,
|
||||
// then even if the producer end has been closed, there's still at
|
||||
// least one item to drain: wait for it. Or we might be EMPTY, with
|
||||
// the queue still open. Either way, wait for signal.
|
||||
mEmptyCond.wait(lock1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT, typename QueueT>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryPop(ElementT & element)
|
||||
{
|
||||
return tryLock(
|
||||
[this, &element](lock_t& lock)
|
||||
{
|
||||
mStorage.push_front(element);
|
||||
lock1.unlock();
|
||||
mEmptyCond.notify_one();
|
||||
return true;
|
||||
// conflate EMPTY, DONE, WAITING: tryPop() behavior when the queue
|
||||
// is closed is implemented by simple inability to push any new
|
||||
// elements
|
||||
return pop_(lock, element) == POPPED;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename Rep, typename Period>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryPopFor(
|
||||
const std::chrono::duration<Rep, Period>& timeout,
|
||||
ElementT& element)
|
||||
{
|
||||
// Convert duration to time_point: passing the same timeout duration to
|
||||
// each of multiple calls is wrong.
|
||||
return tryPopUntil(std::chrono::steady_clock::now() + timeout, element);
|
||||
}
|
||||
|
||||
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename Clock, typename Duration>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil(
|
||||
const std::chrono::time_point<Clock, Duration>& until,
|
||||
ElementT& element)
|
||||
{
|
||||
return tryLockUntil(
|
||||
until,
|
||||
[this, until, &element](lock_t& lock)
|
||||
{
|
||||
// conflate EMPTY, DONE, WAITING
|
||||
return tryPopUntil_(lock, until, element) == POPPED;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// body of tryPopUntil(), called once we have the lock
|
||||
template <typename ElementT, typename QueueT>
|
||||
template <typename Clock, typename Duration>
|
||||
typename LLThreadSafeQueue<ElementT, QueueT>::pop_result
|
||||
LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil_(
|
||||
lock_t& lock,
|
||||
const std::chrono::time_point<Clock, Duration>& until,
|
||||
ElementT& element)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
pop_result popped = pop_(lock, element);
|
||||
if (popped == POPPED || popped == DONE)
|
||||
{
|
||||
// If we succeeded, great! If we've drained the last item, so be
|
||||
// it. Either way, break the loop and tell caller.
|
||||
return popped;
|
||||
}
|
||||
|
||||
// Storage Full. Wait for signal.
|
||||
if (LLCoros::cv_status::timeout == mCapacityCond.wait_until(lock1, endpoint))
|
||||
// EMPTY or WAITING: wait for signal.
|
||||
if (LLCoros::cv_status::timeout == mEmptyCond.wait_until(lock, until))
|
||||
{
|
||||
// timed out -- formally we might recheck both conditions above
|
||||
return false;
|
||||
// timed out -- formally we might recheck
|
||||
// as it is, break loop
|
||||
return popped;
|
||||
}
|
||||
// If we didn't time out, we were notified for some reason. Loop back
|
||||
// to check.
|
||||
|
|
@ -215,102 +519,40 @@ bool LLThreadSafeQueue<ElementT>::tryPushFrontFor(const std::chrono::duration<Re
|
|||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
|
||||
{
|
||||
lock_t lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock())
|
||||
return false;
|
||||
|
||||
if (mClosed)
|
||||
return false;
|
||||
|
||||
if (mStorage.size() >= mCapacity)
|
||||
return false;
|
||||
|
||||
mStorage.push_front(element);
|
||||
lock1.unlock();
|
||||
mEmptyCond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
ElementT LLThreadSafeQueue<ElementT>::popBack(void)
|
||||
{
|
||||
lock_t lock1(mLock);
|
||||
while (true)
|
||||
{
|
||||
if (!mStorage.empty())
|
||||
{
|
||||
ElementT value = mStorage.back();
|
||||
mStorage.pop_back();
|
||||
lock1.unlock();
|
||||
mCapacityCond.notify_one();
|
||||
return value;
|
||||
}
|
||||
|
||||
if (mClosed)
|
||||
{
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
}
|
||||
|
||||
// Storage empty. Wait for signal.
|
||||
mEmptyCond.wait(lock1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element)
|
||||
{
|
||||
lock_t lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock())
|
||||
return false;
|
||||
|
||||
// no need to check mClosed: tryPopBack() behavior when the queue is
|
||||
// closed is implemented by simple inability to push any new elements
|
||||
if (mStorage.empty())
|
||||
return false;
|
||||
|
||||
element = mStorage.back();
|
||||
mStorage.pop_back();
|
||||
lock1.unlock();
|
||||
mCapacityCond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
size_t LLThreadSafeQueue<ElementT>::size(void)
|
||||
template<typename ElementT, typename QueueT>
|
||||
size_t LLThreadSafeQueue<ElementT, QueueT>::size(void)
|
||||
{
|
||||
lock_t lock(mLock);
|
||||
return mStorage.size();
|
||||
}
|
||||
|
||||
template<typename ElementT>
|
||||
void LLThreadSafeQueue<ElementT>::close()
|
||||
|
||||
template<typename ElementT, typename QueueT>
|
||||
void LLThreadSafeQueue<ElementT, QueueT>::close()
|
||||
{
|
||||
lock_t lock(mLock);
|
||||
mClosed = true;
|
||||
lock.unlock();
|
||||
// wake up any blocked popBack() calls
|
||||
// wake up any blocked pop() calls
|
||||
mEmptyCond.notify_all();
|
||||
// wake up any blocked pushFront() calls
|
||||
// wake up any blocked push() calls
|
||||
mCapacityCond.notify_all();
|
||||
}
|
||||
|
||||
template<typename ElementT>
|
||||
bool LLThreadSafeQueue<ElementT>::isClosed()
|
||||
|
||||
template<typename ElementT, typename QueueT>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::isClosed()
|
||||
{
|
||||
lock_t lock(mLock);
|
||||
return mClosed && mStorage.size() == 0;
|
||||
return mClosed;
|
||||
}
|
||||
|
||||
template<typename ElementT>
|
||||
LLThreadSafeQueue<ElementT>::operator bool()
|
||||
|
||||
template<typename ElementT, typename QueueT>
|
||||
bool LLThreadSafeQueue<ElementT, QueueT>::done()
|
||||
{
|
||||
return ! isClosed();
|
||||
lock_t lock(mLock);
|
||||
return mClosed && mStorage.empty();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -90,19 +90,19 @@ namespace tut
|
|||
{
|
||||
Keyed one("one");
|
||||
ensure_equals(Keyed::instanceCount(), 1);
|
||||
Keyed* found = Keyed::getInstance("one");
|
||||
ensure("couldn't find stack Keyed", found);
|
||||
ensure_equals("found wrong Keyed instance", found, &one);
|
||||
auto found = Keyed::getInstance("one");
|
||||
ensure("couldn't find stack Keyed", bool(found));
|
||||
ensure_equals("found wrong Keyed instance", found.get(), &one);
|
||||
{
|
||||
boost::scoped_ptr<Keyed> two(new Keyed("two"));
|
||||
ensure_equals(Keyed::instanceCount(), 2);
|
||||
Keyed* found = Keyed::getInstance("two");
|
||||
ensure("couldn't find heap Keyed", found);
|
||||
ensure_equals("found wrong Keyed instance", found, two.get());
|
||||
auto found = Keyed::getInstance("two");
|
||||
ensure("couldn't find heap Keyed", bool(found));
|
||||
ensure_equals("found wrong Keyed instance", found.get(), two.get());
|
||||
}
|
||||
ensure_equals(Keyed::instanceCount(), 1);
|
||||
}
|
||||
Keyed* found = Keyed::getInstance("one");
|
||||
auto found = Keyed::getInstance("one");
|
||||
ensure("Keyed key lives too long", ! found);
|
||||
ensure_equals(Keyed::instanceCount(), 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* @file threadsafeschedule_test.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-04
|
||||
* @brief Test for threadsafeschedule.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "linden_common.h"
|
||||
// associated header
|
||||
#include "threadsafeschedule.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
#include <chrono>
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
|
||||
using namespace std::literals::chrono_literals; // ms suffix
|
||||
using namespace std::literals::string_literals; // s suffix
|
||||
using Queue = LL::ThreadSafeSchedule<std::string>;
|
||||
|
||||
/*****************************************************************************
|
||||
* TUT
|
||||
*****************************************************************************/
|
||||
namespace tut
|
||||
{
|
||||
struct threadsafeschedule_data
|
||||
{
|
||||
Queue queue;
|
||||
};
|
||||
typedef test_group<threadsafeschedule_data> threadsafeschedule_group;
|
||||
typedef threadsafeschedule_group::object object;
|
||||
threadsafeschedule_group threadsafeschedulegrp("threadsafeschedule");
|
||||
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
set_test_name("push");
|
||||
// Simply calling push() a few times might result in indeterminate
|
||||
// delivery order if the resolution of steady_clock is coarser than
|
||||
// the real time required for each push() call. Explicitly increment
|
||||
// the timestamp for each one -- but since we're passing explicit
|
||||
// timestamps, make the queue reorder them.
|
||||
queue.push(Queue::TimeTuple(Queue::Clock::now() + 20ms, "ghi"));
|
||||
// Given the various push() overloads, you have to match the type
|
||||
// exactly: conversions are ambiguous.
|
||||
queue.push("abc"s);
|
||||
queue.push(Queue::Clock::now() + 10ms, "def");
|
||||
queue.close();
|
||||
auto entry = queue.pop();
|
||||
ensure_equals("failed to pop first", std::get<0>(entry), "abc"s);
|
||||
entry = queue.pop();
|
||||
ensure_equals("failed to pop second", std::get<0>(entry), "def"s);
|
||||
ensure("queue not closed", queue.isClosed());
|
||||
ensure("queue prematurely done", ! queue.done());
|
||||
std::string s;
|
||||
bool popped = queue.tryPopFor(1s, s);
|
||||
ensure("failed to pop third", popped);
|
||||
ensure_equals("third is wrong", s, "ghi"s);
|
||||
popped = queue.tryPop(s);
|
||||
ensure("queue not empty", ! popped);
|
||||
ensure("queue not done", queue.done());
|
||||
}
|
||||
} // namespace tut
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @file tuple_test.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-04
|
||||
* @brief Test for tuple.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "linden_common.h"
|
||||
// associated header
|
||||
#include "tuple.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* TUT
|
||||
*****************************************************************************/
|
||||
namespace tut
|
||||
{
|
||||
struct tuple_data
|
||||
{
|
||||
};
|
||||
typedef test_group<tuple_data> tuple_group;
|
||||
typedef tuple_group::object object;
|
||||
tuple_group tuplegrp("tuple");
|
||||
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
set_test_name("tuple");
|
||||
std::tuple<std::string, int> tup{ "abc", 17 };
|
||||
std::tuple<int, std::string, int> ptup{ tuple_cons(34, tup) };
|
||||
std::tuple<std::string, int> tup2;
|
||||
int i;
|
||||
std::tie(i, tup2) = tuple_split(ptup);
|
||||
ensure_equals("tuple_car() fail", i, 34);
|
||||
ensure_equals("tuple_cdr() (0) fail", std::get<0>(tup2), "abc");
|
||||
ensure_equals("tuple_cdr() (1) fail", std::get<1>(tup2), 17);
|
||||
}
|
||||
} // namespace tut
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/**
|
||||
* @file workqueue_test.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-07
|
||||
* @brief Test for workqueue.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "linden_common.h"
|
||||
// associated header
|
||||
#include "workqueue.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
#include <chrono>
|
||||
#include <deque>
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
#include "llcond.h"
|
||||
#include "llstring.h"
|
||||
#include "stringize.h"
|
||||
|
||||
using namespace LL;
|
||||
using namespace std::literals::chrono_literals; // ms suffix
|
||||
using namespace std::literals::string_literals; // s suffix
|
||||
|
||||
/*****************************************************************************
|
||||
* TUT
|
||||
*****************************************************************************/
|
||||
namespace tut
|
||||
{
|
||||
struct workqueue_data
|
||||
{
|
||||
WorkQueue queue{"queue"};
|
||||
};
|
||||
typedef test_group<workqueue_data> workqueue_group;
|
||||
typedef workqueue_group::object object;
|
||||
workqueue_group workqueuegrp("workqueue");
|
||||
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
set_test_name("name");
|
||||
ensure_equals("didn't capture name", queue.getKey(), "queue");
|
||||
ensure("not findable", WorkQueue::getInstance("queue") == queue.getWeak().lock());
|
||||
WorkQueue q2;
|
||||
ensure("has no name", LLStringUtil::startsWith(q2.getKey(), "WorkQueue"));
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<2>()
|
||||
{
|
||||
set_test_name("post");
|
||||
bool wasRun{ false };
|
||||
// We only get away with binding a simple bool because we're running
|
||||
// the work on the same thread.
|
||||
queue.post([&wasRun](){ wasRun = true; });
|
||||
queue.close();
|
||||
ensure("ran too soon", ! wasRun);
|
||||
queue.runUntilClose();
|
||||
ensure("didn't run", wasRun);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<3>()
|
||||
{
|
||||
set_test_name("postEvery");
|
||||
// record of runs
|
||||
using Shared = std::deque<WorkQueue::TimePoint>;
|
||||
// This is an example of how to share data between the originator of
|
||||
// postEvery(work) and the work item itself, since usually a WorkQueue
|
||||
// is used to dispatch work to a different thread. Neither of them
|
||||
// should call any of LLCond's wait methods: you don't want to stall
|
||||
// either the worker thread or the originating thread (conventionally
|
||||
// main). Use LLCond or a subclass even if all you want to do is
|
||||
// signal the work item that it can quit; consider LLOneShotCond.
|
||||
LLCond<Shared> data;
|
||||
auto start = WorkQueue::TimePoint::clock::now();
|
||||
auto interval = 100ms;
|
||||
queue.postEvery(
|
||||
interval,
|
||||
[&data, count = 0]
|
||||
() mutable
|
||||
{
|
||||
// record the timestamp at which this instance is running
|
||||
data.update_one(
|
||||
[](Shared& data)
|
||||
{
|
||||
data.push_back(WorkQueue::TimePoint::clock::now());
|
||||
});
|
||||
// by the 3rd call, return false to stop
|
||||
return (++count < 3);
|
||||
});
|
||||
// no convenient way to close() our queue while we've got a
|
||||
// postEvery() running, so run until we think we should have exhausted
|
||||
// the iterations
|
||||
queue.runFor(10*interval);
|
||||
// Take a copy of the captured deque.
|
||||
Shared result = data.get();
|
||||
ensure_equals("called wrong number of times", result.size(), 3);
|
||||
// postEvery() assumes you want the first call to happen right away.
|
||||
// Pretend our start time was (interval) earlier than that, to make
|
||||
// our too early/too late tests uniform for all entries.
|
||||
start -= interval;
|
||||
for (size_t i = 0; i < result.size(); ++i)
|
||||
{
|
||||
auto diff = result[i] - start;
|
||||
start += interval;
|
||||
try
|
||||
{
|
||||
ensure(STRINGIZE("call " << i << " too soon"), diff >= interval);
|
||||
ensure(STRINGIZE("call " << i << " too late"), diff < interval*1.5);
|
||||
}
|
||||
catch (const tut::failure&)
|
||||
{
|
||||
auto interval_ms = interval / 1ms;
|
||||
auto diff_ms = diff / 1ms;
|
||||
std::cerr << "interval " << interval_ms
|
||||
<< "ms; diff " << diff_ms << "ms" << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<4>()
|
||||
{
|
||||
set_test_name("postTo");
|
||||
WorkQueue main("main");
|
||||
auto qptr = WorkQueue::getInstance("queue");
|
||||
int result = 0;
|
||||
main.postTo(
|
||||
qptr,
|
||||
[](){ return 17; },
|
||||
// Note that a postTo() *callback* can safely bind a reference to
|
||||
// a variable on the invoking thread, because the callback is run
|
||||
// on the invoking thread.
|
||||
[&result](int i){ result = i; });
|
||||
// this should post the callback to main
|
||||
qptr->runOne();
|
||||
// this should run the callback
|
||||
main.runOne();
|
||||
ensure_equals("failed to run int callback", result, 17);
|
||||
|
||||
std::string alpha;
|
||||
// postTo() handles arbitrary return types
|
||||
main.postTo(
|
||||
qptr,
|
||||
[](){ return "abc"s; },
|
||||
[&alpha](const std::string& s){ alpha = s; });
|
||||
qptr->runPending();
|
||||
main.runPending();
|
||||
ensure_equals("failed to run string callback", alpha, "abc");
|
||||
}
|
||||
} // namespace tut
|
||||
|
|
@ -0,0 +1,373 @@
|
|||
/**
|
||||
* @file threadsafeschedule.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-02
|
||||
* @brief ThreadSafeSchedule is an ordered queue in which every item has an
|
||||
* associated timestamp.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_THREADSAFESCHEDULE_H)
|
||||
#define LL_THREADSAFESCHEDULE_H
|
||||
|
||||
#include "chrono.h"
|
||||
#include "llexception.h"
|
||||
#include "llthreadsafequeue.h"
|
||||
#include "tuple.h"
|
||||
#include <chrono>
|
||||
#include <tuple>
|
||||
|
||||
namespace LL
|
||||
{
|
||||
namespace ThreadSafeSchedulePrivate
|
||||
{
|
||||
using TimePoint = std::chrono::steady_clock::time_point;
|
||||
// Bundle consumer's data with a TimePoint to order items by timestamp.
|
||||
template <typename... Args>
|
||||
using TimestampedTuple = std::tuple<TimePoint, Args...>;
|
||||
|
||||
// comparison functor for TimedTuples -- see TimedQueue comments
|
||||
struct ReverseTupleOrder
|
||||
{
|
||||
template <typename Tuple>
|
||||
bool operator()(const Tuple& left, const Tuple& right) const
|
||||
{
|
||||
return std::get<0>(left) > std::get<0>(right);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
using TimedQueue = PriorityQueueAdapter<
|
||||
TimestampedTuple<Args...>,
|
||||
// std::vector is the default storage for std::priority_queue,
|
||||
// have to restate to specify comparison template parameter
|
||||
std::vector<TimestampedTuple<Args...>>,
|
||||
// std::priority_queue uses a counterintuitive comparison
|
||||
// behavior: the default std::less comparator is used to present
|
||||
// the *highest* value as top(). So to sort by earliest timestamp,
|
||||
// we must invert by using >.
|
||||
ReverseTupleOrder>;
|
||||
} // namespace ThreadSafeSchedulePrivate
|
||||
|
||||
/**
|
||||
* ThreadSafeSchedule is an ordered LLThreadSafeQueue in which every item
|
||||
* is given an associated timestamp. That is, TimePoint is implicitly
|
||||
* prepended to the std::tuple with the specified types.
|
||||
*
|
||||
* Items are popped in increasing chronological order. Moreover, any item
|
||||
* with a timestamp in the future is held back until
|
||||
* std::chrono::steady_clock reaches that timestamp.
|
||||
*/
|
||||
template <typename... Args>
|
||||
class ThreadSafeSchedule:
|
||||
public LLThreadSafeQueue<ThreadSafeSchedulePrivate::TimestampedTuple<Args...>,
|
||||
ThreadSafeSchedulePrivate::TimedQueue<Args...>>
|
||||
{
|
||||
public:
|
||||
using DataTuple = std::tuple<Args...>;
|
||||
using TimeTuple = ThreadSafeSchedulePrivate::TimestampedTuple<Args...>;
|
||||
|
||||
private:
|
||||
using super = LLThreadSafeQueue<TimeTuple, ThreadSafeSchedulePrivate::TimedQueue<Args...>>;
|
||||
using lock_t = typename super::lock_t;
|
||||
// VS 2017 needs this due to a bug:
|
||||
// https://developercommunity.visualstudio.com/t/cannot-access-protected-enumerator-of-enclosing-cl/203430
|
||||
enum pop_result { EMPTY=super::EMPTY, DONE=super::DONE, WAITING=super::WAITING, POPPED=super::POPPED };
|
||||
|
||||
public:
|
||||
using Closed = LLThreadSafeQueueInterrupt;
|
||||
using TimePoint = ThreadSafeSchedulePrivate::TimePoint;
|
||||
using Clock = TimePoint::clock;
|
||||
|
||||
ThreadSafeSchedule(U32 capacity=1024):
|
||||
super(capacity)
|
||||
{}
|
||||
|
||||
/*----------------------------- push() -----------------------------*/
|
||||
/// explicitly pass TimeTuple
|
||||
using super::push;
|
||||
|
||||
/// pass DataTuple with implicit now
|
||||
// This could be ambiguous for Args with a single type. Unfortunately
|
||||
// we can't enable_if an individual method with a condition based on
|
||||
// the *class* template arguments, only on that method's template
|
||||
// arguments. We could specialize this class for the single-Args case;
|
||||
// we could minimize redundancy by breaking out a common base class...
|
||||
void push(const DataTuple& tuple)
|
||||
{
|
||||
push(tuple_cons(Clock::now(), tuple));
|
||||
}
|
||||
|
||||
/// individually pass each component of the TimeTuple
|
||||
void push(const TimePoint& time, Args&&... args)
|
||||
{
|
||||
push(TimeTuple(time, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// individually pass every component except the TimePoint (implies now)
|
||||
// This could be ambiguous if the first specified template parameter
|
||||
// type is also TimePoint. We could try to disambiguate, but a simpler
|
||||
// approach would be for the caller to explicitly construct DataTuple
|
||||
// and call that overload.
|
||||
void push(Args&&... args)
|
||||
{
|
||||
push(Clock::now(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/*--------------------------- tryPush() ----------------------------*/
|
||||
/// explicit TimeTuple
|
||||
using super::tryPush;
|
||||
|
||||
/// DataTuple with implicit now
|
||||
bool tryPush(const DataTuple& tuple)
|
||||
{
|
||||
return tryPush(tuple_cons(Clock::now(), tuple));
|
||||
}
|
||||
|
||||
/// individually pass components
|
||||
bool tryPush(const TimePoint& time, Args&&... args)
|
||||
{
|
||||
return tryPush(TimeTuple(time, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// individually pass components with implicit now
|
||||
bool tryPush(Args&&... args)
|
||||
{
|
||||
return tryPush(Clock::now(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/*-------------------------- tryPushFor() --------------------------*/
|
||||
/// explicit TimeTuple
|
||||
using super::tryPushFor;
|
||||
|
||||
/// DataTuple with implicit now
|
||||
template <typename Rep, typename Period>
|
||||
bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout,
|
||||
const DataTuple& tuple)
|
||||
{
|
||||
return tryPushFor(timeout, tuple_cons(Clock::now(), tuple));
|
||||
}
|
||||
|
||||
/// individually pass components
|
||||
template <typename Rep, typename Period>
|
||||
bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout,
|
||||
const TimePoint& time, Args&&... args)
|
||||
{
|
||||
return tryPushFor(TimeTuple(time, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// individually pass components with implicit now
|
||||
template <typename Rep, typename Period>
|
||||
bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout,
|
||||
Args&&... args)
|
||||
{
|
||||
return tryPushFor(Clock::now(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/*------------------------- tryPushUntil() -------------------------*/
|
||||
/// explicit TimeTuple
|
||||
using super::tryPushUntil;
|
||||
|
||||
/// DataTuple with implicit now
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
const DataTuple& tuple)
|
||||
{
|
||||
return tryPushUntil(until, tuple_cons(Clock::now(), tuple));
|
||||
}
|
||||
|
||||
/// individually pass components
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
const TimePoint& time, Args&&... args)
|
||||
{
|
||||
return tryPushUntil(until, TimeTuple(time, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// individually pass components with implicit now
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
Args&&... args)
|
||||
{
|
||||
return tryPushUntil(until, Clock::now(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/*----------------------------- pop() ------------------------------*/
|
||||
// Our consumer may or may not care about the timestamp associated
|
||||
// with each popped item, so we allow retrieving either DataTuple or
|
||||
// TimeTuple. One potential use would be to observe, and possibly
|
||||
// adjust for, the time lag between the item time and the actual
|
||||
// current time.
|
||||
|
||||
/// pop DataTuple by value
|
||||
// It would be great to notice when sizeof...(Args) == 1 and directly
|
||||
// return the first (only) value, instead of making pop()'s caller
|
||||
// call std::get<0>(value). See push(DataTuple) remarks for why we
|
||||
// haven't yet jumped through those hoops.
|
||||
DataTuple pop()
|
||||
{
|
||||
return tuple_cdr(popWithTime());
|
||||
}
|
||||
|
||||
/// pop TimeTuple by value
|
||||
TimeTuple popWithTime()
|
||||
{
|
||||
lock_t lock(super::mLock);
|
||||
// We can't just sit around waiting forever, given that there may
|
||||
// be items in the queue that are not yet ready but will *become*
|
||||
// ready in the near future. So in fact, with this class, every
|
||||
// pop() becomes a tryPopUntil(), constrained to the timestamp of
|
||||
// the head item. It almost doesn't matter what we specify for the
|
||||
// caller's time constraint -- all we really care about is the
|
||||
// head item's timestamp. Since pop() and popWithTime() are
|
||||
// defined to wait until either an item becomes available or the
|
||||
// queue is closed, loop until one of those things happens. The
|
||||
// constraint we pass just determines how often we'll loop while
|
||||
// waiting.
|
||||
TimeTuple tt;
|
||||
while (true)
|
||||
{
|
||||
// Pick a point suitably far into the future.
|
||||
TimePoint until = TimePoint::clock::now() + std::chrono::hours(24);
|
||||
pop_result popped = tryPopUntil_(lock, until, tt);
|
||||
if (popped == POPPED)
|
||||
return std::move(tt);
|
||||
|
||||
// DONE: throw, just as super::pop() does
|
||||
if (popped == DONE)
|
||||
{
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
}
|
||||
// WAITING: we've still got items to drain.
|
||||
// EMPTY: not closed, so it's worth waiting for more items.
|
||||
// Either way, loop back to wait.
|
||||
}
|
||||
}
|
||||
|
||||
// We can use tryPop(TimeTuple&) just as it stands; the only behavior
|
||||
// difference is in our canPop() override method.
|
||||
using super::tryPop;
|
||||
|
||||
/// tryPop(DataTuple&)
|
||||
bool tryPop(DataTuple& tuple)
|
||||
{
|
||||
TimeTuple tt;
|
||||
if (! super::tryPop(tt))
|
||||
return false;
|
||||
tuple = tuple_cdr(std::move(tt));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// for when Args has exactly one type
|
||||
bool tryPop(typename std::tuple_element<1, TimeTuple>::type& value)
|
||||
{
|
||||
TimeTuple tt;
|
||||
if (! super::tryPop(tt))
|
||||
return false;
|
||||
value = std::get<1>(std::move(tt));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// tryPopFor()
|
||||
template <typename Rep, typename Period, typename Tuple>
|
||||
bool tryPopFor(const std::chrono::duration<Rep, Period>& timeout, Tuple& tuple)
|
||||
{
|
||||
// It's important to use OUR tryPopUntil() implementation, rather
|
||||
// than delegating immediately to our base class.
|
||||
return tryPopUntil(Clock::now() + timeout, tuple);
|
||||
}
|
||||
|
||||
/// tryPopUntil(TimeTuple&)
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
TimeTuple& tuple)
|
||||
{
|
||||
// super::tryPopUntil() wakes up when an item becomes available or
|
||||
// we hit 'until', whichever comes first. Thing is, the current
|
||||
// head of the queue could become ready sooner than either of
|
||||
// those events, and we need to deliver it as soon as it does.
|
||||
// Don't wait past the TimePoint of the head item.
|
||||
// Naturally, lock the queue before peeking at mStorage.
|
||||
return super::tryLockUntil(
|
||||
until,
|
||||
[this, until, &tuple](lock_t& lock)
|
||||
{
|
||||
// Use our time_point_cast to allow for 'until' that's a
|
||||
// time_point type other than TimePoint.
|
||||
return POPPED ==
|
||||
tryPopUntil_(lock, LL::time_point_cast<TimePoint>(until), tuple);
|
||||
});
|
||||
}
|
||||
|
||||
pop_result tryPopUntil_(lock_t& lock, const TimePoint& until, TimeTuple& tuple)
|
||||
{
|
||||
TimePoint adjusted = until;
|
||||
if (! super::mStorage.empty())
|
||||
{
|
||||
// use whichever is earlier: the head item's timestamp, or
|
||||
// the caller's limit
|
||||
adjusted = min(std::get<0>(super::mStorage.front()), adjusted);
|
||||
}
|
||||
// now delegate to base-class tryPopUntil_()
|
||||
pop_result popped;
|
||||
while ((popped = pop_result(super::tryPopUntil_(lock, adjusted, tuple))) == WAITING)
|
||||
{
|
||||
// If super::tryPopUntil_() returns WAITING, it means there's
|
||||
// a head item, but it's not yet time. But it's worth looping
|
||||
// back to recheck.
|
||||
}
|
||||
return popped;
|
||||
}
|
||||
|
||||
/// tryPopUntil(DataTuple&)
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
DataTuple& tuple)
|
||||
{
|
||||
TimeTuple tt;
|
||||
if (! tryPopUntil(until, tt))
|
||||
return false;
|
||||
tuple = tuple_cdr(std::move(tt));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// for when Args has exactly one type
|
||||
template <typename Clock, typename Duration>
|
||||
bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until,
|
||||
typename std::tuple_element<1, TimeTuple>::type& value)
|
||||
{
|
||||
TimeTuple tt;
|
||||
if (! tryPopUntil(until, tt))
|
||||
return false;
|
||||
value = std::get<1>(std::move(tt));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*------------------------------ etc. ------------------------------*/
|
||||
// We can't hide items that aren't yet ready because we can't traverse
|
||||
// the underlying priority_queue: it has no iterators, only top(). So
|
||||
// a consumer could observe size() > 0 and yet tryPop() returns false.
|
||||
// Shrug, in a multi-consumer scenario that would be expected behavior.
|
||||
using super::size;
|
||||
// open/closed state
|
||||
using super::close;
|
||||
using super::isClosed;
|
||||
using super::done;
|
||||
|
||||
private:
|
||||
// this method is called by base class pop_() every time we're
|
||||
// considering whether to deliver the current head element
|
||||
bool canPop(const TimeTuple& head) const override
|
||||
{
|
||||
// an item with a future timestamp isn't yet ready to pop
|
||||
// (should we add some slop for overhead?)
|
||||
return std::get<0>(head) <= Clock::now();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace LL
|
||||
|
||||
#endif /* ! defined(LL_THREADSAFESCHEDULE_H) */
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* @file tuple.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-04
|
||||
* @brief A couple tuple utilities
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_TUPLE_H)
|
||||
#define LL_TUPLE_H
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits> // std::remove_reference
|
||||
#include <utility> // std::pair
|
||||
|
||||
/**
|
||||
* tuple_cons() behaves like LISP cons: it uses std::tuple_cat() to prepend a
|
||||
* new item of arbitrary type to an existing std::tuple.
|
||||
*/
|
||||
template <typename First, typename... Rest, typename Tuple_=std::tuple<Rest...>>
|
||||
auto tuple_cons(First&& first, Tuple_&& rest)
|
||||
{
|
||||
// All we need to do is make a tuple containing 'first', and let
|
||||
// tuple_cat() do the hard part.
|
||||
return std::tuple_cat(std::tuple<First>(std::forward<First>(first)),
|
||||
std::forward<Tuple_>(rest));
|
||||
}
|
||||
|
||||
/**
|
||||
* tuple_car() behaves like LISP car: it extracts the first item from a
|
||||
* std::tuple.
|
||||
*/
|
||||
template <typename... Args, typename Tuple_=std::tuple<Args...>>
|
||||
auto tuple_car(Tuple_&& tuple)
|
||||
{
|
||||
return std::get<0>(std::forward<Tuple_>(tuple));
|
||||
}
|
||||
|
||||
/**
|
||||
* tuple_cdr() behaves like LISP cdr: it returns a new tuple containing
|
||||
* everything BUT the first item.
|
||||
*/
|
||||
// derived from https://stackoverflow.com/a/24046437
|
||||
template <typename Tuple, std::size_t... Indices>
|
||||
auto tuple_cdr_(Tuple&& tuple, const std::index_sequence<Indices...>)
|
||||
{
|
||||
// Given an index sequence from [0..N-1), extract tuple items [1..N)
|
||||
return std::make_tuple(std::get<Indices+1u>(std::forward<Tuple>(tuple))...);
|
||||
}
|
||||
|
||||
template <typename Tuple>
|
||||
auto tuple_cdr(Tuple&& tuple)
|
||||
{
|
||||
return tuple_cdr_(
|
||||
std::forward<Tuple>(tuple),
|
||||
// Pass helper function an index sequence one item shorter than tuple
|
||||
std::make_index_sequence<
|
||||
std::tuple_size<
|
||||
// tuple_size doesn't like reference types
|
||||
typename std::remove_reference<Tuple>::type
|
||||
>::value - 1u>
|
||||
());
|
||||
}
|
||||
|
||||
/**
|
||||
* tuple_split(), the opposite of tuple_cons(), has no direct analog in LISP.
|
||||
* It returns a std::pair of tuple_car(), tuple_cdr(). We could call this
|
||||
* function tuple_car_cdr(), or tuple_slice() or some such. But tuple_split()
|
||||
* feels more descriptive.
|
||||
*/
|
||||
template <typename... Args, typename Tuple_=std::tuple<Args...>>
|
||||
auto tuple_split(Tuple_&& tuple)
|
||||
{
|
||||
// We're not really worried about forwarding multiple times a tuple that
|
||||
// might contain move-only items, because the implementation above only
|
||||
// applies std::get() exactly once to each item.
|
||||
return std::make_pair(tuple_car(std::forward<Tuple_>(tuple)),
|
||||
tuple_cdr(std::forward<Tuple_>(tuple)));
|
||||
}
|
||||
|
||||
#endif /* ! defined(LL_TUPLE_H) */
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* @file workqueue.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-10-06
|
||||
* @brief Implementation for WorkQueue.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "linden_common.h"
|
||||
// associated header
|
||||
#include "workqueue.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "llcoros.h"
|
||||
#include LLCOROS_MUTEX_HEADER
|
||||
#include "llerror.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
|
||||
using Mutex = LLCoros::Mutex;
|
||||
using Lock = LLCoros::LockType;
|
||||
|
||||
LL::WorkQueue::WorkQueue(const std::string& name):
|
||||
super(makeName(name))
|
||||
{
|
||||
// TODO: register for "LLApp" events so we can implicitly close() on
|
||||
// viewer shutdown.
|
||||
}
|
||||
|
||||
void LL::WorkQueue::close()
|
||||
{
|
||||
mQueue.close();
|
||||
}
|
||||
|
||||
void LL::WorkQueue::runUntilClose()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
callWork(mQueue.pop());
|
||||
}
|
||||
}
|
||||
catch (const Queue::Closed&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
bool LL::WorkQueue::runPending()
|
||||
{
|
||||
for (Work work; mQueue.tryPop(work); )
|
||||
{
|
||||
callWork(work);
|
||||
}
|
||||
return ! mQueue.done();
|
||||
}
|
||||
|
||||
bool LL::WorkQueue::runOne()
|
||||
{
|
||||
Work work;
|
||||
if (mQueue.tryPop(work))
|
||||
{
|
||||
callWork(work);
|
||||
}
|
||||
return ! mQueue.done();
|
||||
}
|
||||
|
||||
bool LL::WorkQueue::runUntil(const TimePoint& until)
|
||||
{
|
||||
// Should we subtract some slop to allow for typical Work execution time?
|
||||
// How much slop?
|
||||
Work work;
|
||||
while (TimePoint::clock::now() < until && mQueue.tryPopUntil(until, work))
|
||||
{
|
||||
callWork(work);
|
||||
}
|
||||
return ! mQueue.done();
|
||||
}
|
||||
|
||||
std::string LL::WorkQueue::makeName(const std::string& name)
|
||||
{
|
||||
if (! name.empty())
|
||||
return name;
|
||||
|
||||
static U32 discriminator = 0;
|
||||
static Mutex mutex;
|
||||
U32 num;
|
||||
{
|
||||
// Protect discriminator from concurrent access by different threads.
|
||||
// It can't be thread_local, else two racing threads will come up with
|
||||
// the same name.
|
||||
Lock lk(mutex);
|
||||
num = discriminator++;
|
||||
}
|
||||
return STRINGIZE("WorkQueue" << num);
|
||||
}
|
||||
|
||||
void LL::WorkQueue::callWork(const Queue::DataTuple& work)
|
||||
{
|
||||
// ThreadSafeSchedule::pop() always delivers a tuple, even when
|
||||
// there's only one data field per item, as for us.
|
||||
callWork(std::get<0>(work));
|
||||
}
|
||||
|
||||
void LL::WorkQueue::callWork(const Work& work)
|
||||
{
|
||||
try
|
||||
{
|
||||
work();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// No matter what goes wrong with any individual work item, the worker
|
||||
// thread must go on! Log our own instance name with the exception.
|
||||
LOG_UNHANDLED_EXCEPTION(getKey());
|
||||
}
|
||||
}
|
||||
|
||||
void LL::WorkQueue::error(const std::string& msg)
|
||||
{
|
||||
LL_ERRS("WorkQueue") << msg << LL_ENDL;
|
||||
}
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
/**
|
||||
* @file workqueue.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2021-09-30
|
||||
* @brief Queue used for inter-thread work passing.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Copyright (c) 2021, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_WORKQUEUE_H)
|
||||
#define LL_WORKQUEUE_H
|
||||
|
||||
#include "llinstancetracker.h"
|
||||
#include "threadsafeschedule.h"
|
||||
#include <chrono>
|
||||
#include <functional> // std::function
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <utility> // std::pair
|
||||
#include <vector>
|
||||
|
||||
namespace LL
|
||||
{
|
||||
/**
|
||||
* A typical WorkQueue has a string name that can be used to find it.
|
||||
*/
|
||||
class WorkQueue: public LLInstanceTracker<WorkQueue, std::string>
|
||||
{
|
||||
private:
|
||||
using super = LLInstanceTracker<WorkQueue, std::string>;
|
||||
|
||||
public:
|
||||
using Work = std::function<void()>;
|
||||
|
||||
private:
|
||||
using Queue = ThreadSafeSchedule<Work>;
|
||||
// helper for postEvery()
|
||||
template <typename Rep, typename Period, typename CALLABLE>
|
||||
class BackJack;
|
||||
|
||||
public:
|
||||
using TimePoint = Queue::TimePoint;
|
||||
using TimedWork = Queue::TimeTuple;
|
||||
using Closed = Queue::Closed;
|
||||
|
||||
/**
|
||||
* You may omit the WorkQueue name, in which case a unique name is
|
||||
* synthesized; for practical purposes that makes it anonymous.
|
||||
*/
|
||||
WorkQueue(const std::string& name = std::string());
|
||||
|
||||
/**
|
||||
* Since the point of WorkQueue is to pass work to some other worker
|
||||
* thread(s) asynchronously, it's important that the WorkQueue continue
|
||||
* to exist until the worker thread(s) have drained it. To communicate
|
||||
* that it's time for them to quit, close() the queue.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/*---------------------- fire and forget API -----------------------*/
|
||||
|
||||
/// fire-and-forget, but at a particular (future?) time
|
||||
template <typename CALLABLE>
|
||||
void post(const TimePoint& time, CALLABLE&& callable)
|
||||
{
|
||||
// Defer reifying an arbitrary CALLABLE until we hit this method.
|
||||
// All other methods should accept CALLABLEs of arbitrary type to
|
||||
// avoid multiple levels of std::function indirection.
|
||||
mQueue.push(TimedWork(time, std::move(callable)));
|
||||
}
|
||||
|
||||
/// fire-and-forget
|
||||
template <typename CALLABLE>
|
||||
void post(CALLABLE&& callable)
|
||||
{
|
||||
// We use TimePoint::clock::now() instead of TimePoint's
|
||||
// representation of the epoch because this WorkQueue may contain
|
||||
// a mix of past-due TimedWork items and TimedWork items scheduled
|
||||
// for the future. Sift this new item into the correct place.
|
||||
post(TimePoint::clock::now(), std::move(callable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch a callable returning bool that will trigger repeatedly at
|
||||
* specified interval, until the callable returns false.
|
||||
*
|
||||
* If you need to signal that callable from outside, DO NOT bind a
|
||||
* reference to a simple bool! That's not thread-safe. Instead, bind
|
||||
* an LLCond variant, e.g. LLOneShotCond or LLBoolCond.
|
||||
*/
|
||||
template <typename Rep, typename Period, typename CALLABLE>
|
||||
void postEvery(const std::chrono::duration<Rep, Period>& interval,
|
||||
CALLABLE&& callable);
|
||||
|
||||
/*------------------------- handshake API --------------------------*/
|
||||
|
||||
/**
|
||||
* Post work to another WorkQueue to be run at a specified time,
|
||||
* requesting a specific callback to be run on this WorkQueue on
|
||||
* completion.
|
||||
*
|
||||
* Returns true if able to post, false if the other WorkQueue is
|
||||
* inaccessible.
|
||||
*/
|
||||
// Apparently some Microsoft header file defines a macro CALLBACK? The
|
||||
// natural template argument name CALLBACK produces very weird Visual
|
||||
// Studio compile errors that seem utterly unrelated to this source
|
||||
// code.
|
||||
template <typename CALLABLE, typename FOLLOWUP>
|
||||
bool postTo(WorkQueue::weak_t target,
|
||||
const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback)
|
||||
{
|
||||
// We're being asked to post to the WorkQueue at target.
|
||||
// target is a weak_ptr: have to lock it to check it.
|
||||
auto tptr = target.lock();
|
||||
if (! tptr)
|
||||
// can't post() if the target WorkQueue has been destroyed
|
||||
return false;
|
||||
|
||||
// Here we believe target WorkQueue still exists. Post to it a
|
||||
// lambda that packages our callable, our callback and a weak_ptr
|
||||
// to this originating WorkQueue.
|
||||
tptr->post(
|
||||
time,
|
||||
[reply = super::getWeak(),
|
||||
callable = std::move(callable),
|
||||
callback = std::move(callback)]
|
||||
()
|
||||
{
|
||||
// Call the callable in any case -- but to minimize
|
||||
// copying the result, immediately bind it into a reply
|
||||
// lambda. The reply lambda also binds the original
|
||||
// callback, so that when we, the originating WorkQueue,
|
||||
// finally receive and process the reply lambda, we'll
|
||||
// call the bound callback with the bound result -- on the
|
||||
// same thread that originally called postTo().
|
||||
auto rlambda =
|
||||
[result = callable(),
|
||||
callback = std::move(callback)]
|
||||
()
|
||||
{ callback(std::move(result)); };
|
||||
// Check if this originating WorkQueue still exists.
|
||||
// Remember, the outer lambda is now running on a thread
|
||||
// servicing the target WorkQueue, and real time has
|
||||
// elapsed since postTo()'s tptr->post() call.
|
||||
// reply is a weak_ptr: have to lock it to check it.
|
||||
auto rptr = reply.lock();
|
||||
if (rptr)
|
||||
{
|
||||
// Only post reply lambda if the originating WorkQueue
|
||||
// still exists. If not -- who would we tell? Log it?
|
||||
try
|
||||
{
|
||||
rptr->post(std::move(rlambda));
|
||||
}
|
||||
catch (const Closed&)
|
||||
{
|
||||
// Originating WorkQueue might still exist, but
|
||||
// might be Closed. Same thing: just discard the
|
||||
// callback.
|
||||
}
|
||||
}
|
||||
});
|
||||
// looks like we were able to post()
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post work to another WorkQueue, requesting a specific callback to
|
||||
* be run on this WorkQueue on completion.
|
||||
*
|
||||
* Returns true if able to post, false if the other WorkQueue is
|
||||
* inaccessible.
|
||||
*/
|
||||
template <typename CALLABLE, typename FOLLOWUP>
|
||||
bool postTo(WorkQueue::weak_t target,
|
||||
CALLABLE&& callable, FOLLOWUP&& callback)
|
||||
{
|
||||
return postTo(target, TimePoint::clock::now(), std::move(callable), std::move(callback));
|
||||
}
|
||||
|
||||
/*--------------------------- worker API ---------------------------*/
|
||||
|
||||
/**
|
||||
* runUntilClose() pulls TimedWork items off this WorkQueue until the
|
||||
* queue is closed, at which point it returns. This would be the
|
||||
* typical entry point for a simple worker thread.
|
||||
*/
|
||||
void runUntilClose();
|
||||
|
||||
/**
|
||||
* runPending() runs all TimedWork items that are ready to run. It
|
||||
* returns true if the queue remains open, false if the queue has been
|
||||
* closed. This could be used by a thread whose primary purpose is to
|
||||
* serve the queue, but also wants to do other things with its idle time.
|
||||
*/
|
||||
bool runPending();
|
||||
|
||||
/**
|
||||
* runOne() runs at most one ready TimedWork item -- zero if none are
|
||||
* ready. It returns true if the queue remains open, false if the
|
||||
* queue has been closed.
|
||||
*/
|
||||
bool runOne();
|
||||
|
||||
/**
|
||||
* runFor() runs a subset of ready TimedWork items, until the
|
||||
* timeslice has been exceeded. It returns true if the queue remains
|
||||
* open, false if the queue has been closed. This could be used by a
|
||||
* busy main thread to lend a bounded few CPU cycles to this WorkQueue
|
||||
* without risking the WorkQueue blowing out the length of any one
|
||||
* frame.
|
||||
*/
|
||||
template <typename Rep, typename Period>
|
||||
bool runFor(const std::chrono::duration<Rep, Period>& timeslice)
|
||||
{
|
||||
return runUntil(TimePoint::clock::now() + timeslice);
|
||||
}
|
||||
|
||||
/**
|
||||
* runUntil() is just like runFor(), only with a specific end time
|
||||
* instead of a timeslice duration.
|
||||
*/
|
||||
bool runUntil(const TimePoint& until);
|
||||
|
||||
private:
|
||||
static void error(const std::string& msg);
|
||||
static std::string makeName(const std::string& name);
|
||||
void callWork(const Queue::DataTuple& work);
|
||||
void callWork(const Work& work);
|
||||
Queue mQueue;
|
||||
};
|
||||
|
||||
/**
|
||||
* BackJack is, in effect, a hand-rolled lambda, binding a WorkQueue, a
|
||||
* CALLABLE that returns bool, a TimePoint and an interval at which to
|
||||
* relaunch it. As long as the callable continues returning true, BackJack
|
||||
* keeps resubmitting it to the target WorkQueue.
|
||||
*/
|
||||
// Why is BackJack a class and not a lambda? Because, unlike a lambda, a
|
||||
// class method gets its own 'this' pointer -- which we need to resubmit
|
||||
// the whole BackJack callable.
|
||||
template <typename Rep, typename Period, typename CALLABLE>
|
||||
class WorkQueue::BackJack
|
||||
{
|
||||
public:
|
||||
// bind the desired data
|
||||
BackJack(WorkQueue::weak_t target,
|
||||
const WorkQueue::TimePoint& start,
|
||||
const std::chrono::duration<Rep, Period>& interval,
|
||||
CALLABLE&& callable):
|
||||
mTarget(target),
|
||||
mStart(start),
|
||||
mInterval(interval),
|
||||
mCallable(std::move(callable))
|
||||
{}
|
||||
|
||||
// Call by target WorkQueue -- note that although WE require a
|
||||
// callable returning bool, WorkQueue wants a void callable. We
|
||||
// consume the bool.
|
||||
void operator()()
|
||||
{
|
||||
// If mCallable() throws an exception, don't catch it here: if it
|
||||
// throws once, it's likely to throw every time, so it's a waste
|
||||
// of time to arrange to call it again.
|
||||
if (mCallable())
|
||||
{
|
||||
// Modify mStart to the new start time we desire. If we simply
|
||||
// added mInterval to now, we'd get actual timings of
|
||||
// (mInterval + slop), where 'slop' is the latency between the
|
||||
// previous mStart and the WorkQueue actually calling us.
|
||||
// Instead, add mInterval to mStart so that at least we
|
||||
// register our intent to fire at exact mIntervals.
|
||||
mStart += mInterval;
|
||||
|
||||
// We're being called at this moment by the target WorkQueue.
|
||||
// Assume it still exists, rather than checking the result of
|
||||
// lock().
|
||||
// Resubmit the whole *this callable: that's why we're a class
|
||||
// rather than a lambda. Allow moving *this so we can carry a
|
||||
// move-only callable; but naturally this statement must be
|
||||
// the last time we reference this instance, which may become
|
||||
// moved-from.
|
||||
try
|
||||
{
|
||||
mTarget.lock()->post(mStart, std::move(*this));
|
||||
}
|
||||
catch (const Closed&)
|
||||
{
|
||||
// Once this queue is closed, oh well, just stop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
WorkQueue::weak_t mTarget;
|
||||
WorkQueue::TimePoint mStart;
|
||||
std::chrono::duration<Rep, Period> mInterval;
|
||||
CALLABLE mCallable;
|
||||
};
|
||||
|
||||
template <typename Rep, typename Period, typename CALLABLE>
|
||||
void WorkQueue::postEvery(const std::chrono::duration<Rep, Period>& interval,
|
||||
CALLABLE&& callable)
|
||||
{
|
||||
if (interval.count() <= 0)
|
||||
{
|
||||
// It's essential that postEvery() be called with a positive
|
||||
// interval, since each call to BackJack posts another instance of
|
||||
// itself at (start + interval) and we order by target time. A
|
||||
// zero or negative interval would result in that BackJack
|
||||
// instance going to the head of the queue every time, immediately
|
||||
// ready to run. Effectively that would produce an infinite loop,
|
||||
// a denial of service on this WorkQueue.
|
||||
error("postEvery(interval) may not be 0");
|
||||
}
|
||||
// Instantiate and post a suitable BackJack, binding a weak_ptr to
|
||||
// self, the current time, the desired interval and the desired
|
||||
// callable.
|
||||
post(
|
||||
BackJack<Rep, Period, CALLABLE>(
|
||||
getWeak(), TimePoint::clock::now(), interval, std::move(callable)));
|
||||
}
|
||||
|
||||
} // namespace LL
|
||||
|
||||
#endif /* ! defined(LL_WORKQUEUE_H) */
|
||||
|
|
@ -177,7 +177,6 @@ if (DARWIN)
|
|||
set(copy_dylibs
|
||||
libapr-1.0.dylib
|
||||
libaprutil-1.0.dylib
|
||||
libexception_handler.dylib
|
||||
libnghttp2*.dylib
|
||||
liburiparser*.dylib
|
||||
${EXPAT_COPY}
|
||||
|
|
|
|||
|
|
@ -23,13 +23,6 @@
|
|||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#if LL_WINDOWS
|
||||
#define SAFE_SSL 1
|
||||
#elif LL_DARWIN
|
||||
#define SAFE_SSL 1
|
||||
#else
|
||||
#define SAFE_SSL 1
|
||||
#endif
|
||||
|
||||
#include "linden_common.h" // Modifies curl/curl.h interfaces
|
||||
#include "httpcommon.h"
|
||||
|
|
@ -38,10 +31,6 @@
|
|||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#if SAFE_SSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <functional> // std::hash
|
||||
#endif
|
||||
|
||||
|
||||
namespace LLCore
|
||||
|
|
@ -281,9 +270,6 @@ namespace LLHttp
|
|||
{
|
||||
namespace
|
||||
{
|
||||
typedef boost::shared_ptr<LLMutex> LLMutex_ptr;
|
||||
std::vector<LLMutex_ptr> sSSLMutex;
|
||||
|
||||
CURL *getCurlTemplateHandle()
|
||||
{
|
||||
static CURL *curlpTemplateHandle = NULL;
|
||||
|
|
@ -348,34 +334,6 @@ void deallocateEasyCurl(CURL *curlp)
|
|||
}
|
||||
|
||||
|
||||
#if SAFE_SSL
|
||||
//static
|
||||
void ssl_locking_callback(int mode, int type, const char *file, int line)
|
||||
{
|
||||
if (type >= sSSLMutex.size())
|
||||
{
|
||||
LL_WARNS() << "Attempt to get unknown MUTEX in SSL Lock." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (mode & CRYPTO_LOCK)
|
||||
{
|
||||
sSSLMutex[type]->lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
sSSLMutex[type]->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
unsigned long ssl_thread_id(void)
|
||||
{
|
||||
// std::thread::id is very deliberately opaque, but we can hash it
|
||||
return std::hash<LLThread::id_t>()(LLThread::currentID());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
void initialize()
|
||||
|
|
@ -387,27 +345,11 @@ void initialize()
|
|||
|
||||
check_curl_code(code, CURL_GLOBAL_ALL);
|
||||
|
||||
#if SAFE_SSL
|
||||
S32 mutex_count = CRYPTO_num_locks();
|
||||
for (S32 i = 0; i < mutex_count; i++)
|
||||
{
|
||||
sSSLMutex.push_back(LLMutex_ptr(new LLMutex()));
|
||||
}
|
||||
CRYPTO_set_id_callback(&ssl_thread_id);
|
||||
CRYPTO_set_locking_callback(&ssl_locking_callback);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
#if SAFE_SSL
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
sSSLMutex.clear();
|
||||
#endif
|
||||
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ LLImageDecodeThread::~LLImageDecodeThread()
|
|||
// virtual
|
||||
S32 LLImageDecodeThread::update(F32 max_time_ms)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
for (creation_list_t::iterator iter = mCreationList.begin();
|
||||
iter != mCreationList.end(); ++iter)
|
||||
|
|
@ -71,6 +72,7 @@ S32 LLImageDecodeThread::update(F32 max_time_ms)
|
|||
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
|
||||
U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
handle_t handle = generateHandle();
|
||||
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
|
||||
|
|
@ -118,6 +120,7 @@ LLImageDecodeThread::ImageRequest::~ImageRequest()
|
|||
// Returns true when done, whether or not decode was successful.
|
||||
bool LLImageDecodeThread::ImageRequest::processRequest()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
const F32 decode_time_slice = .1f;
|
||||
bool done = true;
|
||||
if (!mDecodedRaw && mFormattedImage.notNull())
|
||||
|
|
@ -164,6 +167,7 @@ bool LLImageDecodeThread::ImageRequest::processRequest()
|
|||
|
||||
void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (mResponder.notNull())
|
||||
{
|
||||
bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux);
|
||||
|
|
|
|||
|
|
@ -52,24 +52,28 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
if (src_len > dst_len) return 0;
|
||||
|
||||
// OpenSSL uses "cipher contexts" to hold encryption parameters.
|
||||
EVP_CIPHER_CTX context;
|
||||
EVP_CIPHER_CTX_init(&context);
|
||||
EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new();
|
||||
if (!context)
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::encrypt EVP_CIPHER_CTX initiation failure" << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We want a blowfish cyclic block chain cipher, but need to set
|
||||
// the key length before we pass in a key, so call EncryptInit
|
||||
// first with NULLs.
|
||||
EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
|
||||
EVP_EncryptInit_ex(context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize);
|
||||
|
||||
// Complete initialization. Per EVP_EncryptInit man page, the
|
||||
// cipher pointer must be NULL. Apparently initial_vector must
|
||||
// be 8 bytes for blowfish, as this is the block size.
|
||||
unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
|
||||
EVP_EncryptInit_ex(context, NULL, NULL, mSecret, initial_vector);
|
||||
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(&context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(&context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(&context);
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(context);
|
||||
LL_DEBUGS() << "LLBlowfishCipher blocksize " << blocksize
|
||||
<< " keylen " << keylen
|
||||
<< " iv_len " << iv_length
|
||||
|
|
@ -77,7 +81,7 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
|
||||
int output_len = 0;
|
||||
int temp_len = 0;
|
||||
if (!EVP_EncryptUpdate(&context,
|
||||
if (!EVP_EncryptUpdate(context,
|
||||
dst,
|
||||
&output_len,
|
||||
src,
|
||||
|
|
@ -89,18 +93,18 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
|
||||
// There may be some final data left to encrypt if the input is
|
||||
// not an exact multiple of the block size.
|
||||
if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
|
||||
if (!EVP_EncryptFinal_ex(context, (unsigned char*)(dst + output_len), &temp_len))
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << LL_ENDL;
|
||||
goto ERROR;
|
||||
}
|
||||
output_len += temp_len;
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&context);
|
||||
EVP_CIPHER_CTX_free(context);
|
||||
return output_len;
|
||||
|
||||
ERROR:
|
||||
EVP_CIPHER_CTX_cleanup(&context);
|
||||
EVP_CIPHER_CTX_free(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,10 @@ class domMesh;
|
|||
|
||||
#define MAX_MODEL_FACES 8
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLMeshSkinInfo
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
LLMeshSkinInfo();
|
||||
LLMeshSkinInfo(LLSD& data);
|
||||
|
|
@ -55,15 +57,17 @@ public:
|
|||
matrix_list_t mInvBindMatrix;
|
||||
matrix_list_t mAlternateBindMatrix;
|
||||
|
||||
LLMatrix4a mBindShapeMatrix;
|
||||
LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
|
||||
float mPelvisOffset;
|
||||
bool mLockScaleIfJointPosition;
|
||||
bool mInvalidJointsScrubbed;
|
||||
bool mJointNumsInitialized;
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLModel : public LLVolume
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
|
||||
enum
|
||||
|
|
@ -285,7 +289,7 @@ public:
|
|||
EModelStatus mStatus ;
|
||||
|
||||
int mSubmodelID;
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
typedef std::vector<LLPointer<LLModel> > model_list;
|
||||
typedef std::queue<LLPointer<LLModel> > model_queue;
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages
|
|||
|
||||
void LLCubeMap::initGLData()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);
|
||||
|
|
@ -453,6 +454,7 @@ BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
|
|||
|
||||
void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
F32 v_min, v_max, h_min, h_max;
|
||||
LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
|
||||
center.normVec();
|
||||
|
|
|
|||
|
|
@ -460,6 +460,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
|
|||
|
||||
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (mFTFace == NULL)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -547,9 +547,19 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
|
|||
return cur_x / sScaleX;
|
||||
}
|
||||
|
||||
void LLFontGL::generateASCIIglyphs()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED
|
||||
for (U32 i = 32; (i < 127); i++)
|
||||
{
|
||||
mFontFreetype->getGlyphInfo(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
|
||||
S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, EWordWrapStyle end_on_word_boundary) const
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED
|
||||
if (!wchars || !wchars[0] || max_chars == 0)
|
||||
{
|
||||
return 0;
|
||||
|
|
@ -829,6 +839,8 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
|
|||
{
|
||||
sFontRegistry->reset();
|
||||
}
|
||||
|
||||
LLFontGL::loadDefaultFonts();
|
||||
}
|
||||
|
||||
// Force standard fonts to get generated up front.
|
||||
|
|
@ -838,6 +850,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
|
|||
// static
|
||||
bool LLFontGL::loadDefaultFonts()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED
|
||||
bool succ = true;
|
||||
succ &= (NULL != getFontSansSerifSmall());
|
||||
succ &= (NULL != getFontSansSerif());
|
||||
|
|
@ -845,10 +858,18 @@ bool LLFontGL::loadDefaultFonts()
|
|||
succ &= (NULL != getFontSansSerifHuge());
|
||||
succ &= (NULL != getFontSansSerifBold());
|
||||
succ &= (NULL != getFontMonospace());
|
||||
succ &= (NULL != getFontExtChar());
|
||||
return succ;
|
||||
}
|
||||
|
||||
void LLFontGL::loadCommonFonts()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED
|
||||
getFont(LLFontDescriptor("SansSerif", "Small", BOLD));
|
||||
getFont(LLFontDescriptor("SansSerif", "Large", BOLD));
|
||||
getFont(LLFontDescriptor("SansSerif", "Huge", BOLD));
|
||||
getFont(LLFontDescriptor("Monospace", "Medium", 0));
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFontGL::destroyDefaultFonts()
|
||||
{
|
||||
|
|
@ -1015,7 +1036,7 @@ LLFontGL* LLFontGL::getFontSansSerifBig()
|
|||
//static
|
||||
LLFontGL* LLFontGL::getFontSansSerifHuge()
|
||||
{
|
||||
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
|
||||
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Huge",0));
|
||||
return fontp;
|
||||
}
|
||||
|
||||
|
|
@ -1026,12 +1047,6 @@ LLFontGL* LLFontGL::getFontSansSerifBold()
|
|||
return fontp;
|
||||
}
|
||||
|
||||
//static
|
||||
LLFontGL* LLFontGL::getFontExtChar()
|
||||
{
|
||||
return getFontSansSerif();
|
||||
}
|
||||
|
||||
//static
|
||||
LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -160,12 +160,15 @@ public:
|
|||
|
||||
const LLFontDescriptor& getFontDesc() const;
|
||||
|
||||
void generateASCIIglyphs();
|
||||
|
||||
|
||||
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true);
|
||||
|
||||
// Load sans-serif, sans-serif-small, etc.
|
||||
// Slow, requires multiple seconds to load fonts.
|
||||
static bool loadDefaultFonts();
|
||||
static void loadCommonFonts();
|
||||
static void destroyDefaultFonts();
|
||||
static void destroyAllGL();
|
||||
|
||||
|
|
@ -190,7 +193,6 @@ public:
|
|||
static LLFontGL* getFontSansSerifBig();
|
||||
static LLFontGL* getFontSansSerifHuge();
|
||||
static LLFontGL* getFontSansSerifBold();
|
||||
static LLFontGL* getFontExtChar();
|
||||
static LLFontGL* getFont(const LLFontDescriptor& desc);
|
||||
// Use with legacy names like "SANSSERIF_SMALL" or "OCRA"
|
||||
static LLFontGL* getFontByName(const std::string& name);
|
||||
|
|
|
|||
|
|
@ -597,6 +597,11 @@ LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc)
|
|||
<<" style=[" << ((S32) desc.getStyle()) << "]"
|
||||
<< " size=[" << desc.getSize() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//generate glyphs for ASCII chars to avoid stalls later
|
||||
fontp->generateASCIIglyphs();
|
||||
}
|
||||
return fontp;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,9 +434,6 @@ LLGLManager::LLGLManager() :
|
|||
mHasMapBufferRange(FALSE),
|
||||
mHasFlushBufferRange(FALSE),
|
||||
mHasPBuffer(FALSE),
|
||||
mHasShaderObjects(FALSE),
|
||||
mHasVertexShader(FALSE),
|
||||
mHasFragmentShader(FALSE),
|
||||
mNumTextureImageUnits(0),
|
||||
mHasOcclusionQuery(FALSE),
|
||||
mHasTimerQuery(FALSE),
|
||||
|
|
@ -775,14 +772,9 @@ bool LLGLManager::initGL()
|
|||
|
||||
stop_glerror();
|
||||
|
||||
stop_glerror();
|
||||
|
||||
if (mHasFragmentShader)
|
||||
{
|
||||
GLint num_tex_image_units;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
|
||||
mNumTextureImageUnits = llmin(num_tex_image_units, 32);
|
||||
}
|
||||
GLint num_tex_image_units;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
|
||||
mNumTextureImageUnits = llmin(num_tex_image_units, 32);
|
||||
|
||||
if (LLRender::sGLCoreProfile)
|
||||
{
|
||||
|
|
@ -975,9 +967,9 @@ void LLGLManager::asLLSD(LLSD& info)
|
|||
info["has_map_buffer_range"] = mHasMapBufferRange;
|
||||
info["has_flush_buffer_range"] = mHasFlushBufferRange;
|
||||
info["has_pbuffer"] = mHasPBuffer;
|
||||
info["has_shader_objects"] = mHasShaderObjects;
|
||||
info["has_vertex_shader"] = mHasVertexShader;
|
||||
info["has_fragment_shader"] = mHasFragmentShader;
|
||||
info["has_shader_objects"] = std::string("Assumed TRUE"); // was mHasShaderObjects;
|
||||
info["has_vertex_shader"] = std::string("Assumed TRUE"); // was mHasVertexShader;
|
||||
info["has_fragment_shader"] = std::string("Assumed TRUE"); // was mHasFragmentShader;
|
||||
info["num_texture_image_units"] = mNumTextureImageUnits;
|
||||
info["has_occlusion_query"] = mHasOcclusionQuery;
|
||||
info["has_timer_query"] = mHasTimerQuery;
|
||||
|
|
@ -1083,9 +1075,6 @@ void LLGLManager::initExtensions()
|
|||
mHasCubeMap = FALSE;
|
||||
mHasOcclusionQuery = FALSE;
|
||||
mHasPointParameters = FALSE;
|
||||
mHasShaderObjects = FALSE;
|
||||
mHasVertexShader = FALSE;
|
||||
mHasFragmentShader = FALSE;
|
||||
mHasTextureRectangle = FALSE;
|
||||
#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
|
||||
mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
|
||||
|
|
@ -1143,10 +1132,6 @@ void LLGLManager::initExtensions()
|
|||
#if !LL_DARWIN
|
||||
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
|
||||
#endif
|
||||
mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
|
||||
mHasVertexShader = ExtensionExists("GL_ARB_vertex_program", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_vertex_shader", gGLHExts.mSysExts)
|
||||
&& (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
|
||||
mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
|
||||
#endif
|
||||
|
||||
#if LL_LINUX
|
||||
|
|
@ -1169,9 +1154,6 @@ void LLGLManager::initExtensions()
|
|||
mHasCubeMap = FALSE;
|
||||
mHasOcclusionQuery = FALSE;
|
||||
mHasPointParameters = FALSE;
|
||||
mHasShaderObjects = FALSE;
|
||||
mHasVertexShader = FALSE;
|
||||
mHasFragmentShader = FALSE;
|
||||
LL_WARNS("RenderInit") << "GL extension support DISABLED via LL_GL_NOEXT" << LL_ENDL;
|
||||
}
|
||||
else if (getenv("LL_GL_BASICEXT")) /* Flawfinder: ignore */
|
||||
|
|
@ -1184,9 +1166,6 @@ void LLGLManager::initExtensions()
|
|||
mHasAnisotropic = FALSE;
|
||||
//mHasCubeMap = FALSE; // apparently fatal on Intel 915 & similar
|
||||
//mHasOcclusionQuery = FALSE; // source of many ATI system hangs
|
||||
mHasShaderObjects = FALSE;
|
||||
mHasVertexShader = FALSE;
|
||||
mHasFragmentShader = FALSE;
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;
|
||||
}
|
||||
|
|
@ -1208,9 +1187,6 @@ void LLGLManager::initExtensions()
|
|||
if (strchr(blacklist,'j')) mHasCubeMap = FALSE;//S
|
||||
// if (strchr(blacklist,'k')) mHasATIVAO = FALSE;//S
|
||||
if (strchr(blacklist,'l')) mHasOcclusionQuery = FALSE;
|
||||
if (strchr(blacklist,'m')) mHasShaderObjects = FALSE;//S
|
||||
if (strchr(blacklist,'n')) mHasVertexShader = FALSE;//S
|
||||
if (strchr(blacklist,'o')) mHasFragmentShader = FALSE;//S
|
||||
if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S
|
||||
if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S
|
||||
if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
|
||||
|
|
@ -1257,18 +1233,6 @@ void LLGLManager::initExtensions()
|
|||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL;
|
||||
}
|
||||
if (!mHasShaderObjects)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_shader_objects" << LL_ENDL;
|
||||
}
|
||||
if (!mHasVertexShader)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_vertex_shader" << LL_ENDL;
|
||||
}
|
||||
if (!mHasFragmentShader)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL;
|
||||
}
|
||||
if (!mHasBlendFuncSeparate)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL;
|
||||
|
|
@ -1436,134 +1400,132 @@ void LLGLManager::initExtensions()
|
|||
glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB");
|
||||
glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB");
|
||||
}
|
||||
if (mHasShaderObjects)
|
||||
{
|
||||
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
|
||||
glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
|
||||
glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB");
|
||||
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB");
|
||||
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB");
|
||||
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB");
|
||||
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB");
|
||||
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB");
|
||||
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB");
|
||||
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB");
|
||||
glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB");
|
||||
glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB");
|
||||
glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB");
|
||||
glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB");
|
||||
glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB");
|
||||
glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB");
|
||||
glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB");
|
||||
glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB");
|
||||
glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB");
|
||||
glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB");
|
||||
glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB");
|
||||
glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB");
|
||||
glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB");
|
||||
glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB");
|
||||
glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB");
|
||||
glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB");
|
||||
glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB");
|
||||
glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB");
|
||||
glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB");
|
||||
glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv");
|
||||
glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB");
|
||||
glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB");
|
||||
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB");
|
||||
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB");
|
||||
glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB");
|
||||
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB");
|
||||
glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB");
|
||||
glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB");
|
||||
glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB");
|
||||
glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB");
|
||||
}
|
||||
if (mHasVertexShader)
|
||||
{
|
||||
LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL;
|
||||
|
||||
// nSight doesn't support use of ARB funcs that have been normalized in the API
|
||||
if (!LLRender::sNsightDebugSupport)
|
||||
{
|
||||
glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB");
|
||||
glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB");
|
||||
}
|
||||
else
|
||||
{
|
||||
glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation");
|
||||
glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation");
|
||||
}
|
||||
// Assume shader capabilities
|
||||
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
|
||||
glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
|
||||
glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB");
|
||||
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB");
|
||||
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB");
|
||||
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB");
|
||||
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB");
|
||||
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB");
|
||||
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB");
|
||||
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB");
|
||||
glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB");
|
||||
glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB");
|
||||
glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB");
|
||||
glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB");
|
||||
glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB");
|
||||
glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB");
|
||||
glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB");
|
||||
glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB");
|
||||
glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB");
|
||||
glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB");
|
||||
glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB");
|
||||
glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB");
|
||||
glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB");
|
||||
glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB");
|
||||
glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB");
|
||||
glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB");
|
||||
glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB");
|
||||
glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB");
|
||||
glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB");
|
||||
glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv");
|
||||
glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB");
|
||||
glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB");
|
||||
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB");
|
||||
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB");
|
||||
glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB");
|
||||
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB");
|
||||
glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB");
|
||||
glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB");
|
||||
glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB");
|
||||
glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB");
|
||||
|
||||
glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB");
|
||||
glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB");
|
||||
glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB");
|
||||
glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB");
|
||||
glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB");
|
||||
glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB");
|
||||
glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB");
|
||||
glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB");
|
||||
glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB");
|
||||
glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB");
|
||||
glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB");
|
||||
glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB");
|
||||
glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB");
|
||||
glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB");
|
||||
glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB");
|
||||
glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB");
|
||||
glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB");
|
||||
glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB");
|
||||
glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB");
|
||||
glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB");
|
||||
glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB");
|
||||
glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB");
|
||||
glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB");
|
||||
glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB");
|
||||
glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB");
|
||||
glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB");
|
||||
glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB");
|
||||
glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB");
|
||||
glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB");
|
||||
glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB");
|
||||
glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB");
|
||||
glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB");
|
||||
glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB");
|
||||
glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB");
|
||||
glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB");
|
||||
glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
|
||||
glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
|
||||
glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
|
||||
glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
|
||||
glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
|
||||
glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
|
||||
glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
|
||||
glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB");
|
||||
glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB");
|
||||
glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB");
|
||||
glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB");
|
||||
glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB");
|
||||
glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB");
|
||||
glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB");
|
||||
glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB");
|
||||
glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB");
|
||||
glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB");
|
||||
glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB");
|
||||
glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB");
|
||||
glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB");
|
||||
glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB");
|
||||
glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB");
|
||||
glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB");
|
||||
glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB");
|
||||
glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB");
|
||||
glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB");
|
||||
glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB");
|
||||
glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB");
|
||||
glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB");
|
||||
}
|
||||
LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL;
|
||||
LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL;
|
||||
|
||||
// nSight doesn't support use of ARB funcs that have been normalized in the API
|
||||
if (!LLRender::sNsightDebugSupport)
|
||||
{
|
||||
glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB");
|
||||
glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB");
|
||||
}
|
||||
else
|
||||
{
|
||||
glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation");
|
||||
glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation");
|
||||
}
|
||||
|
||||
glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB");
|
||||
glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB");
|
||||
glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB");
|
||||
glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB");
|
||||
glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB");
|
||||
glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB");
|
||||
glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB");
|
||||
glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB");
|
||||
glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB");
|
||||
glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB");
|
||||
glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB");
|
||||
glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB");
|
||||
glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB");
|
||||
glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB");
|
||||
glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB");
|
||||
glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB");
|
||||
glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB");
|
||||
glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB");
|
||||
glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB");
|
||||
glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB");
|
||||
glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB");
|
||||
glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB");
|
||||
glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB");
|
||||
glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB");
|
||||
glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB");
|
||||
glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB");
|
||||
glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB");
|
||||
glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB");
|
||||
glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB");
|
||||
glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB");
|
||||
glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB");
|
||||
glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB");
|
||||
glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB");
|
||||
glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB");
|
||||
glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB");
|
||||
glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
|
||||
glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
|
||||
glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
|
||||
glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
|
||||
glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
|
||||
glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
|
||||
glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
|
||||
glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB");
|
||||
glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB");
|
||||
glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB");
|
||||
glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB");
|
||||
glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB");
|
||||
glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB");
|
||||
glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB");
|
||||
glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB");
|
||||
glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB");
|
||||
glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB");
|
||||
glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB");
|
||||
glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB");
|
||||
glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB");
|
||||
glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB");
|
||||
glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB");
|
||||
glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB");
|
||||
glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB");
|
||||
glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB");
|
||||
glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB");
|
||||
glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB");
|
||||
glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB");
|
||||
glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB");
|
||||
|
||||
LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL;
|
||||
#endif
|
||||
|
||||
mInited = TRUE;
|
||||
mInited = TRUE;
|
||||
}
|
||||
|
||||
void rotate_quat(LLQuaternion& rotation)
|
||||
|
|
@ -2116,7 +2078,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
|
|||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
gGL.getTexUnit(0)->activate();
|
||||
|
||||
if (gGLManager.mHasVertexShader && LLGLSLShader::sNoFixedFunction)
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{ //make sure vertex attribs are all disabled
|
||||
GLint count;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &count);
|
||||
|
|
|
|||
|
|
@ -94,9 +94,6 @@ public:
|
|||
BOOL mHasMapBufferRange;
|
||||
BOOL mHasFlushBufferRange;
|
||||
BOOL mHasPBuffer;
|
||||
BOOL mHasShaderObjects;
|
||||
BOOL mHasVertexShader;
|
||||
BOOL mHasFragmentShader;
|
||||
S32 mNumTextureImageUnits;
|
||||
BOOL mHasOcclusionQuery;
|
||||
BOOL mHasTimerQuery;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,6 @@ struct LLGLSLShaderCompareTimeElapsed
|
|||
//static
|
||||
void LLGLSLShader::finishProfile(bool emit_report)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED
|
||||
sProfileEnabled = false;
|
||||
|
||||
if (emit_report)
|
||||
|
|
@ -209,6 +208,7 @@ void LLGLSLShader::dumpStats()
|
|||
//static
|
||||
void LLGLSLShader::startProfile()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (sProfileEnabled && sCurBoundShaderPtr)
|
||||
{
|
||||
sCurBoundShaderPtr->placeProfileQuery();
|
||||
|
|
@ -219,6 +219,7 @@ void LLGLSLShader::startProfile()
|
|||
//static
|
||||
void LLGLSLShader::stopProfile(U32 count, U32 mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (sProfileEnabled && sCurBoundShaderPtr)
|
||||
{
|
||||
sCurBoundShaderPtr->readProfileQuery(count, mode);
|
||||
|
|
@ -385,6 +386,8 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
|
|||
U32 varying_count,
|
||||
const char** varyings)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
unloadInternal();
|
||||
|
||||
sInstances.insert(this);
|
||||
|
|
@ -589,6 +592,8 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
|
|||
|
||||
BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
//before linking, make sure reserved attributes always have consistent locations
|
||||
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
|
||||
{
|
||||
|
|
@ -650,6 +655,8 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
|
|||
|
||||
void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
return;
|
||||
|
|
@ -771,6 +778,8 @@ void LLGLSLShader::removePermutation(std::string name)
|
|||
|
||||
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
|
||||
type == GL_SAMPLER_2D_MULTISAMPLE)
|
||||
{ //this here is a texture
|
||||
|
|
@ -783,7 +792,9 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
|
|||
|
||||
BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
|
||||
{
|
||||
BOOL res = TRUE;
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
BOOL res = TRUE;
|
||||
|
||||
mTotalUniformSize = 0;
|
||||
mActiveTextureChannels = 0;
|
||||
|
|
@ -926,6 +937,8 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
|
|||
|
||||
BOOL LLGLSLShader::link(BOOL suppress_errors)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors);
|
||||
|
||||
if (!success && !suppress_errors)
|
||||
|
|
@ -938,56 +951,52 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)
|
|||
|
||||
void LLGLSLShader::bind()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
gGL.flush();
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
|
||||
if (sCurBoundShader != mProgramObject) // Don't re-bind current shader
|
||||
{
|
||||
LLVertexBuffer::unbind();
|
||||
glUseProgramObjectARB(mProgramObject);
|
||||
sCurBoundShader = mProgramObject;
|
||||
sCurBoundShaderPtr = this;
|
||||
if (mUniformsDirty)
|
||||
{
|
||||
LLShaderMgr::instance()->updateShaderUniforms(this);
|
||||
mUniformsDirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mUniformsDirty)
|
||||
{
|
||||
LLShaderMgr::instance()->updateShaderUniforms(this);
|
||||
mUniformsDirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::unbind()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
gGL.flush();
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
stop_glerror();
|
||||
if (gGLManager.mIsNVIDIA)
|
||||
{
|
||||
for (U32 i = 0; i < mAttribute.size(); ++i)
|
||||
{
|
||||
vertexAttrib4f(i, 0,0,0,1);
|
||||
stop_glerror();
|
||||
}
|
||||
}
|
||||
LLVertexBuffer::unbind();
|
||||
glUseProgramObjectARB(0);
|
||||
sCurBoundShader = 0;
|
||||
sCurBoundShaderPtr = NULL;
|
||||
stop_glerror();
|
||||
}
|
||||
stop_glerror();
|
||||
LLVertexBuffer::unbind();
|
||||
glUseProgramObjectARB(0);
|
||||
sCurBoundShader = 0;
|
||||
sCurBoundShaderPtr = NULL;
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
void LLGLSLShader::bindNoShader(void)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
LLVertexBuffer::unbind();
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
glUseProgramObjectARB(0);
|
||||
sCurBoundShader = 0;
|
||||
sCurBoundShaderPtr = NULL;
|
||||
}
|
||||
glUseProgramObjectARB(0);
|
||||
sCurBoundShader = 0;
|
||||
sCurBoundShaderPtr = NULL;
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
S32 channel = 0;
|
||||
channel = getUniformLocation(uniform);
|
||||
|
||||
|
|
@ -996,6 +1005,8 @@ S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LL
|
|||
|
||||
S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
|
|
@ -1006,7 +1017,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
|
|||
|
||||
if (uniform > -1)
|
||||
{
|
||||
gGL.getTexUnit(uniform)->bind(texture, mode);
|
||||
gGL.getTexUnit(uniform)->bindFast(texture);
|
||||
gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
|
||||
}
|
||||
|
||||
|
|
@ -1015,6 +1026,8 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
|
|||
|
||||
S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
S32 channel = 0;
|
||||
channel = getUniformLocation(uniform);
|
||||
|
||||
|
|
@ -1023,6 +1036,8 @@ S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureT
|
|||
|
||||
S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
|
|
@ -1033,7 +1048,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
|||
|
||||
if (uniform > -1)
|
||||
{
|
||||
gGL.getTexUnit(uniform)->unbind(mode);
|
||||
gGL.getTexUnit(uniform)->unbindFast(mode);
|
||||
}
|
||||
|
||||
return uniform;
|
||||
|
|
@ -1041,6 +1056,8 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
|||
|
||||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
|
|
@ -1058,6 +1075,8 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTex
|
|||
|
||||
S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
|
|
@ -1348,6 +1367,7 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c
|
|||
void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (mProgramObject)
|
||||
{
|
||||
if (mUniform.size() <= index)
|
||||
|
|
@ -1382,6 +1402,8 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
|
|||
|
||||
GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
GLint ret = -1;
|
||||
if (mProgramObject)
|
||||
{
|
||||
|
|
@ -1406,6 +1428,8 @@ GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
|
|||
|
||||
GLint LLGLSLShader::getUniformLocation(U32 index)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
GLint ret = -1;
|
||||
if (mProgramObject)
|
||||
{
|
||||
|
|
@ -1418,6 +1442,8 @@ GLint LLGLSLShader::getUniformLocation(U32 index)
|
|||
|
||||
GLint LLGLSLShader::getAttribLocation(U32 attrib)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (attrib < mAttribute.size())
|
||||
{
|
||||
return mAttribute[attrib];
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ LLTexUnit::eTextureType LLGLTexture::getTarget(void) const
|
|||
|
||||
BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
llassert(mGLTexturep.notNull()) ;
|
||||
|
||||
return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ;
|
||||
|
|
@ -269,6 +270,7 @@ BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos,
|
|||
|
||||
BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
llassert(mGLTexturep.notNull()) ;
|
||||
|
||||
return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ;
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ private:
|
|||
protected:
|
||||
void setTexelsPerImage();
|
||||
|
||||
//note: do not make this function public.
|
||||
public:
|
||||
/*virtual*/ LLImageGL* getGLTexture() const ;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "llgl.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llrender.h"
|
||||
#include "llwindow.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const F32 MIN_TEXTURE_LIFETIME = 10.f;
|
||||
|
|
@ -170,15 +171,32 @@ BOOL is_little_endian()
|
|||
|
||||
return (*c == 0x78) ;
|
||||
}
|
||||
|
||||
LLImageGLThread* LLImageGLThread::sInstance = nullptr;
|
||||
|
||||
//static
|
||||
void LLImageGL::initClass(S32 num_catagories, BOOL skip_analyze_alpha /* = false */)
|
||||
void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
sSkipAnalyzeAlpha = skip_analyze_alpha;
|
||||
LLImageGLThread::sInstance = new LLImageGLThread(window);
|
||||
LLImageGLThread::sInstance->start();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImageGL::updateClass()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLImageGLThread::sInstance->executeCallbacks();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImageGL::cleanupClass()
|
||||
{
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLImageGLThread::sInstance->mFunctionQueue.close();
|
||||
delete LLImageGLThread::sInstance;
|
||||
LLImageGLThread::sInstance = nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -656,6 +674,7 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for
|
|||
|
||||
void LLImageGL::setImage(const LLImageRaw* imageraw)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
llassert((imageraw->getWidth() == getWidth(mCurrentDiscardLevel)) &&
|
||||
(imageraw->getHeight() == getHeight(mCurrentDiscardLevel)) &&
|
||||
(imageraw->getComponents() == getComponents()));
|
||||
|
|
@ -699,9 +718,8 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
|||
}
|
||||
|
||||
llverify(gGL.getTexUnit(0)->bind(this));
|
||||
|
||||
|
||||
if (mUseMipMaps)
|
||||
|
||||
if (mUseMipMaps)
|
||||
{
|
||||
if (data_hasmips)
|
||||
{
|
||||
|
|
@ -781,7 +799,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
|||
glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
}
|
||||
|
||||
LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
|
||||
LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
|
||||
w, h,
|
||||
mFormatPrimary, mFormatType,
|
||||
data_in, mAllowCompression);
|
||||
|
|
@ -878,7 +896,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
|||
stop_glerror();
|
||||
}
|
||||
|
||||
LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression);
|
||||
LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression);
|
||||
if (m == 0)
|
||||
{
|
||||
analyzeAlpha(data_in, w, h);
|
||||
|
|
@ -1067,6 +1085,7 @@ void LLImageGL::postAddToAtlas()
|
|||
|
||||
BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (!width || !height)
|
||||
{
|
||||
return TRUE;
|
||||
|
|
@ -1163,6 +1182,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
|
|||
|
||||
BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update);
|
||||
}
|
||||
|
||||
|
|
@ -1201,119 +1221,119 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
|
|||
|
||||
// static
|
||||
static LLTrace::BlockTimerStatHandle FTM_SET_MANUAL_IMAGE("setManualImage");
|
||||
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression)
|
||||
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_SET_MANUAL_IMAGE);
|
||||
bool use_scratch = false;
|
||||
U32* scratch = NULL;
|
||||
if (LLRender::sGLCoreProfile)
|
||||
{
|
||||
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_ALPHA is deprecated, convert to RGBA
|
||||
use_scratch = true;
|
||||
scratch = new U32[width*height];
|
||||
LL_RECORD_BLOCK_TIME(FTM_SET_MANUAL_IMAGE);
|
||||
bool use_scratch = false;
|
||||
U32* scratch = NULL;
|
||||
if (LLRender::sGLCoreProfile)
|
||||
{
|
||||
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_ALPHA is deprecated, convert to RGBA
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U32 pixel_count = (U32) (width*height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8* pix = (U8*) &scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = 0;
|
||||
pix[3] = ((U8*) pixels)[i];
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = 0;
|
||||
pix[3] = ((U8*)pixels)[i];
|
||||
}
|
||||
|
||||
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
|
||||
use_scratch = true;
|
||||
scratch = new U32[width*height];
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
|
||||
U32 pixel_count = (U32) (width*height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*) pixels)[i*2+0];
|
||||
U8 alpha = ((U8*) pixels)[i*2+1];
|
||||
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
U8* pix = (U8*) &scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = alpha;
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i * 2 + 0];
|
||||
U8 alpha = ((U8*)pixels)[i * 2 + 1];
|
||||
|
||||
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
|
||||
use_scratch = true;
|
||||
scratch = new U32[width*height];
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = alpha;
|
||||
}
|
||||
|
||||
U32 pixel_count = (U32) (width*height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*) pixels)[i];
|
||||
|
||||
U8* pix = (U8*) &scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = 255;
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGB8;
|
||||
}
|
||||
}
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
|
||||
if (LLImageGL::sCompressTextures && allow_compression)
|
||||
{
|
||||
switch (intformat)
|
||||
{
|
||||
case GL_RGB:
|
||||
case GL_RGB8:
|
||||
intformat = GL_COMPRESSED_RGB;
|
||||
break;
|
||||
case GL_SRGB:
|
||||
case GL_SRGB8:
|
||||
intformat = GL_COMPRESSED_SRGB;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
case GL_RGBA8:
|
||||
intformat = GL_COMPRESSED_RGBA;
|
||||
break;
|
||||
case GL_SRGB_ALPHA:
|
||||
case GL_SRGB8_ALPHA8:
|
||||
intformat = GL_COMPRESSED_SRGB_ALPHA;
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
case GL_LUMINANCE8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_LUMINANCE8_ALPHA8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
case GL_ALPHA8:
|
||||
intformat = GL_COMPRESSED_ALPHA;
|
||||
break;
|
||||
default:
|
||||
LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
|
||||
use_scratch = true;
|
||||
scratch = new U32[width * height];
|
||||
|
||||
stop_glerror();
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("glTexImage2D");
|
||||
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
|
||||
}
|
||||
stop_glerror();
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i];
|
||||
|
||||
if (use_scratch)
|
||||
{
|
||||
delete [] scratch;
|
||||
}
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = 255;
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGB8;
|
||||
}
|
||||
}
|
||||
|
||||
if (LLImageGL::sCompressTextures && allow_compression)
|
||||
{
|
||||
switch (intformat)
|
||||
{
|
||||
case GL_RGB:
|
||||
case GL_RGB8:
|
||||
intformat = GL_COMPRESSED_RGB;
|
||||
break;
|
||||
case GL_SRGB:
|
||||
case GL_SRGB8:
|
||||
intformat = GL_COMPRESSED_SRGB;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
case GL_RGBA8:
|
||||
intformat = GL_COMPRESSED_RGBA;
|
||||
break;
|
||||
case GL_SRGB_ALPHA:
|
||||
case GL_SRGB8_ALPHA8:
|
||||
intformat = GL_COMPRESSED_SRGB_ALPHA;
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
case GL_LUMINANCE8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_LUMINANCE8_ALPHA8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
case GL_ALPHA8:
|
||||
intformat = GL_COMPRESSED_ALPHA;
|
||||
break;
|
||||
default:
|
||||
LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("glTexImage2D");
|
||||
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
|
||||
}
|
||||
stop_glerror();
|
||||
|
||||
if (use_scratch)
|
||||
{
|
||||
delete[] scratch;
|
||||
}
|
||||
}
|
||||
|
||||
//create an empty GL texture: just create a texture name
|
||||
|
|
@ -1336,6 +1356,7 @@ BOOL LLImageGL::createGLTexture()
|
|||
if(mTexName)
|
||||
{
|
||||
LLImageGL::deleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
|
||||
mTexName = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1697,7 +1718,7 @@ void LLImageGL::destroyGLTexture()
|
|||
mTextureMemory = (S32Bytes)0;
|
||||
}
|
||||
|
||||
LLImageGL::deleteTextures(1, &mTexName);
|
||||
LLImageGL::deleteTextures(1, &mTexName);
|
||||
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
|
||||
mTexName = 0;
|
||||
mGLTextureCreated = FALSE ;
|
||||
|
|
@ -2238,3 +2259,90 @@ void LLImageGL::resetCurTexSizebar()
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips);
|
||||
*/
|
||||
|
||||
LLImageGLThread::LLImageGLThread(LLWindow* window)
|
||||
: LLThread("LLImageGL"), mWindow(window)
|
||||
{
|
||||
mFinished = false;
|
||||
|
||||
mContext = mWindow->createSharedContext();
|
||||
}
|
||||
|
||||
// post a function to be executed on the LLImageGL background thread
|
||||
|
||||
bool LLImageGLThread::post(const std::function<void()>& func)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mFunctionQueue.size() < mFunctionQueue.capacity())
|
||||
{
|
||||
//NOTE: tryPushFront will return immediately if the lock is held
|
||||
// desired behavior here is to push and return true unless the
|
||||
// queue is full or closed
|
||||
mFunctionQueue.pushFront(func);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (LLThreadSafeQueueInterrupt e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//post a callback to be executed on the main thread
|
||||
|
||||
bool LLImageGLThread::postCallback(const std::function<void()>& callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
mCallbackQueue.pushFront(callback);
|
||||
}
|
||||
catch (LLThreadSafeQueueInterrupt e)
|
||||
{
|
||||
//thread is closing, drop request
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLImageGLThread::executeCallbacks()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
//executed from main thread
|
||||
std::function<void()> callback;
|
||||
while (mCallbackQueue.tryPopBack(callback))
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("iglt - callback");
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageGLThread::run()
|
||||
{
|
||||
mWindow->makeContextCurrent(mContext);
|
||||
gGL.init();
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
std::function<void()> curFunc = mFunctionQueue.popBack();
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("iglt - function")
|
||||
curFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (LLThreadSafeQueueInterrupt e)
|
||||
{
|
||||
//queue is closed, fall out of run loop
|
||||
}
|
||||
gGL.shutdown();
|
||||
mWindow->destroySharedContext(mContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,11 @@
|
|||
#include "llrefcount.h"
|
||||
#include "v2math.h"
|
||||
#include "llunits.h"
|
||||
|
||||
#include "llthreadsafequeue.h"
|
||||
#include "llrender.h"
|
||||
class LLTextureAtlas ;
|
||||
class LLWindow;
|
||||
|
||||
#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20)
|
||||
#define MEGA_BYTES_TO_BYTES(x) ((x) << 20)
|
||||
|
||||
|
|
@ -102,7 +104,7 @@ public:
|
|||
void setAllowCompression(bool allow) { mAllowCompression = allow; }
|
||||
|
||||
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
|
||||
|
||||
|
||||
BOOL createGLTexture() ;
|
||||
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
|
||||
S32 category = sMaxCategories-1);
|
||||
|
|
@ -265,7 +267,8 @@ public:
|
|||
#endif
|
||||
|
||||
public:
|
||||
static void initClass(S32 num_catagories, BOOL skip_analyze_alpha = false);
|
||||
static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false);
|
||||
static void updateClass();
|
||||
static void cleanupClass() ;
|
||||
|
||||
private:
|
||||
|
|
@ -301,4 +304,30 @@ public:
|
|||
|
||||
};
|
||||
|
||||
class LLImageGLThread : public LLThread
|
||||
{
|
||||
public:
|
||||
LLImageGLThread(LLWindow* window);
|
||||
|
||||
// post a function to be executed on the LLImageGL background thread
|
||||
bool post(const std::function<void()>& func);
|
||||
|
||||
//post a callback to be executed on the main thread
|
||||
bool postCallback(const std::function<void()>& callback);
|
||||
|
||||
void executeCallbacks();
|
||||
|
||||
void run() override;
|
||||
|
||||
LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
|
||||
LLThreadSafeQueue<std::function<void()>> mCallbackQueue;
|
||||
|
||||
LLWindow* mWindow;
|
||||
void* mContext;
|
||||
LLAtomicBool mFinished;
|
||||
|
||||
static LLImageGLThread* sInstance;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLIMAGEGL_H
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include "lltexture.h"
|
||||
#include "llshadermgr.h"
|
||||
|
||||
LLRender gGL;
|
||||
thread_local LLRender gGL;
|
||||
|
||||
// Handy copies of last good GL matrices
|
||||
F32 gGLModelView[16];
|
||||
|
|
@ -229,8 +229,20 @@ void LLTexUnit::disable(void)
|
|||
}
|
||||
}
|
||||
|
||||
void LLTexUnit::bindFast(LLTexture* texture)
|
||||
{
|
||||
LLImageGL* gl_tex = texture->getGLTexture();
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
|
||||
gGL.mCurrTextureUnitIndex = mIndex;
|
||||
mCurrTexture = gl_tex->getTexName();
|
||||
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
|
||||
mHasMipMaps = gl_tex->mHasMipMaps;
|
||||
}
|
||||
|
||||
bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
stop_glerror();
|
||||
if (mIndex >= 0)
|
||||
{
|
||||
|
|
@ -459,6 +471,28 @@ void LLTexUnit::unbind(eTextureType type)
|
|||
}
|
||||
}
|
||||
|
||||
void LLTexUnit::unbindFast(eTextureType type)
|
||||
{
|
||||
activate();
|
||||
|
||||
// Disabled caching of binding state.
|
||||
if (mCurrTexType == type)
|
||||
{
|
||||
mCurrTexture = 0;
|
||||
|
||||
// Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping".
|
||||
mTexColorSpace = TCS_LINEAR;
|
||||
if (type == LLTexUnit::TT_TEXTURE)
|
||||
{
|
||||
glBindTexture(sGLTextureType[type], sWhiteTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(sGLTextureType[type], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
|
||||
{
|
||||
if (mIndex < 0 || mCurrTexture == 0) return;
|
||||
|
|
@ -1243,8 +1277,6 @@ void LLRender::syncLightState()
|
|||
|
||||
void LLRender::syncMatrices()
|
||||
{
|
||||
stop_glerror();
|
||||
|
||||
static const U32 name[] =
|
||||
{
|
||||
LLShaderMgr::MODELVIEW_MATRIX,
|
||||
|
|
@ -1415,8 +1447,6 @@ void LLRender::syncMatrices()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
|
||||
|
|
@ -1927,6 +1957,7 @@ void LLRender::flush()
|
|||
{
|
||||
if (mCount > 0)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (!mUIOffset.empty())
|
||||
{
|
||||
sUICalls++;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,17 @@ public:
|
|||
bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false);
|
||||
bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
|
||||
|
||||
// bind implementation for inner loops
|
||||
// makes the following assumptions:
|
||||
// - No need for gGL.flush()
|
||||
// - texture is not null
|
||||
// - gl_tex->getTexName() is not zero
|
||||
// - This texture is not being bound redundantly
|
||||
// - USE_SRGB_DECODE is disabled
|
||||
// - mTexOptionsDirty is false
|
||||
// -
|
||||
void bindFast(LLTexture* texture);
|
||||
|
||||
// Binds a cubemap to this texture unit
|
||||
// (automatically enables the texture unit for cubemaps)
|
||||
bool bind(LLCubeMap* cubeMap);
|
||||
|
|
@ -177,6 +188,9 @@ public:
|
|||
// (only if there's a texture of the given type currently bound)
|
||||
void unbind(eTextureType type);
|
||||
|
||||
// Fast but unsafe version of unbind
|
||||
void unbindFast(eTextureType type);
|
||||
|
||||
// Sets the addressing mode used to sample the texture
|
||||
// Warning: this stays set for the bound texture forever,
|
||||
// make sure you want to permanently change the address mode for the bound texture.
|
||||
|
|
@ -511,7 +525,7 @@ extern F32 gGLLastProjection[16];
|
|||
extern F32 gGLProjection[16];
|
||||
extern S32 gGLViewport[4];
|
||||
|
||||
extern LLRender gGL;
|
||||
extern thread_local LLRender gGL;
|
||||
|
||||
// This rotation matrix moves the default OpenGL reference frame
|
||||
// (-Z at, Y up) to Cory's favorite reference frame (X at, Z up)
|
||||
|
|
|
|||
|
|
@ -67,11 +67,9 @@ public:
|
|||
virtual S32 getWidth(S32 discard_level = -1) const;
|
||||
virtual S32 getHeight(S32 discard_level = -1) const;
|
||||
virtual bool isActiveFetching();
|
||||
virtual LLImageGL* getGLTexture() const;
|
||||
|
||||
private:
|
||||
//note: do not make this function public.
|
||||
virtual LLImageGL* getGLTexture() const;
|
||||
|
||||
virtual void updateBindStatsForTester();
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -787,6 +787,18 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
|
|||
placeFence();
|
||||
}
|
||||
|
||||
void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
|
||||
{
|
||||
mMappable = false;
|
||||
gGL.syncMatrices();
|
||||
|
||||
U16* idx = ((U16*)(U8*)mAlignedIndexOffset) + indices_offset;
|
||||
|
||||
LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00)
|
||||
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
|
||||
idx);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
|
||||
{
|
||||
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
|
||||
|
|
@ -2272,6 +2284,21 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool LLVertexBuffer::bindGLBufferFast()
|
||||
{
|
||||
if (mGLBuffer != sGLRenderBuffer || !sVBOActive)
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
sBindCount++;
|
||||
sVBOActive = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_BIND_GL_INDICES("Bind Indices");
|
||||
|
||||
bool LLVertexBuffer::bindGLIndices(bool force_bind)
|
||||
|
|
@ -2297,6 +2324,21 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool LLVertexBuffer::bindGLIndicesFast()
|
||||
{
|
||||
if (mGLIndices != sGLRenderIndices || !sIBOActive)
|
||||
{
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
|
||||
sGLRenderIndices = mGLIndices;
|
||||
sBindCount++;
|
||||
sIBOActive = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLVertexBuffer::flush()
|
||||
{
|
||||
if (useVBOs())
|
||||
|
|
@ -2487,6 +2529,26 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
|
|||
}
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setBufferFast(U32 data_mask)
|
||||
{
|
||||
//set up pointers if the data mask is different ...
|
||||
bool setup = (sLastMask != data_mask);
|
||||
|
||||
|
||||
const bool bindBuffer = bindGLBufferFast();
|
||||
const bool bindIndices = bindGLIndicesFast();
|
||||
|
||||
setup = setup || bindBuffer || bindIndices;
|
||||
|
||||
setupClientArrays(data_mask);
|
||||
|
||||
if (data_mask && setup)
|
||||
{
|
||||
setupVertexBufferFast(data_mask);
|
||||
sSetCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// virtual (default)
|
||||
void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
|
||||
{
|
||||
|
|
@ -2644,6 +2706,99 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
|
|||
llglassertok();
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setupVertexBufferFast(U32 data_mask)
|
||||
{
|
||||
U8* base = (U8*)mAlignedOffset;
|
||||
|
||||
if (data_mask & MAP_NORMAL)
|
||||
{
|
||||
S32 loc = TYPE_NORMAL;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
|
||||
glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TEXCOORD3)
|
||||
{
|
||||
S32 loc = TYPE_TEXCOORD3;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
|
||||
glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TEXCOORD2)
|
||||
{
|
||||
S32 loc = TYPE_TEXCOORD2;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
|
||||
glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TEXCOORD1)
|
||||
{
|
||||
S32 loc = TYPE_TEXCOORD1;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
|
||||
glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TANGENT)
|
||||
{
|
||||
S32 loc = TYPE_TANGENT;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
|
||||
glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TEXCOORD0)
|
||||
{
|
||||
S32 loc = TYPE_TEXCOORD0;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
|
||||
glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
|
||||
}
|
||||
if (data_mask & MAP_COLOR)
|
||||
{
|
||||
S32 loc = TYPE_COLOR;
|
||||
//bind emissive instead of color pointer if emissive is present
|
||||
void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);
|
||||
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
|
||||
}
|
||||
if (data_mask & MAP_EMISSIVE)
|
||||
{
|
||||
S32 loc = TYPE_EMISSIVE;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
|
||||
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
|
||||
|
||||
if (!(data_mask & MAP_COLOR))
|
||||
{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps
|
||||
loc = TYPE_COLOR;
|
||||
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
|
||||
}
|
||||
}
|
||||
if (data_mask & MAP_WEIGHT)
|
||||
{
|
||||
S32 loc = TYPE_WEIGHT;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
|
||||
glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
|
||||
}
|
||||
if (data_mask & MAP_WEIGHT4)
|
||||
{
|
||||
S32 loc = TYPE_WEIGHT4;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]);
|
||||
glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
|
||||
}
|
||||
if (data_mask & MAP_CLOTHWEIGHT)
|
||||
{
|
||||
S32 loc = TYPE_CLOTHWEIGHT;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
|
||||
glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
|
||||
}
|
||||
if (data_mask & MAP_TEXTURE_INDEX)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
S32 loc = TYPE_TEXTURE_INDEX;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12);
|
||||
glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
|
||||
#endif
|
||||
}
|
||||
if (data_mask & MAP_VERTEX)
|
||||
{
|
||||
S32 loc = TYPE_VERTEX;
|
||||
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
|
||||
glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
|
||||
}
|
||||
}
|
||||
|
||||
LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count)
|
||||
: mType(type), mIndex(index), mCount(count)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -210,13 +210,17 @@ protected:
|
|||
|
||||
virtual ~LLVertexBuffer(); // use unref()
|
||||
|
||||
virtual void setupVertexBuffer(U32 data_mask); // pure virtual, called from mapBuffer()
|
||||
virtual void setupVertexBuffer(U32 data_mask);
|
||||
void setupVertexBufferFast(U32 data_mask);
|
||||
|
||||
void setupVertexArray();
|
||||
|
||||
void genBuffer(U32 size);
|
||||
void genIndices(U32 size);
|
||||
bool bindGLBuffer(bool force_bind = false);
|
||||
bool bindGLBufferFast();
|
||||
bool bindGLIndices(bool force_bind = false);
|
||||
bool bindGLIndicesFast();
|
||||
bool bindGLArray();
|
||||
void releaseBuffer();
|
||||
void releaseIndices();
|
||||
|
|
@ -239,6 +243,8 @@ public:
|
|||
|
||||
// set for rendering
|
||||
virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
|
||||
void setBufferFast(U32 data_mask); // calls setupVertexBufferFast(), assumes data_mask is not 0 among other assumptions
|
||||
|
||||
void flush(); //flush pending data to GL memory
|
||||
// allocate buffer
|
||||
bool allocateBuffer(S32 nverts, S32 nindices, bool create);
|
||||
|
|
@ -290,6 +296,9 @@ public:
|
|||
void drawArrays(U32 mode, U32 offset, U32 count) const;
|
||||
void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
|
||||
|
||||
//implementation for inner loops that does no safety checking
|
||||
void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
|
||||
|
||||
//for debugging, validate data in given range is valid
|
||||
void validateRange(U32 start, U32 end, U32 count, U32 offset) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1387,7 +1387,7 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)
|
|||
|
||||
LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)
|
||||
{
|
||||
return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName));
|
||||
return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName).get());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -554,29 +554,25 @@ void LLStatBar::draw()
|
|||
void LLStatBar::setStat(const std::string& stat_name)
|
||||
{
|
||||
using namespace LLTrace;
|
||||
const StatType<CountAccumulator>* count_stat;
|
||||
const StatType<EventAccumulator>* event_stat;
|
||||
const StatType<SampleAccumulator>* sample_stat;
|
||||
const StatType<MemAccumulator>* mem_stat;
|
||||
|
||||
if ((count_stat = StatType<CountAccumulator>::getInstance(stat_name)))
|
||||
if (auto count_stat = StatType<CountAccumulator>::getInstance(stat_name))
|
||||
{
|
||||
mStat.countStatp = count_stat;
|
||||
mStat.countStatp = count_stat.get();
|
||||
mStatType = STAT_COUNT;
|
||||
}
|
||||
else if ((event_stat = StatType<EventAccumulator>::getInstance(stat_name)))
|
||||
else if (auto event_stat = StatType<EventAccumulator>::getInstance(stat_name))
|
||||
{
|
||||
mStat.eventStatp = event_stat;
|
||||
mStat.eventStatp = event_stat.get();
|
||||
mStatType = STAT_EVENT;
|
||||
}
|
||||
else if ((sample_stat = StatType<SampleAccumulator>::getInstance(stat_name)))
|
||||
else if (auto sample_stat = StatType<SampleAccumulator>::getInstance(stat_name))
|
||||
{
|
||||
mStat.sampleStatp = sample_stat;
|
||||
mStat.sampleStatp = sample_stat.get();
|
||||
mStatType = STAT_SAMPLE;
|
||||
}
|
||||
else if ((mem_stat = StatType<MemAccumulator>::getInstance(stat_name)))
|
||||
else if (auto mem_stat = StatType<MemAccumulator>::getInstance(stat_name))
|
||||
{
|
||||
mStat.memStatp = mem_stat;
|
||||
mStat.memStatp = mem_stat.get();
|
||||
mStatType = STAT_MEM;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,7 +288,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
|
|||
|
||||
if (vsync)
|
||||
{
|
||||
[glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval];
|
||||
GLint value = 1;
|
||||
[glContext setValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||
} else {
|
||||
// supress this error after move to Xcode 7:
|
||||
// error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
|
||||
|
|
|
|||
|
|
@ -78,7 +78,18 @@ public:
|
|||
BOOL setSize(LLCoordWindow size);
|
||||
virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
|
||||
virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) = 0;
|
||||
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
|
||||
|
||||
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
|
||||
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
|
||||
virtual void* createSharedContext() = 0;
|
||||
//make the given context current on the current thread
|
||||
virtual void makeContextCurrent(void* context) = 0;
|
||||
//destroy the given context that was retrieved by createSharedContext()
|
||||
//Must be called on the same thread that called createSharedContext()
|
||||
virtual void destroySharedContext(void* context) = 0;
|
||||
|
||||
|
||||
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
|
||||
virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
|
||||
virtual void showCursor() = 0;
|
||||
virtual void hideCursor() = 0;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ public:
|
|||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
|
||||
void* createSharedContext() { return nullptr; }
|
||||
void makeContextCurrent(void*) {}
|
||||
void destroySharedContext(void*) {}
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
|
||||
/*virtual*/ void showCursor() {};
|
||||
|
|
|
|||
|
|
@ -1907,6 +1907,34 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
|
|||
allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit
|
||||
}
|
||||
|
||||
class sharedContext
|
||||
{
|
||||
public:
|
||||
CGLContextObj mContext;
|
||||
};
|
||||
|
||||
void* LLWindowMacOSX::createSharedContext()
|
||||
{
|
||||
sharedContext* sc = new sharedContext();
|
||||
CGLCreateContext(mPixelFormat, mContext, &(sc->mContext));
|
||||
|
||||
return (void *)sc;
|
||||
}
|
||||
|
||||
void LLWindowMacOSX::makeContextCurrent(void* context)
|
||||
{
|
||||
CGLSetCurrentContext(((sharedContext*)context)->mContext);
|
||||
}
|
||||
|
||||
void LLWindowMacOSX::destroySharedContext(void* context)
|
||||
{
|
||||
sharedContext* sc = (sharedContext*)context;
|
||||
|
||||
CGLDestroyContext(sc->mContext);
|
||||
|
||||
delete sc;
|
||||
}
|
||||
|
||||
void LLWindowMacOSX::interruptLanguageTextInput()
|
||||
{
|
||||
commitCurrentPreedit(mGLView);
|
||||
|
|
|
|||
|
|
@ -41,85 +41,84 @@
|
|||
#undef verify
|
||||
#undef require
|
||||
|
||||
|
||||
class LLWindowMacOSX : public LLWindow
|
||||
{
|
||||
public:
|
||||
/*virtual*/ void show();
|
||||
/*virtual*/ void hide();
|
||||
/*virtual*/ void close();
|
||||
/*virtual*/ BOOL getVisible();
|
||||
/*virtual*/ BOOL getMinimized();
|
||||
/*virtual*/ BOOL getMaximized();
|
||||
/*virtual*/ BOOL maximize();
|
||||
/*virtual*/ void minimize();
|
||||
/*virtual*/ void restore();
|
||||
/*virtual*/ BOOL getFullscreen();
|
||||
/*virtual*/ BOOL getPosition(LLCoordScreen *position);
|
||||
/*virtual*/ BOOL getSize(LLCoordScreen *size);
|
||||
/*virtual*/ BOOL getSize(LLCoordWindow *size);
|
||||
/*virtual*/ BOOL setPosition(LLCoordScreen position);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
|
||||
/*virtual*/ void showCursor();
|
||||
/*virtual*/ void hideCursor();
|
||||
/*virtual*/ void showCursorFromMouseMove();
|
||||
/*virtual*/ void hideCursorUntilMouseMove();
|
||||
/*virtual*/ BOOL isCursorHidden();
|
||||
/*virtual*/ void updateCursor();
|
||||
/*virtual*/ ECursorType getCursor() const;
|
||||
/*virtual*/ void captureMouse();
|
||||
/*virtual*/ void releaseMouse();
|
||||
/*virtual*/ void setMouseClipping( BOOL b );
|
||||
/*virtual*/ BOOL isClipboardTextAvailable();
|
||||
/*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
|
||||
/*virtual*/ BOOL copyTextToClipboard(const LLWString & src);
|
||||
/*virtual*/ void flashIcon(F32 seconds);
|
||||
/*virtual*/ F32 getGamma();
|
||||
/*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
|
||||
/*virtual*/ U32 getFSAASamples();
|
||||
/*virtual*/ void setFSAASamples(const U32 fsaa_samples);
|
||||
/*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma)
|
||||
/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
|
||||
/*virtual*/ void gatherInput();
|
||||
/*virtual*/ void delayInputProcessing() {};
|
||||
/*virtual*/ void swapBuffers();
|
||||
void show() override;
|
||||
void hide() override;
|
||||
void close() override;
|
||||
BOOL getVisible() override;
|
||||
BOOL getMinimized() override;
|
||||
BOOL getMaximized() override;
|
||||
BOOL maximize() override;
|
||||
void minimize() override;
|
||||
void restore() override;
|
||||
BOOL getFullscreen();
|
||||
BOOL getPosition(LLCoordScreen *position) override;
|
||||
BOOL getSize(LLCoordScreen *size) override;
|
||||
BOOL getSize(LLCoordWindow *size) override;
|
||||
BOOL setPosition(LLCoordScreen position) override;
|
||||
BOOL setSizeImpl(LLCoordScreen size) override;
|
||||
BOOL setSizeImpl(LLCoordWindow size) override;
|
||||
BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) override;
|
||||
BOOL setCursorPosition(LLCoordWindow position) override;
|
||||
BOOL getCursorPosition(LLCoordWindow *position) override;
|
||||
void showCursor() override;
|
||||
void hideCursor() override;
|
||||
void showCursorFromMouseMove() override;
|
||||
void hideCursorUntilMouseMove() override;
|
||||
BOOL isCursorHidden() override;
|
||||
void updateCursor() override;
|
||||
ECursorType getCursor() const override;
|
||||
void captureMouse() override;
|
||||
void releaseMouse() override;
|
||||
void setMouseClipping( BOOL b ) override;
|
||||
BOOL isClipboardTextAvailable() override;
|
||||
BOOL pasteTextFromClipboard(LLWString &dst) override;
|
||||
BOOL copyTextToClipboard(const LLWString & src) override;
|
||||
void flashIcon(F32 seconds) override;
|
||||
F32 getGamma() override;
|
||||
BOOL setGamma(const F32 gamma) override; // Set the gamma
|
||||
U32 getFSAASamples() override;
|
||||
void setFSAASamples(const U32 fsaa_samples) override;
|
||||
BOOL restoreGamma() override; // Restore original gamma table (before updating gamma)
|
||||
ESwapMethod getSwapMethod() override { return mSwapMethod; }
|
||||
void gatherInput() override;
|
||||
void delayInputProcessing() override {};
|
||||
void swapBuffers() override;
|
||||
|
||||
// handy coordinate space conversion routines
|
||||
/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
|
||||
/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to);
|
||||
/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to);
|
||||
/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to);
|
||||
/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to);
|
||||
/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to);
|
||||
BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
|
||||
BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
|
||||
BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override;
|
||||
BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override;
|
||||
BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override;
|
||||
BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override;
|
||||
|
||||
/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
|
||||
/*virtual*/ F32 getNativeAspectRatio();
|
||||
/*virtual*/ F32 getPixelAspectRatio();
|
||||
/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
|
||||
LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
|
||||
F32 getNativeAspectRatio() override;
|
||||
F32 getPixelAspectRatio() override;
|
||||
void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
|
||||
|
||||
/*virtual*/ void beforeDialog();
|
||||
/*virtual*/ void afterDialog();
|
||||
void beforeDialog() override;
|
||||
void afterDialog() override;
|
||||
|
||||
/*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
|
||||
BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
|
||||
|
||||
/*virtual*/ void *getPlatformWindow();
|
||||
/*virtual*/ void bringToFront() {};
|
||||
void *getPlatformWindow() override;
|
||||
void bringToFront() override {};
|
||||
|
||||
/*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b);
|
||||
/*virtual*/ void interruptLanguageTextInput();
|
||||
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
|
||||
/*virtual*/ F32 getSystemUISize();
|
||||
void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) override;
|
||||
void interruptLanguageTextInput() override;
|
||||
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
|
||||
F32 getSystemUISize() override;
|
||||
|
||||
static std::vector<std::string> getDisplaysResolutionList();
|
||||
|
||||
static std::vector<std::string> getDynamicFallbackFontList();
|
||||
|
||||
// Provide native key event data
|
||||
/*virtual*/ LLSD getNativeKeyData();
|
||||
LLSD getNativeKeyData() override;
|
||||
|
||||
void* getWindow() { return mWindow; }
|
||||
LLWindowCallbacks* getCallbacks() { return mCallbacks; }
|
||||
|
|
@ -132,6 +131,15 @@ public:
|
|||
|
||||
bool allowsLanguageInput() { return mLanguageTextInputAllowed; }
|
||||
|
||||
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
|
||||
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
|
||||
void* createSharedContext() override;
|
||||
//make the given context current on the current thread
|
||||
void makeContextCurrent(void* context) override;
|
||||
//destroy the given context that was retrieved by createSharedContext()
|
||||
//Must be called on the same thread that called createSharedContext()
|
||||
void destroySharedContext(void* context) override;
|
||||
|
||||
protected:
|
||||
LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
|
||||
|
|
@ -141,7 +149,7 @@ protected:
|
|||
~LLWindowMacOSX();
|
||||
|
||||
void initCursors();
|
||||
BOOL isValid();
|
||||
BOOL isValid() override;
|
||||
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
|
||||
|
||||
|
||||
|
|
@ -157,7 +165,7 @@ protected:
|
|||
BOOL shouldPostQuit() { return mPostQuit; }
|
||||
|
||||
//Satisfy MAINT-3135 and MAINT-3288 with a flag.
|
||||
/*virtual */ void setOldResize(bool oldresize) {setResizeMode(oldresize, mGLView); }
|
||||
/*virtual */ void setOldResize(bool oldresize) override {setResizeMode(oldresize, mGLView); }
|
||||
|
||||
private:
|
||||
void restoreGLContext();
|
||||
|
|
@ -231,9 +239,9 @@ public:
|
|||
LLSplashScreenMacOSX();
|
||||
virtual ~LLSplashScreenMacOSX();
|
||||
|
||||
/*virtual*/ void showImpl();
|
||||
/*virtual*/ void updateImpl(const std::string& mesg);
|
||||
/*virtual*/ void hideImpl();
|
||||
void showImpl();
|
||||
void updateImpl(const std::string& mesg);
|
||||
void hideImpl();
|
||||
|
||||
private:
|
||||
WindowRef mWindow;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -33,11 +33,46 @@
|
|||
#include "llwindow.h"
|
||||
#include "llwindowcallbacks.h"
|
||||
#include "lldragdropwin32.h"
|
||||
#include "llthread.h"
|
||||
#include "llthreadsafequeue.h"
|
||||
|
||||
// Hack for async host by name
|
||||
#define LL_WM_HOST_RESOLVED (WM_APP + 1)
|
||||
typedef void (*LLW32MsgCallback)(const MSG &msg);
|
||||
|
||||
class LLWindowWin32;
|
||||
|
||||
// Thread that owns the Window Handle
|
||||
class LLWindowWin32Thread : public LLThread
|
||||
{
|
||||
public:
|
||||
class Message
|
||||
{
|
||||
public:
|
||||
LRESULT mMsg;
|
||||
};
|
||||
|
||||
static const int MAX_QUEUE_SIZE = 2048;
|
||||
|
||||
LLThreadSafeQueue<MSG> mMessageQueue;
|
||||
LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
|
||||
|
||||
bool mFinished = false;
|
||||
|
||||
LLWindowWin32Thread(LLWindowWin32* window);
|
||||
|
||||
void run() override;
|
||||
|
||||
void post(const std::function<void()>& func);
|
||||
|
||||
private:
|
||||
|
||||
// call PeekMessage and pull enqueue messages for later processing
|
||||
void gatherInput();
|
||||
LLWindowWin32* mWindow = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class LLWindowWin32 : public LLWindow
|
||||
{
|
||||
public:
|
||||
|
|
@ -58,6 +93,9 @@ public:
|
|||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
void* createSharedContext() override;
|
||||
void makeContextCurrent(void* context) override;
|
||||
void destroySharedContext(void* context) override;
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
|
||||
/*virtual*/ void showCursor();
|
||||
|
|
@ -172,9 +210,9 @@ protected:
|
|||
WCHAR *mWindowTitle;
|
||||
WCHAR *mWindowClassName;
|
||||
|
||||
HWND mWindowHandle; // window handle
|
||||
HGLRC mhRC; // OpenGL rendering context
|
||||
HDC mhDC; // Windows Device context handle
|
||||
HWND mWindowHandle = 0; // window handle
|
||||
HGLRC mhRC = 0; // OpenGL rendering context
|
||||
HDC mhDC = 0; // Windows Device context handle
|
||||
HINSTANCE mhInstance; // handle to application instance
|
||||
WNDPROC mWndProc; // user-installable window proc
|
||||
RECT mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
|
||||
|
|
@ -221,7 +259,12 @@ protected:
|
|||
|
||||
BOOL mMouseVanish;
|
||||
|
||||
LLWindowWin32Thread* mWindowThread = nullptr;
|
||||
LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
|
||||
void post(const std::function<void()>& func);
|
||||
|
||||
friend class LLWindowManager;
|
||||
friend class LLWindowWin32Thread;
|
||||
};
|
||||
|
||||
class LLSplashScreenWin32 : public LLSplashScreen
|
||||
|
|
|
|||
|
|
@ -405,8 +405,8 @@ public:
|
|||
const T& default_value,
|
||||
const std::string& comment = "Declared In Code")
|
||||
{
|
||||
mCachedControlPtr = LLControlCache<T>::getInstance(name);
|
||||
if (mCachedControlPtr.isNull())
|
||||
mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
|
||||
if (! mCachedControlPtr)
|
||||
{
|
||||
mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
|
||||
}
|
||||
|
|
@ -415,8 +415,8 @@ public:
|
|||
LLCachedControl(LLControlGroup& group,
|
||||
const std::string& name)
|
||||
{
|
||||
mCachedControlPtr = LLControlCache<T>::getInstance(name);
|
||||
if (mCachedControlPtr.isNull())
|
||||
mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
|
||||
if (! mCachedControlPtr)
|
||||
{
|
||||
mCachedControlPtr = new LLControlCache<T>(group, name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
project(mac_crash_logger)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLCoreHttp)
|
||||
include(LLCrashLogger)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
include(LLXML)
|
||||
include(Linking)
|
||||
include(LLSharedLibs)
|
||||
include(Boost)
|
||||
|
||||
include_directories(
|
||||
${LLCOREHTTP_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLCRASHLOGGER_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
)
|
||||
include_directories(SYSTEM
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
${LLXML_SYSTEM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(mac_crash_logger_SOURCE_FILES
|
||||
mac_crash_logger.cpp
|
||||
llcrashloggermac.cpp
|
||||
llcrashloggermacdelegate.mm
|
||||
)
|
||||
|
||||
set(mac_crash_logger_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llcrashloggermac.h
|
||||
llcrashloggermacdelegate.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${mac_crash_logger_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
list(APPEND mac_crash_logger_SOURCE_FILES ${mac_crash_logger_HEADER_FILES})
|
||||
|
||||
set(mac_crash_logger_RESOURCE_FILES
|
||||
CrashReporter.nib/
|
||||
)
|
||||
set_source_files_properties(
|
||||
${mac_crash_logger_RESOURCE_FILES}
|
||||
PROPERTIES
|
||||
HEADER_FILE_ONLY TRUE
|
||||
)
|
||||
SOURCE_GROUP("Resources" FILES ${mac_crash_logger_RESOURCE_FILES})
|
||||
list(APPEND mac_crash_logger_SOURCE_FILES ${mac_crash_logger_RESOURCE_FILES})
|
||||
|
||||
add_executable(mac-crash-logger
|
||||
MACOSX_BUNDLE
|
||||
${mac_crash_logger_SOURCE_FILES})
|
||||
|
||||
set_target_properties(mac-crash-logger
|
||||
PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
)
|
||||
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
|
||||
target_link_libraries(mac-crash-logger
|
||||
${LLCRASHLOGGER_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${COCOA_LIBRARIES}
|
||||
${LLXML_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLCOREHTTP_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${BOOST_CONTEXT_LIBRARY}
|
||||
${BOOST_FIBER_LIBRARY}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET mac-crash-logger POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
-E
|
||||
copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CrashReporter.nib
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-crash-logger.app/Contents/Resources/CrashReporter.nib
|
||||
)
|
||||
|
||||
ll_deploy_sharedlibs_command(mac-crash-logger)
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>mac-crash-logger</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string></string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>CrashReporter</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
/**
|
||||
* @file llcrashloggermac.cpp
|
||||
* @brief Mac OSX crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#include "llcrashloggermac.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
|
||||
#include "llerror.h"
|
||||
#include "llfile.h"
|
||||
#include "lltimer.h"
|
||||
#include "llstring.h"
|
||||
#include "lldir.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
// Windows Message Handlers
|
||||
|
||||
BOOL gFirstDialog = TRUE;
|
||||
LLFILE *gDebugFile = NULL;
|
||||
|
||||
std::string gUserNotes = "";
|
||||
bool gSendReport = false;
|
||||
bool gRememberChoice = false;
|
||||
|
||||
LLCrashLoggerMac::LLCrashLoggerMac(void)
|
||||
{
|
||||
}
|
||||
|
||||
LLCrashLoggerMac::~LLCrashLoggerMac(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::init(void)
|
||||
{
|
||||
bool ok = LLCrashLogger::init();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void LLCrashLoggerMac::gatherPlatformSpecificFiles()
|
||||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::frame()
|
||||
{
|
||||
|
||||
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
|
||||
{
|
||||
gSendReport = true;
|
||||
}
|
||||
|
||||
if(gSendReport)
|
||||
{
|
||||
setUserText(gUserNotes);
|
||||
sendCrashLogs();
|
||||
}
|
||||
|
||||
LL_INFOS() << "Sending of logs complete" << LL_ENDL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::cleanup()
|
||||
{
|
||||
commonCleanup();
|
||||
mKeyMaster.releaseMaster();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* @file llcrashloggermac.h
|
||||
* @brief Mac OSX crash logger definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLCRASHLOGGERMAC_H
|
||||
#define LLCRASHLOGGERMAC_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llcrashlogger.h"
|
||||
#include "llstring.h"
|
||||
|
||||
class LLCrashLoggerMac : public LLCrashLogger
|
||||
{
|
||||
public:
|
||||
LLCrashLoggerMac(void);
|
||||
~LLCrashLoggerMac(void);
|
||||
virtual bool init();
|
||||
virtual bool frame();
|
||||
virtual bool cleanup();
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
* @file llcrashloggermacdelegate.h
|
||||
* @brief Mac OSX crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
/*
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface LLCrashLoggerMacDelegate : NSObject <NSApplicationDelegate>
|
||||
{
|
||||
IBOutlet NSTextField *crashText;
|
||||
IBOutlet NSButton *rememberCheck;
|
||||
|
||||
NSWindow *_window;
|
||||
bool mRemember;
|
||||
|
||||
}
|
||||
|
||||
- (void)setWindow:(NSWindow *)newWindow;
|
||||
- (NSWindow *)window;
|
||||
|
||||
- (IBAction)remember:(id)sender;
|
||||
- (IBAction)send:(id)sender;
|
||||
- (IBAction)cancel:(id)sender;
|
||||
|
||||
@property (assign) IBOutlet NSWindow *window;
|
||||
|
||||
@end
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/**
|
||||
* @file llcrashloggermacdelegate.mm
|
||||
* @brief Mac OSX crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
#import "llcrashloggermacdelegate.h"
|
||||
#include <iostream>
|
||||
|
||||
extern std::string gUserNotes;
|
||||
extern bool gSendReport;
|
||||
extern bool gRememberChoice;
|
||||
|
||||
@implementation LLCrashLoggerMacDelegate
|
||||
|
||||
- (void)setWindow:(NSWindow *)window
|
||||
{
|
||||
_window = window;
|
||||
}
|
||||
|
||||
- (NSWindow *)window
|
||||
{
|
||||
return _window;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
std::string* NSToString( NSString *ns_str )
|
||||
{
|
||||
return ( new std::string([ns_str UTF8String]) );
|
||||
}
|
||||
|
||||
- (IBAction)remember:(id)sender
|
||||
{
|
||||
gRememberChoice = [rememberCheck state];
|
||||
}
|
||||
|
||||
- (IBAction)send:(id)sender
|
||||
{
|
||||
std::string* user_input = NSToString([crashText stringValue]);
|
||||
gUserNotes = *user_input;
|
||||
gSendReport = true;
|
||||
}
|
||||
|
||||
- (IBAction)cancel:(id)sender
|
||||
{
|
||||
[ _window close];
|
||||
}
|
||||
@end
|
||||
*/
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
* @file mac_crash_logger.cpp
|
||||
* @brief Mac OSX crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llcrashloggermac.h"
|
||||
#include "indra_constants.h"
|
||||
#include "llpidlock.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
LLCrashLoggerMac app;
|
||||
app.parseCommandOptions(argc, argv);
|
||||
|
||||
LLSD options = LLApp::instance()->getOptionData(
|
||||
LLApp::PRIORITY_COMMAND_LINE);
|
||||
|
||||
if (! app.init())
|
||||
{
|
||||
LL_WARNS() << "Unable to initialize application." << LL_ENDL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (app.getCrashBehavior() != CRASH_BEHAVIOR_ALWAYS_SEND)
|
||||
{
|
||||
// return NSApplicationMain(argc, (const char **)argv);
|
||||
}
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -111,9 +111,6 @@ if (DARWIN)
|
|||
LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
|
||||
)
|
||||
|
||||
## turns on C++11 using Cmake
|
||||
target_compile_features(media_plugin_cef PRIVATE cxx_range_for)
|
||||
|
||||
add_custom_command(TARGET media_plugin_cef
|
||||
POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "@executable_path/Chromium Embedded Framework"
|
||||
"@executable_path/../../../../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@
|
|||
#include "llpluginmessageclasses.h"
|
||||
#include "media_plugin_base.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
|
||||
#include "vlc/vlc.h"
|
||||
#include "vlc/libvlc_version.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1836,10 +1836,6 @@ if (WINDOWS)
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/featuretable_xp.txt
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/ssleay32.dll
|
||||
${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll
|
||||
${ARCH_PREBUILT_DIRS_DEBUG}/ssleay32.dll
|
||||
${viewer_APPSETTINGS_FILES}
|
||||
SLPlugin
|
||||
media_plugin_cef
|
||||
|
|
@ -1856,11 +1852,15 @@ if (WINDOWS)
|
|||
list(APPEND COPY_INPUT_DEPENDENCIES
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk_x64.dll
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/ortp_x64.dll
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libcrypto-1_1-x64.dll
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libssl-1_1-x64.dll
|
||||
)
|
||||
else (ADDRESS_SIZE EQUAL 64)
|
||||
list(APPEND COPY_INPUT_DEPENDENCIES
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk.dll
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/ortp.dll
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libcrypto-1_1.dll
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libssl-1_1.dll
|
||||
)
|
||||
endif (ADDRESS_SIZE EQUAL 64)
|
||||
|
||||
|
|
@ -1914,11 +1914,9 @@ if (WINDOWS)
|
|||
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
|
||||
endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
|
||||
|
||||
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin)
|
||||
|
||||
if (NOT USE_BUGSPLAT)
|
||||
add_dependencies(${VIEWER_BINARY_NAME} windows-crash-logger)
|
||||
endif (NOT USE_BUGSPLAT)
|
||||
add_dependencies(${VIEWER_BINARY_NAME}
|
||||
SLPlugin
|
||||
)
|
||||
|
||||
# sets the 'working directory' for debugging from visual studio.
|
||||
# Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
|
||||
|
|
@ -2228,10 +2226,6 @@ if (DARWIN)
|
|||
|
||||
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef)
|
||||
|
||||
if (NOT USE_BUGSPLAT)
|
||||
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
|
||||
endif (NOT USE_BUGSPLAT)
|
||||
|
||||
if (ENABLE_SIGNING)
|
||||
set(SIGNING_SETTING "--signature=${SIGNING_IDENTITY}")
|
||||
else (ENABLE_SIGNING)
|
||||
|
|
@ -2273,62 +2267,7 @@ endif (INSTALL)
|
|||
|
||||
# Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh
|
||||
if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE)
|
||||
if (NOT USE_BUGSPLAT)
|
||||
# Breakpad symbol-file generation
|
||||
set(SYMBOL_SEARCH_DIRS "")
|
||||
if (WINDOWS)
|
||||
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
|
||||
# slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad
|
||||
# set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe")
|
||||
set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}")
|
||||
set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest)
|
||||
endif (WINDOWS)
|
||||
if (DARWIN)
|
||||
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
|
||||
# *TODO: Generate these search dirs in the cmake files related to each binary.
|
||||
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
|
||||
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
|
||||
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
|
||||
set(VIEWER_EXE_GLOBS "'${product}' SLPlugin")
|
||||
set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger")
|
||||
set(VIEWER_LIB_GLOB "*.dylib")
|
||||
endif (DARWIN)
|
||||
if (LINUX)
|
||||
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged")
|
||||
set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
|
||||
set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin")
|
||||
set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*")
|
||||
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
|
||||
endif (LINUX)
|
||||
|
||||
if(CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
|
||||
else(CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
# set LLBUILD_CONFIG to be a shell variable evaluated at build time
|
||||
# reflecting the configuration we are currently building.
|
||||
set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR})
|
||||
endif(CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
|
||||
COMMAND "${PYTHON_EXECUTABLE}"
|
||||
ARGS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
|
||||
"${LLBUILD_CONFIG}"
|
||||
"${SYMBOL_SEARCH_DIRS}"
|
||||
"${VIEWER_EXE_GLOBS}"
|
||||
"${VIEWER_LIB_GLOB}"
|
||||
"${AUTOBUILD_INSTALL_DIR}/bin/dump_syms"
|
||||
"${VIEWER_SYMBOL_FILE}"
|
||||
DEPENDS generate_breakpad_symbols.py
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME} "${VIEWER_COPY_MANIFEST}")
|
||||
add_dependencies(generate_symbols ${VIEWER_BINARY_NAME})
|
||||
if (WINDOWS OR LINUX)
|
||||
add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}")
|
||||
endif (WINDOWS OR LINUX)
|
||||
|
||||
else (NOT USE_BUGSPLAT)
|
||||
if (BUGSPLAT_DB)
|
||||
# BugSplat symbol-file generation
|
||||
if (WINDOWS)
|
||||
# Just pack up a tarball containing only the .pdb file for the
|
||||
|
|
@ -2412,7 +2351,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
|
|||
if (LINUX)
|
||||
# TBD
|
||||
endif (LINUX)
|
||||
endif (NOT USE_BUGSPLAT)
|
||||
endif (BUGSPLAT_DB)
|
||||
|
||||
# for both Bugsplat and Breakpad
|
||||
add_dependencies(llpackage generate_symbols)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.4.23
|
||||
6.4.24
|
||||
|
|
|
|||
|
|
@ -9814,7 +9814,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderGlow</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -1,166 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file generate_breakpad_symbols.py
|
||||
@author Brad Kittenbrink <brad@lindenlab.com>
|
||||
@brief Simple tool for generating google_breakpad symbol information
|
||||
for the crash reporter.
|
||||
|
||||
$LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2010-2011, Linden Research, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
version 2.1 of the License only.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
|
||||
import collections
|
||||
import fnmatch
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import shlex
|
||||
import subprocess
|
||||
import tarfile
|
||||
import StringIO
|
||||
import pprint
|
||||
|
||||
DEBUG=False
|
||||
|
||||
def usage():
|
||||
print >>sys.stderr, "usage: %s search_dirs viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0]
|
||||
|
||||
class MissingModuleError(Exception):
|
||||
def __init__(self, modules):
|
||||
Exception.__init__(self, "Failed to find required modules: %r" % modules)
|
||||
self.modules = modules
|
||||
|
||||
def main(configuration, search_dirs, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file):
|
||||
print "generate_breakpad_symbols run with args: %s" % str((configuration, search_dirs, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
|
||||
|
||||
if not re.match("release", configuration, re.IGNORECASE):
|
||||
print "skipping breakpad symbol generation for non-release build."
|
||||
return 0
|
||||
|
||||
# split up list of viewer_exes
|
||||
# "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin']
|
||||
viewer_exes = shlex.split(viewer_exes)
|
||||
|
||||
found_required = dict([(module, False) for module in viewer_exes])
|
||||
|
||||
def matches(f):
|
||||
if f in viewer_exes:
|
||||
found_required[f] = True
|
||||
return True
|
||||
return fnmatch.fnmatch(f, libs_suffix)
|
||||
|
||||
search_dirs = search_dirs.split(";")
|
||||
|
||||
def list_files():
|
||||
for search_dir in search_dirs:
|
||||
for (dirname, subdirs, filenames) in os.walk(search_dir):
|
||||
if DEBUG:
|
||||
print "scanning '%s' for modules..." % dirname
|
||||
for f in itertools.ifilter(matches, filenames):
|
||||
yield os.path.join(dirname, f)
|
||||
|
||||
def dump_module(m):
|
||||
print "dumping module '%s' with '%s'..." % (m, dump_syms_tool)
|
||||
dsym_full_path = m
|
||||
child = subprocess.Popen([dump_syms_tool, dsym_full_path] , stdout=subprocess.PIPE)
|
||||
out, err = child.communicate()
|
||||
return (m,child.returncode, out, err)
|
||||
|
||||
|
||||
modules = {}
|
||||
|
||||
for m in list_files():
|
||||
if DEBUG:
|
||||
print "examining module '%s' ... " % m,
|
||||
filename=os.path.basename(m)
|
||||
if -1 != m.find("DWARF"):
|
||||
# Just use this module; it has the symbols we want.
|
||||
modules[filename] = m
|
||||
if DEBUG:
|
||||
print "found dSYM entry"
|
||||
elif filename not in modules:
|
||||
# Only use this if we don't already have a (possibly better) entry.
|
||||
modules[filename] = m
|
||||
if DEBUG:
|
||||
print "found new entry"
|
||||
elif DEBUG:
|
||||
print "ignoring entry"
|
||||
|
||||
|
||||
print "Found these following modules:"
|
||||
pprint.pprint( modules )
|
||||
|
||||
out = tarfile.open(viewer_symbol_file, 'w:bz2')
|
||||
for (filename,status,symbols,err) in itertools.imap(dump_module, modules.values()):
|
||||
if status == 0:
|
||||
module_line = symbols[:symbols.index('\n')]
|
||||
module_line = module_line.split()
|
||||
hash_id = module_line[3]
|
||||
module = ' '.join(module_line[4:])
|
||||
if sys.platform in ['win32', 'cygwin']:
|
||||
mod_name = module[:module.rindex('.pdb')]
|
||||
else:
|
||||
mod_name = module
|
||||
symbolfile = StringIO.StringIO(symbols)
|
||||
info = tarfile.TarInfo("%(module)s/%(hash_id)s/%(mod_name)s.sym" % dict(module=module, hash_id=hash_id, mod_name=mod_name))
|
||||
info.size = symbolfile.len
|
||||
out.addfile(info, symbolfile)
|
||||
else:
|
||||
print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err)
|
||||
|
||||
out.close()
|
||||
|
||||
missing_modules = [m for (m,_) in
|
||||
itertools.ifilter(lambda (k,v): not v, found_required.iteritems())
|
||||
]
|
||||
if missing_modules:
|
||||
print >> sys.stderr, "failed to generate %s" % viewer_symbol_file
|
||||
os.remove(viewer_symbol_file)
|
||||
raise MissingModuleError(missing_modules)
|
||||
|
||||
symbols = tarfile.open(viewer_symbol_file, 'r:bz2')
|
||||
tarfile_members = symbols.getnames()
|
||||
symbols.close()
|
||||
|
||||
for required_module in viewer_exes:
|
||||
def match_module_basename(m):
|
||||
return os.path.splitext(required_module)[0].lower() \
|
||||
== os.path.splitext(os.path.basename(m))[0].lower()
|
||||
# there must be at least one .sym file in tarfile_members that matches
|
||||
# each required module (ignoring file extensions)
|
||||
if not any(itertools.imap(match_module_basename, tarfile_members)):
|
||||
print >> sys.stderr, "failed to find required %s in generated %s" \
|
||||
% (required_module, viewer_symbol_file)
|
||||
os.remove(viewer_symbol_file)
|
||||
raise MissingModuleError([required_module])
|
||||
|
||||
print "successfully generated %s including required modules '%s'" % (viewer_symbol_file, viewer_exes)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 7:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
sys.exit(main(*sys.argv[1:]))
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/sh
|
||||
if [[ $SKIP_NOTARIZATION == "true" ]]; then
|
||||
echo "Skipping notarization"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CONFIG_FILE="$build_secrets_checkout/code-signing-osx/notarize_creds.sh"
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
source $CONFIG_FILE
|
||||
app_file="$1"
|
||||
zip_file=${app_file/app/zip}
|
||||
ditto -c -k --keepParent "$app_file" "$zip_file"
|
||||
if [ -f "$zip_file" ]; then
|
||||
res=$(xcrun altool --notarize-app --primary-bundle-id "com.secondlife.viewer" \
|
||||
--username $USERNAME \
|
||||
--password $PASSWORD \
|
||||
--asc-provider $ASC_PROVIDER \
|
||||
--file "$zip_file" 2>&1)
|
||||
requestUUID=$(echo $res | awk '/RequestUUID/ { print $NF; }')
|
||||
|
||||
echo "Apple Notarization RequestUUID: $requestUUID"
|
||||
|
||||
if [[ -n $requestUUID ]]; then
|
||||
status="in progress"
|
||||
while [[ "$status" == "in progress" ]]; do
|
||||
sleep 30
|
||||
status=$(xcrun altool --notarization-info "$requestUUID" \
|
||||
--username $USERNAME \
|
||||
--password $PASSWORD 2>&1 \
|
||||
| awk -F ': ' '/Status:/ { print $2; }' )
|
||||
echo "$status"
|
||||
done
|
||||
# log results
|
||||
xcrun altool --notarization-info "$requestUUID" \
|
||||
--username $USERNAME \
|
||||
--password $PASSWORD
|
||||
|
||||
#remove temporary file
|
||||
rm "$zip_file"
|
||||
|
||||
if [["$status" == "success"]]; then
|
||||
xcrun stapler staple "$app_file"
|
||||
elif [["$status" == "invalid"]]; then
|
||||
echo "Notarization error: failed to process the app file"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Notarization error: couldn't get request UUID"
|
||||
echo $res
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -613,7 +613,7 @@ static void settings_modify()
|
|||
LLPipeline::sRenderDeferred = LLPipeline::sRenderTransparentWater && LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
|
||||
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
|
||||
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
|
||||
gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
|
||||
gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
|
||||
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
|
||||
}
|
||||
|
||||
|
|
@ -737,7 +737,7 @@ LLAppViewer::LLAppViewer()
|
|||
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
|
||||
# endif // ! LL_BUGSPLAT
|
||||
mDumpPath = logdir;
|
||||
setMiniDumpDir(logdir);
|
||||
|
||||
setDebugFileNames(logdir);
|
||||
}
|
||||
|
||||
|
|
@ -1010,19 +1010,6 @@ bool LLAppViewer::init()
|
|||
return 0;
|
||||
}
|
||||
|
||||
// If we don't have the right shader requirements.
|
||||
if (!gGLManager.mHasShaderObjects
|
||||
|| !gGLManager.mHasVertexShader
|
||||
|| !gGLManager.mHasFragmentShader)
|
||||
{
|
||||
LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedShaderRequirements");
|
||||
OSMessageBox(
|
||||
details.getString(),
|
||||
LLStringUtil::null,
|
||||
OSMB_OK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Without SSE2 support we will crash almost immediately, warn here.
|
||||
if (!gSysCPU.hasSSE2())
|
||||
{
|
||||
|
|
@ -2026,7 +2013,9 @@ bool LLAppViewer::cleanup()
|
|||
if (LLConversationLog::instanceExists())
|
||||
{
|
||||
LLConversationLog::instance().cache();
|
||||
}
|
||||
}
|
||||
|
||||
clearSecHandler();
|
||||
|
||||
if (mPurgeCacheOnExit)
|
||||
{
|
||||
|
|
@ -2356,7 +2345,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
|
|||
LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name()
|
||||
<< " - from location " << location_key << LL_ENDL;
|
||||
|
||||
LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);
|
||||
auto settings_group = LLControlGroup::getInstance(file.name);
|
||||
if(!settings_group)
|
||||
{
|
||||
LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;
|
||||
|
|
@ -2653,7 +2642,7 @@ bool LLAppViewer::initConfiguration()
|
|||
group_part = name.substr(0, pos);
|
||||
name_part = name.substr(pos+1);
|
||||
LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL;
|
||||
LLControlGroup* g = LLControlGroup::getInstance(group_part);
|
||||
auto g = LLControlGroup::getInstance(group_part);
|
||||
if (g) control = g->getControl(name_part);
|
||||
}
|
||||
else
|
||||
|
|
@ -4844,6 +4833,7 @@ void LLAppViewer::idle()
|
|||
LLNotificationsUI::LLToast::updateClass();
|
||||
LLSmoothInterpolation::updateInterpolants();
|
||||
LLMortician::updateClass();
|
||||
LLImageGL::updateClass();
|
||||
LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
|
||||
LLDirPickerThread::clearDead();
|
||||
F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ public:
|
|||
|
||||
virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism.
|
||||
// return false if the error trap needed restoration.
|
||||
virtual void initCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report?
|
||||
static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon.
|
||||
void checkForCrash();
|
||||
|
||||
|
|
|
|||
|
|
@ -222,14 +222,7 @@ LLAppViewerMacOSX::~LLAppViewerMacOSX()
|
|||
|
||||
bool LLAppViewerMacOSX::init()
|
||||
{
|
||||
bool success = LLAppViewer::init();
|
||||
|
||||
if (success)
|
||||
{
|
||||
LLAppViewer* pApp = LLAppViewer::instance();
|
||||
pApp->initCrashReporting();
|
||||
}
|
||||
return success;
|
||||
return LLAppViewer::init();
|
||||
}
|
||||
|
||||
// MacOSX may add and addition command line arguement for the process serial number.
|
||||
|
|
@ -347,28 +340,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
|
|||
return reset_count == 0;
|
||||
}
|
||||
|
||||
void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
|
||||
{
|
||||
#if defined LL_BUGSPLAT
|
||||
LL_DEBUGS("InitOSX", "Bugsplat") << "using BugSplat crash logger" << LL_ENDL;
|
||||
#elif LL_SEND_CRASH_REPORTS
|
||||
LL_DEBUGS("InitOSX") << "Initializing legacy crash logger" << LL_ENDL;
|
||||
std::string command_str = "mac-crash-logger.app";
|
||||
|
||||
std::stringstream pid_str;
|
||||
pid_str << LLApp::getPid();
|
||||
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
|
||||
std::string appname = gDirUtilp->getExecutableFilename();
|
||||
std::string str[] = { "-pid", pid_str.str(), "-dumpdir", logdir, "-procname", appname.c_str() };
|
||||
std::vector< std::string > args( str, str + ( sizeof ( str ) / sizeof ( std::string ) ) );
|
||||
LL_WARNS() << "about to launch mac-crash-logger" << pid_str.str()
|
||||
<< " " << logdir << " " << appname << LL_ENDL;
|
||||
launchApplication(&command_str, &args);
|
||||
#else
|
||||
LL_DEBUGS("InitOSX") << "No crash logger enabled" << LL_ENDL;
|
||||
#endif // ! LL_BUGSPLAT
|
||||
}
|
||||
|
||||
std::string LLAppViewerMacOSX::generateSerialNumber()
|
||||
{
|
||||
char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ public:
|
|||
|
||||
protected:
|
||||
virtual bool restoreErrorTrap();
|
||||
virtual void initCrashReporting(bool reportFreeze);
|
||||
|
||||
std::string generateSerialNumber();
|
||||
virtual bool initParseCommandLine(LLCommandLineParser& clp);
|
||||
|
|
|
|||
|
|
@ -603,9 +603,6 @@ bool LLAppViewerWin32::init()
|
|||
#if ! defined(LL_BUGSPLAT)
|
||||
#pragma message("Building without BugSplat")
|
||||
|
||||
LLAppViewer* pApp = LLAppViewer::instance();
|
||||
pApp->initCrashReporting();
|
||||
|
||||
#else // LL_BUGSPLAT
|
||||
#pragma message("Building with BugSplat")
|
||||
|
||||
|
|
@ -850,57 +847,6 @@ bool LLAppViewerWin32::restoreErrorTrap()
|
|||
return true; // we don't check for handler collisions on windows, so just say they're ok
|
||||
}
|
||||
|
||||
void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
|
||||
{
|
||||
if (isSecondInstance()) return; //BUG-5707 do not start another crash reporter for second instance.
|
||||
|
||||
const char* logger_name = "win_crash_logger.exe";
|
||||
std::string exe_path = gDirUtilp->getExecutableDir();
|
||||
exe_path += gDirUtilp->getDirDelimiter();
|
||||
exe_path += logger_name;
|
||||
|
||||
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
|
||||
std::string appname = gDirUtilp->getExecutableFilename();
|
||||
|
||||
S32 slen = logdir.length() -1;
|
||||
S32 end = slen;
|
||||
while (logdir.at(end) == '/' || logdir.at(end) == '\\') end--;
|
||||
|
||||
if (slen !=end)
|
||||
{
|
||||
logdir = logdir.substr(0,end+1);
|
||||
}
|
||||
//std::string arg_str = "\"" + exe_path + "\" -dumpdir \"" + logdir + "\" -procname \"" + appname + "\" -pid " + stringize(LLApp::getPid());
|
||||
//_spawnl(_P_NOWAIT, exe_path.c_str(), arg_str.c_str(), NULL);
|
||||
std::string arg_str = "\"" + exe_path + "\" -dumpdir \"" + logdir + "\" -procname \"" + appname + "\" -pid " + stringize(LLApp::getPid());
|
||||
|
||||
STARTUPINFO startInfo={sizeof(startInfo)};
|
||||
PROCESS_INFORMATION processInfo;
|
||||
|
||||
std::wstring exe_wstr;
|
||||
exe_wstr = utf8str_to_utf16str(exe_path);
|
||||
|
||||
std::wstring arg_wstr;
|
||||
arg_wstr = utf8str_to_utf16str(arg_str);
|
||||
|
||||
LL_INFOS("CrashReport") << "Creating crash reporter process " << exe_path << " with params: " << arg_str << LL_ENDL;
|
||||
if(CreateProcess(exe_wstr.c_str(),
|
||||
&arg_wstr[0], // Application arguments
|
||||
0,
|
||||
0,
|
||||
FALSE,
|
||||
CREATE_DEFAULT_ERROR_MODE,
|
||||
0,
|
||||
0, // Working directory
|
||||
&startInfo,
|
||||
&processInfo) == FALSE)
|
||||
// Could not start application -> call 'GetLastError()'
|
||||
{
|
||||
LL_WARNS("CrashReport") << "CreateProcess failed " << GetLastError() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,9 +51,8 @@ protected:
|
|||
bool initHardwareTest() override; // Win32 uses DX9 to test hardware.
|
||||
bool initParseCommandLine(LLCommandLineParser& clp) override;
|
||||
|
||||
bool beingDebugged() override;
|
||||
bool restoreErrorTrap() override;
|
||||
void initCrashReporting(bool reportFreeze) override;
|
||||
virtual bool beingDebugged();
|
||||
virtual bool restoreErrorTrap();
|
||||
|
||||
bool sendURLToOtherInstance(const std::string& url) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@ LLBrowserNotification::LLBrowserNotification()
|
|||
bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification)
|
||||
{
|
||||
LLUUID media_id = notification->getPayload()["media_id"].asUUID();
|
||||
LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id);
|
||||
auto media_instance = LLMediaCtrl::getInstance(media_id);
|
||||
if (media_instance)
|
||||
{
|
||||
media_instance->showNotification(notification);
|
||||
}
|
||||
else if (LLViewerMediaFocus::instance().getControlsMediaID() == media_id)
|
||||
{
|
||||
LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(media_id);
|
||||
auto impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(media_id);
|
||||
if (impl)
|
||||
{
|
||||
impl->showNotification(notification);
|
||||
|
|
|
|||
|
|
@ -234,8 +234,6 @@ void LLDrawable::markDead()
|
|||
|
||||
LLVOVolume* LLDrawable::getVOVolume() const
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED
|
||||
|
||||
LLViewerObject* objectp = mVObjp;
|
||||
if ( !isDead() && objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -404,6 +404,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask, BOOL batch_textures)
|
|||
|
||||
void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
|
||||
{
|
||||
LLDrawInfo* pparams = *i;
|
||||
|
|
@ -452,6 +453,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
|
|||
|
||||
void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if (!params.mCount)
|
||||
{
|
||||
return;
|
||||
|
|
@ -469,7 +471,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
|
|||
{
|
||||
if (params.mTextureList[i].notNull())
|
||||
{
|
||||
gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
|
||||
gGL.getTexUnit(i)->bindFast(params.mTextureList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -477,8 +479,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
|
|||
{ //not batching textures or batch has only 1 texture -- might need a texture matrix
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
params.mTexture->addTextureStats(params.mVSize);
|
||||
gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
|
||||
gGL.getTexUnit(0)->bindFast(params.mTexture);
|
||||
if (params.mTextureMatrix)
|
||||
{
|
||||
tex_setup = true;
|
||||
|
|
@ -490,24 +491,20 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
|
|||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (params.mVertexBuffer.notNull())
|
||||
{
|
||||
if (params.mGroup)
|
||||
{
|
||||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
if (params.mGroup)
|
||||
{
|
||||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
|
||||
params.mVertexBuffer->setBuffer(mask);
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
}
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
|
||||
params.mVertexBuffer->setBufferFast(mask);
|
||||
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
|
||||
if (tex_setup)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,19 +55,7 @@ static BOOL deferred_render = FALSE;
|
|||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETUP("Alpha Setup");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED("Alpha Deferred");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETBUFFER("Alpha SetBuffer");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DRAW("Alpha Draw");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_TEX_BINDS("Alpha Tex Binds");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MATS("Alpha Mat Tex Binds");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GLOW("Alpha Glow Binds");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SHADER_BINDS("Alpha Shader Binds");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS("Alpha Def Binds");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS("Alpha Def Tex Binds");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MESH_REBUILD("Alpha Mesh Rebuild");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_EMISSIVE("Alpha Emissive");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_LIGHT_SETUP("Alpha Light Setup");
|
||||
|
||||
LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
|
||||
LLRenderPass(type), current_shader(NULL), target_shader(NULL),
|
||||
|
|
@ -86,6 +74,10 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
|
|||
void LLDrawPoolAlpha::prerender()
|
||||
{
|
||||
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
|
||||
|
||||
// TODO: is this even necessay? These are probably set to never discard
|
||||
LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f);
|
||||
LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f);
|
||||
}
|
||||
|
||||
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
|
||||
|
|
@ -309,7 +301,7 @@ void LLDrawPoolAlpha::render(S32 pass)
|
|||
gGL.diffuseColor4f(1,0,0,1);
|
||||
|
||||
LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
|
||||
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ;
|
||||
gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep);
|
||||
renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
|
||||
LLVertexBuffer::MAP_TEXCOORD0);
|
||||
|
||||
|
|
@ -358,9 +350,8 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
|
|||
{
|
||||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
params.mVertexBuffer->setBuffer(mask);
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
params.mVertexBuffer->setBufferFast(mask);
|
||||
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -383,27 +374,23 @@ inline bool IsEmissive(LLDrawInfo& params)
|
|||
|
||||
inline void Draw(LLDrawInfo* draw, U32 mask)
|
||||
{
|
||||
draw->mVertexBuffer->setBuffer(mask);
|
||||
draw->mVertexBuffer->setBufferFast(mask);
|
||||
LLRenderPass::applyModelMatrix(*draw);
|
||||
draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
|
||||
gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode);
|
||||
draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
|
||||
}
|
||||
|
||||
bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader)
|
||||
bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS);
|
||||
|
||||
bool tex_setup = false;
|
||||
|
||||
if (deferred_render && use_material && current_shader)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS);
|
||||
if (draw->mNormalMap)
|
||||
{
|
||||
{
|
||||
draw->mNormalMap->addTextureStats(draw->mVSize);
|
||||
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
|
||||
}
|
||||
|
||||
|
||||
if (draw->mSpecularMap)
|
||||
{
|
||||
draw->mSpecularMap->addTextureStats(draw->mVSize);
|
||||
|
|
@ -412,18 +399,16 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate
|
|||
}
|
||||
else if (current_shader == simple_shader)
|
||||
{
|
||||
LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(draw->mVSize);
|
||||
LLViewerFetchedTexture::sWhiteImagep->addTextureStats(draw->mVSize);
|
||||
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
|
||||
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
|
||||
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
|
||||
}
|
||||
if (use_shaders && draw->mTextureList.size() > 1)
|
||||
if (draw->mTextureList.size() > 1)
|
||||
{
|
||||
for (U32 i = 0; i < draw->mTextureList.size(); ++i)
|
||||
{
|
||||
if (draw->mTextureList[i].notNull())
|
||||
{
|
||||
gGL.getTexUnit(i)->bind(draw->mTextureList[i], TRUE);
|
||||
gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -431,16 +416,15 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate
|
|||
{ //not batching textures or batch has only 1 texture -- might need a texture matrix
|
||||
if (draw->mTexture.notNull())
|
||||
{
|
||||
draw->mTexture->addTextureStats(draw->mVSize);
|
||||
if (use_shaders && use_material)
|
||||
if (use_material)
|
||||
{
|
||||
current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(draw->mTexture, TRUE) ;
|
||||
gGL.getTexUnit(0)->bindFast(draw->mTexture);
|
||||
}
|
||||
|
||||
|
||||
if (draw->mTextureMatrix)
|
||||
{
|
||||
tex_setup = true;
|
||||
|
|
@ -452,7 +436,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate
|
|||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -470,37 +454,15 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup)
|
|||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples)
|
||||
{
|
||||
gPipeline.enableLightsDynamic();
|
||||
simple_shader->bind();
|
||||
simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
|
||||
simple_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
|
||||
simple_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f);
|
||||
simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f);
|
||||
bool use_shaders = gPipeline.canUseVertexShaders();
|
||||
for (LLDrawInfo* draw : simples)
|
||||
{
|
||||
bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader);
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
Draw(draw, mask);
|
||||
RestoreTexSetup(tex_setup);
|
||||
}
|
||||
simple_shader->unbind();
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights)
|
||||
{
|
||||
gPipeline.enableLightsFullbright();
|
||||
fullbright_shader->bind();
|
||||
fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f);
|
||||
bool use_shaders = gPipeline.canUseVertexShaders();
|
||||
|
||||
for (LLDrawInfo* draw : fullbrights)
|
||||
{
|
||||
bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader);
|
||||
bool tex_setup = TexSetup(draw, false, fullbright_shader);
|
||||
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
|
||||
|
|
@ -511,65 +473,10 @@ void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& full
|
|||
fullbright_shader->unbind();
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials)
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
current_shader = NULL;
|
||||
|
||||
gPipeline.enableLightsDynamic();
|
||||
bool use_shaders = gPipeline.canUseVertexShaders();
|
||||
for (LLDrawInfo* draw : materials)
|
||||
{
|
||||
U32 mask = draw->mShaderMask;
|
||||
|
||||
llassert(mask < LLMaterial::SHADER_COUNT);
|
||||
target_shader = (LLPipeline::sUnderWaterRender) ? &(gDeferredMaterialWaterProgram[mask]) : &(gDeferredMaterialProgram[mask]);
|
||||
|
||||
if (current_shader != target_shader)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS);
|
||||
if (current_shader)
|
||||
{
|
||||
gPipeline.unbindDeferredShader(*current_shader);
|
||||
}
|
||||
gPipeline.bindDeferredShader(*target_shader);
|
||||
current_shader = target_shader;
|
||||
}
|
||||
|
||||
bool tex_setup = TexSetup(draw, use_shaders, true, current_shader);
|
||||
|
||||
current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, draw->mSpecColor.mV[0], draw->mSpecColor.mV[1], draw->mSpecColor.mV[2], draw->mSpecColor.mV[3]);
|
||||
current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, draw->mEnvIntensity);
|
||||
current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, draw->mFullbright ? 1.f : 0.f);
|
||||
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS);
|
||||
if (draw->mNormalMap)
|
||||
{
|
||||
draw->mNormalMap->addTextureStats(draw->mVSize);
|
||||
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
|
||||
}
|
||||
|
||||
if (draw->mSpecularMap)
|
||||
{
|
||||
draw->mSpecularMap->addTextureStats(draw->mVSize);
|
||||
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
|
||||
}
|
||||
}
|
||||
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
Draw(draw, mask);
|
||||
RestoreTexSetup(tex_setup);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
|
||||
{
|
||||
draw->mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
|
||||
draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
|
||||
gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode);
|
||||
draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
|
||||
draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw)
|
||||
|
|
@ -599,10 +506,10 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
|
|||
// install glow-accumulating blend mode
|
||||
// don't touch color, add to alpha (glow)
|
||||
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
|
||||
bool use_shaders = gPipeline.canUseVertexShaders();
|
||||
|
||||
for (LLDrawInfo* draw : emissives)
|
||||
{
|
||||
bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader);
|
||||
bool tex_setup = TexSetup(draw, false, emissive_shader);
|
||||
drawEmissive(mask, draw);
|
||||
RestoreTexSetup(tex_setup);
|
||||
}
|
||||
|
|
@ -620,8 +527,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
BOOL initialized_lighting = FALSE;
|
||||
BOOL light_enabled = TRUE;
|
||||
|
||||
BOOL use_shaders = gPipeline.canUseVertexShaders();
|
||||
|
||||
for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
|
||||
{
|
||||
LLSpatialGroup* group = *i;
|
||||
|
|
@ -631,8 +536,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
if (group->getSpatialPartition()->mRenderByGroup &&
|
||||
!group->isDead())
|
||||
{
|
||||
std::vector<LLDrawInfo*> emissives;
|
||||
std::vector<LLDrawInfo*> fullbrights;
|
||||
static std::vector<LLDrawInfo*> emissives;
|
||||
static std::vector<LLDrawInfo*> fullbrights;
|
||||
emissives.resize(0);
|
||||
fullbrights.resize(0);
|
||||
|
||||
bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE
|
||||
|| group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE;
|
||||
|
|
@ -649,6 +556,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
|
||||
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("ra - push batch")
|
||||
LLDrawInfo& params = **k;
|
||||
U32 have_mask = params.mVertexBuffer->getTypeMask() & mask;
|
||||
if (have_mask != mask)
|
||||
|
|
@ -696,34 +604,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
// Turn off lighting if it hasn't already been so.
|
||||
if (light_enabled || !initialized_lighting)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP);
|
||||
|
||||
initialized_lighting = TRUE;
|
||||
if (use_shaders)
|
||||
{
|
||||
target_shader = fullbright_shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.enableLightsFullbright();
|
||||
}
|
||||
target_shader = fullbright_shader;
|
||||
|
||||
light_enabled = FALSE;
|
||||
}
|
||||
}
|
||||
// Turn on lighting if it isn't already.
|
||||
else if (!light_enabled || !initialized_lighting)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP);
|
||||
|
||||
initialized_lighting = TRUE;
|
||||
if (use_shaders)
|
||||
{
|
||||
target_shader = simple_shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.enableLightsDynamic();
|
||||
}
|
||||
target_shader = simple_shader;
|
||||
light_enabled = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -741,7 +632,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
|
||||
if (current_shader != target_shader)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS);
|
||||
gPipeline.bindDeferredShader(*target_shader);
|
||||
current_shader = target_shader;
|
||||
}
|
||||
|
|
@ -755,25 +645,19 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
target_shader = fullbright_shader;
|
||||
}
|
||||
|
||||
if(use_shaders && (current_shader != target_shader))
|
||||
if(current_shader != target_shader)
|
||||
{// If we need shaders, and we're not ALREADY using the proper shader, then bind it
|
||||
// (this way we won't rebind shaders unnecessarily).
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SHADER_BINDS);
|
||||
current_shader = target_shader;
|
||||
current_shader->bind();
|
||||
}
|
||||
else if (!use_shaders && current_shader != NULL)
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
current_shader = NULL;
|
||||
}
|
||||
|
||||
LLVector4 spec_color(1, 1, 1, 1);
|
||||
F32 env_intensity = 0.0f;
|
||||
F32 brightness = 1.0f;
|
||||
|
||||
// We have a material. Supply the appropriate data here.
|
||||
if (use_shaders && mat && deferred_render)
|
||||
if (mat && deferred_render)
|
||||
{
|
||||
spec_color = params.mSpecColor;
|
||||
env_intensity = params.mEnvIntensity;
|
||||
|
|
@ -792,20 +676,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
|
||||
bool tex_setup = TexSetup(¶ms, use_shaders, use_shaders && (mat != nullptr), current_shader);
|
||||
bool tex_setup = TexSetup(¶ms, (mat != nullptr), current_shader);
|
||||
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH);
|
||||
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
|
||||
gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
|
||||
params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
|
||||
params.mVertexBuffer->setBufferFast(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
|
||||
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DRAW);
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -814,8 +694,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
draw_glow_for_this_partition &&
|
||||
params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_EMISSIVE);
|
||||
|
||||
if (batch_emissives)
|
||||
{
|
||||
emissives.push_back(¶ms);
|
||||
|
|
@ -835,19 +713,29 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool rebind = false;
|
||||
if (batch_fullbrights)
|
||||
{
|
||||
light_enabled = false;
|
||||
renderFullbrights(mask, fullbrights);
|
||||
if (!fullbrights.empty())
|
||||
{
|
||||
light_enabled = false;
|
||||
renderFullbrights(mask, fullbrights);
|
||||
rebind = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (batch_emissives)
|
||||
{
|
||||
light_enabled = true;
|
||||
renderEmissives(mask, emissives);
|
||||
if (!emissives.empty())
|
||||
{
|
||||
light_enabled = true;
|
||||
renderEmissives(mask, emissives);
|
||||
rebind = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_shader)
|
||||
if (current_shader && rebind)
|
||||
{
|
||||
current_shader->bind();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,15 +75,13 @@ private:
|
|||
LLGLSLShader* fullbright_shader;
|
||||
LLGLSLShader* emissive_shader;
|
||||
|
||||
void renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples);
|
||||
void renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
|
||||
void renderMaterials(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
|
||||
void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
|
||||
|
||||
void drawEmissive(U32 mask, LLDrawInfo* draw);
|
||||
void drawEmissiveInline(U32 mask, LLDrawInfo* draw);
|
||||
|
||||
bool TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader);
|
||||
bool TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader);
|
||||
void RestoreTexSetup(bool tex_setup);
|
||||
|
||||
// our 'normal' alpha blend function for this pass
|
||||
|
|
|
|||
|
|
@ -1685,7 +1685,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
|
|||
renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
|
||||
renderRigged(avatarp, RIGGED_NORMMAP);
|
||||
renderRigged(avatarp, RIGGED_NORMMAP_MASK);
|
||||
renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
|
||||
renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
|
||||
renderRigged(avatarp, RIGGED_SPECMAP);
|
||||
renderRigged(avatarp, RIGGED_SPECMAP_MASK);
|
||||
renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
|
||||
|
|
@ -2067,56 +2067,12 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
|
|||
LLVector4a* pos = (LLVector4a*) position.get();
|
||||
|
||||
LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;
|
||||
|
||||
if (skin == nullptr)
|
||||
{
|
||||
skin = vobj->getSkinInfo();
|
||||
}
|
||||
|
||||
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, skin);
|
||||
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, vobj->getMeshID());
|
||||
const LLMatrix4a* mat = &(mpc.mMatrixPalette[0]);
|
||||
const LLMatrix4a& bind_shape_matrix = mpc.mBindShapeMatrix;
|
||||
|
||||
LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin);
|
||||
const LLMatrix4a& bind_shape_matrix = skin->mBindShapeMatrix;
|
||||
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
U8* joint_indices_cursor = vol_face.mJointIndices;
|
||||
// fast path with joint indices separate from weights
|
||||
if (joint_indices_cursor)
|
||||
{
|
||||
LLMatrix4a src[4];
|
||||
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
|
||||
{
|
||||
LLMatrix4a final_mat;
|
||||
//LLMatrix4a final_mat_correct;
|
||||
|
||||
F32* jw = just_weights[j].getF32ptr();
|
||||
|
||||
LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src);
|
||||
|
||||
joint_indices_cursor += 4;
|
||||
|
||||
LLVector4a& v = vol_face.mPositions[j];
|
||||
|
||||
LLVector4a t;
|
||||
LLVector4a dst;
|
||||
bind_shape_matrix.affineTransform(v, t);
|
||||
final_mat.affineTransform(t, dst);
|
||||
pos[j] = dst;
|
||||
|
||||
if (norm)
|
||||
{
|
||||
LLVector4a& n = vol_face.mNormals[j];
|
||||
bind_shape_matrix.rotate(n, t);
|
||||
final_mat.rotate(t, dst);
|
||||
dst.normalize3fast();
|
||||
norm[j] = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
// slow path with joint indices calculated from weights
|
||||
else
|
||||
#endif
|
||||
if (!mpc.mMatrixPalette.empty())
|
||||
{
|
||||
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
|
||||
{
|
||||
|
|
@ -2152,9 +2108,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
return;
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
|
||||
const LLMeshSkinInfo* lastSkin = nullptr;
|
||||
LLUUID lastMeshId;
|
||||
|
||||
for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
|
||||
{
|
||||
|
|
@ -2188,19 +2142,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
continue;
|
||||
}
|
||||
|
||||
const LLMeshSkinInfo* skin = vobj->getSkinInfo();
|
||||
if (!skin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//stop_glerror();
|
||||
|
||||
//const LLVolumeFace& vol_face = volume->getVolumeFace(te);
|
||||
//updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face);
|
||||
|
||||
//stop_glerror();
|
||||
|
||||
U32 data_mask = LLFace::getRiggedDataMask(type);
|
||||
|
||||
LLVertexBuffer* buff = face->getVertexBuffer();
|
||||
|
|
@ -2290,34 +2231,33 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
{
|
||||
if (sShaderLevel > 0)
|
||||
{
|
||||
if (lastSkin != skin) // <== only upload matrix palette to GL if the skininfo changed
|
||||
auto& meshId = vobj->getMeshID();
|
||||
|
||||
if (lastMeshId != meshId) // <== only upload matrix palette to GL if the skininfo changed
|
||||
{
|
||||
// upload matrix palette to shader
|
||||
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, skin);
|
||||
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, meshId);
|
||||
U32 count = mpc.mMatrixPalette.size();
|
||||
|
||||
stop_glerror();
|
||||
if (count == 0)
|
||||
{
|
||||
//skin info not loaded yet, don't render
|
||||
continue;
|
||||
}
|
||||
|
||||
LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
|
||||
count,
|
||||
FALSE,
|
||||
(GLfloat*) &(mpc.mGLMp[0]));
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
lastMeshId = meshId;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_mask &= ~LLVertexBuffer::MAP_WEIGHT4;
|
||||
}
|
||||
|
||||
lastSkin = skin;
|
||||
|
||||
/*if (glow)
|
||||
{
|
||||
gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow());
|
||||
}*/
|
||||
|
||||
if (mat)
|
||||
{
|
||||
//order is important here LLRender::DIFFUSE_MAP should be last, becouse it change
|
||||
|
|
@ -2332,13 +2272,17 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
{
|
||||
specular = face->getTexture(LLRender::SPECULAR_MAP);
|
||||
}
|
||||
if (specular)
|
||||
if (specular && specular_channel >= 0)
|
||||
{
|
||||
gGL.getTexUnit(specular_channel)->bind(specular);
|
||||
gGL.getTexUnit(specular_channel)->bindFast(specular);
|
||||
}
|
||||
|
||||
gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP));
|
||||
gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP), false, true);
|
||||
if (normal_channel >= 0)
|
||||
{
|
||||
gGL.getTexUnit(normal_channel)->bindFast(face->getTexture(LLRender::NORMAL_MAP));
|
||||
}
|
||||
|
||||
gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture(LLRender::DIFFUSE_MAP));
|
||||
|
||||
|
||||
LLColor4 col = mat->getSpecularLightColor();
|
||||
|
|
@ -2369,23 +2313,28 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
sVertexProgram->setMinimumAlpha(0.f);
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
|
||||
{
|
||||
LLViewerTexture* tex = face->getTexture(i);
|
||||
if (tex)
|
||||
{
|
||||
tex->addTextureStats(avatar->getPixelArea());
|
||||
}
|
||||
}
|
||||
if (!LLPipeline::sShadowRender && !LLPipeline::sReflectionRender)
|
||||
{
|
||||
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
|
||||
{
|
||||
LLViewerTexture* tex = face->getTexture(i);
|
||||
if (tex)
|
||||
{
|
||||
tex->addTextureStats(avatar->getPixelArea());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture());
|
||||
sVertexProgram->setMinimumAlpha(0.f);
|
||||
if (normal_channel > -1)
|
||||
{
|
||||
LLDrawPoolBump::bindBumpMap(face, normal_channel);
|
||||
}
|
||||
|
||||
gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture());
|
||||
|
||||
}
|
||||
|
||||
if (face->mTextureMatrix && vobj->mTexAnimMode)
|
||||
|
|
@ -2399,8 +2348,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix);
|
||||
}
|
||||
|
||||
buff->setBuffer(data_mask);
|
||||
buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
|
||||
buff->setBufferFast(data_mask);
|
||||
buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset);
|
||||
|
||||
if (tex_index <= 1)
|
||||
{
|
||||
|
|
@ -2411,11 +2360,9 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
|||
}
|
||||
else
|
||||
{
|
||||
buff->setBuffer(data_mask);
|
||||
buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
|
||||
buff->setBufferFast(data_mask);
|
||||
buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset);
|
||||
}
|
||||
|
||||
gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2476,8 +2423,6 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
|
|||
continue;
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
|
||||
LLVolumeFace& vol_face = volume->getVolumeFace(te);
|
||||
updateRiggedFaceVertexBuffer(avatar, face, vobj, volume, vol_face);
|
||||
}
|
||||
|
|
@ -2501,47 +2446,58 @@ void LLDrawPoolAvatar::updateSkinInfoMatrixPalettes(LLVOAvatar* avatarp)
|
|||
}
|
||||
}
|
||||
|
||||
const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLMeshSkinInfo* skin)
|
||||
const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLUUID& meshId)
|
||||
{
|
||||
MatrixPaletteCache& entry = mMatrixPaletteCache[skin];
|
||||
MatrixPaletteCache& entry = mMatrixPaletteCache[meshId];
|
||||
|
||||
if (entry.mFrame != gFrameCount)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(meshId);
|
||||
entry.mFrame = gFrameCount;
|
||||
//build matrix palette
|
||||
U32 count = LLSkinningUtil::getMeshJointCount(skin);
|
||||
entry.mMatrixPalette.resize(count);
|
||||
LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp);
|
||||
|
||||
const LLMatrix4a* mat = &(entry.mMatrixPalette[0]);
|
||||
|
||||
stop_glerror();
|
||||
|
||||
entry.mGLMp.resize(count * 12);
|
||||
|
||||
F32* mp = &(entry.mGLMp[0]);
|
||||
|
||||
for (U32 i = 0; i < count; ++i)
|
||||
if (skin != nullptr)
|
||||
{
|
||||
F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
|
||||
entry.mBindShapeMatrix = skin->mBindShapeMatrix;
|
||||
|
||||
U32 idx = i * 12;
|
||||
//build matrix palette
|
||||
U32 count = LLSkinningUtil::getMeshJointCount(skin);
|
||||
entry.mMatrixPalette.resize(count);
|
||||
LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp);
|
||||
|
||||
mp[idx + 0] = m[0];
|
||||
mp[idx + 1] = m[1];
|
||||
mp[idx + 2] = m[2];
|
||||
mp[idx + 3] = m[12];
|
||||
const LLMatrix4a* mat = &(entry.mMatrixPalette[0]);
|
||||
|
||||
mp[idx + 4] = m[4];
|
||||
mp[idx + 5] = m[5];
|
||||
mp[idx + 6] = m[6];
|
||||
mp[idx + 7] = m[13];
|
||||
entry.mGLMp.resize(count * 12);
|
||||
|
||||
mp[idx + 8] = m[8];
|
||||
mp[idx + 9] = m[9];
|
||||
mp[idx + 10] = m[10];
|
||||
mp[idx + 11] = m[14];
|
||||
F32* mp = &(entry.mGLMp[0]);
|
||||
|
||||
for (U32 i = 0; i < count; ++i)
|
||||
{
|
||||
F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
|
||||
|
||||
U32 idx = i * 12;
|
||||
|
||||
mp[idx + 0] = m[0];
|
||||
mp[idx + 1] = m[1];
|
||||
mp[idx + 2] = m[2];
|
||||
mp[idx + 3] = m[12];
|
||||
|
||||
mp[idx + 4] = m[4];
|
||||
mp[idx + 5] = m[5];
|
||||
mp[idx + 6] = m[6];
|
||||
mp[idx + 7] = m[13];
|
||||
|
||||
mp[idx + 8] = m[8];
|
||||
mp[idx + 9] = m[9];
|
||||
mp[idx + 10] = m[10];
|
||||
mp[idx + 11] = m[14];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.mMatrixPalette.resize(0);
|
||||
entry.mGLMp.resize(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,12 +283,13 @@ typedef enum
|
|||
|
||||
std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES];
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class MatrixPaletteCache
|
||||
{
|
||||
public:
|
||||
U32 mFrame;
|
||||
LLMeshSkinInfo::matrix_list_t mMatrixPalette;
|
||||
|
||||
LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
|
||||
// Float array ready to be sent to GL
|
||||
std::vector<F32> mGLMp;
|
||||
|
||||
|
|
@ -296,11 +297,11 @@ typedef enum
|
|||
mFrame(gFrameCount-1)
|
||||
{
|
||||
}
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLMeshSkinInfo* skin);
|
||||
const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLUUID& meshId);
|
||||
|
||||
typedef std::unordered_map<const LLMeshSkinInfo*, MatrixPaletteCache> matrix_palette_cache_t;
|
||||
typedef std::unordered_map<LLUUID, MatrixPaletteCache> matrix_palette_cache_t;
|
||||
matrix_palette_cache_t mMatrixPaletteCache;
|
||||
|
||||
/*virtual*/ LLViewerTexture *getDebugTexture();
|
||||
|
|
|
|||
|
|
@ -677,6 +677,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel)
|
|||
//static
|
||||
BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
//Note: texture atlas does not support bump texture now.
|
||||
LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ;
|
||||
if(!tex)
|
||||
|
|
@ -693,7 +694,7 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi
|
|||
break;
|
||||
case BE_BRIGHTNESS:
|
||||
case BE_DARKNESS:
|
||||
bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
|
||||
bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -709,12 +710,12 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi
|
|||
{
|
||||
if (channel == -2)
|
||||
{
|
||||
gGL.getTexUnit(1)->bind(bump);
|
||||
gGL.getTexUnit(0)->bind(bump);
|
||||
gGL.getTexUnit(1)->bindFast(bump);
|
||||
gGL.getTexUnit(0)->bindFast(bump);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(channel)->bind(bump);
|
||||
gGL.getTexUnit(channel)->bindFast(bump);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -1497,6 +1498,7 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
|
|||
|
||||
void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
applyModelMatrix(params);
|
||||
|
||||
bool tex_setup = false;
|
||||
|
|
@ -1507,7 +1509,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
|
|||
{
|
||||
if (params.mTextureList[i].notNull())
|
||||
{
|
||||
gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
|
||||
gGL.getTexUnit(i)->bindFast(params.mTextureList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1522,13 +1524,6 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gGL.getTexUnit(1)->activate();
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->activate();
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||
|
|
@ -1545,8 +1540,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
|
|||
{
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
gGL.getTexUnit(diffuse_channel)->bind(params.mTexture);
|
||||
params.mTexture->addTextureStats(params.mVSize);
|
||||
gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1559,10 +1553,10 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
|
|||
{
|
||||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
params.mVertexBuffer->setBuffer(mask);
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
if (tex_setup)
|
||||
params.mVertexBuffer->setBufferFast(mask);
|
||||
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
|
||||
if (tex_setup)
|
||||
{
|
||||
if (mShiny)
|
||||
{
|
||||
|
|
@ -1570,12 +1564,6 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gGL.getTexUnit(1)->activate();
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
gGL.loadIdentity();
|
||||
}
|
||||
gGL.getTexUnit(0)->activate();
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "lltextureentry.h"
|
||||
#include "lluuid.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class LLImageRaw;
|
||||
class LLSpatialGroup;
|
||||
class LLDrawInfo;
|
||||
|
|
@ -161,7 +163,7 @@ private:
|
|||
static void onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump );
|
||||
|
||||
private:
|
||||
typedef std::map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t;
|
||||
typedef std::unordered_map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t;
|
||||
bump_image_map_t mBrightnessEntries;
|
||||
bump_image_map_t mDarknessEntries;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ void LLDrawPoolMaterials::endDeferredPass(S32 pass)
|
|||
|
||||
void LLDrawPoolMaterials::renderDeferred(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
static const U32 type_list[] =
|
||||
{
|
||||
LLRenderPass::PASS_MATERIAL,
|
||||
|
|
@ -157,7 +158,10 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
|
|||
mShader->setMinimumAlpha(params.mAlphaMaskCutoff);
|
||||
mShader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f);
|
||||
|
||||
pushBatch(params, mask, TRUE);
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
pushMaterialsBatch(params, mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,49 +175,37 @@ void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex)
|
|||
mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex);
|
||||
}
|
||||
|
||||
void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
|
||||
void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
applyModelMatrix(params);
|
||||
|
||||
bool tex_setup = false;
|
||||
|
||||
if (batch_textures && params.mTextureList.size() > 1)
|
||||
//not batching textures or batch has only 1 texture -- might need a texture matrix
|
||||
if (params.mTextureMatrix)
|
||||
{
|
||||
for (U32 i = 0; i < params.mTextureList.size(); ++i)
|
||||
//if (mShiny)
|
||||
{
|
||||
if (params.mTextureList[i].notNull())
|
||||
{
|
||||
gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
|
||||
}
|
||||
gGL.getTexUnit(0)->activate();
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
}
|
||||
|
||||
gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||
gPipeline.mTextureMatrixOps++;
|
||||
|
||||
tex_setup = true;
|
||||
}
|
||||
else
|
||||
{ //not batching textures or batch has only 1 texture -- might need a texture matrix
|
||||
if (params.mTextureMatrix)
|
||||
{
|
||||
//if (mShiny)
|
||||
{
|
||||
gGL.getTexUnit(0)->activate();
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE);
|
||||
}
|
||||
|
||||
gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||
gPipeline.mTextureMatrixOps++;
|
||||
|
||||
tex_setup = true;
|
||||
}
|
||||
|
||||
if (mShaderLevel > 1 && texture)
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
gGL.getTexUnit(diffuse_channel)->bind(params.mTexture);
|
||||
params.mTexture->addTextureStats(params.mVSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -224,9 +216,9 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture,
|
|||
|
||||
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
|
||||
|
||||
params.mVertexBuffer->setBuffer(mask);
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
params.mVertexBuffer->setBufferFast(mask);
|
||||
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
|
||||
if (tex_setup)
|
||||
{
|
||||
gGL.getTexUnit(0)->activate();
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public:
|
|||
void bindSpecularMap(LLViewerTexture* tex);
|
||||
void bindNormalMap(LLViewerTexture* tex);
|
||||
|
||||
/*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
|
||||
/*virtual*/ void pushMaterialsBatch(LLDrawInfo& params, U32 mask);
|
||||
};
|
||||
|
||||
#endif //LL_LLDRAWPOOLMATERIALS_H
|
||||
|
|
|
|||
|
|
@ -150,13 +150,6 @@ void LLDrawPoolGlow::render(S32 pass)
|
|||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
|
||||
{
|
||||
//gGL.diffuseColor4ubv(params.mGlowColor.mV);
|
||||
LLRenderPass::pushBatch(params, mask, texture, batch_textures);
|
||||
}
|
||||
|
||||
|
||||
LLDrawPoolSimple::LLDrawPoolSimple() :
|
||||
LLRenderPass(POOL_SIMPLE)
|
||||
{
|
||||
|
|
@ -199,11 +192,7 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
|
|||
}
|
||||
else
|
||||
{
|
||||
// don't use shaders!
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,11 +290,7 @@ void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
|
|||
}
|
||||
else
|
||||
{
|
||||
// don't use shaders!
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,11 +377,7 @@ void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
|
|||
}
|
||||
else
|
||||
{
|
||||
// don't use shaders!
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -483,6 +464,7 @@ void LLDrawPoolSimple::endDeferredPass(S32 pass)
|
|||
|
||||
void LLDrawPoolSimple::renderDeferred(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
LLGLDisable alpha_test(GL_ALPHA_TEST);
|
||||
|
||||
|
|
@ -567,11 +549,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
|
|||
else
|
||||
{
|
||||
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
|
||||
// don't use shaders!
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,6 @@ public:
|
|||
/*virtual*/ S32 getNumPasses();
|
||||
|
||||
void render(S32 pass = 0);
|
||||
void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -82,13 +82,7 @@ void LLDrawPoolSky::render(S32 pass)
|
|||
}
|
||||
else
|
||||
{
|
||||
// don't use shaders!
|
||||
if (gGLManager.mHasShaderObjects)
|
||||
{
|
||||
// Ironically, we must support shader objects to be
|
||||
// able to use this call.
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
mShader = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue