bgfx.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414
  1. /*
  2. * Copyright 2011-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include "bgfx_p.h"
  6. #if BGFX_CONFIG_USE_TINYSTL
  7. namespace tinystl
  8. {
  9. void* bgfx_allocator::static_allocate(size_t _bytes)
  10. {
  11. return bgfx::g_realloc(NULL, _bytes);
  12. }
  13. void bgfx_allocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
  14. {
  15. bgfx::g_free(_ptr);
  16. }
  17. } // namespace tinystl
  18. #endif // BGFX_CONFIG_USE_TINYSTL
  19. namespace bgfx
  20. {
  21. #define BGFX_MAIN_THREAD_MAGIC 0x78666762
  22. #if BGFX_CONFIG_MULTITHREADED
  23. # define BGFX_CHECK_MAIN_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC == s_threadIndex, "Must be called from main thread.")
  24. # define BGFX_CHECK_RENDER_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC != s_threadIndex, "Must be called from render thread.")
  25. #else
  26. # define BGFX_CHECK_MAIN_THREAD()
  27. # define BGFX_CHECK_RENDER_THREAD()
  28. #endif // BGFX_CONFIG_MULTITHREADED
  29. #if BX_PLATFORM_WINDOWS
  30. HWND g_bgfxHwnd = NULL;
  31. void winSetHwnd(::HWND _hwnd)
  32. {
  33. g_bgfxHwnd = _hwnd;
  34. }
  35. #elif BX_PLATFORM_OSX
  36. void* g_bgfxNSWindow = NULL;
  37. void osxSetNSWindow(void* _nsWindow)
  38. {
  39. g_bgfxNSWindow = _nsWindow;
  40. }
  41. #endif // BX_PLATFORM_*
  42. struct CallbackStub : public CallbackI
  43. {
  44. virtual ~CallbackStub()
  45. {
  46. }
  47. virtual void fatal(Fatal::Enum _code, const char* _str) BX_OVERRIDE
  48. {
  49. BX_TRACE("0x%08x: %s", _code, _str);
  50. BX_UNUSED(_code);
  51. BX_UNUSED(_str);
  52. abort();
  53. }
  54. virtual uint32_t cacheReadSize(uint64_t /*_id*/) BX_OVERRIDE
  55. {
  56. return 0;
  57. }
  58. virtual bool cacheRead(uint64_t /*_id*/, void* /*_data*/, uint32_t /*_size*/) BX_OVERRIDE
  59. {
  60. return false;
  61. }
  62. virtual void cacheWrite(uint64_t /*_id*/, const void* /*_data*/, uint32_t /*_size*/) BX_OVERRIDE
  63. {
  64. }
  65. virtual void screenShot(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _pitch, const void* _data, uint32_t /*_size*/, bool _yflip) BX_OVERRIDE
  66. {
  67. saveTga(_filePath, _width, _height, _pitch, _data, false, _yflip);
  68. }
  69. virtual void captureBegin(uint32_t /*_width*/, uint32_t /*_height*/, uint32_t /*_pitch*/, TextureFormat::Enum /*_format*/, bool /*_yflip*/) BX_OVERRIDE
  70. {
  71. BX_TRACE("Warning: using capture without callback (a.k.a. pointless).");
  72. }
  73. virtual void captureEnd() BX_OVERRIDE
  74. {
  75. }
  76. virtual void captureFrame(const void* /*_data*/, uint32_t /*_size*/) BX_OVERRIDE
  77. {
  78. }
  79. };
  80. static CallbackStub s_callbackStub;
  81. static void* reallocStub(void* _ptr, size_t _size)
  82. {
  83. void* ptr = ::realloc(_ptr, _size);
  84. BX_CHECK(NULL != ptr, "Out of memory!");
  85. // BX_TRACE("alloc %d, %p", _size, ptr);
  86. return ptr;
  87. }
  88. static void freeStub(void* _ptr)
  89. {
  90. // BX_TRACE("free %p", _ptr);
  91. ::free(_ptr);
  92. }
  93. CallbackI* g_callback = &s_callbackStub;
  94. ReallocFn g_realloc = reallocStub;
  95. FreeFn g_free = freeStub;
  96. static BX_THREAD uint32_t s_threadIndex = 0;
  97. static Context s_ctx;
  98. void fatal(Fatal::Enum _code, const char* _format, ...)
  99. {
  100. char temp[8192];
  101. va_list argList;
  102. va_start(argList, _format);
  103. vsnprintf(temp, sizeof(temp), _format, argList);
  104. va_end(argList);
  105. temp[sizeof(temp)-1] = '\0';
  106. g_callback->fatal(_code, temp);
  107. }
  108. inline void vec4MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat)
  109. {
  110. _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _vec[3] * _mat[12];
  111. _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _vec[3] * _mat[13];
  112. _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _vec[3] * _mat[14];
  113. _result[3] = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _vec[3] * _mat[15];
  114. }
  115. void mtxMul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
  116. {
  117. vec4MulMtx(&_result[ 0], &_a[ 0], _b);
  118. vec4MulMtx(&_result[ 4], &_a[ 4], _b);
  119. vec4MulMtx(&_result[ 8], &_a[ 8], _b);
  120. vec4MulMtx(&_result[12], &_a[12], _b);
  121. }
  122. void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far)
  123. {
  124. const float aa = 2.0f/(_right - _left);
  125. const float bb = 2.0f/(_top - _bottom);
  126. const float cc = 1.0f/(_far - _near);
  127. const float dd = (_left + _right)/(_left - _right);
  128. const float ee = (_top + _bottom)/(_bottom - _top);
  129. const float ff = _near / (_near - _far);
  130. memset(_result, 0, sizeof(float)*16);
  131. _result[0] = aa;
  132. _result[5] = bb;
  133. _result[10] = cc;
  134. _result[12] = dd;
  135. _result[13] = ee;
  136. _result[14] = ff;
  137. _result[15] = 1.0f;
  138. }
  139. void saveTga(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, bool _grayscale, bool _yflip)
  140. {
  141. FILE* file = fopen(_filePath, "wb");
  142. if ( NULL != file )
  143. {
  144. uint8_t type = _grayscale ? 3 : 2;
  145. uint8_t bpp = _grayscale ? 8 : 32;
  146. putc(0, file);
  147. putc(0, file);
  148. putc(type, file);
  149. putc(0, file);
  150. putc(0, file);
  151. putc(0, file);
  152. putc(0, file);
  153. putc(0, file);
  154. putc(0, file);
  155. putc(0, file);
  156. putc(0, file);
  157. putc(0, file);
  158. putc(_width&0xff, file);
  159. putc( (_width>>8)&0xff, file);
  160. putc(_height&0xff, file);
  161. putc( (_height>>8)&0xff, file);
  162. putc(bpp, file);
  163. putc(32, file);
  164. uint32_t dstPitch = _width*bpp/8;
  165. if (_yflip)
  166. {
  167. uint8_t* data = (uint8_t*)_src + _srcPitch*_height - _srcPitch;
  168. for (uint32_t yy = 0; yy < _height; ++yy)
  169. {
  170. fwrite(data, dstPitch, 1, file);
  171. data -= _srcPitch;
  172. }
  173. }
  174. else
  175. {
  176. uint8_t* data = (uint8_t*)_src;
  177. for (uint32_t yy = 0; yy < _height; ++yy)
  178. {
  179. fwrite(data, dstPitch, 1, file);
  180. data += _srcPitch;
  181. }
  182. }
  183. fclose(file);
  184. }
  185. }
  186. #include "charset.h"
  187. void charsetFillTexture(const uint8_t* _charset, uint8_t* _rgba, uint32_t _height, uint32_t _pitch, uint32_t _bpp)
  188. {
  189. for (uint32_t ii = 0; ii < 256; ++ii)
  190. {
  191. uint8_t* pix = &_rgba[ii*8*_bpp];
  192. for (uint32_t yy = 0; yy < _height; ++yy)
  193. {
  194. for (uint32_t xx = 0; xx < 8; ++xx)
  195. {
  196. uint8_t bit = 1<<(7-xx);
  197. memset(&pix[xx*_bpp], _charset[ii*_height+yy]&bit ? 255 : 0, _bpp);
  198. }
  199. pix += _pitch;
  200. }
  201. }
  202. }
  203. static const uint32_t numCharsPerBatch = 1024;
  204. static const uint32_t numBatchVertices = numCharsPerBatch*4;
  205. static const uint32_t numBatchIndices = numCharsPerBatch*6;
  206. void TextVideoMemBlitter::init()
  207. {
  208. BGFX_CHECK_MAIN_THREAD();
  209. m_decl.begin();
  210. m_decl.add(Attrib::Position, 3, AttribType::Float);
  211. m_decl.add(Attrib::Color0, 4, AttribType::Uint8, true);
  212. m_decl.add(Attrib::Color1, 4, AttribType::Uint8, true);
  213. m_decl.add(Attrib::TexCoord0, 2, AttribType::Float);
  214. m_decl.end();
  215. uint16_t width = 2048;
  216. uint16_t height = 24;
  217. uint8_t bpp = 1;
  218. uint32_t pitch = width*bpp;
  219. const Memory* mem;
  220. mem = alloc(pitch*height);
  221. uint8_t* rgba = mem->data;
  222. charsetFillTexture(vga8x8, rgba, 8, pitch, bpp);
  223. charsetFillTexture(vga8x16, &rgba[8*pitch], 16, pitch, bpp);
  224. m_texture = createTexture2D(width, height, 1, TextureFormat::L8
  225. , BGFX_TEXTURE_MIN_POINT
  226. | BGFX_TEXTURE_MAG_POINT
  227. | BGFX_TEXTURE_MIP_POINT
  228. | BGFX_TEXTURE_U_CLAMP
  229. | BGFX_TEXTURE_V_CLAMP
  230. , mem
  231. );
  232. #if BGFX_CONFIG_RENDERER_DIRECT3D9
  233. mem = makeRef(vs_debugfont_dx9, sizeof(vs_debugfont_dx9) );
  234. #elif BGFX_CONFIG_RENDERER_DIRECT3D11
  235. mem = makeRef(vs_debugfont_dx11, sizeof(vs_debugfont_dx11) );
  236. #else
  237. mem = makeRef(vs_debugfont_glsl, sizeof(vs_debugfont_glsl) );
  238. #endif // BGFX_CONFIG_RENDERER_
  239. VertexShaderHandle vsh = createVertexShader(mem);
  240. #if BGFX_CONFIG_RENDERER_DIRECT3D9
  241. mem = makeRef(fs_debugfont_dx9, sizeof(fs_debugfont_dx9) );
  242. #elif BGFX_CONFIG_RENDERER_DIRECT3D11
  243. mem = makeRef(fs_debugfont_dx11, sizeof(fs_debugfont_dx11) );
  244. #else
  245. mem = makeRef(fs_debugfont_glsl, sizeof(fs_debugfont_glsl) );
  246. #endif // BGFX_CONFIG_RENDERER_
  247. FragmentShaderHandle fsh = createFragmentShader(mem);
  248. m_program = createProgram(vsh, fsh);
  249. destroyVertexShader(vsh);
  250. destroyFragmentShader(fsh);
  251. m_vb = s_ctx.createTransientVertexBuffer(numBatchVertices*m_decl.m_stride, &m_decl);
  252. m_ib = s_ctx.createTransientIndexBuffer(numBatchIndices*2);
  253. }
  254. void TextVideoMemBlitter::shutdown()
  255. {
  256. BGFX_CHECK_MAIN_THREAD();
  257. destroyProgram(m_program);
  258. destroyTexture(m_texture);
  259. s_ctx.destroyTransientVertexBuffer(m_vb);
  260. s_ctx.destroyTransientIndexBuffer(m_ib);
  261. }
  262. void TextVideoMemBlitter::blit(const TextVideoMem& _mem)
  263. {
  264. BGFX_CHECK_RENDER_THREAD();
  265. struct Vertex
  266. {
  267. float m_x;
  268. float m_y;
  269. float m_z;
  270. uint32_t m_fg;
  271. uint32_t m_bg;
  272. float m_u;
  273. float m_v;
  274. };
  275. static uint32_t palette[16] =
  276. {
  277. 0x0,
  278. 0xff0000cc,
  279. 0xff069a4e,
  280. 0xff00a0c4,
  281. 0xffa46534,
  282. 0xff7b5075,
  283. 0xff9a9806,
  284. 0xffcfd7d3,
  285. 0xff535755,
  286. 0xff2929ef,
  287. 0xff34e28a,
  288. 0xff4fe9fc,
  289. 0xffcf9f72,
  290. 0xffa87fad,
  291. 0xffe2e234,
  292. 0xffeceeee,
  293. };
  294. uint32_t yy = 0;
  295. uint32_t xx = 0;
  296. const float texelWidth = 1.0f/2048.0f;
  297. const float texelWidthHalf = texelWidth*0.5f;
  298. const float texelHeight = 1.0f/24.0f;
  299. #if BGFX_CONFIG_RENDERER_DIRECT3D9
  300. const float texelHeightHalf = texelHeight*0.5f;
  301. #else
  302. const float texelHeightHalf = 0.0f;
  303. #endif // BGFX_CONFIG_RENDERER_
  304. const float utop = (_mem.m_small ? 0.0f : 8.0f)*texelHeight + texelHeightHalf;
  305. const float ubottom = (_mem.m_small ? 8.0f : 24.0f)*texelHeight + texelHeightHalf;
  306. const float fontHeight = (_mem.m_small ? 8.0f : 16.0f);
  307. setup();
  308. for (;yy < _mem.m_height;)
  309. {
  310. Vertex* vertex = (Vertex*)m_vb->data;
  311. uint16_t* indices = (uint16_t*)m_ib->data;
  312. uint32_t startVertex = 0;
  313. uint32_t numIndices = 0;
  314. for (; yy < _mem.m_height && numIndices < numBatchIndices; ++yy)
  315. {
  316. xx = xx < _mem.m_width ? xx : 0;
  317. const uint8_t* line = &_mem.m_mem[(yy*_mem.m_width+xx)*2];
  318. for (; xx < _mem.m_width && numIndices < numBatchIndices; ++xx)
  319. {
  320. uint8_t ch = line[0];
  321. uint8_t attr = line[1];
  322. if (0 != (ch|attr)
  323. && (' ' != ch || 0 != (attr&0xf0) ) )
  324. {
  325. uint32_t fg = palette[attr&0xf];
  326. uint32_t bg = palette[(attr>>4)&0xf];
  327. Vertex vert[4] =
  328. {
  329. { (xx )*8.0f, (yy )*fontHeight, 0.0f, fg, bg, (ch )*8.0f*texelWidth - texelWidthHalf, utop },
  330. { (xx+1)*8.0f, (yy )*fontHeight, 0.0f, fg, bg, (ch+1)*8.0f*texelWidth - texelWidthHalf, utop },
  331. { (xx+1)*8.0f, (yy+1)*fontHeight, 0.0f, fg, bg, (ch+1)*8.0f*texelWidth - texelWidthHalf, ubottom },
  332. { (xx )*8.0f, (yy+1)*fontHeight, 0.0f, fg, bg, (ch )*8.0f*texelWidth - texelWidthHalf, ubottom },
  333. };
  334. memcpy(vertex, vert, sizeof(vert) );
  335. vertex += 4;
  336. indices[0] = startVertex+0;
  337. indices[1] = startVertex+1;
  338. indices[2] = startVertex+2;
  339. indices[3] = startVertex+2;
  340. indices[4] = startVertex+3;
  341. indices[5] = startVertex+0;
  342. startVertex += 4;
  343. indices += 6;
  344. numIndices += 6;
  345. }
  346. line += 2;
  347. }
  348. if (numIndices >= numBatchIndices)
  349. {
  350. break;
  351. }
  352. }
  353. render(numIndices);
  354. }
  355. }
  356. void ClearQuad::init()
  357. {
  358. BGFX_CHECK_MAIN_THREAD();
  359. #if BGFX_CONFIG_RENDERER_DIRECT3D11
  360. m_decl.begin();
  361. m_decl.add(Attrib::Position, 3, AttribType::Float);
  362. m_decl.add(Attrib::Color0, 4, AttribType::Uint8, true);
  363. m_decl.end();
  364. const Memory* mem;
  365. mem = alloc(sizeof(vs_clear_dx11)+1);
  366. memcpy(mem->data, vs_clear_dx11, mem->size-1);
  367. VertexShaderHandle vsh = createVertexShader(mem);
  368. mem = alloc(sizeof(fs_clear_dx11)+1);
  369. memcpy(mem->data, fs_clear_dx11, mem->size-1);
  370. FragmentShaderHandle fsh = createFragmentShader(mem);
  371. m_program = createProgram(vsh, fsh);
  372. destroyVertexShader(vsh);
  373. destroyFragmentShader(fsh);
  374. m_vb = s_ctx.createTransientVertexBuffer(4*m_decl.m_stride, &m_decl);
  375. mem = alloc(6*sizeof(uint16_t) );
  376. uint16_t* indices = (uint16_t*)mem->data;
  377. indices[0] = 0;
  378. indices[1] = 1;
  379. indices[2] = 2;
  380. indices[3] = 2;
  381. indices[4] = 3;
  382. indices[5] = 0;
  383. m_ib = s_ctx.createIndexBuffer(mem);
  384. #endif // BGFX_CONFIG_RENDERER_DIRECT3D11
  385. }
  386. void ClearQuad::shutdown()
  387. {
  388. BGFX_CHECK_MAIN_THREAD();
  389. #if BGFX_CONFIG_RENDERER_DIRECT3D11
  390. destroyProgram(m_program);
  391. destroyIndexBuffer(m_ib);
  392. s_ctx.destroyTransientVertexBuffer(m_vb);
  393. #endif // BGFX_CONFIG_RENDERER_DIRECT3D11
  394. }
  395. static const char* s_predefinedName[PredefinedUniform::Count] =
  396. {
  397. "u_viewRect",
  398. "u_viewTexel",
  399. "u_view",
  400. "u_viewProj",
  401. "u_viewProjX",
  402. "u_model",
  403. "u_modelView",
  404. "u_modelViewProj",
  405. "u_modelViewProjX",
  406. "u_alphaRef",
  407. };
  408. const char* getPredefinedUniformName(PredefinedUniform::Enum _enum)
  409. {
  410. return s_predefinedName[_enum];
  411. }
  412. PredefinedUniform::Enum nameToPredefinedUniformEnum(const char* _name)
  413. {
  414. for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii)
  415. {
  416. if (0 == strcmp(_name, s_predefinedName[ii]) )
  417. {
  418. return PredefinedUniform::Enum(ii);
  419. }
  420. }
  421. return PredefinedUniform::Count;
  422. }
  423. void Frame::submit(uint8_t _id, int32_t _depth)
  424. {
  425. if (m_discard)
  426. {
  427. m_discard = false;
  428. return;
  429. }
  430. if (BGFX_CONFIG_MAX_DRAW_CALLS-1 <= m_num
  431. || (0 == m_state.m_numVertices && 0 == m_state.m_numIndices) )
  432. {
  433. ++m_numDropped;
  434. return;
  435. }
  436. BX_WARN(invalidHandle != m_key.m_program, "Program with invalid handle");
  437. if (invalidHandle != m_key.m_program)
  438. {
  439. m_key.m_depth = _depth;
  440. m_key.m_view = _id;
  441. m_key.m_seq = s_ctx.m_seq[_id] & s_ctx.m_seqMask[_id];
  442. s_ctx.m_seq[_id]++;
  443. uint64_t key = m_key.encode();
  444. m_sortKeys[m_num] = key;
  445. m_sortValues[m_num] = m_numRenderStates;
  446. ++m_num;
  447. m_state.m_constEnd = m_constantBuffer->getPos();
  448. m_state.m_flags |= m_flags;
  449. m_renderState[m_numRenderStates] = m_state;
  450. ++m_numRenderStates;
  451. }
  452. m_state.clear();
  453. m_flags = BGFX_STATE_NONE;
  454. }
  455. void Frame::submitMask(uint32_t _viewMask, int32_t _depth)
  456. {
  457. if (m_discard)
  458. {
  459. m_discard = false;
  460. return;
  461. }
  462. if (BGFX_CONFIG_MAX_DRAW_CALLS-1 <= m_num
  463. || (0 == m_state.m_numVertices && 0 == m_state.m_numIndices) )
  464. {
  465. m_numDropped += uint32_cntbits(_viewMask);
  466. return;
  467. }
  468. BX_WARN(invalidHandle != m_key.m_program, "Program with invalid handle");
  469. if (invalidHandle != m_key.m_program)
  470. {
  471. m_key.m_depth = _depth;
  472. for (uint32_t id = 0, viewMask = _viewMask, ntz = uint32_cnttz(_viewMask); 0 != viewMask; viewMask >>= 1, id += 1, ntz = uint32_cnttz(viewMask) )
  473. {
  474. viewMask >>= ntz;
  475. id += ntz;
  476. m_key.m_view = id;
  477. m_key.m_seq = s_ctx.m_seq[id] & s_ctx.m_seqMask[id];
  478. s_ctx.m_seq[id]++;
  479. uint64_t key = m_key.encode();
  480. m_sortKeys[m_num] = key;
  481. m_sortValues[m_num] = m_numRenderStates;
  482. ++m_num;
  483. }
  484. m_state.m_constEnd = m_constantBuffer->getPos();
  485. m_state.m_flags |= m_flags;
  486. m_renderState[m_numRenderStates] = m_state;
  487. ++m_numRenderStates;
  488. }
  489. m_state.clear();
  490. m_flags = BGFX_STATE_NONE;
  491. }
  492. void Frame::sort()
  493. {
  494. bx::radixSort64(m_sortKeys, s_ctx.m_tempKeys, m_sortValues, s_ctx.m_tempValues, m_num);
  495. }
  496. RendererType::Enum getRendererType()
  497. {
  498. #if BGFX_CONFIG_RENDERER_DIRECT3D9
  499. return RendererType::Direct3D9;
  500. #elif BGFX_CONFIG_RENDERER_DIRECT3D11
  501. return RendererType::Direct3D11;
  502. #elif BGFX_CONFIG_RENDERER_OPENGL
  503. return RendererType::OpenGL;
  504. #elif BGFX_CONFIG_RENDERER_OPENGLES2
  505. return RendererType::OpenGLES2;
  506. #elif BGFX_CONFIG_RENDERER_OPENGLES3
  507. return RendererType::OpenGLES3;
  508. #else
  509. return RendererType::Null;
  510. #endif // BGFX_CONFIG_RENDERER_
  511. }
  512. void init(CallbackI* _callback, ReallocFn _realloc, FreeFn _free)
  513. {
  514. if (NULL != _callback)
  515. {
  516. g_callback = _callback;
  517. }
  518. if (NULL != _realloc
  519. && NULL != _free)
  520. {
  521. g_realloc = _realloc;
  522. g_free = _free;
  523. }
  524. s_threadIndex = BGFX_MAIN_THREAD_MAGIC;
  525. // On NaCl renderer is on the main thread.
  526. s_ctx.init(!BX_PLATFORM_NACL);
  527. }
  528. void shutdown()
  529. {
  530. BGFX_CHECK_MAIN_THREAD();
  531. s_ctx.shutdown();
  532. s_threadIndex = 0;
  533. g_callback = &s_callbackStub;
  534. g_realloc = reallocStub;
  535. g_free = freeStub;
  536. }
  537. void reset(uint32_t _width, uint32_t _height, uint32_t _flags)
  538. {
  539. BGFX_CHECK_MAIN_THREAD();
  540. s_ctx.reset(_width, _height, _flags);
  541. }
  542. void frame()
  543. {
  544. BGFX_CHECK_MAIN_THREAD();
  545. s_ctx.frame();
  546. }
  547. bool renderFrame()
  548. {
  549. BGFX_CHECK_RENDER_THREAD();
  550. return s_ctx.renderFrame();
  551. }
  552. const uint32_t g_uniformTypeSize[UniformType::Count] =
  553. {
  554. sizeof(int32_t),
  555. sizeof(float),
  556. 0,
  557. 1*sizeof(int32_t),
  558. 1*sizeof(float),
  559. 2*sizeof(float),
  560. 3*sizeof(float),
  561. 4*sizeof(float),
  562. 3*3*sizeof(float),
  563. 4*4*sizeof(float),
  564. };
  565. void ConstantBuffer::writeUniform(UniformType::Enum _type, uint16_t _loc, const void* _value, uint16_t _num)
  566. {
  567. uint32_t opcode = encodeOpcode(_type, _loc, _num, true);
  568. write(opcode);
  569. write(_value, g_uniformTypeSize[_type]*_num);
  570. }
  571. void ConstantBuffer::writeUniformRef(UniformType::Enum _type, uint16_t _loc, const void* _value, uint16_t _num)
  572. {
  573. uint32_t opcode = encodeOpcode(_type, _loc, _num, false);
  574. write(opcode);
  575. write(&_value, sizeof(void*) );
  576. }
  577. void Context::init(bool _createRenderThread)
  578. {
  579. BX_CHECK(!m_rendererInitialized, "Already initialized?");
  580. BX_TRACE("init");
  581. m_exit = false;
  582. m_frames = 0;
  583. m_render = &m_frame[0];
  584. m_submit = &m_frame[1];
  585. m_debug = BGFX_DEBUG_NONE;
  586. m_submit->create();
  587. m_render->create();
  588. #if BGFX_CONFIG_MULTITHREADED
  589. if (_createRenderThread)
  590. {
  591. m_thread.init(renderThread, this);
  592. }
  593. #else
  594. BX_UNUSED(_createRenderThread);
  595. #endif // BGFX_CONFIG_MULTITHREADED
  596. memset(m_rt, 0xff, sizeof(m_rt) );
  597. memset(m_clear, 0, sizeof(m_clear) );
  598. memset(m_rect, 0, sizeof(m_rect) );
  599. memset(m_seq, 0, sizeof(m_seq) );
  600. memset(m_seqMask, 0, sizeof(m_seqMask) );
  601. for (uint32_t ii = 0; ii < countof(m_rect); ++ii)
  602. {
  603. m_rect[ii].m_width = 1;
  604. m_rect[ii].m_height = 1;
  605. }
  606. m_declRef.init();
  607. frameNoRenderWait();
  608. getCommandBuffer(CommandBuffer::RendererInit);
  609. m_textVideoMemBlitter.init();
  610. m_clearQuad.init();
  611. m_submit->m_transientVb = createTransientVertexBuffer(BGFX_CONFIG_TRANSIENT_VERTEX_BUFFER_SIZE);
  612. m_submit->m_transientIb = createTransientIndexBuffer(BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE);
  613. frame();
  614. m_submit->m_transientVb = createTransientVertexBuffer(BGFX_CONFIG_TRANSIENT_VERTEX_BUFFER_SIZE);
  615. m_submit->m_transientIb = createTransientIndexBuffer(BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE);
  616. frame();
  617. }
  618. void Context::shutdown()
  619. {
  620. BX_TRACE("shutdown");
  621. getCommandBuffer(CommandBuffer::RendererShutdownBegin);
  622. frame();
  623. destroyTransientVertexBuffer(m_submit->m_transientVb);
  624. destroyTransientIndexBuffer(m_submit->m_transientIb);
  625. m_textVideoMemBlitter.shutdown();
  626. m_clearQuad.shutdown();
  627. frame();
  628. destroyTransientVertexBuffer(m_submit->m_transientVb);
  629. destroyTransientIndexBuffer(m_submit->m_transientIb);
  630. frame();
  631. getCommandBuffer(CommandBuffer::RendererShutdownEnd);
  632. frame();
  633. m_declRef.shutdown(m_vertexDeclHandle);
  634. #if BGFX_CONFIG_MULTITHREADED
  635. if (m_thread.isRunning() )
  636. {
  637. m_thread.shutdown();
  638. }
  639. #endif // BGFX_CONFIG_MULTITHREADED
  640. renderSemWait();
  641. m_submit->destroy();
  642. m_render->destroy();
  643. #if BGFX_CONFIG_DEBUG
  644. # define CHECK_HANDLE_LEAK(_handleAlloc) \
  645. do { \
  646. BX_WARN(0 == _handleAlloc.getNumHandles(), "LEAK: " #_handleAlloc " %d (max: %d)", _handleAlloc.getNumHandles(), _handleAlloc.getMaxHandles() ); \
  647. } while (0)
  648. CHECK_HANDLE_LEAK(m_dynamicIndexBufferHandle);
  649. CHECK_HANDLE_LEAK(m_dynamicVertexBufferHandle);
  650. CHECK_HANDLE_LEAK(m_indexBufferHandle);
  651. CHECK_HANDLE_LEAK(m_vertexDeclHandle);
  652. CHECK_HANDLE_LEAK(m_vertexBufferHandle);
  653. CHECK_HANDLE_LEAK(m_vertexShaderHandle);
  654. CHECK_HANDLE_LEAK(m_fragmentShaderHandle);
  655. CHECK_HANDLE_LEAK(m_programHandle);
  656. CHECK_HANDLE_LEAK(m_textureHandle);
  657. CHECK_HANDLE_LEAK(m_renderTargetHandle);
  658. CHECK_HANDLE_LEAK(m_uniformHandle);
  659. # undef CHECK_HANDLE_LEAK
  660. #endif // BGFX_CONFIG_DEBUG
  661. }
  662. const Memory* alloc(uint32_t _size)
  663. {
  664. Memory* mem = (Memory*)g_realloc(NULL, sizeof(Memory) + _size);
  665. mem->size = _size;
  666. mem->data = (uint8_t*)mem + sizeof(Memory);
  667. return mem;
  668. }
  669. const Memory* makeRef(const void* _data, uint32_t _size)
  670. {
  671. Memory* mem = (Memory*)g_realloc(NULL, sizeof(Memory) );
  672. mem->size = _size;
  673. mem->data = (uint8_t*)_data;
  674. return mem;
  675. }
  676. void release(const Memory* _mem)
  677. {
  678. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  679. g_free(const_cast<Memory*>(_mem) );
  680. }
  681. void setDebug(uint32_t _debug)
  682. {
  683. BGFX_CHECK_MAIN_THREAD();
  684. s_ctx.m_debug = _debug;
  685. }
  686. void dbgTextClear(uint8_t _attr, bool _small)
  687. {
  688. BGFX_CHECK_MAIN_THREAD();
  689. s_ctx.dbgTextClear(_attr, _small);
  690. }
  691. void dbgTextPrintf(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, ...)
  692. {
  693. BGFX_CHECK_MAIN_THREAD();
  694. va_list argList;
  695. va_start(argList, _format);
  696. s_ctx.dbgTextPrintfVargs(_x, _y, _attr, _format, argList);
  697. va_end(argList);
  698. }
  699. IndexBufferHandle createIndexBuffer(const Memory* _mem)
  700. {
  701. BGFX_CHECK_MAIN_THREAD();
  702. return s_ctx.createIndexBuffer(_mem);
  703. }
  704. void destroyIndexBuffer(IndexBufferHandle _handle)
  705. {
  706. BGFX_CHECK_MAIN_THREAD();
  707. s_ctx.destroyIndexBuffer(_handle);
  708. }
  709. VertexBufferHandle createVertexBuffer(const Memory* _mem, const VertexDecl& _decl)
  710. {
  711. return s_ctx.createVertexBuffer(_mem, _decl);
  712. }
  713. void destroyVertexBuffer(VertexBufferHandle _handle)
  714. {
  715. BGFX_CHECK_MAIN_THREAD();
  716. s_ctx.destroyVertexBuffer(_handle);
  717. }
  718. DynamicIndexBufferHandle createDynamicIndexBuffer(uint16_t _num)
  719. {
  720. BGFX_CHECK_MAIN_THREAD();
  721. return s_ctx.createDynamicIndexBuffer(_num);
  722. }
  723. DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem)
  724. {
  725. BGFX_CHECK_MAIN_THREAD();
  726. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  727. return s_ctx.createDynamicIndexBuffer(_mem);
  728. }
  729. void updateDynamicIndexBuffer(DynamicIndexBufferHandle _handle, const Memory* _mem)
  730. {
  731. BGFX_CHECK_MAIN_THREAD();
  732. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  733. s_ctx.updateDynamicIndexBuffer(_handle, _mem);
  734. }
  735. void destroyDynamicIndexBuffer(DynamicIndexBufferHandle _handle)
  736. {
  737. BGFX_CHECK_MAIN_THREAD();
  738. s_ctx.destroyDynamicIndexBuffer(_handle);
  739. }
  740. DynamicVertexBufferHandle createDynamicVertexBuffer(uint16_t _num, const VertexDecl& _decl)
  741. {
  742. BGFX_CHECK_MAIN_THREAD();
  743. return s_ctx.createDynamicVertexBuffer(_num, _decl);
  744. }
  745. DynamicVertexBufferHandle createDynamicVertexBuffer(const Memory* _mem, const VertexDecl& _decl)
  746. {
  747. BGFX_CHECK_MAIN_THREAD();
  748. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  749. return s_ctx.createDynamicVertexBuffer(_mem, _decl);
  750. }
  751. void updateDynamicVertexBuffer(DynamicVertexBufferHandle _handle, const Memory* _mem)
  752. {
  753. BGFX_CHECK_MAIN_THREAD();
  754. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  755. s_ctx.updateDynamicVertexBuffer(_handle, _mem);
  756. }
  757. void destroyDynamicVertexBuffer(DynamicVertexBufferHandle _handle)
  758. {
  759. BGFX_CHECK_MAIN_THREAD();
  760. s_ctx.destroyDynamicVertexBuffer(_handle);
  761. }
  762. bool checkAvailTransientIndexBuffer(uint16_t _num)
  763. {
  764. BGFX_CHECK_MAIN_THREAD();
  765. return s_ctx.m_submit->checkAvailTransientIndexBuffer(_num);
  766. }
  767. void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint16_t _num)
  768. {
  769. BGFX_CHECK_MAIN_THREAD();
  770. BX_CHECK(NULL != _tib, "_tib can't be NULL");
  771. return s_ctx.allocTransientIndexBuffer(_tib, _num);
  772. }
  773. bool checkAvailTransientVertexBuffer(uint16_t _num, const VertexDecl& _decl)
  774. {
  775. BGFX_CHECK_MAIN_THREAD();
  776. return s_ctx.m_submit->checkAvailTransientVertexBuffer(_num, _decl.m_stride);
  777. }
  778. void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint16_t _num, const VertexDecl& _decl)
  779. {
  780. BGFX_CHECK_MAIN_THREAD();
  781. BX_CHECK(NULL != _tvb, "_tvb can't be NULL");
  782. return s_ctx.allocTransientVertexBuffer(_tvb, _num, _decl);
  783. }
  784. const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride)
  785. {
  786. BGFX_CHECK_MAIN_THREAD();
  787. return s_ctx.allocInstanceDataBuffer(_num, _stride);
  788. }
  789. VertexShaderHandle createVertexShader(const Memory* _mem)
  790. {
  791. BGFX_CHECK_MAIN_THREAD();
  792. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  793. return s_ctx.createVertexShader(_mem);
  794. }
  795. void destroyVertexShader(VertexShaderHandle _handle)
  796. {
  797. BGFX_CHECK_MAIN_THREAD();
  798. s_ctx.destroyVertexShader(_handle);
  799. }
  800. FragmentShaderHandle createFragmentShader(const Memory* _mem)
  801. {
  802. BGFX_CHECK_MAIN_THREAD();
  803. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  804. return s_ctx.createFragmentShader(_mem);
  805. }
  806. void destroyFragmentShader(FragmentShaderHandle _handle)
  807. {
  808. BGFX_CHECK_MAIN_THREAD();
  809. s_ctx.destroyFragmentShader(_handle);
  810. }
  811. ProgramHandle createProgram(VertexShaderHandle _vsh, FragmentShaderHandle _fsh)
  812. {
  813. BGFX_CHECK_MAIN_THREAD();
  814. return s_ctx.createProgram(_vsh, _fsh);
  815. }
  816. void destroyProgram(ProgramHandle _handle)
  817. {
  818. BGFX_CHECK_MAIN_THREAD();
  819. s_ctx.destroyProgram(_handle);
  820. }
  821. static const uint32_t s_bitsPerPixel[TextureFormat::Count] =
  822. {
  823. 4, // BC1
  824. 8, // BC2
  825. 8, // BC3
  826. 4, // BC4
  827. 8, // BC5
  828. 0, // Unknown
  829. 8, // L8
  830. 32, // BGRX8
  831. 32, // BGRA8
  832. 64, // RGBA16
  833. 64, // RGBA16F
  834. 16, // R5G6B5
  835. 16, // RGBA4
  836. 16, // RGB5A1
  837. 32, // RGB10A2
  838. };
  839. void calcTextureSize(TextureInfo& _info, uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format)
  840. {
  841. _width = uint32_max(1, _width);
  842. _height = uint32_max(1, _height);
  843. _depth = uint32_max(1, _depth);
  844. _numMips = uint32_max(1, _numMips);
  845. uint32_t width = _width;
  846. uint32_t height = _height;
  847. uint32_t depth = _depth;
  848. uint32_t bpp = s_bitsPerPixel[_format];
  849. uint32_t size = 0;
  850. for (uint32_t lod = 0; lod < _numMips; ++lod)
  851. {
  852. width = uint32_max(1, width);
  853. height = uint32_max(1, height);
  854. depth = uint32_max(1, depth);
  855. size += _width*_height*depth*bpp/8;
  856. width >>= 1;
  857. height >>= 1;
  858. depth >>= 1;
  859. }
  860. _info.format = _format;
  861. _info.storageSize = size;
  862. _info.width = _width;
  863. _info.height = _height;
  864. _info.depth = _depth;
  865. _info.numMips = _numMips;
  866. _info.bitsPerPixel = bpp;
  867. }
  868. TextureHandle createTexture(const Memory* _mem, uint32_t _flags, TextureInfo* _info)
  869. {
  870. BGFX_CHECK_MAIN_THREAD();
  871. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  872. return s_ctx.createTexture(_mem, _flags, _info);
  873. }
  874. TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
  875. {
  876. BGFX_CHECK_MAIN_THREAD();
  877. #if BGFX_CONFIG_DEBUG
  878. if (NULL != _mem)
  879. {
  880. TextureInfo ti;
  881. calcTextureSize(ti, _width, _height, 1, _numMips, _format);
  882. BX_CHECK(ti.storageSize == _mem->size
  883. , "createTexture2D: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
  884. , ti.storageSize
  885. , _mem->size
  886. );
  887. }
  888. #endif // BGFX_CONFIG_DEBUG
  889. uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
  890. const Memory* mem = alloc(size);
  891. bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
  892. uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
  893. bx::write(&writer, magic);
  894. TextureCreate tc;
  895. tc.m_flags = _flags;
  896. tc.m_width = _width;
  897. tc.m_height = _height;
  898. tc.m_sides = 0;
  899. tc.m_depth = 0;
  900. tc.m_numMips = _numMips;
  901. tc.m_format = uint8_t(_format);
  902. tc.m_cubeMap = false;
  903. tc.m_mem = _mem;
  904. bx::write(&writer, tc);
  905. return s_ctx.createTexture(mem, _flags, NULL);
  906. }
  907. TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
  908. {
  909. BGFX_CHECK_MAIN_THREAD();
  910. #if BGFX_CONFIG_DEBUG
  911. if (NULL != _mem)
  912. {
  913. TextureInfo ti;
  914. calcTextureSize(ti, _width, _height, _depth, _numMips, _format);
  915. BX_CHECK(ti.storageSize == _mem->size
  916. , "createTexture3D: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
  917. , ti.storageSize
  918. , _mem->size
  919. );
  920. }
  921. #endif // BGFX_CONFIG_DEBUG
  922. uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
  923. const Memory* mem = alloc(size);
  924. bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
  925. uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
  926. bx::write(&writer, magic);
  927. TextureCreate tc;
  928. tc.m_flags = _flags;
  929. tc.m_width = _width;
  930. tc.m_height = _height;
  931. tc.m_sides = 0;
  932. tc.m_depth = _depth;
  933. tc.m_numMips = _numMips;
  934. tc.m_format = uint8_t(_format);
  935. tc.m_cubeMap = false;
  936. tc.m_mem = _mem;
  937. bx::write(&writer, tc);
  938. return s_ctx.createTexture(mem, _flags, NULL);
  939. }
  940. TextureHandle createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
  941. {
  942. BGFX_CHECK_MAIN_THREAD();
  943. #if BGFX_CONFIG_DEBUG
  944. if (NULL != _mem)
  945. {
  946. TextureInfo ti;
  947. calcTextureSize(ti, _width, _width, 1, _numMips, _format);
  948. BX_CHECK(ti.storageSize*_sides == _mem->size
  949. , "createTextureCube: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
  950. , ti.storageSize*_sides
  951. , _mem->size
  952. );
  953. }
  954. #endif // BGFX_CONFIG_DEBUG
  955. uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
  956. const Memory* mem = alloc(size);
  957. bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
  958. uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
  959. bx::write(&writer, magic);
  960. TextureCreate tc;
  961. tc.m_flags = _flags;
  962. tc.m_width = _width;
  963. tc.m_height = _width;
  964. tc.m_sides = _sides;
  965. tc.m_depth = 0;
  966. tc.m_numMips = _numMips;
  967. tc.m_format = uint8_t(_format);
  968. tc.m_cubeMap = true;
  969. tc.m_mem = _mem;
  970. bx::write(&writer, tc);
  971. return s_ctx.createTexture(mem, _flags, NULL);
  972. }
  973. void destroyTexture(TextureHandle _handle)
  974. {
  975. BGFX_CHECK_MAIN_THREAD();
  976. s_ctx.destroyTexture(_handle);
  977. }
  978. void updateTexture2D(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem)
  979. {
  980. BGFX_CHECK_MAIN_THREAD();
  981. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  982. if (_width == 0
  983. || _height == 0)
  984. {
  985. release(_mem);
  986. }
  987. else
  988. {
  989. s_ctx.updateTexture(_handle, 0, _mip, _x, _y, 0, _width, _height, 1, _mem);
  990. }
  991. }
  992. void updateTexture3D(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, const Memory* _mem)
  993. {
  994. BGFX_CHECK_MAIN_THREAD();
  995. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  996. if (_width == 0
  997. || _height == 0
  998. || _depth == 0)
  999. {
  1000. release(_mem);
  1001. }
  1002. else
  1003. {
  1004. s_ctx.updateTexture(_handle, 0, _mip, _x, _y, _z, _width, _height, _depth, _mem);
  1005. }
  1006. }
  1007. void updateTextureCube(TextureHandle _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem)
  1008. {
  1009. BGFX_CHECK_MAIN_THREAD();
  1010. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  1011. BX_CHECK(_side >= 0 && _side <= 5, "Invalid side %d.", _side);
  1012. if (_width == 0
  1013. || _height == 0)
  1014. {
  1015. release(_mem);
  1016. }
  1017. else
  1018. {
  1019. s_ctx.updateTexture(_handle, _side, _mip, _x, _y, 0, _width, _height, 1, _mem);
  1020. }
  1021. }
  1022. RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags)
  1023. {
  1024. BGFX_CHECK_MAIN_THREAD();
  1025. BX_WARN(0 != _width && 0 != _height, "Render target resolution width or height cannot be 0 (width %d, height %d).", _width, _height);
  1026. return s_ctx.createRenderTarget(uint16_max(1, _width), uint16_max(1, _height), _flags, _textureFlags);
  1027. }
  1028. void destroyRenderTarget(RenderTargetHandle _handle)
  1029. {
  1030. BGFX_CHECK_MAIN_THREAD();
  1031. s_ctx.destroyRenderTarget(_handle);
  1032. }
  1033. UniformHandle createUniform(const char* _name, UniformType::Enum _type, uint16_t _num)
  1034. {
  1035. BGFX_CHECK_MAIN_THREAD();
  1036. return s_ctx.createUniform(_name, _type, _num);
  1037. }
  1038. void destroyUniform(UniformHandle _handle)
  1039. {
  1040. BGFX_CHECK_MAIN_THREAD();
  1041. s_ctx.destroyUniform(_handle);
  1042. }
  1043. void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
  1044. {
  1045. BGFX_CHECK_MAIN_THREAD();
  1046. s_ctx.setViewRect(_id, _x, _y, _width, _height);
  1047. }
  1048. void setViewRectMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
  1049. {
  1050. BGFX_CHECK_MAIN_THREAD();
  1051. s_ctx.setViewRectMask(_viewMask, _x, _y, _width, _height);
  1052. }
  1053. void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
  1054. {
  1055. BGFX_CHECK_MAIN_THREAD();
  1056. s_ctx.setViewClear(_id, _flags, _rgba, _depth, _stencil);
  1057. }
  1058. void setViewClearMask(uint32_t _viewMask, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
  1059. {
  1060. BGFX_CHECK_MAIN_THREAD();
  1061. s_ctx.setViewClearMask(_viewMask, _flags, _rgba, _depth, _stencil);
  1062. }
  1063. void setViewSeq(uint8_t _id, bool _enabled)
  1064. {
  1065. BGFX_CHECK_MAIN_THREAD();
  1066. s_ctx.setViewSeq(_id, _enabled);
  1067. }
  1068. void setViewSeqMask(uint32_t _viewMask, bool _enabled)
  1069. {
  1070. BGFX_CHECK_MAIN_THREAD();
  1071. s_ctx.setViewSeqMask(_viewMask, _enabled);
  1072. }
  1073. void setViewRenderTarget(uint8_t _id, RenderTargetHandle _handle)
  1074. {
  1075. BGFX_CHECK_MAIN_THREAD();
  1076. s_ctx.setViewRenderTarget(_id, _handle);
  1077. }
  1078. void setViewRenderTargetMask(uint32_t _mask, RenderTargetHandle _handle)
  1079. {
  1080. BGFX_CHECK_MAIN_THREAD();
  1081. s_ctx.setViewRenderTargetMask(_mask, _handle);
  1082. }
  1083. void setViewTransform(uint8_t _id, const void* _view, const void* _proj, uint8_t _other)
  1084. {
  1085. BGFX_CHECK_MAIN_THREAD();
  1086. s_ctx.m_submit->setViewTransform(_id, _view, _proj, _other);
  1087. }
  1088. void setViewTransformMask(uint32_t _viewMask, const void* _view, const void* _proj, uint8_t _other)
  1089. {
  1090. BGFX_CHECK_MAIN_THREAD();
  1091. s_ctx.m_submit->setViewTransformMask(_viewMask, _view, _proj, _other);
  1092. }
  1093. void setState(uint64_t _state)
  1094. {
  1095. BGFX_CHECK_MAIN_THREAD();
  1096. s_ctx.m_submit->setState(_state);
  1097. }
  1098. void setStencil(uint32_t _fstencil, uint32_t _bstencil)
  1099. {
  1100. BGFX_CHECK_MAIN_THREAD();
  1101. s_ctx.m_submit->setStencil(_fstencil, _bstencil);
  1102. }
  1103. uint32_t setTransform(const void* _mtx, uint16_t _num)
  1104. {
  1105. BGFX_CHECK_MAIN_THREAD();
  1106. return s_ctx.m_submit->setTransform(_mtx, _num);
  1107. }
  1108. void setTransform(uint32_t _cache, uint16_t _num)
  1109. {
  1110. BGFX_CHECK_MAIN_THREAD();
  1111. s_ctx.m_submit->setTransform(_cache, _num);
  1112. }
  1113. void setUniform(UniformHandle _handle, const void* _value, uint16_t _num)
  1114. {
  1115. BGFX_CHECK_MAIN_THREAD();
  1116. s_ctx.setUniform(_handle, _value, _num);
  1117. }
  1118. void setUniform(ProgramHandle _program, UniformHandle _handle, const void* _value)
  1119. {
  1120. BGFX_CHECK_MAIN_THREAD();
  1121. s_ctx.setUniform(_program, _handle, _value);
  1122. }
  1123. void setIndexBuffer(IndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices)
  1124. {
  1125. BGFX_CHECK_MAIN_THREAD();
  1126. s_ctx.m_submit->setIndexBuffer(_handle, _firstIndex, _numIndices);
  1127. }
  1128. void setIndexBuffer(DynamicIndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices)
  1129. {
  1130. BGFX_CHECK_MAIN_THREAD();
  1131. s_ctx.m_submit->setIndexBuffer(s_ctx.m_dynamicIndexBuffers[_handle.idx].m_handle, _firstIndex, _numIndices);
  1132. }
  1133. void setIndexBuffer(const TransientIndexBuffer* _tib, uint32_t _numIndices)
  1134. {
  1135. BGFX_CHECK_MAIN_THREAD();
  1136. BX_CHECK(NULL != _tib, "_tib can't be NULL");
  1137. uint32_t numIndices = uint32_min(_numIndices, _tib->size/2);
  1138. s_ctx.m_submit->setIndexBuffer(_tib, numIndices);
  1139. }
  1140. void setVertexBuffer(VertexBufferHandle _handle, uint32_t _numVertices)
  1141. {
  1142. BGFX_CHECK_MAIN_THREAD();
  1143. s_ctx.m_submit->setVertexBuffer(_handle, _numVertices);
  1144. }
  1145. void setVertexBuffer(DynamicVertexBufferHandle _handle, uint32_t _numVertices)
  1146. {
  1147. BGFX_CHECK_MAIN_THREAD();
  1148. s_ctx.m_submit->setVertexBuffer(s_ctx.m_dynamicVertexBuffers[_handle.idx], _numVertices);
  1149. }
  1150. void setVertexBuffer(const TransientVertexBuffer* _tvb, uint32_t _numVertices)
  1151. {
  1152. BGFX_CHECK_MAIN_THREAD();
  1153. BX_CHECK(NULL != _tvb, "_tvb can't be NULL");
  1154. s_ctx.m_submit->setVertexBuffer(_tvb, _numVertices);
  1155. }
  1156. void setInstanceDataBuffer(const InstanceDataBuffer* _idb, uint16_t _num)
  1157. {
  1158. BGFX_CHECK_MAIN_THREAD();
  1159. s_ctx.m_submit->setInstanceDataBuffer(_idb, _num);
  1160. }
  1161. void setProgram(ProgramHandle _handle)
  1162. {
  1163. BGFX_CHECK_MAIN_THREAD();
  1164. s_ctx.m_submit->setProgram(_handle);
  1165. }
  1166. void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle)
  1167. {
  1168. BGFX_CHECK_MAIN_THREAD();
  1169. s_ctx.m_submit->setTexture(_stage, _sampler, _handle);
  1170. }
  1171. void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth)
  1172. {
  1173. BGFX_CHECK_MAIN_THREAD();
  1174. s_ctx.m_submit->setTexture(_stage, _sampler, _handle, _depth);
  1175. }
  1176. void submit(uint8_t _id, int32_t _depth)
  1177. {
  1178. BGFX_CHECK_MAIN_THREAD();
  1179. s_ctx.m_submit->submit(_id, _depth);
  1180. }
  1181. void submitMask(uint32_t _viewMask, int32_t _depth)
  1182. {
  1183. BGFX_CHECK_MAIN_THREAD();
  1184. s_ctx.m_submit->submitMask(_viewMask, _depth);
  1185. }
  1186. void saveScreenShot(const char* _filePath)
  1187. {
  1188. BGFX_CHECK_MAIN_THREAD();
  1189. uint32_t len = (uint32_t)strlen(_filePath)+1;
  1190. const Memory* mem = alloc(len);
  1191. memcpy(mem->data, _filePath, mem->size);
  1192. return s_ctx.saveScreenShot(mem);
  1193. }
  1194. }