gl.odin 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. // machine generated, do not edit
  2. package sokol_gl
  3. /*
  4. sokol_gl.h -- OpenGL 1.x style rendering on top of sokol_gfx.h
  5. Project URL: https://github.com/floooh/sokol
  6. Do this:
  7. #define SOKOL_IMPL or
  8. #define SOKOL_GL_IMPL
  9. before you include this file in *one* C or C++ file to create the
  10. implementation.
  11. The following defines are used by the implementation to select the
  12. platform-specific embedded shader code (these are the same defines as
  13. used by sokol_gfx.h and sokol_app.h):
  14. SOKOL_GLCORE
  15. SOKOL_GLES3
  16. SOKOL_D3D11
  17. SOKOL_METAL
  18. SOKOL_WGPU
  19. SOKOL_VULKAN
  20. ...optionally provide the following macros to override defaults:
  21. SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
  22. SOKOL_GL_API_DECL - public function declaration prefix (default: extern)
  23. SOKOL_API_DECL - same as SOKOL_GL_API_DECL
  24. SOKOL_API_IMPL - public function implementation prefix (default: -)
  25. SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
  26. If sokol_gl.h is compiled as a DLL, define the following before
  27. including the declaration or implementation:
  28. SOKOL_DLL
  29. On Windows, SOKOL_DLL will define SOKOL_GL_API_DECL as __declspec(dllexport)
  30. or __declspec(dllimport) as needed.
  31. Include the following headers before including sokol_gl.h:
  32. sokol_gfx.h
  33. Matrix functions have been taken from MESA and Regal.
  34. FEATURE OVERVIEW:
  35. =================
  36. sokol_gl.h implements a subset of the OpenGLES 1.x feature set useful for
  37. when you just want to quickly render a bunch of triangles or
  38. lines without having to mess with buffers and shaders.
  39. The current feature set is mostly useful for debug visualizations
  40. and simple UI-style 2D rendering:
  41. What's implemented:
  42. - vertex components:
  43. - position (x, y, z)
  44. - 2D texture coords (u, v)
  45. - color (r, g, b, a)
  46. - primitive types:
  47. - triangle list and strip
  48. - line list and strip
  49. - quad list (TODO: quad strips)
  50. - point list
  51. - one texture layer (no multi-texturing)
  52. - viewport and scissor-rect with selectable origin (top-left or bottom-left)
  53. - all GL 1.x matrix stack functions, and additionally equivalent
  54. functions for gluPerspective and gluLookat
  55. Notable GLES 1.x features that are *NOT* implemented:
  56. - vertex lighting (this is the most likely GL feature that might be added later)
  57. - vertex arrays (although providing whole chunks of vertex data at once
  58. might be a useful feature for a later version)
  59. - texture coordinate generation
  60. - line width
  61. - all pixel store functions
  62. - no ALPHA_TEST
  63. - no clear functions (clearing is handled by the sokol-gfx render pass)
  64. - fog
  65. Notable differences to GL:
  66. - No "enum soup" for render states etc, instead there's a
  67. 'pipeline stack', this is similar to GL's matrix stack,
  68. but for pipeline-state-objects. The pipeline object at
  69. the top of the pipeline stack defines the active set of render states
  70. - All angles are in radians, not degrees (note the sgl_rad() and
  71. sgl_deg() conversion functions)
  72. - No enable/disable state for scissor test, this is always enabled
  73. STEP BY STEP:
  74. =============
  75. --- To initialize sokol-gl, call:
  76. sgl_setup(const sgl_desc_t* desc)
  77. NOTE that sgl_setup() must be called *after* initializing sokol-gfx
  78. (via sg_setup). This is because sgl_setup() needs to create
  79. sokol-gfx resource objects.
  80. If you're intending to render to the default pass, and also don't
  81. want to tweak memory usage, and don't want any logging output you can
  82. just keep sgl_desc_t zero-initialized:
  83. sgl_setup(&(sgl_desc_t*){ 0 });
  84. In this case, sokol-gl will create internal sg_pipeline objects that
  85. are compatible with the sokol-app default framebuffer.
  86. I would recommend to at least install a logging callback so that
  87. you'll see any warnings and errors. The easiest way is through
  88. sokol_log.h:
  89. #include "sokol_log.h"
  90. sgl_setup(&(sgl_desc_t){
  91. .logger.func = slog_func.
  92. });
  93. If you want to render into a framebuffer with different pixel-format
  94. and MSAA attributes you need to provide the matching attributes in the
  95. sgl_setup() call:
  96. sgl_setup(&(sgl_desc_t*){
  97. .color_format = SG_PIXELFORMAT_...,
  98. .depth_format = SG_PIXELFORMAT_...,
  99. .sample_count = ...,
  100. });
  101. To reduce memory usage, or if you need to create more then the default number of
  102. contexts, pipelines, vertices or draw commands, set the following sgl_desc_t
  103. members:
  104. .context_pool_size (default: 4)
  105. .pipeline_pool_size (default: 64)
  106. .max_vertices (default: 64k)
  107. .max_commands (default: 16k)
  108. Finally you can change the face winding for front-facing triangles
  109. and quads:
  110. .face_winding - default is SG_FACEWINDING_CCW
  111. The default winding for front faces is counter-clock-wise. This is
  112. the same as OpenGL's default, but different from sokol-gfx.
  113. --- Optionally create additional context objects if you want to render into
  114. multiple sokol-gfx render passes (or generally if you want to
  115. use multiple independent sokol-gl "state buckets")
  116. sgl_context ctx = sgl_make_context(const sgl_context_desc_t* desc)
  117. For details on rendering with sokol-gl contexts, search below for
  118. WORKING WITH CONTEXTS.
  119. --- Optionally create pipeline-state-objects if you need render state
  120. that differs from sokol-gl's default state:
  121. sgl_pipeline pip = sgl_make_pipeline(const sg_pipeline_desc* desc)
  122. ...this creates a pipeline object that's compatible with the currently
  123. active context, alternatively call:
  124. sgl_pipeline_pip = sgl_context_make_pipeline(sgl_context ctx, const sg_pipeline_desc* desc)
  125. ...to create a pipeline object that's compatible with an explicitly
  126. provided context.
  127. The similarity with sokol_gfx.h's sg_pipeline type and sg_make_pipeline()
  128. function is intended. sgl_make_pipeline() also takes a standard
  129. sokol-gfx sg_pipeline_desc object to describe the render state, but
  130. without:
  131. - shader
  132. - vertex layout
  133. - color- and depth-pixel-formats
  134. - primitive type (lines, triangles, ...)
  135. - MSAA sample count
  136. Those will be filled in by sgl_make_pipeline(). Note that each
  137. call to sgl_make_pipeline() needs to create several sokol-gfx
  138. pipeline objects (one for each primitive type).
  139. 'depth.write_enabled' will be forced to 'false' if the context this
  140. pipeline object is intended for has its depth pixel format set to
  141. SG_PIXELFORMAT_NONE (which means the framebuffer this context is used
  142. with doesn't have a depth-stencil surface).
  143. --- if you need to destroy sgl_pipeline objects before sgl_shutdown():
  144. sgl_destroy_pipeline(sgl_pipeline pip)
  145. --- After sgl_setup() you can call any of the sokol-gl functions anywhere
  146. in a frame, *except* sgl_draw(). The 'vanilla' functions
  147. will only change internal sokol-gl state, and not call any sokol-gfx
  148. functions.
  149. --- Unlike OpenGL, sokol-gl has a function to reset internal state to
  150. a known default. This is useful at the start of a sequence of
  151. rendering operations:
  152. void sgl_defaults(void)
  153. This will set the following default state:
  154. - current texture coordinate to u=0.0f, v=0.0f
  155. - current color to white (rgba all 1.0f)
  156. - current point size to 1.0f
  157. - unbind the current texture and texturing will be disabled
  158. - *all* matrices will be set to identity (also the projection matrix)
  159. - the default render state will be set by loading the 'default pipeline'
  160. into the top of the pipeline stack
  161. The current matrix- and pipeline-stack-depths will not be changed by
  162. sgl_defaults().
  163. --- change the currently active renderstate through the
  164. pipeline-stack functions, this works similar to the
  165. traditional GL matrix stack:
  166. ...load the default pipeline state on the top of the pipeline stack:
  167. sgl_load_default_pipeline()
  168. ...load a specific pipeline on the top of the pipeline stack:
  169. sgl_load_pipeline(sgl_pipeline pip)
  170. ...push and pop the pipeline stack:
  171. sgl_push_pipeline()
  172. sgl_pop_pipeline()
  173. --- control texturing with:
  174. sgl_enable_texture()
  175. sgl_disable_texture()
  176. sgl_texture(sg_view tex_view, sg_sampler smp)
  177. NOTE: the tex_view and smp handles can be invalid (SG_INVALID_ID), in this
  178. case, sokol-gl will fall back to the internal default (white) texture
  179. and sampler.
  180. --- set the current viewport and scissor rect with:
  181. sgl_viewport(int x, int y, int w, int h, bool origin_top_left)
  182. sgl_scissor_rect(int x, int y, int w, int h, bool origin_top_left)
  183. ...or call these alternatives which take float arguments (this might allow
  184. to avoid casting between float and integer in more strongly typed languages
  185. when floating point pixel coordinates are used):
  186. sgl_viewportf(float x, float y, float w, float h, bool origin_top_left)
  187. sgl_scissor_rectf(float x, float y, float w, float h, bool origin_top_left)
  188. ...these calls add a new command to the internal command queue, so
  189. that the viewport or scissor rect are set at the right time relative
  190. to other sokol-gl calls.
  191. --- adjust the transform matrices, matrix manipulation works just like
  192. the OpenGL matrix stack:
  193. ...set the current matrix mode:
  194. sgl_matrix_mode_modelview()
  195. sgl_matrix_mode_projection()
  196. sgl_matrix_mode_texture()
  197. ...load the identity matrix into the current matrix:
  198. sgl_load_identity()
  199. ...translate, rotate and scale the current matrix:
  200. sgl_translate(float x, float y, float z)
  201. sgl_rotate(float angle_rad, float x, float y, float z)
  202. sgl_scale(float x, float y, float z)
  203. NOTE that all angles in sokol-gl are in radians, not in degree.
  204. Convert between radians and degree with the helper functions:
  205. float sgl_rad(float deg) - degrees to radians
  206. float sgl_deg(float rad) - radians to degrees
  207. ...directly load the current matrix from a float[16] array:
  208. sgl_load_matrix(const float m[16])
  209. sgl_load_transpose_matrix(const float m[16])
  210. ...directly multiply the current matrix from a float[16] array:
  211. sgl_mult_matrix(const float m[16])
  212. sgl_mult_transpose_matrix(const float m[16])
  213. The memory layout of those float[16] arrays is the same as in OpenGL.
  214. ...more matrix functions:
  215. sgl_frustum(float left, float right, float bottom, float top, float near, float far)
  216. sgl_ortho(float left, float right, float bottom, float top, float near, float far)
  217. sgl_perspective(float fov_y, float aspect, float near, float far)
  218. sgl_lookat(float eye_x, float eye_y, float eye_z, float center_x, float center_y, float center_z, float up_x, float up_y, float up_z)
  219. These functions work the same as glFrustum(), glOrtho(), gluPerspective()
  220. and gluLookAt().
  221. ...and finally to push / pop the current matrix stack:
  222. sgl_push_matrix(void)
  223. sgl_pop_matrix(void)
  224. Again, these work the same as glPushMatrix() and glPopMatrix().
  225. --- perform primitive rendering:
  226. ...set the current texture coordinate and color 'registers' with or
  227. point size with:
  228. sgl_t2f(float u, float v) - set current texture coordinate
  229. sgl_c*(...) - set current color
  230. sgl_point_size(float size) - set current point size
  231. There are several functions for setting the color (as float values,
  232. unsigned byte values, packed as unsigned 32-bit integer, with
  233. and without alpha).
  234. NOTE that these are the only functions that can be called both inside
  235. sgl_begin_*() / sgl_end() and outside.
  236. Also NOTE that point size is currently hardwired to 1.0f if the D3D11
  237. backend is used.
  238. ...start a primitive vertex sequence with:
  239. sgl_begin_points()
  240. sgl_begin_lines()
  241. sgl_begin_line_strip()
  242. sgl_begin_triangles()
  243. sgl_begin_triangle_strip()
  244. sgl_begin_quads()
  245. ...after sgl_begin_*() specify vertices:
  246. sgl_v*(...)
  247. sgl_v*_t*(...)
  248. sgl_v*_c*(...)
  249. sgl_v*_t*_c*(...)
  250. These functions write a new vertex to sokol-gl's internal vertex buffer,
  251. optionally with texture-coords and color. If the texture coordinate
  252. and/or color is missing, it will be taken from the current texture-coord
  253. and color 'register'.
  254. ...finally, after specifying vertices, call:
  255. sgl_end()
  256. This will record a new draw command in sokol-gl's internal command
  257. list, or it will extend the previous draw command if no relevant
  258. state has changed since the last sgl_begin/end pair.
  259. --- inside a sokol-gfx rendering pass, call the sgl_draw() function
  260. to render the currently active context:
  261. sgl_draw()
  262. ...or alternatively call:
  263. sgl_context_draw(ctx)
  264. ...to render an explicitly provided context.
  265. This will render everything that has been recorded in the context since
  266. the last call to sgl_draw() through sokol-gfx, and will 'rewind' the internal
  267. vertex-, uniform- and command-buffers.
  268. --- each sokol-gl context tracks internal error states which can
  269. be obtains via:
  270. sgl_error_t sgl_error()
  271. ...alternatively with an explicit context argument:
  272. sgl_error_t sgl_context_error(ctx);
  273. ...this returns a struct with the following booleans:
  274. .any - true if any of the below errors is true
  275. .vertices_full - internal vertex buffer is full (checked in sgl_end())
  276. .uniforms_full - the internal uniforms buffer is full (checked in sgl_end())
  277. .commands_full - the internal command buffer is full (checked in sgl_end())
  278. .stack_overflow - matrix- or pipeline-stack overflow
  279. .stack_underflow - matrix- or pipeline-stack underflow
  280. .no_context - the active context no longer exists
  281. ...depending on the above error state, sgl_draw() may skip rendering
  282. completely, or only draw partial geometry
  283. --- you can get the number of recorded vertices and draw commands in the current
  284. frame and active sokol-gl context via:
  285. int sgl_num_vertices()
  286. int sgl_num_commands()
  287. ...this allows you to check whether the vertex or command pools are running
  288. full before the overflow actually happens (in this case you could also
  289. check the error booleans in the result of sgl_error()).
  290. RENDER LAYERS
  291. =============
  292. Render layers allow to split sokol-gl rendering into separate draw-command
  293. groups which can then be rendered separately in a sokol-gfx draw pass. This
  294. allows to mix/interleave sokol-gl rendering with other render operations.
  295. Layered rendering is controlled through two functions:
  296. sgl_layer(int layer_id)
  297. sgl_draw_layer(int layer_id)
  298. (and the context-variant sgl_draw_layer(): sgl_context_draw_layer()
  299. The sgl_layer() function sets the 'current layer', any sokol-gl calls
  300. which internally record draw commands will also store the current layer
  301. in the draw command, and later in a sokol-gfx render pass, a call
  302. to sgl_draw_layer() will only render the draw commands that have
  303. a matching layer.
  304. The default layer is '0', this is active after sokol-gl setup, and
  305. is also restored at the start of a new frame (but *not* by calling
  306. sgl_defaults()).
  307. NOTE that calling sgl_draw() is equivalent with sgl_draw_layer(0)
  308. (in general you should either use either use sgl_draw() or
  309. sgl_draw_layer() in an application, but not both).
  310. WORKING WITH CONTEXTS:
  311. ======================
  312. If you want to render to more than one sokol-gfx render pass you need to
  313. work with additional sokol-gl context objects (one context object for
  314. each offscreen rendering pass, in addition to the implicitly created
  315. 'default context'.
  316. All sokol-gl state is tracked per context, and there is always a "current
  317. context" (with the notable exception that the currently set context is
  318. destroyed, more on that later).
  319. Using multiple contexts can also be useful if you only render in
  320. a single pass, but want to maintain multiple independent "state buckets".
  321. To create new context object, call:
  322. sgl_context ctx = sgl_make_context(&(sgl_context_desc){
  323. .max_vertices = ..., // default: 64k
  324. .max_commands = ..., // default: 16k
  325. .color_format = ...,
  326. .depth_format = ...,
  327. .sample_count = ...,
  328. });
  329. The color_format, depth_format and sample_count items must be compatible
  330. with the render pass the sgl_draw() or sgL_context_draw() function
  331. will be called in.
  332. Creating a context does *not* make the context current. To do this, call:
  333. sgl_set_context(ctx);
  334. The currently active context will implicitly be used by most sokol-gl functions
  335. which don't take an explicit context handle as argument.
  336. To switch back to the default context, pass the global constant SGL_DEFAULT_CONTEXT:
  337. sgl_set_context(SGL_DEFAULT_CONTEXT);
  338. ...or alternatively use the function sgl_default_context() instead of the
  339. global constant:
  340. sgl_set_context(sgl_default_context());
  341. To get the currently active context, call:
  342. sgl_context cur_ctx = sgl_get_context();
  343. The following functions exist in two variants, one which use the currently
  344. active context (set with sgl_set_context()), and another version which
  345. takes an explicit context handle instead:
  346. sgl_make_pipeline() vs sgl_context_make_pipeline()
  347. sgl_error() vs sgl_context_error();
  348. sgl_draw() vs sgl_context_draw();
  349. Except for using the currently active context versus a provided context
  350. handle, the two variants are exactlyidentical, e.g. the following
  351. code sequences do the same thing:
  352. sgl_set_context(ctx);
  353. sgl_pipeline pip = sgl_make_pipeline(...);
  354. sgl_error_t err = sgl_error();
  355. sgl_draw();
  356. vs
  357. sgl_pipeline pip = sgl_context_make_pipeline(ctx, ...);
  358. sgl_error_t err = sgl_context_error(ctx);
  359. sgl_context_draw(ctx);
  360. Destroying the currently active context is a 'soft error'. All following
  361. calls which require a currently active context will silently fail,
  362. and sgl_error() will return SGL_ERROR_NO_CONTEXT.
  363. UNDER THE HOOD:
  364. ===============
  365. sokol_gl.h works by recording vertex data and rendering commands into
  366. memory buffers, and then drawing the recorded commands via sokol_gfx.h
  367. The only functions which call into sokol_gfx.h are:
  368. - sgl_setup()
  369. - sgl_shutdown()
  370. - sgl_draw() (and variants)
  371. sgl_setup() must be called after initializing sokol-gfx.
  372. sgl_shutdown() must be called before shutting down sokol-gfx.
  373. sgl_draw() must be called once per frame inside a sokol-gfx render pass.
  374. All other sokol-gl function can be called anywhere in a frame, since
  375. they just record data into memory buffers owned by sokol-gl.
  376. What happens in:
  377. sgl_setup():
  378. Unique resources shared by all contexts are created:
  379. - a shader object (using embedded shader source or byte code)
  380. - an 8x8 white default texture
  381. The default context is created, which involves:
  382. - 3 memory buffers are created, one for vertex data,
  383. one for uniform data, and one for commands
  384. - a dynamic vertex buffer is created
  385. - the default sgl_pipeline object is created, which involves
  386. creating 5 sg_pipeline objects
  387. One vertex is 24 bytes:
  388. - float3 position
  389. - float2 texture coords
  390. - uint32_t color
  391. One uniform block is 128 bytes:
  392. - mat4 model-view-projection matrix
  393. - mat4 texture matrix
  394. One draw command is ca. 24 bytes for the actual
  395. command code plus command arguments.
  396. Each sgl_end() consumes one command, and one uniform block
  397. (only when the matrices have changed).
  398. The required size for one sgl_begin/end pair is (at most):
  399. (152 + 24 * num_verts) bytes
  400. sgl_shutdown():
  401. - all sokol-gfx resources (buffer, shader, default-texture and
  402. all pipeline objects) are destroyed
  403. - the 3 memory buffers are freed
  404. sgl_draw() (and variants)
  405. - copy all recorded vertex data into the dynamic sokol-gfx buffer
  406. via a call to sg_update_buffer()
  407. - for each recorded command:
  408. - if the layer number stored in the command doesn't match
  409. the layer that's to be rendered, skip to the next
  410. command
  411. - if it's a viewport command, call sg_apply_viewport()
  412. - if it's a scissor-rect command, call sg_apply_scissor_rect()
  413. - if it's a draw command:
  414. - depending on what has changed since the last draw command,
  415. call sg_apply_pipeline(), sg_apply_bindings() and
  416. sg_apply_uniforms()
  417. - finally call sg_draw()
  418. All other functions only modify the internally tracked state, add
  419. data to the vertex, uniform and command buffers, or manipulate
  420. the matrix stack.
  421. ON DRAW COMMAND MERGING
  422. =======================
  423. Not every call to sgl_end() will automatically record a new draw command.
  424. If possible, the previous draw command will simply be extended,
  425. resulting in fewer actual draw calls later in sgl_draw().
  426. A draw command will be merged with the previous command if "no relevant
  427. state has changed" since the last sgl_end(), meaning:
  428. - no calls to sgl_viewport() and sgl_scissor_rect()
  429. - the primitive type hasn't changed
  430. - the primitive type isn't a 'strip type' (no line or triangle strip)
  431. - the pipeline state object hasn't changed
  432. - the current layer hasn't changed
  433. - none of the matrices has changed
  434. - none of the texture state has changed
  435. Merging a draw command simply means that the number of vertices
  436. to render in the previous draw command will be incremented by the
  437. number of vertices in the new draw command.
  438. MEMORY ALLOCATION OVERRIDE
  439. ==========================
  440. You can override the memory allocation functions at initialization time
  441. like this:
  442. void* my_alloc(size_t size, void* user_data) {
  443. return malloc(size);
  444. }
  445. void my_free(void* ptr, void* user_data) {
  446. free(ptr);
  447. }
  448. ...
  449. sgl_setup(&(sgl_desc_t){
  450. // ...
  451. .allocator = {
  452. .alloc_fn = my_alloc,
  453. .free_fn = my_free,
  454. .user_data = ...;
  455. }
  456. });
  457. ...
  458. If no overrides are provided, malloc and free will be used.
  459. ERROR REPORTING AND LOGGING
  460. ===========================
  461. To get any logging information at all you need to provide a logging callback in the setup call,
  462. the easiest way is to use sokol_log.h:
  463. #include "sokol_log.h"
  464. sgl_setup(&(sgl_desc_t){
  465. // ...
  466. .logger.func = slog_func
  467. });
  468. To override logging with your own callback, first write a logging function like this:
  469. void my_log(const char* tag, // e.g. 'sgl'
  470. uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
  471. uint32_t log_item_id, // SGL_LOGITEM_*
  472. const char* message_or_null, // a message string, may be nullptr in release mode
  473. uint32_t line_nr, // line number in sokol_gl.h
  474. const char* filename_or_null, // source filename, may be nullptr in release mode
  475. void* user_data)
  476. {
  477. ...
  478. }
  479. ...and then setup sokol-gl like this:
  480. sgl_setup(&(sgl_desc_t){
  481. .logger = {
  482. .func = my_log,
  483. .user_data = my_user_data,
  484. }
  485. });
  486. The provided logging function must be reentrant (e.g. be callable from
  487. different threads).
  488. If you don't want to provide your own custom logger it is highly recommended to use
  489. the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
  490. errors.
  491. LICENSE
  492. =======
  493. zlib/libpng license
  494. Copyright (c) 2018 Andre Weissflog
  495. This software is provided 'as-is', without any express or implied warranty.
  496. In no event will the authors be held liable for any damages arising from the
  497. use of this software.
  498. Permission is granted to anyone to use this software for any purpose,
  499. including commercial applications, and to alter it and redistribute it
  500. freely, subject to the following restrictions:
  501. 1. The origin of this software must not be misrepresented; you must not
  502. claim that you wrote the original software. If you use this software in a
  503. product, an acknowledgment in the product documentation would be
  504. appreciated but is not required.
  505. 2. Altered source versions must be plainly marked as such, and must not
  506. be misrepresented as being the original software.
  507. 3. This notice may not be removed or altered from any source
  508. distribution.
  509. */
  510. import sg "../gfx"
  511. import "core:c"
  512. _ :: c
  513. SOKOL_DEBUG :: #config(SOKOL_DEBUG, ODIN_DEBUG)
  514. DEBUG :: #config(SOKOL_GL_DEBUG, SOKOL_DEBUG)
  515. USE_GL :: #config(SOKOL_USE_GL, false)
  516. USE_DLL :: #config(SOKOL_DLL, false)
  517. when ODIN_OS == .Windows {
  518. when USE_DLL {
  519. when USE_GL {
  520. when DEBUG { foreign import sokol_gl_clib { "../sokol_dll_windows_x64_gl_debug.lib" } }
  521. else { foreign import sokol_gl_clib { "../sokol_dll_windows_x64_gl_release.lib" } }
  522. } else {
  523. when DEBUG { foreign import sokol_gl_clib { "../sokol_dll_windows_x64_d3d11_debug.lib" } }
  524. else { foreign import sokol_gl_clib { "../sokol_dll_windows_x64_d3d11_release.lib" } }
  525. }
  526. } else {
  527. when USE_GL {
  528. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_windows_x64_gl_debug.lib" } }
  529. else { foreign import sokol_gl_clib { "sokol_gl_windows_x64_gl_release.lib" } }
  530. } else {
  531. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_windows_x64_d3d11_debug.lib" } }
  532. else { foreign import sokol_gl_clib { "sokol_gl_windows_x64_d3d11_release.lib" } }
  533. }
  534. }
  535. } else when ODIN_OS == .Darwin {
  536. when USE_DLL {
  537. when USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib" } }
  538. else when USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_arm64_gl_release.dylib" } }
  539. else when USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_x64_gl_debug.dylib" } }
  540. else when USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_x64_gl_release.dylib" } }
  541. else when !USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib" } }
  542. else when !USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_arm64_metal_release.dylib" } }
  543. else when !USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_x64_metal_debug.dylib" } }
  544. else when !USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_gl_clib { "../dylib/sokol_dylib_macos_x64_metal_release.dylib" } }
  545. } else {
  546. when USE_GL {
  547. when ODIN_ARCH == .arm64 {
  548. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_macos_arm64_gl_debug.a" } }
  549. else { foreign import sokol_gl_clib { "sokol_gl_macos_arm64_gl_release.a" } }
  550. } else {
  551. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_macos_x64_gl_debug.a" } }
  552. else { foreign import sokol_gl_clib { "sokol_gl_macos_x64_gl_release.a" } }
  553. }
  554. } else {
  555. when ODIN_ARCH == .arm64 {
  556. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_macos_arm64_metal_debug.a" } }
  557. else { foreign import sokol_gl_clib { "sokol_gl_macos_arm64_metal_release.a" } }
  558. } else {
  559. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_macos_x64_metal_debug.a" } }
  560. else { foreign import sokol_gl_clib { "sokol_gl_macos_x64_metal_release.a" } }
  561. }
  562. }
  563. }
  564. } else when ODIN_OS == .Linux {
  565. when USE_DLL {
  566. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_linux_x64_gl_debug.so" } }
  567. else { foreign import sokol_gl_clib { "sokol_gl_linux_x64_gl_release.so" } }
  568. } else {
  569. when DEBUG { foreign import sokol_gl_clib { "sokol_gl_linux_x64_gl_debug.a" } }
  570. else { foreign import sokol_gl_clib { "sokol_gl_linux_x64_gl_release.a" } }
  571. }
  572. } else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
  573. // Feed sokol_gl_wasm_gl_debug.a or sokol_gl_wasm_gl_release.a into emscripten compiler.
  574. foreign import sokol_gl_clib { "env.o" }
  575. } else {
  576. #panic("This OS is currently not supported")
  577. }
  578. @(default_calling_convention="c", link_prefix="sgl_")
  579. foreign sokol_gl_clib {
  580. // setup/shutdown/misc
  581. setup :: proc(#by_ptr desc: Desc) ---
  582. shutdown :: proc() ---
  583. rad :: proc(deg: f32) -> f32 ---
  584. deg :: proc(rad: f32) -> f32 ---
  585. error :: proc() -> Error ---
  586. context_error :: proc(ctx: Context) -> Error ---
  587. // context functions
  588. make_context :: proc(#by_ptr desc: Context_Desc) -> Context ---
  589. destroy_context :: proc(ctx: Context) ---
  590. set_context :: proc(ctx: Context) ---
  591. get_context :: proc() -> Context ---
  592. default_context :: proc() -> Context ---
  593. // get information about recorded vertices and commands in current context
  594. num_vertices :: proc() -> c.int ---
  595. num_commands :: proc() -> c.int ---
  596. // draw recorded commands (call inside a sokol-gfx render pass)
  597. draw :: proc() ---
  598. context_draw :: proc(ctx: Context) ---
  599. draw_layer :: proc(#any_int layer_id: c.int) ---
  600. context_draw_layer :: proc(ctx: Context, #any_int layer_id: c.int) ---
  601. // create and destroy pipeline objects
  602. make_pipeline :: proc(#by_ptr desc: sg.Pipeline_Desc) -> Pipeline ---
  603. context_make_pipeline :: proc(ctx: Context, #by_ptr desc: sg.Pipeline_Desc) -> Pipeline ---
  604. destroy_pipeline :: proc(pip: Pipeline) ---
  605. // render state functions
  606. defaults :: proc() ---
  607. viewport :: proc(#any_int x: c.int, #any_int y: c.int, #any_int w: c.int, #any_int h: c.int, origin_top_left: bool) ---
  608. viewportf :: proc(x: f32, y: f32, w: f32, h: f32, origin_top_left: bool) ---
  609. scissor_rect :: proc(#any_int x: c.int, #any_int y: c.int, #any_int w: c.int, #any_int h: c.int, origin_top_left: bool) ---
  610. scissor_rectf :: proc(x: f32, y: f32, w: f32, h: f32, origin_top_left: bool) ---
  611. enable_texture :: proc() ---
  612. disable_texture :: proc() ---
  613. texture :: proc(tex_view: sg.View, smp: sg.Sampler) ---
  614. layer :: proc(#any_int layer_id: c.int) ---
  615. // pipeline stack functions
  616. load_default_pipeline :: proc() ---
  617. load_pipeline :: proc(pip: Pipeline) ---
  618. push_pipeline :: proc() ---
  619. pop_pipeline :: proc() ---
  620. // matrix stack functions
  621. matrix_mode_modelview :: proc() ---
  622. matrix_mode_projection :: proc() ---
  623. matrix_mode_texture :: proc() ---
  624. load_identity :: proc() ---
  625. load_matrix :: proc(m: ^f32) ---
  626. load_transpose_matrix :: proc(m: ^f32) ---
  627. mult_matrix :: proc(m: ^f32) ---
  628. mult_transpose_matrix :: proc(m: ^f32) ---
  629. rotate :: proc(angle_rad: f32, x: f32, y: f32, z: f32) ---
  630. scale :: proc(x: f32, y: f32, z: f32) ---
  631. translate :: proc(x: f32, y: f32, z: f32) ---
  632. frustum :: proc(l: f32, r: f32, b: f32, t: f32, n: f32, f: f32) ---
  633. ortho :: proc(l: f32, r: f32, b: f32, t: f32, n: f32, f: f32) ---
  634. perspective :: proc(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) ---
  635. lookat :: proc(eye_x: f32, eye_y: f32, eye_z: f32, center_x: f32, center_y: f32, center_z: f32, up_x: f32, up_y: f32, up_z: f32) ---
  636. push_matrix :: proc() ---
  637. pop_matrix :: proc() ---
  638. // these functions only set the internal 'current texcoord / color / point size' (valid inside or outside begin/end)
  639. t2f :: proc(u: f32, v: f32) ---
  640. c3f :: proc(r: f32, g: f32, b: f32) ---
  641. c4f :: proc(r: f32, g: f32, b: f32, a: f32) ---
  642. c3b :: proc(r: u8, g: u8, b: u8) ---
  643. c4b :: proc(r: u8, g: u8, b: u8, a: u8) ---
  644. c1i :: proc(rgba: u32) ---
  645. point_size :: proc(s: f32) ---
  646. // define primitives, each begin/end is one draw command
  647. begin_points :: proc() ---
  648. begin_lines :: proc() ---
  649. begin_line_strip :: proc() ---
  650. begin_triangles :: proc() ---
  651. begin_triangle_strip :: proc() ---
  652. begin_quads :: proc() ---
  653. v2f :: proc(x: f32, y: f32) ---
  654. v3f :: proc(x: f32, y: f32, z: f32) ---
  655. v2f_t2f :: proc(x: f32, y: f32, u: f32, v: f32) ---
  656. v3f_t2f :: proc(x: f32, y: f32, z: f32, u: f32, v: f32) ---
  657. v2f_c3f :: proc(x: f32, y: f32, r: f32, g: f32, b: f32) ---
  658. v2f_c3b :: proc(x: f32, y: f32, r: u8, g: u8, b: u8) ---
  659. v2f_c4f :: proc(x: f32, y: f32, r: f32, g: f32, b: f32, a: f32) ---
  660. v2f_c4b :: proc(x: f32, y: f32, r: u8, g: u8, b: u8, a: u8) ---
  661. v2f_c1i :: proc(x: f32, y: f32, rgba: u32) ---
  662. v3f_c3f :: proc(x: f32, y: f32, z: f32, r: f32, g: f32, b: f32) ---
  663. v3f_c3b :: proc(x: f32, y: f32, z: f32, r: u8, g: u8, b: u8) ---
  664. v3f_c4f :: proc(x: f32, y: f32, z: f32, r: f32, g: f32, b: f32, a: f32) ---
  665. v3f_c4b :: proc(x: f32, y: f32, z: f32, r: u8, g: u8, b: u8, a: u8) ---
  666. v3f_c1i :: proc(x: f32, y: f32, z: f32, rgba: u32) ---
  667. v2f_t2f_c3f :: proc(x: f32, y: f32, u: f32, v: f32, r: f32, g: f32, b: f32) ---
  668. v2f_t2f_c3b :: proc(x: f32, y: f32, u: f32, v: f32, r: u8, g: u8, b: u8) ---
  669. v2f_t2f_c4f :: proc(x: f32, y: f32, u: f32, v: f32, r: f32, g: f32, b: f32, a: f32) ---
  670. v2f_t2f_c4b :: proc(x: f32, y: f32, u: f32, v: f32, r: u8, g: u8, b: u8, a: u8) ---
  671. v2f_t2f_c1i :: proc(x: f32, y: f32, u: f32, v: f32, rgba: u32) ---
  672. v3f_t2f_c3f :: proc(x: f32, y: f32, z: f32, u: f32, v: f32, r: f32, g: f32, b: f32) ---
  673. v3f_t2f_c3b :: proc(x: f32, y: f32, z: f32, u: f32, v: f32, r: u8, g: u8, b: u8) ---
  674. v3f_t2f_c4f :: proc(x: f32, y: f32, z: f32, u: f32, v: f32, r: f32, g: f32, b: f32, a: f32) ---
  675. v3f_t2f_c4b :: proc(x: f32, y: f32, z: f32, u: f32, v: f32, r: u8, g: u8, b: u8, a: u8) ---
  676. v3f_t2f_c1i :: proc(x: f32, y: f32, z: f32, u: f32, v: f32, rgba: u32) ---
  677. end :: proc() ---
  678. }
  679. Log_Item :: enum i32 {
  680. OK,
  681. MALLOC_FAILED,
  682. MAKE_PIPELINE_FAILED,
  683. PIPELINE_POOL_EXHAUSTED,
  684. ADD_COMMIT_LISTENER_FAILED,
  685. CONTEXT_POOL_EXHAUSTED,
  686. CANNOT_DESTROY_DEFAULT_CONTEXT,
  687. }
  688. /*
  689. sgl_logger_t
  690. Used in sgl_desc_t to provide a custom logging and error reporting
  691. callback to sokol-gl.
  692. */
  693. Logger :: struct {
  694. func : proc "c" (a0: cstring, a1: u32, a2: u32, a3: cstring, a4: u32, a5: cstring, a6: rawptr),
  695. user_data : rawptr,
  696. }
  697. // sokol_gl pipeline handle (created with sgl_make_pipeline())
  698. Pipeline :: struct {
  699. id : u32,
  700. }
  701. // a context handle (created with sgl_make_context())
  702. Context :: struct {
  703. id : u32,
  704. }
  705. /*
  706. sgl_error_t
  707. Errors are reset each frame after calling sgl_draw(),
  708. get the last error code with sgl_error()
  709. */
  710. Error :: struct {
  711. any : bool,
  712. vertices_full : bool,
  713. uniforms_full : bool,
  714. commands_full : bool,
  715. stack_overflow : bool,
  716. stack_underflow : bool,
  717. no_context : bool,
  718. }
  719. /*
  720. sgl_context_desc_t
  721. Describes the initialization parameters of a rendering context.
  722. Creating additional contexts is useful if you want to render
  723. in separate sokol-gfx passes.
  724. */
  725. Context_Desc :: struct {
  726. max_vertices : c.int,
  727. max_commands : c.int,
  728. color_format : sg.Pixel_Format,
  729. depth_format : sg.Pixel_Format,
  730. sample_count : c.int,
  731. }
  732. /*
  733. sgl_allocator_t
  734. Used in sgl_desc_t to provide custom memory-alloc and -free functions
  735. to sokol_gl.h. If memory management should be overridden, both the
  736. alloc and free function must be provided (e.g. it's not valid to
  737. override one function but not the other).
  738. */
  739. Allocator :: struct {
  740. alloc_fn : proc "c" (a0: c.size_t, a1: rawptr) -> rawptr,
  741. free_fn : proc "c" (a0: rawptr, a1: rawptr),
  742. user_data : rawptr,
  743. }
  744. Desc :: struct {
  745. max_vertices : c.int,
  746. max_commands : c.int,
  747. context_pool_size : c.int,
  748. pipeline_pool_size : c.int,
  749. color_format : sg.Pixel_Format,
  750. depth_format : sg.Pixel_Format,
  751. sample_count : c.int,
  752. face_winding : sg.Face_Winding,
  753. allocator : Allocator,
  754. logger : Logger,
  755. }