-
Notifications
You must be signed in to change notification settings - Fork 1
/
mental_gl.h
2954 lines (2615 loc) · 144 KB
/
mental_gl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* MentalGL (OpenGL debugging functions)
* Published 2018 under the public domain
*
* Authors:
* - Lukas Hermanns (Creator)
*
* HISTORY:
* - v1.00 (03/26/2018): First release
* - v1.01 (01/26/2019): Refinements, MacOS portability
* - v1.02 (10/20/2023): Added mglQueryBindingPoints and mglPrintBindingPoints
* - v1.03 (14/01/2024): Added missing GL states: GL_POLYGON_MODE, GL_FRONT_FACE, GL_PATCH_*, GL_CLIP_*
*
* USAGE EXAMPLE:
* // Optionally enable glGetIntegeri_v and glGetInteger64i_v
* #define MENTAL_GL_GETINTEGERI_V
* #define MENTAL_GL_GETINTEGER64I_V
*
* // Include and implement MentalGL in a single source file
* #define MENTAL_GL_IMPLEMENTATION
* #include "mental_gl.h"
*
* // Do OpenGL stuff ...
*
* // Query current OpenGL state
* MGLRenderState rs;
* mglQueryRenderState(&rs);
*
* // Print queried OpenGL state (ignore optional formatting descriptor, otherwise see 'MGLFormattingOptions' structure)
* MGLString s = mglPrintRenderState(&rs, NULL);
*
* // Print result
* puts(mglGetUTF8String(s));
*
* // Free opaque string object
* mglFreeString(s);
*/
#ifndef MENTAL_GL_H
#define MENTAL_GL_H
#include <stddef.h>
// *****************************************************************
// PUBLIC MACROS
// *****************************************************************
#define MGL_MAX_COMPRESSED_TEXTURE_FORMATS ( 128 )
#define MGL_MAX_PROGRAM_BINARY_FORMATS ( 16 )
#define MGL_MAX_SHADER_BINARY_FORMATS ( 16 )
#define MGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS ( 32 )
#define MGL_MAX_TRANSFORM_FEEDBACK_BUFFER_BINDINGS ( 16 )
#define MGL_MAX_UNIFORM_BUFFER_BINDINGS ( 32 )
#define MGL_MAX_VERTEX_BUFFER_BINDINGS ( 32 )
#define MGL_MAX_TEXTURE_LAYERS ( 32 )
// *****************************************************************
// PUBLIC ENUMERATIONS
// *****************************************************************
// Query formatting order.
enum MGLFormattingOrder
{
MGLFormattingOrderDefault,
MGLFormattingOrderSorted,
};
// *****************************************************************
// PUBLIC STRUCTURES
// *****************************************************************
// Opaque string object used as result mglPrintRenderState.
typedef void* MGLString;
// Query formatting descriptor structure.
typedef struct MGLFormattingOptions
{
char separator; // Character to separate the attributes from their values. By default ' '.
size_t distance; // Distances (in number of characters) between the longest attribute name and the attribute values. By default 1.
size_t array_limit; // Limit of characters for an array. If an array exceeds this limit, it will be printed into multiple lines, one for each element. By default 200.
enum MGLFormattingOrder order; // Specifies the formatting order (if sorted for instance). By default MGLFormattingOrderDefault.
int enable_hex; // Specifies whether unknown enumerations shall be printed as hex codes (if != 0). By default 1.
const char* filter; // Optional filter to only output parameters which contain this string. By default NULL.
}
MGLFormattingOptions;
typedef struct MGLRenderState
{
GLint iActiveTexture; // GL_ACTIVE_TEXTURE
GLfloat fAliasedLineWidthRange[2]; // GL_ALIASED_LINE_WIDTH_RANGE
GLint iArrayBufferBinding; // GL_ARRAY_BUFFER_BINDING
GLboolean bBlend; // GL_BLEND
GLfloat fBlendColor[4]; // GL_BLEND_COLOR
GLint iBlendDstAlpha; // GL_BLEND_DST_ALPHA
GLint iBlendDstRGB; // GL_BLEND_DST_RGB
GLint iBlendEquationAlpha; // GL_BLEND_EQUATION_ALPHA
GLint iBlendEquationRGB; // GL_BLEND_EQUATION_RGB
GLint iBlendSrcAlpha; // GL_BLEND_SRC_ALPHA
GLint iBlendSrcRGB; // GL_BLEND_SRC_RGB
GLint iClipDepthMode; // GL_CLIP_DEPTH_MODE
GLint iClipOrigin; // GL_CLIP_ORIGIN
GLfloat fColorClearValue[4]; // GL_COLOR_CLEAR_VALUE
GLboolean bColorLogicOp; // GL_COLOR_LOGIC_OP
GLboolean bColorWriteMask[4]; // GL_COLOR_WRITEMASK
GLint iCompressedTextureFormats[MGL_MAX_COMPRESSED_TEXTURE_FORMATS]; // GL_COMPRESSED_TEXTURE_FORMATS
GLint iContextFlags; // GL_CONTEXT_FLAGS
GLboolean bCullFace; // GL_CULL_FACE
GLint iCullFaceMode; // GL_CULL_FACE_MODE
GLint iCurrentProgram; // GL_CURRENT_PROGRAM
GLint iDebugGroupStackDepth; // GL_DEBUG_GROUP_STACK_DEPTH
GLdouble dDepthClearValue; // GL_DEPTH_CLEAR_VALUE
GLint iDepthFunc; // GL_DEPTH_FUNC
GLdouble dDepthRange[2]; // GL_DEPTH_RANGE
GLboolean bDepthTest; // GL_DEPTH_TEST
GLboolean bDepthWriteMask; // GL_DEPTH_WRITEMASK
GLint iDispatchIndirectBufferBinding; // GL_DISPATCH_INDIRECT_BUFFER_BINDING
GLboolean bDither; // GL_DITHER
GLboolean bDoubleBuffer; // GL_DOUBLEBUFFER
GLint iDrawBuffer; // GL_DRAW_BUFFER
GLint iDrawBuffer_i[16]; // GL_DRAW_BUFFER<i>
GLint iDrawFramebufferBinding; // GL_DRAW_FRAMEBUFFER_BINDING
GLint iElementArrayBufferBinding; // GL_ELEMENT_ARRAY_BUFFER_BINDING
GLint iFragmentShaderDerivativeHint; // GL_FRAGMENT_SHADER_DERIVATIVE_HINT
GLint iFrontFace; // GL_FRONT_FACE
GLint iImplementationColorReadFormat; // GL_IMPLEMENTATION_COLOR_READ_FORMAT
GLint iImplementationColorReadType; // GL_IMPLEMENTATION_COLOR_READ_TYPE
GLboolean bLineSmooth; // GL_LINE_SMOOTH
GLint iLineSmoothHint; // GL_LINE_SMOOTH_HINT
GLfloat fLineWidth; // GL_LINE_WIDTH
GLint iLayerProvokingVertex; // GL_LAYER_PROVOKING_VERTEX
GLint iLogicOpMode; // GL_LOGIC_OP_MODE
GLint iMajorVersion; // GL_MAJOR_VERSION
GLint iMax3DTextureSize; // GL_MAX_3D_TEXTURE_SIZE
GLint iMaxArrayTextureLayers; // GL_MAX_ARRAY_TEXTURE_LAYERS
GLint iMaxClipDistances; // GL_MAX_CLIP_DISTANCES
GLint iMaxColorTextureSamples; // GL_MAX_COLOR_TEXTURE_SAMPLES
GLint iMaxCombinedAtomicCounters; // GL_MAX_COMBINED_ATOMIC_COUNTERS
GLint iMaxCombinedComputeUniformComponents; // GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS
GLint iMaxCombinedFragmentUniformComponents; // GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
GLint iMaxCombinedGeometryUniformComponents; // GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS
GLint iMaxCombinedShaderStorageBlocks; // GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS
GLint iMaxCombinedTextureImageUnits; // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
GLint iMaxCombinedUniformBlocks; // GL_MAX_COMBINED_UNIFORM_BLOCKS
GLint iMaxCombinedVertexUniformComponents; // GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
GLint iMaxComputeAtomicCounters; // GL_MAX_COMPUTE_ATOMIC_COUNTERS
GLint iMaxComputeAtomicCounterBuffers; // GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
GLint iMaxComputeShaderStorageBlocks; // GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS
GLint iMaxComputeTextureImageUnits; // GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS
GLint iMaxComputeUniformBlocks; // GL_MAX_COMPUTE_UNIFORM_BLOCKS
GLint iMaxComputeUniformComponents; // GL_MAX_COMPUTE_UNIFORM_COMPONENTS
GLint iMaxComputeWorkGroupCount[3]; // GL_MAX_COMPUTE_WORK_GROUP_COUNT
GLint iMaxComputeWorkGroup; // GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS
GLint iMaxComputeWorkGroupSize[3]; // GL_MAX_COMPUTE_WORK_GROUP_SIZE
GLint iMaxCubeMapTextureSize; // GL_MAX_CUBE_MAP_TEXTURE_SIZE
GLint iMaxDebugGroupStackDepth; // GL_MAX_DEBUG_GROUP_STACK_DEPTH
GLint iMaxDepthTextureSamples; // GL_MAX_DEPTH_TEXTURE_SAMPLES
GLint iMaxDrawBuffers; // GL_MAX_DRAW_BUFFERS
GLint iMaxDualSourceDrawBuffers; // GL_MAX_DUAL_SOURCE_DRAW_BUFFERS
GLint iMaxElementIndex; // GL_MAX_ELEMENT_INDEX
GLint iMaxElementsIndices; // GL_MAX_ELEMENTS_INDICES
GLint iMaxElementsVertices; // GL_MAX_ELEMENTS_VERTICES
GLint iMaxFragmentAtomicCounters; // GL_MAX_FRAGMENT_ATOMIC_COUNTERS
GLint iMaxFragmentShaderStorageBlocks; // GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS
GLint iMaxFragmentInputComponents; // GL_MAX_FRAGMENT_INPUT_COMPONENTS
GLint iMaxFragmentUniformComponents; // GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
GLint iMaxFragmentUniformVectors; // GL_MAX_FRAGMENT_UNIFORM_VECTORS
GLint iMaxFragmentUniformBlocks; // GL_MAX_FRAGMENT_UNIFORM_BLOCKS
GLint iMaxFramebufferWidth; // GL_MAX_FRAMEBUFFER_WIDTH
GLint iMaxFramebufferHeight; // GL_MAX_FRAMEBUFFER_HEIGHT
GLint iMaxFramebufferLayers; // GL_MAX_FRAMEBUFFER_LAYERS
GLint iMaxFramebufferSamples; // GL_MAX_FRAMEBUFFER_SAMPLES
GLint iMaxGeometryAtomicCounters; // GL_MAX_GEOMETRY_ATOMIC_COUNTERS
GLint iMaxGeometryShaderStorageBlocks; // GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS
GLint iMaxGeometryInputComponents; // GL_MAX_GEOMETRY_INPUT_COMPONENTS
GLint iMaxGeometryOutputComponents; // GL_MAX_GEOMETRY_OUTPUT_COMPONENTS
GLint iMaxGeometryTextureImageUnits; // GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS
GLint iMaxGeometryUniformBlocks; // GL_MAX_GEOMETRY_UNIFORM_BLOCKS
GLint iMaxGeometryUniformComponents; // GL_MAX_GEOMETRY_UNIFORM_COMPONENTS
GLint iMaxIntegerSamples; // GL_MAX_INTEGER_SAMPLES
GLint iMaxLabelLength; // GL_MAX_LABEL_LENGTH
GLint iMaxProgramTexelOffest; // GL_MAX_PROGRAM_TEXEL_OFFSET
GLint iMaxRectangleTextureSize; // GL_MAX_RECTANGLE_TEXTURE_SIZE
GLint iMaxRenderbufferSize; // GL_MAX_RENDERBUFFER_SIZE
GLint iMaxSampleMaskWords; // GL_MAX_SAMPLE_MASK_WORDS
GLint iMaxServerWaitTimeout; // GL_MAX_SERVER_WAIT_TIMEOUT
GLint iMaxShaderStorageBufferBindings; // GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS
GLint iMaxTessControlAtomicCounters; // GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS
GLint iMaxTessControlShaderStorageBlocks; // GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS
GLint iMaxTessEvaluationAtomicCounters; // GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS
GLint iMaxTessEvaluationShaderStorageBlocks; // GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS
GLint iMaxTextureBufferSize; // GL_MAX_TEXTURE_BUFFER_SIZE
GLint iMaxTextureImageUnits; // GL_MAX_TEXTURE_IMAGE_UNITS
GLfloat fMaxTextureLODBias; // GL_MAX_TEXTURE_LOD_BIAS
GLint iMaxTextureSize; // GL_MAX_TEXTURE_SIZE
GLint iMaxTransformFeedbackBuffers; // GL_MAX_TRANSFORM_FEEDBACK_BUFFERS
GLint iMaxUniformBufferBindings; // GL_MAX_UNIFORM_BUFFER_BINDINGS
GLint iMaxUniformBlockSize; // GL_MAX_UNIFORM_BLOCK_SIZE
GLint iMaxUniformLocations; // GL_MAX_UNIFORM_LOCATIONS
GLint iMaxVaryingComponents; // GL_MAX_VARYING_COMPONENTS
GLint iMaxVaryingVectors; // GL_MAX_VARYING_VECTORS
GLint iMaxVaryingFloats; // GL_MAX_VARYING_FLOATS
GLint iMaxVertexAtomicCounters; // GL_MAX_VERTEX_ATOMIC_COUNTERS
GLint iMaxVertexAttribRelativeOffset; // GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET
GLint iMaxVertexAttribBindings; // GL_MAX_VERTEX_ATTRIB_BINDINGS
GLint iMaxVertexAttribs; // GL_MAX_VERTEX_ATTRIBS
GLint iMaxVertexOutputComponents; // GL_MAX_VERTEX_OUTPUT_COMPONENTS
GLint iMaxVertexShaderStorageBlocks; // GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS
GLint iMaxVertexTextureImageUnits; // GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
GLint iMaxVertexUniformBlocks; // GL_MAX_VERTEX_UNIFORM_BLOCKS
GLint iMaxVertexUniformComponents; // GL_MAX_VERTEX_UNIFORM_COMPONENTS
GLint iMaxVertexUniformVectors; // GL_MAX_VERTEX_UNIFORM_VECTORS
GLint iMaxViewportDims[2]; // GL_MAX_VIEWPORT_DIMS
GLint iMaxViewports; // GL_MAX_VIEWPORTS
GLint iMinMapBufferAlignment; // GL_MIN_MAP_BUFFER_ALIGNMENT
GLint iMinProgramTexelOffest; // GL_MIN_PROGRAM_TEXEL_OFFSET
GLint iMinorVersion; // GL_MINOR_VERSION
GLint iNumCompressedTextureFormats; // GL_NUM_COMPRESSED_TEXTURE_FORMATS
GLint iNumExtensions; // GL_NUM_EXTENSIONS
GLint iNumProgramBinaryFormats; // GL_NUM_PROGRAM_BINARY_FORMATS
GLint iNumShaderBinaryFormats; // GL_NUM_SHADER_BINARY_FORMATS
GLint iPackAlignment; // GL_PACK_ALIGNMENT
GLint iPackImageHeight; // GL_PACK_IMAGE_HEIGHT
GLboolean bPackLSBFirst; // GL_PACK_LSB_FIRST
GLint iPackRowLength; // GL_PACK_ROW_LENGTH
GLint iPackSkipImages; // GL_PACK_SKIP_IMAGES
GLint iPackSkipPixels; // GL_PACK_SKIP_PIXELS
GLint iPackSkipRows; // GL_PACK_SKIP_ROWS
GLboolean bPackSwapBytes; // GL_PACK_SWAP_BYTES
GLint iPatchDefaultInnerLevel; // GL_PATCH_DEFAULT_INNER_LEVEL
GLint iPatchDefaultOuterLevel; // GL_PATCH_DEFAULT_OUTER_LEVEL
GLint iPatchVertices; // GL_PATCH_VERTICES
GLint iPixelPackBufferBinding; // GL_PIXEL_PACK_BUFFER_BINDING
GLint iPixelUnpackBufferBinding; // GL_PIXEL_UNPACK_BUFFER_BINDING
GLfloat fPointFadeThresholdSize; // GL_POINT_FADE_THRESHOLD_SIZE
GLint iPolygonMode[2]; // GL_POLYGON_MODE
GLint iPrimitiveRestartIndex; // GL_PRIMITIVE_RESTART_INDEX
GLint iProgramBinaryFormats[MGL_MAX_PROGRAM_BINARY_FORMATS]; // GL_PROGRAM_BINARY_FORMATS
GLint iProgramPipelineBinding; // GL_PROGRAM_PIPELINE_BINDING
GLboolean bProgramPointSize; // GL_PROGRAM_POINT_SIZE
GLint iProvokingVertex; // GL_PROVOKING_VERTEX
GLfloat fPointSize; // GL_POINT_SIZE
GLfloat fPointSizeGranularity; // GL_POINT_SIZE_GRANULARITY
GLfloat fPointSizeRange[2]; // GL_POINT_SIZE_RANGE
GLfloat fPolygonOffsetFactor; // GL_POLYGON_OFFSET_FACTOR
GLfloat fPolygonOffsetUnits; // GL_POLYGON_OFFSET_UNITS
GLboolean bPolygonOffsetFill; // GL_POLYGON_OFFSET_FILL
GLboolean bPolygonOffsetLine; // GL_POLYGON_OFFSET_LINE
GLboolean bPolygonOffsetPoint; // GL_POLYGON_OFFSET_POINT
GLboolean bPolygonSmooth; // GL_POLYGON_SMOOTH
GLint iPolygonSmoothHint; // GL_POLYGON_SMOOTH_HINT
GLint iReadBuffer; // GL_READ_BUFFER
GLint iReadFramebufferBinding; // GL_READ_FRAMEBUFFER_BINDING
GLint iRenderbufferBinding; // GL_RENDERBUFFER_BINDING
GLint iSampleBuffers; // GL_SAMPLE_BUFFERS
GLfloat fSampleCoverageValue; // GL_SAMPLE_COVERAGE_VALUE
GLboolean bSampleCoverageInvert; // GL_SAMPLE_COVERAGE_INVERT
GLint iSamplerBinding; // GL_SAMPLER_BINDING
GLint iSamples; // GL_SAMPLES
GLint iScissorBox[4]; // GL_SCISSOR_BOX
GLboolean bScissorTest; // GL_SCISSOR_TEST
GLboolean bShaderCompiler; // GL_SHADER_COMPILER
GLint iShaderBinaryFormats[MGL_MAX_SHADER_BINARY_FORMATS]; // GL_SHADER_BINARY_FORMATS
GLint iShaderStorageBufferBinding[MGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS]; // GL_SHADER_STORAGE_BUFFER_BINDING
GLint iShaderStorageBufferOffsetAlignment; // GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
GLint64 iShaderStorageBufferSize[MGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS]; // GL_SHADER_STORAGE_BUFFER_SIZE
GLint64 iShaderStorageBufferStart[MGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS]; // GL_SHADER_STORAGE_BUFFER_START
GLfloat fSmoothLineWidthRange[2]; // GL_SMOOTH_LINE_WIDTH_RANGE
GLfloat fSmoothLineWidthGranularity; // GL_SMOOTH_LINE_WIDTH_GRANULARITY
GLint iStencilBackFail; // GL_STENCIL_BACK_FAIL
GLint iStencilBackFunc; // GL_STENCIL_BACK_FUNC
GLint iStencilBackPassDepthFail; // GL_STENCIL_BACK_PASS_DEPTH_FAIL
GLint iStencilBackPassDepthPass; // GL_STENCIL_BACK_PASS_DEPTH_PASS
GLint iStencilBackRef; // GL_STENCIL_BACK_REF
GLint iStencilBackValueMask; // GL_STENCIL_BACK_VALUE_MASK
GLint iStencilBackWriteMask; // GL_STENCIL_BACK_WRITEMASK
GLint iStencilClearValue; // GL_STENCIL_CLEAR_VALUE
GLint iStencilFail; // GL_STENCIL_FAIL
GLint iStencilFunc; // GL_STENCIL_FUNC
GLint iStencilPassDepthFail; // GL_STENCIL_PASS_DEPTH_FAIL
GLint iStencilPassDepthPass; // GL_STENCIL_PASS_DEPTH_PASS
GLint iStencilRef; // GL_STENCIL_REF
GLboolean bStencilTest; // GL_STENCIL_TEST
GLint iStencilValueMask; // GL_STENCIL_VALUE_MASK
GLint iStencilWriteMask; // GL_STENCIL_WRITEMASK
GLboolean bStereo; // GL_STEREO
GLint iSubPixelBits; // GL_SUBPIXEL_BITS
GLint iTextureBinding1D; // GL_TEXTURE_BINDING_1D
GLint iTextureBinding1DArray; // GL_TEXTURE_BINDING_1D_ARRAY
GLint iTextureBinding2D; // GL_TEXTURE_BINDING_2D
GLint iTextureBinding2DArray; // GL_TEXTURE_BINDING_2D_ARRAY
GLint iTextureBinding2DMultisample; // GL_TEXTURE_BINDING_2D_MULTISAMPLE
GLint iTextureBinding2DMultisampleArray; // GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
GLint iTextureBinding3D; // GL_TEXTURE_BINDING_3D
GLint iTextureBindingBuffer; // GL_TEXTURE_BINDING_BUFFER
GLint iTextureBindingCubeMap; // GL_TEXTURE_BINDING_CUBE_MAP
GLint iTextureBindingRectangle; // GL_TEXTURE_BINDING_RECTANGLE
GLint iTextureCompressionHint; // GL_TEXTURE_COMPRESSION_HINT
GLint iTextureBufferOffsetAlignment; // GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT
GLint64 iTimestamp; // GL_TIMESTAMP
GLint iTransformFeedbackBufferBinding[MGL_MAX_TRANSFORM_FEEDBACK_BUFFER_BINDINGS]; // GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
GLint64 iTransformFeedbackBufferSize[MGL_MAX_TRANSFORM_FEEDBACK_BUFFER_BINDINGS]; // GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
GLint64 iTransformFeedbackBufferStart[MGL_MAX_TRANSFORM_FEEDBACK_BUFFER_BINDINGS]; // GL_TRANSFORM_FEEDBACK_BUFFER_START
GLint iUniformBufferBinding[MGL_MAX_UNIFORM_BUFFER_BINDINGS]; // GL_UNIFORM_BUFFER_BINDING
GLint iUniformBufferOffsetAlignment; // GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
GLint64 iUniformBufferSize[MGL_MAX_UNIFORM_BUFFER_BINDINGS]; // GL_UNIFORM_BUFFER_SIZE
GLint64 iUniformBufferStart[MGL_MAX_UNIFORM_BUFFER_BINDINGS]; // GL_UNIFORM_BUFFER_START
GLint iUnpackAlignment; // GL_UNPACK_ALIGNMENT
GLint iUnpackImageHeight; // GL_UNPACK_IMAGE_HEIGHT
GLboolean bUnpackLSBFirst; // GL_UNPACK_LSB_FIRST
GLint iUnpackRowLength; // GL_UNPACK_ROW_LENGTH
GLint iUnpackSkipImages; // GL_UNPACK_SKIP_IMAGES
GLint iUnpackSkipPixels; // GL_UNPACK_SKIP_PIXELS
GLint iUnpackSkipRows; // GL_UNPACK_SKIP_ROWS
GLboolean bUnpackSwapBytes; // GL_UNPACK_SWAP_BYTES
GLint iVertexArrayBinding; // GL_VERTEX_ARRAY_BINDING
GLint iVertexBindingDivisor[MGL_MAX_VERTEX_BUFFER_BINDINGS]; // GL_VERTEX_BINDING_DIVISOR
GLint iVertexBindingOffset[MGL_MAX_VERTEX_BUFFER_BINDINGS]; // GL_VERTEX_BINDING_OFFSET
GLint iVertexBindingStride[MGL_MAX_VERTEX_BUFFER_BINDINGS]; // GL_VERTEX_BINDING_STRIDE
GLint iViewport[4]; // GL_VIEWPORT
GLint iViewportBoundsRange[2]; // GL_VIEWPORT_BOUNDS_RANGE
GLint iViewportIndexProvokingVertex; // GL_VIEWPORT_INDEX_PROVOKING_VERTEX
GLint iViewportSubPixelBits; // GL_VIEWPORT_SUBPIXEL_BITS
}
MGLRenderState;
typedef struct MGLBindingPoints
{
GLint iTextureBinding1D[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_1D
GLint iTextureBinding1DArray[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_1D_ARRAY
GLint iTextureBinding2D[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_2D
GLint iTextureBinding2DArray[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_2D_ARRAY
GLint iTextureBinding2DMultisample[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_2D_MULTISAMPLE
GLint iTextureBinding2DMultisampleArray[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
GLint iTextureBinding3D[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_3D
GLint iTextureBindingBuffer[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_BUFFER
GLint iTextureBindingCubeMap[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_CUBE_MAP
GLint iTextureBindingRectangle[MGL_MAX_TEXTURE_LAYERS]; // GL_TEXTURE_BINDING_RECTANGLE
}
MGLBindingPoints;
// *****************************************************************
// PUBLIC FUNCTIONS
// *****************************************************************
#ifdef __cplusplus
extern "C" {
#endif
// Queries the entire OpenGL render state and stores it in 'render_state'.
void mglQueryRenderState(MGLRenderState* render_state);
// Queries the entire OpenGL binding points and stores it in 'binding_points'.
void mglQueryBindingPoints(MGLBindingPoints* binding_points);
// Prints the entire OpenGL render states specified by 'render_state' and returns the formatted output string.
MGLString mglPrintRenderState(const MGLRenderState* render_state, const MGLFormattingOptions* formatting);
// Prints the entire OpenGL binding points specified by 'binding_points' and returns the formatted output string.
MGLString mglPrintBindingPoints(const MGLBindingPoints* binding_points, const MGLFormattingOptions* formatting);
// Returns the null-terminated string from the specified opaque object.
const char* mglGetUTF8String(MGLString s);
// Release all resources allocated by this library.
void mglFreeString(MGLString s);
#ifdef __cplusplus
} // /extern "C"
#endif
// *****************************************************************
// IMPLEMENTATION
// *****************************************************************
#ifdef MENTAL_GL_IMPLEMENTATION
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif // /_MSC_VER
#ifdef _WIN32
#include <Windows.h>
#endif
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
# include <OpenGL/OpenGL.h>
#else
# include <GL/GL.h>
# include <GL/glext.h>
#endif
// *****************************************************************
// INTERNAL MACROS
// *****************************************************************
#define MGL_CASE2STR(NAME) case NAME: return #NAME
#define MGL_MIN(A, B) ((A) < (B) ? (A) : (B))
#define MGL_MAX(A, B) ((A) > (B) ? (A) : (B))
#ifndef MGL_MALLOC
#define MGL_MALLOC(TYPE) ((TYPE*)malloc(sizeof(TYPE)))
#endif
#ifndef MGL_CALLOC
#define MGL_CALLOC(TYPE, COUNT) ((TYPE*)calloc(COUNT, sizeof(TYPE)))
#endif
#ifndef MGL_FREE
#define MGL_FREE(OBJ) free(OBJ)
#endif
#define MGL_STRING_MIN_CAPACITY 16
#define MGL_STRING_NPOS (size_t)~0
#define MGL_MAX_NUM_RENDER_STATES 264
// *****************************************************************
// INTERNAL FUNCTION OBJECTS
// *****************************************************************
typedef const char* (*MGLEnumToStringProc)(GLenum);
// *****************************************************************
// INTERNAL STRUCTURES
// *****************************************************************
typedef struct MGLStringInternal
{
size_t cap; // capacity
size_t len; // length
char* buf; // buffer (incl. NUL char)
}
MGLStringInternal;
typedef struct MGLStringPairArray
{
MGLStringInternal* first;
MGLStringInternal* second;
size_t index;
}
MGLStringPairArray;
// *****************************************************************
// INTERNAL FUNCTIONS
// *****************************************************************
#ifdef __cplusplus
extern "C" {
#endif
static void mglStringInternalReset(MGLStringInternal* s)
{
if (s)
{
s->cap = 0;
s->len = 0;
s->buf = NULL;
}
}
// Allocates a new internal string object with the specified initial capacity (minimum is 'MGL_STRING_MIN_CAPACITY')
static void mglStringInternalInit(MGLStringInternal* s, size_t init_cap)
{
if (s)
{
s->cap = MGL_MAX(MGL_STRING_MIN_CAPACITY, init_cap);
s->len = 0;
s->buf = MGL_CALLOC(char, s->cap);
s->buf[0] = '\0';
}
}
// Allocates a new internal string object and initializes the string buffer with the specified null terminated string
static void mglStringInternalInitWith(MGLStringInternal* s, const char* val)
{
if (val)
{
size_t len = strlen(val);
s->cap = MGL_MAX(MGL_STRING_MIN_CAPACITY, len + 1);
s->len = len;
s->buf = MGL_CALLOC(char, s->cap);
memcpy(s->buf, val, s->len);
s->buf[s->len] = '\0';
}
else
mglStringInternalInit(s, 0);
}
// Releases the specified internal string object
static void mglStringInternalFree(MGLStringInternal* s)
{
if (s && s->buf)
MGL_FREE(s->buf);
}
#if 0 // UNUSED
// Allocates enough space for the specified capacity (if its larger than the current string capacity)
static void mglStringInternalReserve(MGLStringInternal* s, size_t cap)
{
if (s && cap > s->cap)
{
// Allocate new string buffer and copy previous string into new buffer
char* new_buf = MGL_CALLOC(char, cap);
memcpy(new_buf, s->buf, s->len);
new_buf[s->len] = '\0';
// Replace previous string
MGL_FREE(s->buf);
s->cap = cap;
s->buf = new_buf;
}
}
// Copies the specified internal string object
static void mglStringInternalCopy(MGLStringInternal* dst, const MGLStringInternal* src)
{
if (dst && src)
{
dst->cap = src->cap;
dst->len = src->len;
dst->buf = MGL_CALLOC(char, dst->cap);
memcpy(dst->buf, src->buf, dst->len + 1);
}
}
#endif // /UNUSED
// Resizes the string to the specified length and fills the new characters with 'chr'
static void mglStringInternalResize(MGLStringInternal* s, size_t len, char chr)
{
if (s)
{
if (len + 1 > s->cap)
{
// Allocate new string buffer and copy previous string into new buffer
size_t new_cap = MGL_MAX(len + 1, s->cap * 2);
char* new_buf = MGL_CALLOC(char, new_cap);
memcpy(new_buf, s->buf, s->len);
// Initialize new characters
if (chr != 0)
{
for (size_t i = s->len; i < len; ++i)
new_buf[i] = chr;
}
new_buf[len] = '\0';
// Replace previous string
MGL_FREE(s->buf);
s->cap = new_cap;
s->len = len;
s->buf = new_buf;
}
else if (len < s->len)
{
if (s->cap > MGL_STRING_MIN_CAPACITY && len < s->cap / 2)
{
// Allocate new string buffer and copy previous partial string into new buffer
size_t new_cap = MGL_MAX(MGL_STRING_MIN_CAPACITY, s->cap / 2);
char* new_buf = MGL_CALLOC(char, new_cap);
memcpy(new_buf, s->buf, len);
new_buf[len] = '\0';
// Replace previous string
MGL_FREE(s->buf);
s->cap = new_cap;
s->len = len;
s->buf = new_buf;
}
else
{
// Set new null terminator
s->buf[len] = '\0';
}
}
else if (len > s->len)
{
// Initialize new characters
if (chr != 0)
{
for (size_t i = s->len; i < len; ++i)
s->buf[i] = chr;
}
s->buf[len] = '\0';
s->len = len;
}
}
}
// Appends the specified appendix to the internal string object
static void mglStringInternalAppend(MGLStringInternal* s, const MGLStringInternal* appendix)
{
if (s && appendix && appendix->len > 0)
{
// Resize string and copy appendix into new area
size_t lhs_len = s->len;
mglStringInternalResize(s, lhs_len + appendix->len, 0);
memcpy(s->buf + lhs_len, appendix->buf, appendix->len);
}
}
// Appends the specified appendix sub-string (with offset and length) to the internal string object
static void mglStringInternalAppendSub(MGLStringInternal* s, const MGLStringInternal* appendix, size_t off, size_t len)
{
if (s && appendix && appendix->len > off && len > 0)
{
// Resize string and copy appendix into new area
size_t lhs_len = s->len;
size_t rhs_len = MGL_MIN(len, appendix->len - off);
if (rhs_len > 0)
{
mglStringInternalResize(s, lhs_len + rhs_len, 0);
memcpy(s->buf + lhs_len, appendix->buf + off, rhs_len);
}
}
}
// Appends the specified appendix to the internal string object
static void mglStringInternalAppendCStr(MGLStringInternal* s, const char* appendix)
{
if (s && appendix && *appendix != '\0')
{
// Resize string and copy appendix into new area
size_t lhs_len = s->len;
size_t rhs_len = strlen(appendix);
mglStringInternalResize(s, lhs_len + rhs_len, 0);
memcpy(s->buf + lhs_len, appendix, rhs_len);
}
}
static size_t mglStringInternalFindChar(const MGLStringInternal* s, char search_char, size_t off, size_t len)
{
if (s)
{
len = MGL_MIN(len, s->len);
for (; off < len; ++off)
{
if (s->buf[off] == search_char)
return off;
}
}
return MGL_STRING_NPOS;
}
static void mglGetIntegers(const GLenum* pnames, GLint* data, GLuint count)
{
for (GLuint i = 0; i < count; ++i)
glGetIntegerv(pnames[i], &(data[i]));
}
static void mglGetIntegerDynamicArray(GLenum pname, GLint* data, GLuint count, GLuint limit)
{
if (count > limit)
{
// Allocate temporary container if the array is too small
GLint* tmp_data = (GLint*)MGL_CALLOC(GLint, count);
glGetIntegerv(pname, tmp_data);
memcpy(data, tmp_data, sizeof(GLint)*limit);
free(tmp_data);
}
else
glGetIntegerv(pname, data);
}
static void mglGetIntegerStaticArray(GLenum pname, GLint* data, GLuint count)
{
#ifdef MENTAL_GL_GETINTEGERI_V
for (GLuint i = 0; i < count; ++i)
glGetIntegeri_v(pname, i, &(data[i]));
#endif
}
static void mglGetInteger64StaticArray(GLenum pname, GLint64* data, GLuint count)
{
#ifdef MENTAL_GL_GETINTEGER64I_V
for (GLuint i = 0; i < count; ++i)
glGetInteger64i_v(pname, i, &(data[i]));
#endif
}
static void mglEnumToHex(char* s, unsigned val)
{
sprintf(s, "0x%*X", 8, val);
for (s += 2; *s == ' '; ++s)
*s = '0';
}
static void mglNextHeadline(MGLStringPairArray* str_array, const char* headline)
{
mglStringInternalInitWith(&(str_array->first[str_array->index]), headline);
mglStringInternalReset(&(str_array->second[str_array->index]));
++(str_array->index);
}
static void mglNextParamString(MGLStringPairArray* str_array, const char* par, const char* val)
{
mglStringInternalInitWith(&(str_array->first[str_array->index]), par);
mglStringInternalInitWith(&(str_array->second[str_array->index]), val);
++(str_array->index);
}
static void mglNextParamInteger(MGLStringPairArray* str_array, const char* par, GLint val)
{
char s_val[16];
sprintf(s_val, "%i", val);
mglNextParamString(str_array, par, s_val);
}
static void mglNextParamUInteger(MGLStringPairArray* str_array, const char* par, GLuint val)
{
char s_val[16];
sprintf(s_val, "%u", val);
mglNextParamString(str_array, par, s_val);
}
static void mglNextParamIntegerHex(MGLStringPairArray* str_array, const char* par, GLint val)
{
char s_hex[11];
mglEnumToHex(s_hex, (unsigned)val);
mglNextParamString(str_array, par, s_hex);
}
static void mglNextParamBoolean(MGLStringPairArray* str_array, const char* par, GLboolean val)
{
mglNextParamString(str_array, par, (val ? "GL_TRUE" : "GL_FALSE"));
}
static void mglNextParamEnum(MGLStringPairArray* str_array, const char* par, GLint val, MGLEnumToStringProc proc)
{
const char* s_val = proc(val);
if (!s_val)
{
char s_hex[11];
mglEnumToHex(s_hex, (unsigned)val);
mglNextParamString(str_array, par, s_hex);
}
else
mglNextParamString(str_array, par, s_val);
}
static void mglNextParamInteger64(MGLStringPairArray* str_array, const char* par, GLint64 val)
{
long long int val_ll = (long long int)val;
char s_val[32];
sprintf(s_val, "%lli", val_ll);
mglNextParamString(str_array, par, s_val);
}
static void mglNextParamFloat(MGLStringPairArray* str_array, const char* par, GLfloat val)
{
double val_d = (double)val;
char s_val[64];
sprintf(s_val, "%f", val_d);
mglNextParamString(str_array, par, s_val);
}
static void mglNextParamDouble(MGLStringPairArray* str_array, const char* par, GLdouble val)
{
char s_val[64];
sprintf(s_val, "%f", val);
mglNextParamString(str_array, par, s_val);
}
static void mglNextParamIntegerArray(MGLStringPairArray* str_array, const char* par, const GLint* val, size_t count, size_t limit, int to_hex)
{
char s_val[16];
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
mglStringInternalAppendCStr(out_val, "{ ");
size_t n = MGL_MIN(count, limit);
for (size_t i = 0; i < n; ++i)
{
if (to_hex)
mglEnumToHex(s_val, (unsigned)val[i]);
else
sprintf(s_val, "%i", val[i]);
mglStringInternalAppendCStr(out_val, s_val);
if (i + 1 < n)
mglStringInternalAppendCStr(out_val, ", ");
}
if (count > limit)
mglStringInternalAppendCStr(out_val, ", ... ");
mglStringInternalAppendCStr(out_val, " }");
++(str_array->index);
}
static void mglNextParamEnumArray(MGLStringPairArray* str_array, const char* par, const GLint* val, size_t count, size_t limit, MGLEnumToStringProc proc)
{
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
mglStringInternalAppendCStr(out_val, "{ ");
size_t n = MGL_MIN(count, limit);
for (size_t i = 0; i < n; ++i)
{
const char* s_val = proc(val[i]);
if (!s_val)
{
char s_hex[11];
mglEnumToHex(s_hex, (unsigned)val[i]);
mglStringInternalAppendCStr(out_val, s_hex);
}
else
mglStringInternalAppendCStr(out_val, s_val);
if (i + 1 < n)
mglStringInternalAppendCStr(out_val, ", ");
}
if (count > limit)
mglStringInternalAppendCStr(out_val, ", ... ");
mglStringInternalAppendCStr(out_val, " }");
++(str_array->index);
}
static void mglNextParamInteger64Array(MGLStringPairArray* str_array, const char* par, const GLint64* val, size_t count, size_t limit)
{
char s_val[32];
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
mglStringInternalAppendCStr(out_val, "{ ");
size_t n = MGL_MIN(count, limit);
for (size_t i = 0; i < n; ++i)
{
sprintf(s_val, "%lli", val[i]);
mglStringInternalAppendCStr(out_val, s_val);
if (i + 1 < n)
mglStringInternalAppendCStr(out_val, ", ");
}
if (count > limit)
mglStringInternalAppendCStr(out_val, ", ... ");
mglStringInternalAppendCStr(out_val, " }");
++(str_array->index);
}
static void mglNextParamBitfield(MGLStringPairArray* str_array, const char* par, GLbitfield val, size_t count, MGLEnumToStringProc proc)
{
size_t num_fields = 0;
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
for (size_t i = 0; i < count; ++i)
{
GLenum flag = (1 << i);
if ((val & flag) != 0)
{
if (num_fields > 0)
mglStringInternalAppendCStr(out_val, " | ");
++num_fields;
const char* s_val = proc(flag);
if (!s_val)
{
char s_hex[11];
mglEnumToHex(s_hex, (unsigned)val);
mglStringInternalAppendCStr(out_val, s_hex);
}
else
mglStringInternalAppendCStr(out_val, s_val);
}
}
if (num_fields == 0)
mglStringInternalAppendCStr(out_val, "0");
++(str_array->index);
}
static void mglNextParamFloatArray(MGLStringPairArray* str_array, const char* par, const GLfloat* val, size_t count)
{
double val_d;
char s_val[64];
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
mglStringInternalAppendCStr(out_val, "{ ");
for (size_t i = 0; i < count; ++i)
{
val_d = (double)val[i];
sprintf(s_val, "%f", val_d);
mglStringInternalAppendCStr(out_val, s_val);
if (i + 1 < count)
mglStringInternalAppendCStr(out_val, ", ");
}
mglStringInternalAppendCStr(out_val, " }");
++(str_array->index);
}
static void mglNextParamDoubleArray(MGLStringPairArray* str_array, const char* par, const GLdouble* val, size_t count)
{
char s_val[64];
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
mglStringInternalAppendCStr(out_val, "{ ");
for (size_t i = 0; i < count; ++i)
{
sprintf(s_val, "%f", val[i]);
mglStringInternalAppendCStr(out_val, s_val);
if (i + 1 < count)
mglStringInternalAppendCStr(out_val, ", ");
}
mglStringInternalAppendCStr(out_val, " }");
++(str_array->index);
}
static void mglNextParamBooleanArray(MGLStringPairArray* str_array, const char* par, const GLboolean* val, size_t count)
{
MGLStringInternal* out_par = &(str_array->first[str_array->index]);
MGLStringInternal* out_val = &(str_array->second[str_array->index]);
mglStringInternalInitWith(out_par, par);
mglStringInternalInit(out_val, 0);
mglStringInternalAppendCStr(out_val, "{ ");
for (size_t i = 0; i < count; ++i)
{
mglStringInternalAppendCStr(out_val, (val[i] != GL_FALSE ? "GL_TRUE" : "GL_FALSE"));
if (i + 1 < count)
mglStringInternalAppendCStr(out_val, ", ");
}
mglStringInternalAppendCStr(out_val, " }");
++(str_array->index);
}
// *****************************************************************
// CONVERSION FUNCTIONS
// *****************************************************************