sokol_debugtext_test.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. //------------------------------------------------------------------------------
  2. // sokol-debugtext-test.c
  3. // For best results, run with ASAN and UBSAN.
  4. //------------------------------------------------------------------------------
  5. #include "sokol_gfx.h"
  6. #include "sokol_log.h"
  7. #define SOKOL_DEBUGTEXT_IMPL
  8. #include "sokol_debugtext.h"
  9. #include "utest.h"
  10. #define T(b) EXPECT_TRUE(b)
  11. #define TFLT(f0,f1) {T(fabs((f0)-(f1))<=(0.000001));}
  12. static void init(void) {
  13. sg_setup(&(sg_desc){ .logger = { .func = slog_func }});
  14. sdtx_setup(&(sdtx_desc_t){ .logger = { .func = slog_func }});
  15. }
  16. static void init_with(const sdtx_desc_t* desc) {
  17. sg_setup(&(sg_desc){0});
  18. sdtx_setup(desc);
  19. }
  20. static void shutdown(void) {
  21. sdtx_shutdown();
  22. sg_shutdown();
  23. }
  24. UTEST(sokol_debugtext, default_init_shutdown) {
  25. init();
  26. T(_sdtx.init_cookie == _SDTX_INIT_COOKIE);
  27. T(_sdtx.desc.context_pool_size == _SDTX_DEFAULT_CONTEXT_POOL_SIZE);
  28. T(_sdtx.desc.printf_buf_size == _SDTX_DEFAULT_PRINTF_BUF_SIZE);
  29. T(_sdtx.desc.context.char_buf_size == _SDTX_DEFAULT_CHAR_BUF_SIZE);
  30. T(_sdtx.desc.context.canvas_width == _SDTX_DEFAULT_CANVAS_WIDTH);
  31. T(_sdtx.desc.context.canvas_height == _SDTX_DEFAULT_CANVAS_HEIGHT);
  32. T(_sdtx.desc.context.tab_width == _SDTX_DEFAULT_TAB_WIDTH);
  33. T(_sdtx.desc.context.color_format == 0);
  34. T(_sdtx.desc.context.depth_format == 0);
  35. T(_sdtx.desc.context.sample_count == 0);
  36. for (int i = 0; i < SDTX_MAX_FONTS; i++) {
  37. T(_sdtx.desc.fonts[i].data.ptr == 0);
  38. T(_sdtx.desc.fonts[i].data.size == 0);
  39. T(_sdtx.desc.fonts[i].first_char == 0);
  40. T(_sdtx.desc.fonts[i].last_char == 0);
  41. }
  42. T(_sdtx.font_img.id != SG_INVALID_ID);
  43. T(_sdtx.shader.id != SG_INVALID_ID);
  44. T(_sdtx.fmt_buf_size == (_SDTX_DEFAULT_CHAR_BUF_SIZE + 1));
  45. T(_sdtx.fmt_buf);
  46. T(_sdtx.def_ctx_id.id != 0);
  47. T(_sdtx.def_ctx_id.id == _sdtx.cur_ctx_id.id);
  48. T(_sdtx.cur_ctx == _sdtx_lookup_context(_sdtx.cur_ctx_id.id));
  49. T(_sdtx.cur_ctx->desc.char_buf_size == _sdtx.desc.context.char_buf_size);
  50. T(_sdtx.cur_ctx->desc.canvas_width == _sdtx.desc.context.canvas_width);
  51. T(_sdtx.cur_ctx->desc.canvas_height == _sdtx.desc.context.canvas_height);
  52. T(_sdtx.cur_ctx->desc.tab_width == _sdtx.desc.context.tab_width);
  53. T(_sdtx.cur_ctx->desc.color_format == 0);
  54. T(_sdtx.cur_ctx->desc.depth_format == 0);
  55. T(_sdtx.cur_ctx->desc.sample_count == 0);
  56. T(_sdtx.cur_ctx->vertices.cap == _SDTX_DEFAULT_CHAR_BUF_SIZE * 6);
  57. T(_sdtx.cur_ctx->vertices.next == 0);
  58. T(_sdtx.cur_ctx->vertices.ptr);
  59. T(_sdtx.cur_ctx->commands.cap == _SDTX_DEFAULT_MAX_COMMANDS);
  60. T(_sdtx.cur_ctx->commands.next == 1);
  61. T(_sdtx.cur_ctx->commands.ptr);
  62. T(_sdtx.cur_ctx->vbuf.id != 0);
  63. T(_sdtx.cur_ctx->pip.id != 0);
  64. TFLT(_sdtx.cur_ctx->canvas_size.x, 640.0f);
  65. TFLT(_sdtx.cur_ctx->canvas_size.y, 480.0f);
  66. TFLT(_sdtx.cur_ctx->glyph_size.x, 8.0f / 640.0f);
  67. TFLT(_sdtx.cur_ctx->glyph_size.y, 8.0f / 480.0f);
  68. TFLT(_sdtx.cur_ctx->origin.x, 0.0f);
  69. TFLT(_sdtx.cur_ctx->origin.y, 0.0f);
  70. TFLT(_sdtx.cur_ctx->pos.x, 0.0f);
  71. TFLT(_sdtx.cur_ctx->pos.y, 0.0f);
  72. TFLT(_sdtx.cur_ctx->tab_width, 4.0f);
  73. T(_sdtx.cur_ctx->color == _SDTX_DEFAULT_COLOR);
  74. T(_sdtx.context_pool.contexts);
  75. T(_sdtx.context_pool.pool.size == (_SDTX_DEFAULT_CONTEXT_POOL_SIZE + 1));
  76. shutdown();
  77. T(_sdtx.init_cookie == 0);
  78. }
  79. UTEST(sokol_debugtext, init_with_params) {
  80. init_with(&(sdtx_desc_t){
  81. .context_pool_size = 2,
  82. .printf_buf_size = 128,
  83. .context = {
  84. .char_buf_size = 256,
  85. .canvas_width = 320,
  86. .canvas_height = 200,
  87. .tab_width = 8,
  88. .color_format = SG_PIXELFORMAT_RGBA8,
  89. .depth_format = SG_PIXELFORMAT_DEPTH_STENCIL,
  90. .sample_count = 4,
  91. }
  92. });
  93. T(_sdtx.init_cookie == _SDTX_INIT_COOKIE);
  94. T(_sdtx.desc.context_pool_size == 2);
  95. T(_sdtx.desc.printf_buf_size == 128);
  96. T(_sdtx.desc.context.char_buf_size == 256);
  97. T(_sdtx.desc.context.canvas_width == 320);
  98. T(_sdtx.desc.context.canvas_height == 200);
  99. T(_sdtx.desc.context.tab_width == 8);
  100. T(_sdtx.desc.context.color_format == SG_PIXELFORMAT_RGBA8);
  101. T(_sdtx.desc.context.depth_format == SG_PIXELFORMAT_DEPTH_STENCIL);
  102. T(_sdtx.desc.context.sample_count == 4);
  103. T(_sdtx.fmt_buf_size == 129);
  104. T(_sdtx.cur_ctx->desc.char_buf_size == _sdtx.desc.context.char_buf_size);
  105. T(_sdtx.cur_ctx->desc.canvas_width == _sdtx.desc.context.canvas_width);
  106. T(_sdtx.cur_ctx->desc.canvas_height == _sdtx.desc.context.canvas_height);
  107. T(_sdtx.cur_ctx->desc.tab_width == _sdtx.desc.context.tab_width);
  108. T(_sdtx.cur_ctx->desc.color_format == SG_PIXELFORMAT_RGBA8);
  109. T(_sdtx.cur_ctx->desc.depth_format == SG_PIXELFORMAT_DEPTH_STENCIL);
  110. T(_sdtx.cur_ctx->desc.sample_count == 4);
  111. T(_sdtx.cur_ctx->vertices.cap == (256 * 6));
  112. TFLT(_sdtx.cur_ctx->canvas_size.x, 320.0f);
  113. TFLT(_sdtx.cur_ctx->canvas_size.y, 200.0f);
  114. TFLT(_sdtx.cur_ctx->glyph_size.x, 8.0f / 320.0f);
  115. TFLT(_sdtx.cur_ctx->glyph_size.y, 8.0f / 200.0f);
  116. TFLT(_sdtx.cur_ctx->tab_width, 8.0f);
  117. T(_sdtx.context_pool.pool.size == 3);
  118. shutdown();
  119. }
  120. UTEST(sokol_debugtext, make_destroy_context) {
  121. init();
  122. sdtx_context ctx_id = sdtx_make_context(&(sdtx_context_desc_t){
  123. .char_buf_size = 64,
  124. .canvas_width = 1024,
  125. .canvas_height = 768,
  126. .tab_width = 3,
  127. .color_format = SG_PIXELFORMAT_RGBA32F,
  128. .sample_count = 2
  129. });
  130. T(ctx_id.id != 0);
  131. T(ctx_id.id != _sdtx.cur_ctx_id.id);
  132. _sdtx_context_t* ctx = _sdtx_lookup_context(ctx_id.id);
  133. T(ctx);
  134. T(ctx != _sdtx.cur_ctx);
  135. T(ctx->desc.char_buf_size == 64);
  136. T(ctx->desc.canvas_width == 1024);
  137. T(ctx->desc.canvas_height == 768);
  138. T(ctx->desc.tab_width == 3);
  139. T(ctx->desc.color_format == SG_PIXELFORMAT_RGBA32F);
  140. T(ctx->desc.depth_format == 0);
  141. T(ctx->desc.sample_count == 2);
  142. T(ctx->vertices.ptr);
  143. T(ctx->vertices.next == 0);
  144. T(ctx->vertices.cap == (64 * 6));
  145. TFLT(ctx->canvas_size.x, 1024.0f);
  146. TFLT(ctx->canvas_size.y, 768.0f);
  147. TFLT(ctx->glyph_size.x, 8.0f / 1024.0f);
  148. TFLT(ctx->glyph_size.y, 8.0f / 768.0f);
  149. TFLT(ctx->tab_width, 3.0f);
  150. sdtx_destroy_context(ctx_id);
  151. T(0 == _sdtx_lookup_context(ctx_id.id));
  152. T(ctx->desc.char_buf_size == 0);
  153. T(ctx->vertices.ptr == 0);
  154. shutdown();
  155. }
  156. UTEST(sokol_debugtext, get_default_context) {
  157. // getting the default context must always return SDTX_DEFAULT_CONTEXT
  158. init();
  159. T(sdtx_get_context().id == SDTX_DEFAULT_CONTEXT.id);
  160. shutdown();
  161. }
  162. UTEST(sokol_debugtext, set_get_context) {
  163. init();
  164. sdtx_context ctx_id = sdtx_make_context(&(sdtx_context_desc_t){ 0 });
  165. T(ctx_id.id != 0);
  166. T(ctx_id.id != _sdtx.cur_ctx_id.id);
  167. sdtx_set_context(ctx_id);
  168. T(sdtx_get_context().id == ctx_id.id);
  169. T(ctx_id.id == _sdtx.cur_ctx_id.id);
  170. const _sdtx_context_t* ctx = _sdtx_lookup_context(ctx_id.id);
  171. T(ctx == _sdtx.cur_ctx);
  172. sdtx_set_context(SDTX_DEFAULT_CONTEXT);
  173. T(sdtx_get_context().id == SDTX_DEFAULT_CONTEXT.id);
  174. T(_sdtx.cur_ctx);
  175. T(ctx != _sdtx.cur_ctx);
  176. T(_sdtx.cur_ctx == _sdtx_lookup_context(_sdtx.def_ctx_id.id));
  177. shutdown();
  178. }
  179. UTEST(sokol_debugtext, destroy_default_context) {
  180. // destroying the default context is not allowed
  181. init();
  182. sdtx_context def_ctx_id = _sdtx.def_ctx_id;
  183. T(def_ctx_id.id == _sdtx.cur_ctx_id.id);
  184. sdtx_destroy_context(def_ctx_id);
  185. T(def_ctx_id.id == _sdtx.def_ctx_id.id);
  186. T(def_ctx_id.id == _sdtx.cur_ctx_id.id);
  187. T(_sdtx.cur_ctx);
  188. shutdown();
  189. }
  190. UTEST(sokol_debugtext, destroy_current_context) {
  191. // destroying the current context has the same effect
  192. // as setting a current context with an invalid context handle
  193. init();
  194. sdtx_context ctx_id = sdtx_make_context(&(sdtx_context_desc_t){ 0 });
  195. sdtx_set_context(ctx_id);
  196. T(sdtx_get_context().id == ctx_id.id);
  197. T(ctx_id.id == _sdtx.cur_ctx_id.id);
  198. T(_sdtx_lookup_context(ctx_id.id) == _sdtx.cur_ctx);
  199. sdtx_destroy_context(ctx_id);
  200. T(_sdtx.cur_ctx_id.id == ctx_id.id);
  201. T(_sdtx.cur_ctx == 0);
  202. T(sdtx_get_context().id == ctx_id.id);
  203. shutdown();
  204. }
  205. UTEST(sokol_debugtext, ignore_invalid_context_handle) {
  206. // trying to render with an invalid context handle must not crash,
  207. // instead ignore all operations
  208. init();
  209. sdtx_context ctx_id = sdtx_make_context(&(sdtx_context_desc_t){ 0 });
  210. sdtx_set_context(ctx_id);
  211. sdtx_destroy_context(ctx_id);
  212. T(0 == _sdtx.cur_ctx);
  213. T(sdtx_get_context().id == ctx_id.id);
  214. sdtx_font(0);
  215. sdtx_canvas(100.0f, 200.0f);
  216. sdtx_origin(10.0f, 10.0f);
  217. sdtx_home();
  218. sdtx_pos(1.0f, 2.0f);
  219. sdtx_pos_x(1.0f);
  220. sdtx_pos_y(2.0f);
  221. sdtx_move(2.0f, 3.0f);
  222. sdtx_move_x(2.0f);
  223. sdtx_move_y(3.0f);
  224. sdtx_crlf();
  225. sdtx_color3b(255, 255, 255);
  226. sdtx_color3f(1.0f, 1.0f, 1.0f);
  227. sdtx_color4b(255, 255, 255, 255);
  228. sdtx_color4f(1.0f, 1.0f, 1.0f, 1.0f);
  229. sdtx_color1i(0xFFFFFFFF);
  230. sdtx_putc('A');
  231. sdtx_puts("Hello World!");
  232. sdtx_putr("Hello World!", 5);
  233. sdtx_printf("Hello World %d %d %d", 1, 2, 3);
  234. shutdown();
  235. }
  236. UTEST(sokol_debugtext, set_font) {
  237. init();
  238. T(0 == _sdtx.cur_ctx->cur_font);
  239. sdtx_font(1);
  240. T(1 == _sdtx.cur_ctx->cur_font);
  241. sdtx_font(2);
  242. T(2 == _sdtx.cur_ctx->cur_font);
  243. shutdown();
  244. }
  245. UTEST(sokol_debugtext, set_canvas) {
  246. init();
  247. sdtx_origin(10.0f, 11.0f);
  248. sdtx_pos(1.0f, 2.0f);
  249. sdtx_canvas(320.0f, 200.0f);
  250. TFLT(_sdtx.cur_ctx->canvas_size.x, 320.0f);
  251. TFLT(_sdtx.cur_ctx->canvas_size.y, 200.0f);
  252. TFLT(_sdtx.cur_ctx->glyph_size.x, 8.0f / 320.0f);
  253. TFLT(_sdtx.cur_ctx->glyph_size.y, 8.0f / 200.0f);
  254. // origin and pos must be reset to 0 when canvas is set
  255. TFLT(_sdtx.cur_ctx->origin.x, 0.0f);
  256. TFLT(_sdtx.cur_ctx->origin.y, 0.0f);
  257. TFLT(_sdtx.cur_ctx->pos.x, 0.0f);
  258. TFLT(_sdtx.cur_ctx->pos.y, 0.0f);
  259. shutdown();
  260. }
  261. UTEST(sokol_debugtext, set_origin) {
  262. init();
  263. sdtx_origin(10.0f, 20.0f);
  264. TFLT(_sdtx.cur_ctx->origin.x, 10.0f);
  265. TFLT(_sdtx.cur_ctx->origin.y, 20.0f);
  266. shutdown();
  267. }
  268. UTEST(sokol_debugtext, cursor_movement) {
  269. init();
  270. sdtx_pos(1.0f, 2.0f);
  271. TFLT(_sdtx.cur_ctx->pos.x, 1.0f);
  272. TFLT(_sdtx.cur_ctx->pos.y, 2.0f);
  273. sdtx_pos_x(5.0f);
  274. TFLT(_sdtx.cur_ctx->pos.x, 5.0f);
  275. TFLT(_sdtx.cur_ctx->pos.y, 2.0f);
  276. sdtx_pos_y(6.0f);
  277. TFLT(_sdtx.cur_ctx->pos.x, 5.0f);
  278. TFLT(_sdtx.cur_ctx->pos.y, 6.0f);
  279. sdtx_move(-1.0f, -3.0f);
  280. TFLT(_sdtx.cur_ctx->pos.x, 4.0f);
  281. TFLT(_sdtx.cur_ctx->pos.y, 3.0f);
  282. sdtx_move_x(+1.0f);
  283. TFLT(_sdtx.cur_ctx->pos.x, 5.0f);
  284. TFLT(_sdtx.cur_ctx->pos.y, 3.0f);
  285. sdtx_move_y(+3.0f);
  286. TFLT(_sdtx.cur_ctx->pos.x, 5.0f);
  287. TFLT(_sdtx.cur_ctx->pos.y, 6.0f);
  288. sdtx_crlf();
  289. TFLT(_sdtx.cur_ctx->pos.x, 0.0f);
  290. TFLT(_sdtx.cur_ctx->pos.y, 7.0f);
  291. sdtx_pos(20.0f, 30.0f);
  292. sdtx_home();
  293. TFLT(_sdtx.cur_ctx->pos.x, 0.0f);
  294. TFLT(_sdtx.cur_ctx->pos.y, 0.0f);
  295. shutdown();
  296. }
  297. UTEST(sokol_debugtext, set_color) {
  298. init();
  299. T(_sdtx.cur_ctx->color == _SDTX_DEFAULT_COLOR);
  300. sdtx_color3b(255, 127, 0);
  301. T(_sdtx.cur_ctx->color == 0xFF007FFF);
  302. sdtx_color4b(0, 127, 255, 255);
  303. T(_sdtx.cur_ctx->color == 0xFFFF7F00);
  304. sdtx_color3f(1.0f, 0.5f, 0.0f);
  305. T(_sdtx.cur_ctx->color == 0xFF007FFF);
  306. sdtx_color4f(0.0f, 0.5f, 1.0f, 1.0f);
  307. T(_sdtx.cur_ctx->color == 0xFFFF7F00);
  308. sdtx_color1i(0xFF000000);
  309. T(_sdtx.cur_ctx->color == 0xFF000000);
  310. shutdown();
  311. }
  312. UTEST(sokol_debugtext, vertex_overflow) {
  313. // overflowing the vertex buffer must not crash
  314. init_with(&(sdtx_desc_t){
  315. .context.char_buf_size = 8,
  316. });
  317. for (int i = 0; i < 32; i++) {
  318. sdtx_putc('A');
  319. }
  320. sdtx_puts("1234567890");
  321. sdtx_putr("1234567890", 5);
  322. sdtx_printf("Hello World %d!\n", 12);
  323. T(_sdtx.cur_ctx->vertices.next == _sdtx.cur_ctx->vertices.cap);
  324. shutdown();
  325. }
  326. UTEST(sokol_debugtext, context_overflow) {
  327. // creating too many contexts should not crash
  328. init_with(&(sdtx_desc_t){
  329. .context_pool_size = 4,
  330. });
  331. T(_sdtx.context_pool.pool.size == 5);
  332. // one slot is taken by the default context
  333. sdtx_context ctx[4];
  334. for (int i = 0; i < 4; i++) {
  335. ctx[i] = sdtx_make_context(&(sdtx_context_desc_t){ 0 });
  336. if (i < 3) {
  337. T(ctx[i].id != 0);
  338. }
  339. else {
  340. T(ctx[i].id == 0);
  341. }
  342. }
  343. // destroying an invalid context should not crash
  344. for (int i = 0; i < 4; i++) {
  345. sdtx_destroy_context(ctx[i]);
  346. }
  347. shutdown();
  348. }
  349. UTEST(sokol_debugtext, printf_overflow) {
  350. // overflowing the printf formatting buffer should not crash
  351. init_with(&(sdtx_desc_t){
  352. .printf_buf_size = 8
  353. });
  354. T(9 == _sdtx.fmt_buf_size);
  355. T(16 == sdtx_printf("Hello %d\n", 123456789));
  356. T('H' == _sdtx.fmt_buf[0])
  357. T('e' == _sdtx.fmt_buf[1])
  358. T('l' == _sdtx.fmt_buf[2])
  359. T('l' == _sdtx.fmt_buf[3])
  360. T('o' == _sdtx.fmt_buf[4])
  361. T(' ' == _sdtx.fmt_buf[5])
  362. T('1' == _sdtx.fmt_buf[6])
  363. T('2' == _sdtx.fmt_buf[7])
  364. T(0 == _sdtx.fmt_buf[8])
  365. shutdown();
  366. }
  367. UTEST(sokol_debugtext, rewind_after_draw) {
  368. // calling sdtx_draw() must rewind the cursor position, font and
  369. // vertex pointer, to keep canvas size and origin as is
  370. init();
  371. sdtx_canvas(256, 128);
  372. TFLT(_sdtx.cur_ctx->canvas_size.x, 256);
  373. TFLT(_sdtx.cur_ctx->canvas_size.y, 128);
  374. sdtx_origin(5, 5);
  375. TFLT(_sdtx.cur_ctx->origin.x, 5);
  376. TFLT(_sdtx.cur_ctx->origin.y, 5);
  377. sdtx_pos(10, 20);
  378. TFLT(_sdtx.cur_ctx->pos.x, 10);
  379. TFLT(_sdtx.cur_ctx->pos.y, 20);
  380. sdtx_font(3);
  381. T(_sdtx.cur_ctx->cur_font == 3);
  382. sdtx_printf("Hello World!\n");
  383. T(_sdtx.cur_ctx->vertices.next != 0);
  384. sg_begin_pass(&(sg_pass){
  385. .swapchain = {
  386. .width = 256,
  387. .height = 256,
  388. .sample_count = 1,
  389. .color_format = SG_PIXELFORMAT_RGBA8,
  390. .depth_format = SG_PIXELFORMAT_DEPTH_STENCIL,
  391. }
  392. });
  393. sdtx_draw();
  394. sg_end_pass();
  395. sg_commit();
  396. TFLT(_sdtx.cur_ctx->canvas_size.x, 256);
  397. TFLT(_sdtx.cur_ctx->canvas_size.y, 128);
  398. TFLT(_sdtx.cur_ctx->origin.x, 5);
  399. TFLT(_sdtx.cur_ctx->origin.y, 5);
  400. TFLT(_sdtx.cur_ctx->pos.x, 0);
  401. TFLT(_sdtx.cur_ctx->pos.x, 0);
  402. T(_sdtx.cur_ctx->cur_font == 0);
  403. T(_sdtx.cur_ctx->vertices.next == 0);
  404. shutdown();
  405. }
  406. UTEST(sokol_debugtext, putr) {
  407. // test if sdtx_putr() draws the right amount of characters
  408. init();
  409. int start_index = _sdtx.cur_ctx->vertices.next;
  410. sdtx_putr("Hello World!", 5);
  411. T((5 * 6) == (_sdtx.cur_ctx->vertices.next - start_index));
  412. start_index = _sdtx.cur_ctx->vertices.next;
  413. sdtx_putr("Hello!\n\n\n\n\n\n\n\n\n\n\n", 10);
  414. // NOTE: the \n's don't result in rendered vertices
  415. T((6 * 6) == (_sdtx.cur_ctx->vertices.next - start_index));
  416. shutdown();
  417. }
  418. UTEST(sokol_debugtext, default_context) {
  419. init();
  420. T(sdtx_default_context().id == SDTX_DEFAULT_CONTEXT.id);
  421. shutdown();
  422. }
  423. // switching layers without any text inbetween should not advance the current draw command
  424. UTEST(sokol_debug_text, empty_layers) {
  425. init();
  426. T(_sdtx.cur_ctx->commands.next == 1);
  427. T(_sdtx.cur_ctx->commands.ptr[0].layer_id == 0);
  428. sdtx_layer(1);
  429. T(_sdtx.cur_ctx->commands.next == 1);
  430. T(_sdtx.cur_ctx->commands.ptr[0].layer_id == 1);
  431. sdtx_layer(2);
  432. T(_sdtx.cur_ctx->commands.next == 1);
  433. T(_sdtx.cur_ctx->commands.ptr[0].layer_id == 2);
  434. sdtx_layer(0);
  435. T(_sdtx.cur_ctx->commands.next == 1);
  436. T(_sdtx.cur_ctx->commands.ptr[0].layer_id == 0);
  437. shutdown();
  438. }
  439. // switching layers with text inbetween should advance the current draw command
  440. UTEST(sokol_debug_text, non_empty_layers) {
  441. init();
  442. T(_sdtx.cur_ctx->commands.next == 1);
  443. T(_sdtx.cur_ctx->commands.ptr[0].layer_id == 0);
  444. T(_sdtx.cur_ctx->commands.ptr[0].first_vertex == 0);
  445. T(_sdtx.cur_ctx->commands.ptr[0].num_vertices == 0);
  446. sdtx_puts("123");
  447. T(_sdtx.cur_ctx->commands.next == 1);
  448. T(_sdtx.cur_ctx->commands.ptr[0].layer_id == 0);
  449. T(_sdtx.cur_ctx->commands.ptr[0].first_vertex == 0);
  450. T(_sdtx.cur_ctx->commands.ptr[0].num_vertices == (3 * 6));
  451. sdtx_layer(1);
  452. sdtx_puts("1234");
  453. T(_sdtx.cur_ctx->commands.next == 2);
  454. T(_sdtx.cur_ctx->commands.ptr[1].layer_id == 1);
  455. T(_sdtx.cur_ctx->commands.ptr[1].first_vertex == (3 * 6));
  456. T(_sdtx.cur_ctx->commands.ptr[1].num_vertices == (4 * 6));
  457. // switching to same layer should not start a new draw commands
  458. sdtx_layer(1);
  459. sdtx_puts("12345");
  460. T(_sdtx.cur_ctx->commands.next == 2);
  461. T(_sdtx.cur_ctx->commands.ptr[1].layer_id == 1);
  462. T(_sdtx.cur_ctx->commands.ptr[1].first_vertex == (3 * 6));
  463. T(_sdtx.cur_ctx->commands.ptr[1].num_vertices == (9 * 6));
  464. sdtx_layer(0);
  465. sdtx_puts("123456");
  466. T(_sdtx.cur_ctx->commands.next == 3);
  467. T(_sdtx.cur_ctx->commands.ptr[2].layer_id == 0);
  468. T(_sdtx.cur_ctx->commands.ptr[2].first_vertex == (12 * 6));
  469. T(_sdtx.cur_ctx->commands.ptr[2].num_vertices == (6 * 6));
  470. shutdown();
  471. }
  472. UTEST(sokol_debug_text, command_buffer_overflow) {
  473. init_with(&(sdtx_desc_t){
  474. .context = {
  475. .max_commands = 4
  476. }
  477. });
  478. sdtx_puts("0");
  479. T(_sdtx.cur_ctx->commands.next == 1);
  480. sdtx_layer(1);
  481. sdtx_puts("1");
  482. T(_sdtx.cur_ctx->commands.next == 2);
  483. sdtx_layer(2);
  484. sdtx_puts("2");
  485. T(_sdtx.cur_ctx->commands.next == 3);
  486. sdtx_layer(3);
  487. sdtx_puts("3");
  488. T(_sdtx.cur_ctx->commands.next == 4);
  489. // from here on should fail
  490. sdtx_layer(4);
  491. sdtx_puts("4");
  492. T(_sdtx.cur_ctx->commands.next == 4);
  493. }