bgfx.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
  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(2048, 24, 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_TRACE("init");
  580. m_submit->create();
  581. m_render->create();
  582. #if BGFX_CONFIG_MULTITHREADED
  583. if (_createRenderThread)
  584. {
  585. m_thread.init(renderThread, this);
  586. }
  587. #else
  588. BX_UNUSED(_createRenderThread);
  589. #endif // BGFX_CONFIG_MULTITHREADED
  590. memset(m_rt, 0xff, sizeof(m_rt) );
  591. memset(m_clear, 0, sizeof(m_clear) );
  592. memset(m_rect, 0, sizeof(m_rect) );
  593. memset(m_seq, 0, sizeof(m_seq) );
  594. memset(m_seqMask, 0, sizeof(m_seqMask) );
  595. for (uint32_t ii = 0; ii < countof(m_rect); ++ii)
  596. {
  597. m_rect[ii].m_width = 1;
  598. m_rect[ii].m_height = 1;
  599. }
  600. gameSemPost();
  601. getCommandBuffer(CommandBuffer::RendererInit);
  602. m_textVideoMemBlitter.init();
  603. m_clearQuad.init();
  604. m_submit->m_transientVb = createTransientVertexBuffer(BGFX_CONFIG_TRANSIENT_VERTEX_BUFFER_SIZE);
  605. m_submit->m_transientIb = createTransientIndexBuffer(BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE);
  606. frame();
  607. m_submit->m_transientVb = createTransientVertexBuffer(BGFX_CONFIG_TRANSIENT_VERTEX_BUFFER_SIZE);
  608. m_submit->m_transientIb = createTransientIndexBuffer(BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE);
  609. frame();
  610. }
  611. void Context::shutdown()
  612. {
  613. BX_TRACE("shutdown");
  614. getCommandBuffer(CommandBuffer::RendererShutdownBegin);
  615. frame();
  616. destroyTransientVertexBuffer(m_submit->m_transientVb);
  617. destroyTransientIndexBuffer(m_submit->m_transientIb);
  618. m_textVideoMemBlitter.shutdown();
  619. m_clearQuad.shutdown();
  620. frame();
  621. destroyTransientVertexBuffer(m_submit->m_transientVb);
  622. destroyTransientIndexBuffer(m_submit->m_transientIb);
  623. frame();
  624. getCommandBuffer(CommandBuffer::RendererShutdownEnd);
  625. frame();
  626. #if BGFX_CONFIG_MULTITHREADED
  627. if (m_thread.isRunning() )
  628. {
  629. m_thread.shutdown();
  630. }
  631. #endif // BGFX_CONFIG_MULTITHREADED
  632. m_submit->destroy();
  633. m_render->destroy();
  634. #if BGFX_CONFIG_DEBUG
  635. # define CHECK_HANDLE_LEAK(_handleAlloc) \
  636. do { \
  637. BX_WARN(0 == _handleAlloc.getNumHandles(), "LEAK: " #_handleAlloc " %d (max: %d)", _handleAlloc.getNumHandles(), _handleAlloc.getMaxHandles() ); \
  638. } while (0)
  639. CHECK_HANDLE_LEAK(m_dynamicIndexBufferHandle);
  640. CHECK_HANDLE_LEAK(m_dynamicVertexBufferHandle);
  641. CHECK_HANDLE_LEAK(m_indexBufferHandle);
  642. CHECK_HANDLE_LEAK(m_vertexDeclHandle);
  643. CHECK_HANDLE_LEAK(m_vertexBufferHandle);
  644. CHECK_HANDLE_LEAK(m_vertexShaderHandle);
  645. CHECK_HANDLE_LEAK(m_fragmentShaderHandle);
  646. CHECK_HANDLE_LEAK(m_programHandle);
  647. CHECK_HANDLE_LEAK(m_textureHandle);
  648. CHECK_HANDLE_LEAK(m_renderTargetHandle);
  649. CHECK_HANDLE_LEAK(m_uniformHandle);
  650. # undef CHECK_HANDLE_LEAK
  651. #endif // BGFX_CONFIG_DEBUG
  652. }
  653. const Memory* alloc(uint32_t _size)
  654. {
  655. Memory* mem = (Memory*)g_realloc(NULL, sizeof(Memory) + _size);
  656. mem->size = _size;
  657. mem->data = (uint8_t*)mem + sizeof(Memory);
  658. return mem;
  659. }
  660. const Memory* makeRef(const void* _data, uint32_t _size)
  661. {
  662. Memory* mem = (Memory*)g_realloc(NULL, sizeof(Memory) );
  663. mem->size = _size;
  664. mem->data = (uint8_t*)_data;
  665. return mem;
  666. }
  667. void release(const Memory* _mem)
  668. {
  669. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  670. g_free(const_cast<Memory*>(_mem) );
  671. }
  672. void setDebug(uint32_t _debug)
  673. {
  674. BGFX_CHECK_MAIN_THREAD();
  675. s_ctx.m_debug = _debug;
  676. }
  677. void dbgTextClear(uint8_t _attr, bool _small)
  678. {
  679. BGFX_CHECK_MAIN_THREAD();
  680. s_ctx.dbgTextClear(_attr, _small);
  681. }
  682. void dbgTextPrintf(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, ...)
  683. {
  684. BGFX_CHECK_MAIN_THREAD();
  685. va_list argList;
  686. va_start(argList, _format);
  687. s_ctx.dbgTextPrintfVargs(_x, _y, _attr, _format, argList);
  688. va_end(argList);
  689. }
  690. IndexBufferHandle createIndexBuffer(const Memory* _mem)
  691. {
  692. BGFX_CHECK_MAIN_THREAD();
  693. return s_ctx.createIndexBuffer(_mem);
  694. }
  695. void destroyIndexBuffer(IndexBufferHandle _handle)
  696. {
  697. BGFX_CHECK_MAIN_THREAD();
  698. s_ctx.destroyIndexBuffer(_handle);
  699. }
  700. VertexBufferHandle createVertexBuffer(const Memory* _mem, const VertexDecl& _decl)
  701. {
  702. return s_ctx.createVertexBuffer(_mem, _decl);
  703. }
  704. void destroyVertexBuffer(VertexBufferHandle _handle)
  705. {
  706. BGFX_CHECK_MAIN_THREAD();
  707. s_ctx.destroyVertexBuffer(_handle);
  708. }
  709. DynamicIndexBufferHandle createDynamicIndexBuffer(uint16_t _num)
  710. {
  711. BGFX_CHECK_MAIN_THREAD();
  712. return s_ctx.createDynamicIndexBuffer(_num);
  713. }
  714. DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem)
  715. {
  716. BGFX_CHECK_MAIN_THREAD();
  717. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  718. return s_ctx.createDynamicIndexBuffer(_mem);
  719. }
  720. void updateDynamicIndexBuffer(DynamicIndexBufferHandle _handle, const Memory* _mem)
  721. {
  722. BGFX_CHECK_MAIN_THREAD();
  723. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  724. s_ctx.updateDynamicIndexBuffer(_handle, _mem);
  725. }
  726. void destroyDynamicIndexBuffer(DynamicIndexBufferHandle _handle)
  727. {
  728. BGFX_CHECK_MAIN_THREAD();
  729. s_ctx.destroyDynamicIndexBuffer(_handle);
  730. }
  731. DynamicVertexBufferHandle createDynamicVertexBuffer(uint16_t _num, const VertexDecl& _decl)
  732. {
  733. BGFX_CHECK_MAIN_THREAD();
  734. return s_ctx.createDynamicVertexBuffer(_num, _decl);
  735. }
  736. DynamicVertexBufferHandle createDynamicVertexBuffer(const Memory* _mem, const VertexDecl& _decl)
  737. {
  738. BGFX_CHECK_MAIN_THREAD();
  739. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  740. return s_ctx.createDynamicVertexBuffer(_mem, _decl);
  741. }
  742. void updateDynamicVertexBuffer(DynamicVertexBufferHandle _handle, const Memory* _mem)
  743. {
  744. BGFX_CHECK_MAIN_THREAD();
  745. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  746. s_ctx.updateDynamicVertexBuffer(_handle, _mem);
  747. }
  748. void destroyDynamicVertexBuffer(DynamicVertexBufferHandle _handle)
  749. {
  750. BGFX_CHECK_MAIN_THREAD();
  751. s_ctx.destroyDynamicVertexBuffer(_handle);
  752. }
  753. bool checkAvailTransientIndexBuffer(uint16_t _num)
  754. {
  755. BGFX_CHECK_MAIN_THREAD();
  756. return s_ctx.m_submit->checkAvailTransientIndexBuffer(_num);
  757. }
  758. void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint16_t _num)
  759. {
  760. BGFX_CHECK_MAIN_THREAD();
  761. BX_CHECK(NULL != _tib, "_tib can't be NULL");
  762. return s_ctx.allocTransientIndexBuffer(_tib, _num);
  763. }
  764. bool checkAvailTransientVertexBuffer(uint16_t _num, const VertexDecl& _decl)
  765. {
  766. BGFX_CHECK_MAIN_THREAD();
  767. return s_ctx.m_submit->checkAvailTransientVertexBuffer(_num, _decl.m_stride);
  768. }
  769. void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint16_t _num, const VertexDecl& _decl)
  770. {
  771. BGFX_CHECK_MAIN_THREAD();
  772. BX_CHECK(NULL != _tvb, "_tvb can't be NULL");
  773. return s_ctx.allocTransientVertexBuffer(_tvb, _num, _decl);
  774. }
  775. const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride)
  776. {
  777. BGFX_CHECK_MAIN_THREAD();
  778. return s_ctx.allocInstanceDataBuffer(_num, _stride);
  779. }
  780. VertexShaderHandle createVertexShader(const Memory* _mem)
  781. {
  782. BGFX_CHECK_MAIN_THREAD();
  783. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  784. return s_ctx.createVertexShader(_mem);
  785. }
  786. void destroyVertexShader(VertexShaderHandle _handle)
  787. {
  788. BGFX_CHECK_MAIN_THREAD();
  789. s_ctx.destroyVertexShader(_handle);
  790. }
  791. FragmentShaderHandle createFragmentShader(const Memory* _mem)
  792. {
  793. BGFX_CHECK_MAIN_THREAD();
  794. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  795. return s_ctx.createFragmentShader(_mem);
  796. }
  797. void destroyFragmentShader(FragmentShaderHandle _handle)
  798. {
  799. BGFX_CHECK_MAIN_THREAD();
  800. s_ctx.destroyFragmentShader(_handle);
  801. }
  802. ProgramHandle createProgram(VertexShaderHandle _vsh, FragmentShaderHandle _fsh)
  803. {
  804. BGFX_CHECK_MAIN_THREAD();
  805. return s_ctx.createProgram(_vsh, _fsh);
  806. }
  807. void destroyProgram(ProgramHandle _handle)
  808. {
  809. BGFX_CHECK_MAIN_THREAD();
  810. s_ctx.destroyProgram(_handle);
  811. }
  812. static const uint32_t s_bitsPerPixel[TextureFormat::Count] =
  813. {
  814. 4, // BC1
  815. 8, // BC2
  816. 8, // BC3
  817. 4, // BC4
  818. 8, // BC5
  819. 0, // Unknown
  820. 8, // L8
  821. 32, // BGRX8
  822. 32, // BGRA8
  823. 64, // RGBA16
  824. 64, // RGBA16F
  825. 16, // R5G6B5
  826. 16, // RGBA4
  827. 16, // RGB5A1
  828. 32, // RGB10A2
  829. };
  830. void calcTextureSize(TextureInfo& _info, uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format)
  831. {
  832. _width = uint32_max(1, _width);
  833. _height = uint32_max(1, _height);
  834. _depth = uint32_max(1, _depth);
  835. _numMips = uint32_max(1, _numMips);
  836. uint32_t width = _width;
  837. uint32_t height = _height;
  838. uint32_t depth = _depth;
  839. uint32_t bpp = s_bitsPerPixel[_format];
  840. uint32_t size = 0;
  841. for (uint32_t lod = 0; lod < _numMips; ++lod)
  842. {
  843. width = uint32_max(1, width);
  844. height = uint32_max(1, height);
  845. depth = uint32_max(1, depth);
  846. size += _width*_height*depth*bpp/8;
  847. width >>= 1;
  848. height >>= 1;
  849. depth >>= 1;
  850. }
  851. _info.format = _format;
  852. _info.storageSize = size;
  853. _info.width = _width;
  854. _info.height = _height;
  855. _info.depth = _depth;
  856. _info.numMips = _numMips;
  857. _info.bitsPerPixel = bpp;
  858. }
  859. TextureHandle createTexture(const Memory* _mem, uint32_t _flags, TextureInfo* _info)
  860. {
  861. BGFX_CHECK_MAIN_THREAD();
  862. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  863. return s_ctx.createTexture(_mem, _flags, _info);
  864. }
  865. TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
  866. {
  867. BGFX_CHECK_MAIN_THREAD();
  868. #if BGFX_CONFIG_DEBUG
  869. if (NULL != _mem)
  870. {
  871. TextureInfo ti;
  872. calcTextureSize(ti, _width, _height, 1, _numMips, _format);
  873. BX_CHECK(ti.storageSize == _mem->size
  874. , "createTexture2D: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
  875. , ti.storageSize
  876. , _mem->size
  877. );
  878. }
  879. #endif // BGFX_CONFIG_DEBUG
  880. uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
  881. const Memory* mem = alloc(size);
  882. bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
  883. uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
  884. bx::write(&writer, magic);
  885. TextureCreate tc;
  886. tc.m_flags = _flags;
  887. tc.m_width = _width;
  888. tc.m_height = _height;
  889. tc.m_sides = 0;
  890. tc.m_depth = 0;
  891. tc.m_numMips = _numMips;
  892. tc.m_format = uint8_t(_format);
  893. tc.m_cubeMap = false;
  894. tc.m_mem = _mem;
  895. bx::write(&writer, tc);
  896. return s_ctx.createTexture(mem, _flags, NULL);
  897. }
  898. TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
  899. {
  900. BGFX_CHECK_MAIN_THREAD();
  901. #if BGFX_CONFIG_DEBUG
  902. if (NULL != _mem)
  903. {
  904. TextureInfo ti;
  905. calcTextureSize(ti, _width, _height, _depth, _numMips, _format);
  906. BX_CHECK(ti.storageSize == _mem->size
  907. , "createTexture3D: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
  908. , ti.storageSize
  909. , _mem->size
  910. );
  911. }
  912. #endif // BGFX_CONFIG_DEBUG
  913. uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
  914. const Memory* mem = alloc(size);
  915. bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
  916. uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
  917. bx::write(&writer, magic);
  918. TextureCreate tc;
  919. tc.m_flags = _flags;
  920. tc.m_width = _width;
  921. tc.m_height = _height;
  922. tc.m_sides = 0;
  923. tc.m_depth = _depth;
  924. tc.m_numMips = _numMips;
  925. tc.m_format = uint8_t(_format);
  926. tc.m_cubeMap = false;
  927. tc.m_mem = _mem;
  928. bx::write(&writer, tc);
  929. return s_ctx.createTexture(mem, _flags, NULL);
  930. }
  931. TextureHandle createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
  932. {
  933. BGFX_CHECK_MAIN_THREAD();
  934. #if BGFX_CONFIG_DEBUG
  935. if (NULL != _mem)
  936. {
  937. TextureInfo ti;
  938. calcTextureSize(ti, _width, _width, 1, _numMips, _format);
  939. BX_CHECK(ti.storageSize*_sides == _mem->size
  940. , "createTextureCube: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
  941. , ti.storageSize*_sides
  942. , _mem->size
  943. );
  944. }
  945. #endif // BGFX_CONFIG_DEBUG
  946. uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
  947. const Memory* mem = alloc(size);
  948. bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
  949. uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
  950. bx::write(&writer, magic);
  951. TextureCreate tc;
  952. tc.m_flags = _flags;
  953. tc.m_width = _width;
  954. tc.m_height = _width;
  955. tc.m_sides = _sides;
  956. tc.m_depth = 0;
  957. tc.m_numMips = _numMips;
  958. tc.m_format = uint8_t(_format);
  959. tc.m_cubeMap = true;
  960. tc.m_mem = _mem;
  961. bx::write(&writer, tc);
  962. return s_ctx.createTexture(mem, _flags, NULL);
  963. }
  964. void destroyTexture(TextureHandle _handle)
  965. {
  966. BGFX_CHECK_MAIN_THREAD();
  967. s_ctx.destroyTexture(_handle);
  968. }
  969. void updateTexture2D(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem)
  970. {
  971. BGFX_CHECK_MAIN_THREAD();
  972. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  973. if (_width == 0
  974. || _height == 0)
  975. {
  976. release(_mem);
  977. }
  978. else
  979. {
  980. s_ctx.updateTexture(_handle, 0, _mip, _x, _y, 0, _width, _height, 1, _mem);
  981. }
  982. }
  983. 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)
  984. {
  985. BGFX_CHECK_MAIN_THREAD();
  986. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  987. if (_width == 0
  988. || _height == 0
  989. || _depth == 0)
  990. {
  991. release(_mem);
  992. }
  993. else
  994. {
  995. s_ctx.updateTexture(_handle, 0, _mip, _x, _y, _z, _width, _height, _depth, _mem);
  996. }
  997. }
  998. 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)
  999. {
  1000. BGFX_CHECK_MAIN_THREAD();
  1001. BX_CHECK(NULL != _mem, "_mem can't be NULL");
  1002. BX_CHECK(_side >= 0 && _side <= 5, "Invalid side %d.", _side);
  1003. if (_width == 0
  1004. || _height == 0)
  1005. {
  1006. release(_mem);
  1007. }
  1008. else
  1009. {
  1010. s_ctx.updateTexture(_handle, _side, _mip, _x, _y, 0, _width, _height, 1, _mem);
  1011. }
  1012. }
  1013. RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags)
  1014. {
  1015. BGFX_CHECK_MAIN_THREAD();
  1016. return s_ctx.createRenderTarget(_width, _height, _flags, _textureFlags);
  1017. }
  1018. void destroyRenderTarget(RenderTargetHandle _handle)
  1019. {
  1020. BGFX_CHECK_MAIN_THREAD();
  1021. s_ctx.destroyRenderTarget(_handle);
  1022. }
  1023. UniformHandle createUniform(const char* _name, UniformType::Enum _type, uint16_t _num)
  1024. {
  1025. BGFX_CHECK_MAIN_THREAD();
  1026. return s_ctx.createUniform(_name, _type, _num);
  1027. }
  1028. void destroyUniform(UniformHandle _handle)
  1029. {
  1030. BGFX_CHECK_MAIN_THREAD();
  1031. s_ctx.destroyUniform(_handle);
  1032. }
  1033. void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
  1034. {
  1035. BGFX_CHECK_MAIN_THREAD();
  1036. s_ctx.setViewRect(_id, _x, _y, _width, _height);
  1037. }
  1038. void setViewRectMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
  1039. {
  1040. BGFX_CHECK_MAIN_THREAD();
  1041. s_ctx.setViewRectMask(_viewMask, _x, _y, _width, _height);
  1042. }
  1043. void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
  1044. {
  1045. BGFX_CHECK_MAIN_THREAD();
  1046. s_ctx.setViewClear(_id, _flags, _rgba, _depth, _stencil);
  1047. }
  1048. void setViewClearMask(uint32_t _viewMask, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
  1049. {
  1050. BGFX_CHECK_MAIN_THREAD();
  1051. s_ctx.setViewClearMask(_viewMask, _flags, _rgba, _depth, _stencil);
  1052. }
  1053. void setViewSeq(uint8_t _id, bool _enabled)
  1054. {
  1055. BGFX_CHECK_MAIN_THREAD();
  1056. s_ctx.setViewSeq(_id, _enabled);
  1057. }
  1058. void setViewSeqMask(uint32_t _viewMask, bool _enabled)
  1059. {
  1060. BGFX_CHECK_MAIN_THREAD();
  1061. s_ctx.setViewSeqMask(_viewMask, _enabled);
  1062. }
  1063. void setViewRenderTarget(uint8_t _id, RenderTargetHandle _handle)
  1064. {
  1065. BGFX_CHECK_MAIN_THREAD();
  1066. s_ctx.setViewRenderTarget(_id, _handle);
  1067. }
  1068. void setViewRenderTargetMask(uint32_t _mask, RenderTargetHandle _handle)
  1069. {
  1070. BGFX_CHECK_MAIN_THREAD();
  1071. s_ctx.setViewRenderTargetMask(_mask, _handle);
  1072. }
  1073. void setViewTransform(uint8_t _id, const void* _view, const void* _proj, uint8_t _other)
  1074. {
  1075. BGFX_CHECK_MAIN_THREAD();
  1076. s_ctx.m_submit->setViewTransform(_id, _view, _proj, _other);
  1077. }
  1078. void setViewTransformMask(uint32_t _viewMask, const void* _view, const void* _proj, uint8_t _other)
  1079. {
  1080. BGFX_CHECK_MAIN_THREAD();
  1081. s_ctx.m_submit->setViewTransformMask(_viewMask, _view, _proj, _other);
  1082. }
  1083. void setState(uint64_t _state)
  1084. {
  1085. BGFX_CHECK_MAIN_THREAD();
  1086. s_ctx.m_submit->setState(_state);
  1087. }
  1088. void setStencil(uint32_t _fstencil, uint32_t _bstencil)
  1089. {
  1090. BGFX_CHECK_MAIN_THREAD();
  1091. s_ctx.m_submit->setStencil(_fstencil, _bstencil);
  1092. }
  1093. uint32_t setTransform(const void* _mtx, uint16_t _num)
  1094. {
  1095. BGFX_CHECK_MAIN_THREAD();
  1096. return s_ctx.m_submit->setTransform(_mtx, _num);
  1097. }
  1098. void setTransform(uint32_t _cache, uint16_t _num)
  1099. {
  1100. BGFX_CHECK_MAIN_THREAD();
  1101. s_ctx.m_submit->setTransform(_cache, _num);
  1102. }
  1103. void setUniform(UniformHandle _handle, const void* _value, uint16_t _num)
  1104. {
  1105. BGFX_CHECK_MAIN_THREAD();
  1106. s_ctx.setUniform(_handle, _value, _num);
  1107. }
  1108. void setUniform(ProgramHandle _program, UniformHandle _handle, const void* _value)
  1109. {
  1110. BGFX_CHECK_MAIN_THREAD();
  1111. s_ctx.setUniform(_program, _handle, _value);
  1112. }
  1113. void setIndexBuffer(IndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices)
  1114. {
  1115. BGFX_CHECK_MAIN_THREAD();
  1116. s_ctx.m_submit->setIndexBuffer(_handle, _firstIndex, _numIndices);
  1117. }
  1118. void setIndexBuffer(DynamicIndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices)
  1119. {
  1120. BGFX_CHECK_MAIN_THREAD();
  1121. s_ctx.m_submit->setIndexBuffer(s_ctx.m_dynamicIndexBuffers[_handle.idx].m_handle, _firstIndex, _numIndices);
  1122. }
  1123. void setIndexBuffer(const TransientIndexBuffer* _tib, uint32_t _numIndices)
  1124. {
  1125. BGFX_CHECK_MAIN_THREAD();
  1126. BX_CHECK(NULL != _tib, "_tib can't be NULL");
  1127. uint32_t numIndices = uint32_min(_numIndices, _tib->size/2);
  1128. s_ctx.m_submit->setIndexBuffer(_tib, numIndices);
  1129. }
  1130. void setVertexBuffer(VertexBufferHandle _handle, uint32_t _numVertices)
  1131. {
  1132. BGFX_CHECK_MAIN_THREAD();
  1133. s_ctx.m_submit->setVertexBuffer(_handle, _numVertices);
  1134. }
  1135. void setVertexBuffer(DynamicVertexBufferHandle _handle, uint32_t _numVertices)
  1136. {
  1137. BGFX_CHECK_MAIN_THREAD();
  1138. s_ctx.m_submit->setVertexBuffer(s_ctx.m_dynamicVertexBuffers[_handle.idx], _numVertices);
  1139. }
  1140. void setVertexBuffer(const TransientVertexBuffer* _tvb, uint32_t _numVertices)
  1141. {
  1142. BGFX_CHECK_MAIN_THREAD();
  1143. BX_CHECK(NULL != _tvb, "_tvb can't be NULL");
  1144. s_ctx.m_submit->setVertexBuffer(_tvb, _numVertices);
  1145. }
  1146. void setInstanceDataBuffer(const InstanceDataBuffer* _idb, uint16_t _num)
  1147. {
  1148. BGFX_CHECK_MAIN_THREAD();
  1149. s_ctx.m_submit->setInstanceDataBuffer(_idb, _num);
  1150. }
  1151. void setProgram(ProgramHandle _handle)
  1152. {
  1153. BGFX_CHECK_MAIN_THREAD();
  1154. s_ctx.m_submit->setProgram(_handle);
  1155. }
  1156. void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle)
  1157. {
  1158. BGFX_CHECK_MAIN_THREAD();
  1159. s_ctx.m_submit->setTexture(_stage, _sampler, _handle);
  1160. }
  1161. void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth)
  1162. {
  1163. BGFX_CHECK_MAIN_THREAD();
  1164. s_ctx.m_submit->setTexture(_stage, _sampler, _handle, _depth);
  1165. }
  1166. void submit(uint8_t _id, int32_t _depth)
  1167. {
  1168. BGFX_CHECK_MAIN_THREAD();
  1169. s_ctx.m_submit->submit(_id, _depth);
  1170. }
  1171. void submitMask(uint32_t _viewMask, int32_t _depth)
  1172. {
  1173. BGFX_CHECK_MAIN_THREAD();
  1174. s_ctx.m_submit->submitMask(_viewMask, _depth);
  1175. }
  1176. void saveScreenShot(const char* _filePath)
  1177. {
  1178. BGFX_CHECK_MAIN_THREAD();
  1179. uint32_t len = (uint32_t)strlen(_filePath)+1;
  1180. const Memory* mem = alloc(len);
  1181. memcpy(mem->data, _filePath, mem->size);
  1182. return s_ctx.saveScreenShot(mem);
  1183. }
  1184. }