diff --git a/lib/sdl3/MOCK_TESTING_COMPLETE.md b/lib/sdl3/MOCK_TESTING_COMPLETE.md deleted file mode 100644 index a1f1ba5..0000000 --- a/lib/sdl3/MOCK_TESTING_COMPLETE.md +++ /dev/null @@ -1,161 +0,0 @@ -# Mock Testing Implementation Complete - -## Summary - -Successfully implemented a complete test harness for the SDL3 parser that: -1. Generates Zig bindings from C headers (SDL_gpu.h - 169 declarations) -2. Generates C mock implementations with proper SDL header includes -3. Compiles mocks into a static library (71KB with 94 functions) -4. Links Zig tests against the mock library -5. Verifies compilation and execution - -## Build Commands - -### Regenerate test mocks -```bash -zig build regenerate-test-mocks -``` -Generates from SDL_gpu.h: -- `zig-out/gpu_test.zig` - Zig bindings (1,229 lines, 53KB) -- `zig-out/gpu_test_mock.c` - C mock implementations (577 lines, 18KB) - -### Compile check (no tests) -```bash -zig build check-mocks -``` -Verifies the generated code compiles without running tests. - -### Full test suite -```bash -zig build test-mocks -``` -Compiles and runs 7 tests: -- ✅ Can call createGPUDevice with various parameters -- ✅ Can call module-level query functions -- ✅ Device methods compile and link -- ✅ Enum values are distinct -- ✅ Packed struct shader format has correct size and fields -- ✅ Opaque types have correct pointer semantics -- ✅ Large header compilation stress test (169 declarations) - -## Implementation Details - -### Build Pipeline -1. **Parse**: `SDL/include/SDL3/SDL_gpu.h` → 169 declarations -2. **Generate**: Zig bindings + C mocks -3. **Compile**: C mocks → `libtest_mocks.a` (71KB, 94 functions) -4. **Link**: Zig tests + mock library -5. **Test**: Execute and verify - -### File Structure -``` -lib/sdl3/ -├── SDL/include/SDL3/ -│ └── SDL_gpu.h # Input C header (169 declarations) -├── parser/test/ -│ └── mock_test.zig # Test harness (7 tests) -├── zig-out/ -│ ├── gpu_test.zig # Generated bindings -│ └── gpu_test_mock.c # Generated mocks -└── build.zig # Build system integration -``` - -### Generated Mock Example -```c -// Auto-generated C mock implementations -// DO NOT EDIT - Generated by sdl-parser --mocks - -#include -#include - -SDL_GPUDevice * SDL_CreateGPUDevice(SDL_GPUShaderFormat format_flags, bool debug_mode, const char * name) { - (void)format_flags; - (void)debug_mode; - (void)name; - return NULL; -} -``` - -### Generated Binding Example -```zig -pub const GPUDevice = opaque { - pub inline fn createGPUTexture( - gpudevice: *GPUDevice, - createinfo: *const GPUTextureCreateInfo - ) ?*GPUTexture { - return c.SDL_CreateGPUTexture(gpudevice, @ptrCast(createinfo)); - } -}; -``` - -### Test Results -``` -Build Summary: 7/7 steps succeeded; 7/7 tests passed -test-mocks success -+- run test 7 passed 543us MaxRSS:3M - +- compile test Debug native cached 17ms MaxRSS:56M - +- compile lib test_mocks Debug native cached 19ms MaxRSS:55M -``` - -## Verified Capabilities - -✅ Parser generates syntactically valid Zig code (1,229 lines) -✅ Parser generates compilable C mock code (577 lines) -✅ C mocks compile with SDL headers (includes SDL_stdinc.h, SDL_gpu.h) -✅ C mocks compile to static library with 94 exported functions -✅ Zig code links against C mock library -✅ Generated functions are callable from Zig -✅ Generated types (13 opaque, 24 enums, 35 structs, 3 flags) work correctly -✅ Type safety is preserved across C/Zig boundary -✅ Large header (169 declarations) processes successfully - -## Statistics - -**SDL_gpu.h parsing:** -- 169 total declarations - - 13 opaque types (GPUDevice, GPUBuffer, etc.) - - 24 enums (GPUPrimitiveType, GPULoadOp, etc.) - - 35 structs (GPUTextureCreateInfo, etc.) - - 3 flags (GPUShaderFormat, etc.) - - 94 functions (all mocked and linkable) - -**Generated output:** -- Zig bindings: 1,229 lines, 53KB -- C mocks: 577 lines, 18KB -- Compiled library: 71KB, 94 symbols - -## Next Steps - -With mock testing working on full SDL_gpu.h, we can now: -1. Implement dependency resolution for cross-header types (FColor, Rect, etc.) -2. Test with other SDL3 headers (SDL_video.h, SDL_audio.h, etc.) -3. Add integration with real SDL3 library -4. Validate generated bindings match handwritten bindings - -## Time Investment - -- Build system setup: 30 minutes -- API fixes (Zig 0.15): 15 minutes -- Test harness creation: 20 minutes -- SDL header integration: 15 minutes -- Full SDL_gpu.h testing: 10 minutes -- Documentation: 10 minutes -**Total**: ~100 minutes - -## Key Learnings - -1. Zig 0.15 uses `addLibrary(.linkage = .static)` instead of `addStaticLibrary` -2. Must create root_module with target/optimize for libraries -3. `extern fn` declarations need to be in public scope for linkage -4. C mocks should include actual SDL headers for proper type definitions -5. Mock library with 94 functions compiles to only 71KB -6. Large headers (169 declarations) parse and compile successfully -7. Type safety preserved: opaque types, enums, structs all work correctly - ---- - -Date: 2026-01-22 -Status: Complete ✅ -Tests: 7/7 passing -Header: SDL_gpu.h (169 declarations) -Generated: 1,806 lines of code diff --git a/lib/sdl3/parser/SDL_VIDEO_ANALYSIS.md b/lib/sdl3/parser/SDL_VIDEO_ANALYSIS.md deleted file mode 100644 index 194036a..0000000 --- a/lib/sdl3/parser/SDL_VIDEO_ANALYSIS.md +++ /dev/null @@ -1,135 +0,0 @@ -# SDL_video.h Parsing Analysis - -## Current Status: ✅ MOSTLY WORKING - -The SDL_video.h header parses successfully with only minor missing type warnings. All major functionality is captured. - -## Statistics - -- **Total declarations found**: 124 - - Opaque types: 2 - - Typedefs: 6 - - Function pointers: 0 - - Enums: 4 - - Structs: 2 - - Flags: 1 - - Functions: 109 - -## Successfully Resolved Dependencies - -The parser successfully resolves and imports these types from dependency headers: - -✅ **SDL_PixelFormat** (from SDL_pixels.h) -✅ **SDL_Point** (from SDL_rect.h) -✅ **SDL_Rect** (from SDL_rect.h) -✅ **SDL_Surface** (from SDL_surface.h) -✅ **SDL_PropertiesID** (from SDL_properties.h) - -## Missing Type Definitions (7 types) - -These types are referenced but not found in the included headers: - -### 1. EGL-Related Types (5 types) - -These are OpenGL ES/EGL integration types defined within SDL_video.h itself: - -- **SDL_EGLConfig** - `typedef void *SDL_EGLConfig;` -- **SDL_EGLDisplay** - `typedef void *SDL_EGLDisplay;` -- **SDL_EGLSurface** - `typedef void *SDL_EGLSurface;` -- **SDL_EGLAttribArrayCallback** - Function pointer typedef -- **SDL_EGLIntArrayCallback** - Function pointer typedef - -**Root Cause**: These are defined in SDL_video.h but the parser's typedef scanner is not picking them up properly. - -**Issue**: The typedef scanner currently only processes simple typedefs and doesn't handle: -- Pointer typedefs (`typedef void *Type;`) -- Function pointer typedefs with complex signatures - -### 2. OpenGL Types (2 types) - -- **SDL_GLAttr** - Enum type for GL attributes -- **SDL_GLContext** - `typedef struct SDL_GLContextState *SDL_GLContext;` - -**Root Cause**: Similar to EGL types - these are typedef'd in SDL_video.h but not captured by the scanner. - -### 3. Callback Types (1 type) - -- **SDL_HitTest** - `typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(...);` - -**Root Cause**: Function pointer typedef with calling convention modifier. - -### 4. Generic Types (1 type) - -- **SDL_FunctionPointer** - `typedef void (SDLCALL *SDL_FunctionPointer)(void);` - -**Root Cause**: Function pointer typedef. - -## Implementation Plan - -### Phase 1: Enhance Typedef Scanner ✅ PRIORITY - -**Goal**: Make the typedef scanner capture all typedef forms in the same file being parsed. - -**Tasks**: - -1. **Add pointer typedef support** - ```c - typedef void *SDL_EGLConfig; - typedef struct SDL_GLContextState *SDL_GLContext; - ``` - - Pattern: `typedef *;` - - Store as opaque pointer type - -2. **Add function pointer typedef support** - ```c - typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win, const SDL_Point *area, void *data); - typedef void (SDLCALL *SDL_FunctionPointer)(void); - ``` - - Pattern: `typedef (SDLCALL *)();` - - Store as function pointer type with signature - -3. **Add enum typedef support** - ```c - typedef enum SDL_GLAttr { ... } SDL_GLAttr; - ``` - - Pattern: Already handled, but verify it works for GL types - -**Implementation Location**: `src/dependency_resolver.zig` - `scanFileForTypedefs()` - -**Expected Result**: After this phase, all 7 missing types should be found and properly typed. - -### Phase 2: Test and Validate - -1. Run parser on SDL_video.h -2. Verify all 14 originally missing types are now resolved (7 from deps, 7 from typedefs) -3. Verify generated Zig code compiles -4. Check that function signatures using these types are correct - -### Phase 3: Apply to Other Headers - -Once SDL_video.h parses completely clean, apply the same pattern to other headers with similar issues. - -## Error Categories - -### Category A: Typedef Scanner Limitations ⭐ PRIMARY ISSUE -- **Impact**: 7/14 missing types (50%) -- **Difficulty**: Medium -- **Files affected**: SDL_video.h, potentially others -- **Solution**: Enhance typedef scanner (Phase 1) - -### Category B: Cross-header Dependencies ✅ SOLVED -- **Impact**: 7/14 missing types (50%) - but these work! -- **Difficulty**: N/A (already working) -- **Solution**: Existing dependency resolver handles this correctly - -## Success Metrics - -After implementing Phase 1: -- ⬜ Zero "Could not find definition" warnings for SDL_video.h -- ⬜ Generated code compiles without errors -- ⬜ All 124 declarations properly typed -- ⬜ Can use as template for other complex headers - -## Notes - -The current parsing system is quite robust. The main gap is in the typedef scanner not recognizing all forms of typedef. This is a focused, solvable problem that will unlock SDL_video.h and similar headers. diff --git a/lib/sdl3/parser/output/SDL_gpu.h.json b/lib/sdl3/parser/output/SDL_gpu.h.json new file mode 100644 index 0000000..0bf05c3 --- /dev/null +++ b/lib/sdl3/parser/output/SDL_gpu.h.json @@ -0,0 +1,189 @@ +{ + "header": "SDL_gpu.h", + "opaque_types": [ + {"name": "SDL_GPUDevice"}, + {"name": "SDL_GPUBuffer"}, + {"name": "SDL_GPUTransferBuffer"}, + {"name": "SDL_GPUTexture"}, + {"name": "SDL_GPUSampler"}, + {"name": "SDL_GPUShader"}, + {"name": "SDL_GPUComputePipeline"}, + {"name": "SDL_GPUGraphicsPipeline"}, + {"name": "SDL_GPUCommandBuffer"}, + {"name": "SDL_GPURenderPass"}, + {"name": "SDL_GPUComputePass"}, + {"name": "SDL_GPUCopyPass"}, + {"name": "SDL_GPUFence"} + ], + "typedefs": [ + {"name": "SDL_GPUShaderFormat", "underlying_type": "Uint32"} + ], + "function_pointers": [ + ], + "enums": [ + {"name": "SDL_GPUPrimitiveType", "values": []}, + {"name": "SDL_GPULoadOp", "values": []}, + {"name": "SDL_GPUStoreOp", "values": []}, + {"name": "SDL_GPUIndexElementSize", "values": []}, + {"name": "SDL_GPUTextureFormat", "values": [{"name": "SDL_GPU_TEXTUREFORMAT_INVALID"}, {"name": "SDL_GPU_TEXTUREFORMAT_A8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8_SNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8_SNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16_SNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16_SNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32G32_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32G32_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT"}, {"name": "SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_D16_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_D24_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_D32_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT"}, {"name": "SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT"}]}, + {"name": "SDL_GPUTextureType", "values": []}, + {"name": "SDL_GPUSampleCount", "values": []}, + {"name": "SDL_GPUCubeMapFace", "values": [{"name": "SDL_GPU_CUBEMAPFACE_POSITIVEX"}, {"name": "SDL_GPU_CUBEMAPFACE_NEGATIVEX"}, {"name": "SDL_GPU_CUBEMAPFACE_POSITIVEY"}, {"name": "SDL_GPU_CUBEMAPFACE_NEGATIVEY"}, {"name": "SDL_GPU_CUBEMAPFACE_POSITIVEZ"}, {"name": "SDL_GPU_CUBEMAPFACE_NEGATIVEZ"}]}, + {"name": "SDL_GPUTransferBufferUsage", "values": [{"name": "SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD"}, {"name": "SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD"}]}, + {"name": "SDL_GPUShaderStage", "values": [{"name": "SDL_GPU_SHADERSTAGE_VERTEX"}, {"name": "SDL_GPU_SHADERSTAGE_FRAGMENT"}]}, + {"name": "SDL_GPUVertexElementFormat", "values": [{"name": "SDL_GPU_VERTEXELEMENTFORMAT_INVALID"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_INT"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_INT2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_INT3"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_INT4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UINT"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UINT2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UINT3"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UINT4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_FLOAT"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_BYTE2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_BYTE4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_BYTE2_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_BYTE4_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_SHORT2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_SHORT4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_USHORT2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_USHORT4"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_SHORT2_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_SHORT4_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_USHORT2_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_USHORT4_NORM"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_HALF2"}, {"name": "SDL_GPU_VERTEXELEMENTFORMAT_HALF4"}]}, + {"name": "SDL_GPUVertexInputRate", "values": []}, + {"name": "SDL_GPUFillMode", "values": []}, + {"name": "SDL_GPUCullMode", "values": []}, + {"name": "SDL_GPUFrontFace", "values": []}, + {"name": "SDL_GPUCompareOp", "values": [{"name": "SDL_GPU_COMPAREOP_INVALID"}]}, + {"name": "SDL_GPUStencilOp", "values": [{"name": "SDL_GPU_STENCILOP_INVALID"}]}, + {"name": "SDL_GPUBlendOp", "values": [{"name": "SDL_GPU_BLENDOP_INVALID"}]}, + {"name": "SDL_GPUBlendFactor", "values": [{"name": "SDL_GPU_BLENDFACTOR_INVALID"}]}, + {"name": "SDL_GPUFilter", "values": []}, + {"name": "SDL_GPUSamplerMipmapMode", "values": []}, + {"name": "SDL_GPUSamplerAddressMode", "values": []}, + {"name": "SDL_GPUPresentMode", "values": [{"name": "SDL_GPU_PRESENTMODE_VSYNC"}, {"name": "SDL_GPU_PRESENTMODE_IMMEDIATE"}, {"name": "SDL_GPU_PRESENTMODE_MAILBOX"}]}, + {"name": "SDL_GPUSwapchainComposition", "values": [{"name": "SDL_GPU_SWAPCHAINCOMPOSITION_SDR"}, {"name": "SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR"}, {"name": "SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR"}, {"name": "SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084"}]} + ], + "structs": [ + {"name": "SDL_GPUViewport", "fields": [{"name": "x", "type": "float", "comment": "The left offset of the viewport."}, {"name": "y", "type": "float", "comment": "The top offset of the viewport."}, {"name": "w", "type": "float", "comment": "The width of the viewport."}, {"name": "h", "type": "float", "comment": "The height of the viewport."}, {"name": "min_depth", "type": "float", "comment": "The minimum depth of the viewport."}, {"name": "max_depth", "type": "float", "comment": "The maximum depth of the viewport."}]}, + {"name": "SDL_GPUTextureTransferInfo", "fields": [{"name": "transfer_buffer", "type": "SDL_GPUTransferBuffer *", "comment": "The transfer buffer used in the transfer operation."}, {"name": "offset", "type": "Uint32", "comment": "The starting byte of the image data in the transfer buffer."}, {"name": "pixels_per_row", "type": "Uint32", "comment": "The number of pixels from one row to the next."}, {"name": "rows_per_layer", "type": "Uint32", "comment": "The number of rows from one layer/depth-slice to the next."}]}, + {"name": "SDL_GPUTransferBufferLocation", "fields": [{"name": "transfer_buffer", "type": "SDL_GPUTransferBuffer *", "comment": "The transfer buffer used in the transfer operation."}, {"name": "offset", "type": "Uint32", "comment": "The starting byte of the buffer data in the transfer buffer."}]}, + {"name": "SDL_GPUTextureLocation", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture used in the copy operation."}, {"name": "mip_level", "type": "Uint32", "comment": "The mip level index of the location."}, {"name": "layer", "type": "Uint32", "comment": "The layer index of the location."}, {"name": "x", "type": "Uint32", "comment": "The left offset of the location."}, {"name": "y", "type": "Uint32", "comment": "The top offset of the location."}, {"name": "z", "type": "Uint32", "comment": "The front offset of the location."}]}, + {"name": "SDL_GPUTextureRegion", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture used in the copy operation."}, {"name": "mip_level", "type": "Uint32", "comment": "The mip level index to transfer."}, {"name": "layer", "type": "Uint32", "comment": "The layer index to transfer."}, {"name": "x", "type": "Uint32", "comment": "The left offset of the region."}, {"name": "y", "type": "Uint32", "comment": "The top offset of the region."}, {"name": "z", "type": "Uint32", "comment": "The front offset of the region."}, {"name": "w", "type": "Uint32", "comment": "The width of the region."}, {"name": "h", "type": "Uint32", "comment": "The height of the region."}, {"name": "d", "type": "Uint32", "comment": "The depth of the region."}]}, + {"name": "SDL_GPUBlitRegion", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture."}, {"name": "mip_level", "type": "Uint32", "comment": "The mip level index of the region."}, {"name": "layer_or_depth_plane", "type": "Uint32", "comment": "The layer index or depth plane of the region. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures."}, {"name": "x", "type": "Uint32", "comment": "The left offset of the region."}, {"name": "y", "type": "Uint32", "comment": "The top offset of the region."}, {"name": "w", "type": "Uint32", "comment": "The width of the region."}, {"name": "h", "type": "Uint32", "comment": "The height of the region."}]}, + {"name": "SDL_GPUBufferLocation", "fields": [{"name": "buffer", "type": "SDL_GPUBuffer *", "comment": "The buffer."}, {"name": "offset", "type": "Uint32", "comment": "The starting byte within the buffer."}]}, + {"name": "SDL_GPUBufferRegion", "fields": [{"name": "buffer", "type": "SDL_GPUBuffer *", "comment": "The buffer."}, {"name": "offset", "type": "Uint32", "comment": "The starting byte within the buffer."}, {"name": "size", "type": "Uint32", "comment": "The size in bytes of the region."}]}, + {"name": "SDL_GPUIndirectDrawCommand", "fields": [{"name": "num_vertices", "type": "Uint32", "comment": "The number of vertices to draw."}, {"name": "num_instances", "type": "Uint32", "comment": "The number of instances to draw."}, {"name": "first_vertex", "type": "Uint32", "comment": "The index of the first vertex to draw."}, {"name": "first_instance", "type": "Uint32", "comment": "The ID of the first instance to draw."}]}, + {"name": "SDL_GPUIndexedIndirectDrawCommand", "fields": [{"name": "num_indices", "type": "Uint32", "comment": "The number of indices to draw per instance."}, {"name": "num_instances", "type": "Uint32", "comment": "The number of instances to draw."}, {"name": "first_index", "type": "Uint32", "comment": "The base index within the index buffer."}, {"name": "vertex_offset", "type": "Sint32", "comment": "The value added to the vertex index before indexing into the vertex buffer."}, {"name": "first_instance", "type": "Uint32", "comment": "The ID of the first instance to draw."}]}, + {"name": "SDL_GPUIndirectDispatchCommand", "fields": [{"name": "groupcount_x", "type": "Uint32", "comment": "The number of local workgroups to dispatch in the X dimension."}, {"name": "groupcount_y", "type": "Uint32", "comment": "The number of local workgroups to dispatch in the Y dimension."}, {"name": "groupcount_z", "type": "Uint32", "comment": "The number of local workgroups to dispatch in the Z dimension."}]}, + {"name": "SDL_GPUSamplerCreateInfo", "fields": [{"name": "min_filter", "type": "SDL_GPUFilter", "comment": "The minification filter to apply to lookups."}, {"name": "mag_filter", "type": "SDL_GPUFilter", "comment": "The magnification filter to apply to lookups."}, {"name": "mipmap_mode", "type": "SDL_GPUSamplerMipmapMode", "comment": "The mipmap filter to apply to lookups."}, {"name": "address_mode_u", "type": "SDL_GPUSamplerAddressMode", "comment": "The addressing mode for U coordinates outside [0, 1)."}, {"name": "address_mode_v", "type": "SDL_GPUSamplerAddressMode", "comment": "The addressing mode for V coordinates outside [0, 1)."}, {"name": "address_mode_w", "type": "SDL_GPUSamplerAddressMode", "comment": "The addressing mode for W coordinates outside [0, 1)."}, {"name": "mip_lod_bias", "type": "float", "comment": "The bias to be added to mipmap LOD calculation."}, {"name": "max_anisotropy", "type": "float", "comment": "The anisotropy value clamp used by the sampler. If enable_anisotropy is false, this is ignored."}, {"name": "compare_op", "type": "SDL_GPUCompareOp", "comment": "The comparison operator to apply to fetched data before filtering."}, {"name": "min_lod", "type": "float", "comment": "Clamps the minimum of the computed LOD value."}, {"name": "max_lod", "type": "float", "comment": "Clamps the maximum of the computed LOD value."}, {"name": "enable_anisotropy", "type": "bool", "comment": "true to enable anisotropic filtering."}, {"name": "enable_compare", "type": "bool", "comment": "true to enable comparison against a reference value during lookups."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPUVertexBufferDescription", "fields": [{"name": "slot", "type": "Uint32", "comment": "The binding slot of the vertex buffer."}, {"name": "pitch", "type": "Uint32", "comment": "The byte pitch between consecutive elements of the vertex buffer."}, {"name": "input_rate", "type": "SDL_GPUVertexInputRate", "comment": "Whether attribute addressing is a function of the vertex index or instance index."}, {"name": "instance_step_rate", "type": "Uint32", "comment": "Reserved for future use. Must be set to 0."}]}, + {"name": "SDL_GPUVertexAttribute", "fields": [{"name": "location", "type": "Uint32", "comment": "The shader input location index."}, {"name": "buffer_slot", "type": "Uint32", "comment": "The binding slot of the associated vertex buffer."}, {"name": "format", "type": "SDL_GPUVertexElementFormat", "comment": "The size and type of the attribute data."}, {"name": "offset", "type": "Uint32", "comment": "The byte offset of this attribute relative to the start of the vertex element."}]}, + {"name": "SDL_GPUVertexInputState", "fields": [{"name": "vertex_buffer_descriptions", "type": "const SDL_GPUVertexBufferDescription *", "comment": "A pointer to an array of vertex buffer descriptions."}, {"name": "num_vertex_buffers", "type": "Uint32", "comment": "The number of vertex buffer descriptions in the above array."}, {"name": "vertex_attributes", "type": "const SDL_GPUVertexAttribute *", "comment": "A pointer to an array of vertex attribute descriptions."}, {"name": "num_vertex_attributes", "type": "Uint32", "comment": "The number of vertex attribute descriptions in the above array."}]}, + {"name": "SDL_GPUStencilOpState", "fields": [{"name": "fail_op", "type": "SDL_GPUStencilOp", "comment": "The action performed on samples that fail the stencil test."}, {"name": "pass_op", "type": "SDL_GPUStencilOp", "comment": "The action performed on samples that pass the depth and stencil tests."}, {"name": "depth_fail_op", "type": "SDL_GPUStencilOp", "comment": "The action performed on samples that pass the stencil test and fail the depth test."}, {"name": "compare_op", "type": "SDL_GPUCompareOp", "comment": "The comparison operator used in the stencil test."}]}, + {"name": "SDL_GPUColorTargetBlendState", "fields": [{"name": "src_color_blendfactor", "type": "SDL_GPUBlendFactor", "comment": "The value to be multiplied by the source RGB value."}, {"name": "dst_color_blendfactor", "type": "SDL_GPUBlendFactor", "comment": "The value to be multiplied by the destination RGB value."}, {"name": "color_blend_op", "type": "SDL_GPUBlendOp", "comment": "The blend operation for the RGB components."}, {"name": "src_alpha_blendfactor", "type": "SDL_GPUBlendFactor", "comment": "The value to be multiplied by the source alpha."}, {"name": "dst_alpha_blendfactor", "type": "SDL_GPUBlendFactor", "comment": "The value to be multiplied by the destination alpha."}, {"name": "alpha_blend_op", "type": "SDL_GPUBlendOp", "comment": "The blend operation for the alpha component."}, {"name": "color_write_mask", "type": "SDL_GPUColorComponentFlags", "comment": "A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false."}, {"name": "enable_blend", "type": "bool", "comment": "Whether blending is enabled for the color target."}, {"name": "enable_color_write_mask", "type": "bool", "comment": "Whether the color write mask is enabled."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}]}, + {"name": "SDL_GPUShaderCreateInfo", "fields": [{"name": "code_size", "type": "size_t", "comment": "The size in bytes of the code pointed to."}, {"name": "code", "type": "const Uint8 *", "comment": "A pointer to shader code."}, {"name": "entrypoint", "type": "const char *", "comment": "A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader."}, {"name": "format", "type": "SDL_GPUShaderFormat", "comment": "The format of the shader code."}, {"name": "stage", "type": "SDL_GPUShaderStage", "comment": "The stage the shader program corresponds to."}, {"name": "num_samplers", "type": "Uint32", "comment": "The number of samplers defined in the shader."}, {"name": "num_storage_textures", "type": "Uint32", "comment": "The number of storage textures defined in the shader."}, {"name": "num_storage_buffers", "type": "Uint32", "comment": "The number of storage buffers defined in the shader."}, {"name": "num_uniform_buffers", "type": "Uint32", "comment": "The number of uniform buffers defined in the shader."}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPUTextureCreateInfo", "fields": [{"name": "type", "type": "SDL_GPUTextureType", "comment": "The base dimensionality of the texture."}, {"name": "format", "type": "SDL_GPUTextureFormat", "comment": "The pixel format of the texture."}, {"name": "usage", "type": "SDL_GPUTextureUsageFlags", "comment": "How the texture is intended to be used by the client."}, {"name": "width", "type": "Uint32", "comment": "The width of the texture."}, {"name": "height", "type": "Uint32", "comment": "The height of the texture."}, {"name": "layer_count_or_depth", "type": "Uint32", "comment": "The layer count or depth of the texture. This value is treated as a layer count on 2D array textures, and as a depth value on 3D textures."}, {"name": "num_levels", "type": "Uint32", "comment": "The number of mip levels in the texture."}, {"name": "sample_count", "type": "SDL_GPUSampleCount", "comment": "The number of samples per texel. Only applies if the texture is used as a render target."}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPUBufferCreateInfo", "fields": [{"name": "usage", "type": "SDL_GPUBufferUsageFlags", "comment": "How the buffer is intended to be used by the client."}, {"name": "size", "type": "Uint32", "comment": "The size in bytes of the buffer."}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPUTransferBufferCreateInfo", "fields": [{"name": "usage", "type": "SDL_GPUTransferBufferUsage", "comment": "How the transfer buffer is intended to be used by the client."}, {"name": "size", "type": "Uint32", "comment": "The size in bytes of the transfer buffer."}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPURasterizerState", "fields": [{"name": "fill_mode", "type": "SDL_GPUFillMode", "comment": "Whether polygons will be filled in or drawn as lines."}, {"name": "cull_mode", "type": "SDL_GPUCullMode", "comment": "The facing direction in which triangles will be culled."}, {"name": "front_face", "type": "SDL_GPUFrontFace", "comment": "The vertex winding that will cause a triangle to be determined as front-facing."}, {"name": "depth_bias_constant_factor", "type": "float", "comment": "A scalar factor controlling the depth value added to each fragment."}, {"name": "depth_bias_clamp", "type": "float", "comment": "The maximum depth bias of a fragment."}, {"name": "depth_bias_slope_factor", "type": "float", "comment": "A scalar factor applied to a fragment's slope in depth calculations."}, {"name": "enable_depth_bias", "type": "bool", "comment": "true to bias fragment depth values."}, {"name": "enable_depth_clip", "type": "bool", "comment": "true to enable depth clip, false to enable depth clamp."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}]}, + {"name": "SDL_GPUMultisampleState", "fields": [{"name": "sample_count", "type": "SDL_GPUSampleCount", "comment": "The number of samples to be used in rasterization."}, {"name": "sample_mask", "type": "Uint32", "comment": "Reserved for future use. Must be set to 0."}, {"name": "enable_mask", "type": "bool", "comment": "Reserved for future use. Must be set to false."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "padding3", "type": "Uint8"}]}, + {"name": "SDL_GPUDepthStencilState", "fields": [{"name": "compare_op", "type": "SDL_GPUCompareOp", "comment": "The comparison operator used for depth testing."}, {"name": "back_stencil_state", "type": "SDL_GPUStencilOpState", "comment": "The stencil op state for back-facing triangles."}, {"name": "front_stencil_state", "type": "SDL_GPUStencilOpState", "comment": "The stencil op state for front-facing triangles."}, {"name": "compare_mask", "type": "Uint8", "comment": "Selects the bits of the stencil values participating in the stencil test."}, {"name": "write_mask", "type": "Uint8", "comment": "Selects the bits of the stencil values updated by the stencil test."}, {"name": "enable_depth_test", "type": "bool", "comment": "true enables the depth test."}, {"name": "enable_depth_write", "type": "bool", "comment": "true enables depth writes. Depth writes are always disabled when enable_depth_test is false."}, {"name": "enable_stencil_test", "type": "bool", "comment": "true enables the stencil test."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "padding3", "type": "Uint8"}]}, + {"name": "SDL_GPUColorTargetDescription", "fields": [{"name": "format", "type": "SDL_GPUTextureFormat", "comment": "The pixel format of the texture to be used as a color target."}, {"name": "blend_state", "type": "SDL_GPUColorTargetBlendState", "comment": "The blend state to be used for the color target."}]}, + {"name": "SDL_GPUGraphicsPipelineTargetInfo", "fields": [{"name": "color_target_descriptions", "type": "const SDL_GPUColorTargetDescription *", "comment": "A pointer to an array of color target descriptions."}, {"name": "num_color_targets", "type": "Uint32", "comment": "The number of color target descriptions in the above array."}, {"name": "depth_stencil_format", "type": "SDL_GPUTextureFormat", "comment": "The pixel format of the depth-stencil target. Ignored if has_depth_stencil_target is false."}, {"name": "has_depth_stencil_target", "type": "bool", "comment": "true specifies that the pipeline uses a depth-stencil target."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "padding3", "type": "Uint8"}]}, + {"name": "SDL_GPUGraphicsPipelineCreateInfo", "fields": [{"name": "vertex_shader", "type": "SDL_GPUShader *", "comment": "The vertex shader used by the graphics pipeline."}, {"name": "fragment_shader", "type": "SDL_GPUShader *", "comment": "The fragment shader used by the graphics pipeline."}, {"name": "vertex_input_state", "type": "SDL_GPUVertexInputState", "comment": "The vertex layout of the graphics pipeline."}, {"name": "primitive_type", "type": "SDL_GPUPrimitiveType", "comment": "The primitive topology of the graphics pipeline."}, {"name": "rasterizer_state", "type": "SDL_GPURasterizerState", "comment": "The rasterizer state of the graphics pipeline."}, {"name": "multisample_state", "type": "SDL_GPUMultisampleState", "comment": "The multisample state of the graphics pipeline."}, {"name": "depth_stencil_state", "type": "SDL_GPUDepthStencilState", "comment": "The depth-stencil state of the graphics pipeline."}, {"name": "target_info", "type": "SDL_GPUGraphicsPipelineTargetInfo", "comment": "Formats and blend modes for the render targets of the graphics pipeline."}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPUComputePipelineCreateInfo", "fields": [{"name": "code_size", "type": "size_t", "comment": "The size in bytes of the compute shader code pointed to."}, {"name": "code", "type": "const Uint8 *", "comment": "A pointer to compute shader code."}, {"name": "entrypoint", "type": "const char *", "comment": "A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader."}, {"name": "format", "type": "SDL_GPUShaderFormat", "comment": "The format of the compute shader code."}, {"name": "num_samplers", "type": "Uint32", "comment": "The number of samplers defined in the shader."}, {"name": "num_readonly_storage_textures", "type": "Uint32", "comment": "The number of readonly storage textures defined in the shader."}, {"name": "num_readonly_storage_buffers", "type": "Uint32", "comment": "The number of readonly storage buffers defined in the shader."}, {"name": "num_readwrite_storage_textures", "type": "Uint32", "comment": "The number of read-write storage textures defined in the shader."}, {"name": "num_readwrite_storage_buffers", "type": "Uint32", "comment": "The number of read-write storage buffers defined in the shader."}, {"name": "num_uniform_buffers", "type": "Uint32", "comment": "The number of uniform buffers defined in the shader."}, {"name": "threadcount_x", "type": "Uint32", "comment": "The number of threads in the X dimension. This should match the value in the shader."}, {"name": "threadcount_y", "type": "Uint32", "comment": "The number of threads in the Y dimension. This should match the value in the shader."}, {"name": "threadcount_z", "type": "Uint32", "comment": "The number of threads in the Z dimension. This should match the value in the shader."}, {"name": "props", "type": "SDL_PropertiesID", "comment": "A properties ID for extensions. Should be 0 if no extensions are needed."}]}, + {"name": "SDL_GPUColorTargetInfo", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture that will be used as a color target by a render pass."}, {"name": "mip_level", "type": "Uint32", "comment": "The mip level to use as a color target."}, {"name": "layer_or_depth_plane", "type": "Uint32", "comment": "The layer index or depth plane to use as a color target. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures."}, {"name": "clear_color", "type": "SDL_FColor", "comment": "The color to clear the color target to at the start of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used."}, {"name": "load_op", "type": "SDL_GPULoadOp", "comment": "What is done with the contents of the color target at the beginning of the render pass."}, {"name": "store_op", "type": "SDL_GPUStoreOp", "comment": "What is done with the results of the render pass."}, {"name": "resolve_texture", "type": "SDL_GPUTexture *", "comment": "The texture that will receive the results of a multisample resolve operation. Ignored if a RESOLVE* store_op is not used."}, {"name": "resolve_mip_level", "type": "Uint32", "comment": "The mip level of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used."}, {"name": "resolve_layer", "type": "Uint32", "comment": "The layer index of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used."}, {"name": "cycle", "type": "bool", "comment": "true cycles the texture if the texture is bound and load_op is not LOAD"}, {"name": "cycle_resolve_texture", "type": "bool", "comment": "true cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}]}, + {"name": "SDL_GPUDepthStencilTargetInfo", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture that will be used as the depth stencil target by the render pass."}, {"name": "clear_depth", "type": "float", "comment": "The value to clear the depth component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used."}, {"name": "load_op", "type": "SDL_GPULoadOp", "comment": "What is done with the depth contents at the beginning of the render pass."}, {"name": "store_op", "type": "SDL_GPUStoreOp", "comment": "What is done with the depth results of the render pass."}, {"name": "stencil_load_op", "type": "SDL_GPULoadOp", "comment": "What is done with the stencil contents at the beginning of the render pass."}, {"name": "stencil_store_op", "type": "SDL_GPUStoreOp", "comment": "What is done with the stencil results of the render pass."}, {"name": "cycle", "type": "bool", "comment": "true cycles the texture if the texture is bound and any load ops are not LOAD"}, {"name": "clear_stencil", "type": "Uint8", "comment": "The value to clear the stencil component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}]}, + {"name": "SDL_GPUBlitInfo", "fields": [{"name": "source", "type": "SDL_GPUBlitRegion", "comment": "The source region for the blit."}, {"name": "destination", "type": "SDL_GPUBlitRegion", "comment": "The destination region for the blit."}, {"name": "load_op", "type": "SDL_GPULoadOp", "comment": "What is done with the contents of the destination before the blit."}, {"name": "clear_color", "type": "SDL_FColor", "comment": "The color to clear the destination region to before the blit. Ignored if load_op is not SDL_GPU_LOADOP_CLEAR."}, {"name": "flip_mode", "type": "SDL_FlipMode", "comment": "The flip mode for the source region."}, {"name": "filter", "type": "SDL_GPUFilter", "comment": "The filter mode used when blitting."}, {"name": "cycle", "type": "bool", "comment": "true cycles the destination texture if it is already bound."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "padding3", "type": "Uint8"}]}, + {"name": "SDL_GPUBufferBinding", "fields": [{"name": "buffer", "type": "SDL_GPUBuffer *", "comment": "The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_VERTEX for SDL_BindGPUVertexBuffers, or SDL_GPU_BUFFERUSAGE_INDEX for SDL_BindGPUIndexBuffer."}, {"name": "offset", "type": "Uint32", "comment": "The starting byte of the data to bind in the buffer."}]}, + {"name": "SDL_GPUTextureSamplerBinding", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER."}, {"name": "sampler", "type": "SDL_GPUSampler *", "comment": "The sampler to bind."}]}, + {"name": "SDL_GPUStorageBufferReadWriteBinding", "fields": [{"name": "buffer", "type": "SDL_GPUBuffer *", "comment": "The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE."}, {"name": "cycle", "type": "bool", "comment": "true cycles the buffer if it is already bound."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "padding3", "type": "Uint8"}]}, + {"name": "SDL_GPUStorageTextureReadWriteBinding", "fields": [{"name": "texture", "type": "SDL_GPUTexture *", "comment": "The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE or SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE."}, {"name": "mip_level", "type": "Uint32", "comment": "The mip level index to bind."}, {"name": "layer", "type": "Uint32", "comment": "The layer index to bind."}, {"name": "cycle", "type": "bool", "comment": "true cycles the texture if it is already bound."}, {"name": "padding1", "type": "Uint8"}, {"name": "padding2", "type": "Uint8"}, {"name": "padding3", "type": "Uint8"}]} + ], + "unions": [ + ], + "flags": [ + {"name": "SDL_GPUTextureUsageFlags", "underlying_type": "Uint32", "values": [{"name": "SDL_GPU_TEXTUREUSAGE_SAMPLER", "value": "(1u << 0)", "comment": "Texture supports sampling."}, {"name": "SDL_GPU_TEXTUREUSAGE_COLOR_TARGET", "value": "(1u << 1)", "comment": "Texture is a color render target."}, {"name": "SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET", "value": "(1u << 2)", "comment": "Texture is a depth stencil target."}, {"name": "SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ", "value": "(1u << 3)", "comment": "Texture supports storage reads in graphics stages."}, {"name": "SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ", "value": "(1u << 4)", "comment": "Texture supports storage reads in the compute stage."}, {"name": "SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE", "value": "(1u << 5)", "comment": "Texture supports storage writes in the compute stage."}, {"name": "SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE", "value": "(1u << 6)", "comment": "Texture supports reads and writes in the same compute shader. This is NOT equivalent to READ | WRITE."}]}, + {"name": "SDL_GPUBufferUsageFlags", "underlying_type": "Uint32", "values": [{"name": "SDL_GPU_BUFFERUSAGE_VERTEX", "value": "(1u << 0)", "comment": "Buffer is a vertex buffer."}, {"name": "SDL_GPU_BUFFERUSAGE_INDEX", "value": "(1u << 1)", "comment": "Buffer is an index buffer."}, {"name": "SDL_GPU_BUFFERUSAGE_INDIRECT", "value": "(1u << 2)", "comment": "Buffer is an indirect buffer."}, {"name": "SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ", "value": "(1u << 3)", "comment": "Buffer supports storage reads in graphics stages."}, {"name": "SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ", "value": "(1u << 4)", "comment": "Buffer supports storage reads in the compute stage."}, {"name": "SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE", "value": "(1u << 5)", "comment": "Buffer supports storage writes in the compute stage."}]}, + {"name": "SDL_GPUColorComponentFlags", "underlying_type": "Uint8", "values": [{"name": "SDL_GPU_COLORCOMPONENT_R", "value": "(1u << 0)", "comment": "the red component"}, {"name": "SDL_GPU_COLORCOMPONENT_G", "value": "(1u << 1)", "comment": "the green component"}, {"name": "SDL_GPU_COLORCOMPONENT_B", "value": "(1u << 2)", "comment": "the blue component"}, {"name": "SDL_GPU_COLORCOMPONENT_A", "value": "(1u << 3)", "comment": "the alpha component"}]} + ], + "functions": [ + {"name": "SDL_GPUSupportsShaderFormats", "return_type": "bool", "parameters": [{"name": "format_flags", "type": "SDL_GPUShaderFormat"}, {"name": "name", "type": "const char *"}]}, + {"name": "SDL_GPUSupportsProperties", "return_type": "bool", "parameters": [{"name": "props", "type": "SDL_PropertiesID"}]}, + {"name": "SDL_CreateGPUDevice", "return_type": "SDL_GPUDevice *", "parameters": [{"name": "format_flags", "type": "SDL_GPUShaderFormat"}, {"name": "debug_mode", "type": "bool"}, {"name": "name", "type": "const char *"}]}, + {"name": "SDL_CreateGPUDeviceWithProperties", "return_type": "SDL_GPUDevice *", "parameters": [{"name": "props", "type": "SDL_PropertiesID"}]}, + {"name": "SDL_DestroyGPUDevice", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]}, + {"name": "SDL_GetNumGPUDrivers", "return_type": "int", "parameters": []}, + {"name": "SDL_GetGPUDriver", "return_type": "const char *", "parameters": [{"name": "index", "type": "int"}]}, + {"name": "SDL_GetGPUDeviceDriver", "return_type": "const char *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]}, + {"name": "SDL_GetGPUShaderFormats", "return_type": "SDL_GPUShaderFormat", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]}, + {"name": "SDL_CreateGPUComputePipeline", "return_type": "SDL_GPUComputePipeline *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUComputePipelineCreateInfo *"}]}, + {"name": "SDL_CreateGPUGraphicsPipeline", "return_type": "SDL_GPUGraphicsPipeline *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUGraphicsPipelineCreateInfo *"}]}, + {"name": "SDL_CreateGPUSampler", "return_type": "SDL_GPUSampler *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUSamplerCreateInfo *"}]}, + {"name": "SDL_CreateGPUShader", "return_type": "SDL_GPUShader *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUShaderCreateInfo *"}]}, + {"name": "SDL_CreateGPUTexture", "return_type": "SDL_GPUTexture *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUTextureCreateInfo *"}]}, + {"name": "SDL_CreateGPUBuffer", "return_type": "SDL_GPUBuffer *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUBufferCreateInfo *"}]}, + {"name": "SDL_CreateGPUTransferBuffer", "return_type": "SDL_GPUTransferBuffer *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "createinfo", "type": "const SDL_GPUTransferBufferCreateInfo *"}]}, + {"name": "SDL_SetGPUBufferName", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "buffer", "type": "SDL_GPUBuffer *"}, {"name": "text", "type": "const char *"}]}, + {"name": "SDL_SetGPUTextureName", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "texture", "type": "SDL_GPUTexture *"}, {"name": "text", "type": "const char *"}]}, + {"name": "SDL_InsertGPUDebugLabel", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "text", "type": "const char *"}]}, + {"name": "SDL_PushGPUDebugGroup", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "name", "type": "const char *"}]}, + {"name": "SDL_PopGPUDebugGroup", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}]}, + {"name": "SDL_ReleaseGPUTexture", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "texture", "type": "SDL_GPUTexture *"}]}, + {"name": "SDL_ReleaseGPUSampler", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "sampler", "type": "SDL_GPUSampler *"}]}, + {"name": "SDL_ReleaseGPUBuffer", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "buffer", "type": "SDL_GPUBuffer *"}]}, + {"name": "SDL_ReleaseGPUTransferBuffer", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "transfer_buffer", "type": "SDL_GPUTransferBuffer *"}]}, + {"name": "SDL_ReleaseGPUComputePipeline", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "compute_pipeline", "type": "SDL_GPUComputePipeline *"}]}, + {"name": "SDL_ReleaseGPUShader", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "shader", "type": "SDL_GPUShader *"}]}, + {"name": "SDL_ReleaseGPUGraphicsPipeline", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "graphics_pipeline", "type": "SDL_GPUGraphicsPipeline *"}]}, + {"name": "SDL_AcquireGPUCommandBuffer", "return_type": "SDL_GPUCommandBuffer *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]}, + {"name": "SDL_PushGPUVertexUniformData", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "slot_index", "type": "Uint32"}, {"name": "data", "type": "const void *"}, {"name": "length", "type": "Uint32"}]}, + {"name": "SDL_PushGPUFragmentUniformData", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "slot_index", "type": "Uint32"}, {"name": "data", "type": "const void *"}, {"name": "length", "type": "Uint32"}]}, + {"name": "SDL_PushGPUComputeUniformData", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "slot_index", "type": "Uint32"}, {"name": "data", "type": "const void *"}, {"name": "length", "type": "Uint32"}]}, + {"name": "SDL_BeginGPURenderPass", "return_type": "SDL_GPURenderPass *", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "color_target_infos", "type": "const SDL_GPUColorTargetInfo *"}, {"name": "num_color_targets", "type": "Uint32"}, {"name": "depth_stencil_target_info", "type": "const SDL_GPUDepthStencilTargetInfo *"}]}, + {"name": "SDL_BindGPUGraphicsPipeline", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "graphics_pipeline", "type": "SDL_GPUGraphicsPipeline *"}]}, + {"name": "SDL_SetGPUViewport", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "viewport", "type": "const SDL_GPUViewport *"}]}, + {"name": "SDL_SetGPUScissor", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "scissor", "type": "const SDL_Rect *"}]}, + {"name": "SDL_SetGPUBlendConstants", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "blend_constants", "type": "SDL_FColor"}]}, + {"name": "SDL_SetGPUStencilReference", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "reference", "type": "Uint8"}]}, + {"name": "SDL_BindGPUVertexBuffers", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "bindings", "type": "const SDL_GPUBufferBinding *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUIndexBuffer", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "binding", "type": "const SDL_GPUBufferBinding *"}, {"name": "index_element_size", "type": "SDL_GPUIndexElementSize"}]}, + {"name": "SDL_BindGPUVertexSamplers", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "texture_sampler_bindings", "type": "const SDL_GPUTextureSamplerBinding *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUVertexStorageTextures", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "storage_textures", "type": "SDL_GPUTexture *const *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUVertexStorageBuffers", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "storage_buffers", "type": "SDL_GPUBuffer *const *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUFragmentSamplers", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "texture_sampler_bindings", "type": "const SDL_GPUTextureSamplerBinding *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUFragmentStorageTextures", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "storage_textures", "type": "SDL_GPUTexture *const *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUFragmentStorageBuffers", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "storage_buffers", "type": "SDL_GPUBuffer *const *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_DrawGPUIndexedPrimitives", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "num_indices", "type": "Uint32"}, {"name": "num_instances", "type": "Uint32"}, {"name": "first_index", "type": "Uint32"}, {"name": "vertex_offset", "type": "Sint32"}, {"name": "first_instance", "type": "Uint32"}]}, + {"name": "SDL_DrawGPUPrimitives", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "num_vertices", "type": "Uint32"}, {"name": "num_instances", "type": "Uint32"}, {"name": "first_vertex", "type": "Uint32"}, {"name": "first_instance", "type": "Uint32"}]}, + {"name": "SDL_DrawGPUPrimitivesIndirect", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "buffer", "type": "SDL_GPUBuffer *"}, {"name": "offset", "type": "Uint32"}, {"name": "draw_count", "type": "Uint32"}]}, + {"name": "SDL_DrawGPUIndexedPrimitivesIndirect", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}, {"name": "buffer", "type": "SDL_GPUBuffer *"}, {"name": "offset", "type": "Uint32"}, {"name": "draw_count", "type": "Uint32"}]}, + {"name": "SDL_EndGPURenderPass", "return_type": "void", "parameters": [{"name": "render_pass", "type": "SDL_GPURenderPass *"}]}, + {"name": "SDL_BeginGPUComputePass", "return_type": "SDL_GPUComputePass *", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "storage_texture_bindings", "type": "const SDL_GPUStorageTextureReadWriteBinding *"}, {"name": "num_storage_texture_bindings", "type": "Uint32"}, {"name": "storage_buffer_bindings", "type": "const SDL_GPUStorageBufferReadWriteBinding *"}, {"name": "num_storage_buffer_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUComputePipeline", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}, {"name": "compute_pipeline", "type": "SDL_GPUComputePipeline *"}]}, + {"name": "SDL_BindGPUComputeSamplers", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "texture_sampler_bindings", "type": "const SDL_GPUTextureSamplerBinding *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUComputeStorageTextures", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "storage_textures", "type": "SDL_GPUTexture *const *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_BindGPUComputeStorageBuffers", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}, {"name": "first_slot", "type": "Uint32"}, {"name": "storage_buffers", "type": "SDL_GPUBuffer *const *"}, {"name": "num_bindings", "type": "Uint32"}]}, + {"name": "SDL_DispatchGPUCompute", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}, {"name": "groupcount_x", "type": "Uint32"}, {"name": "groupcount_y", "type": "Uint32"}, {"name": "groupcount_z", "type": "Uint32"}]}, + {"name": "SDL_DispatchGPUComputeIndirect", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}, {"name": "buffer", "type": "SDL_GPUBuffer *"}, {"name": "offset", "type": "Uint32"}]}, + {"name": "SDL_EndGPUComputePass", "return_type": "void", "parameters": [{"name": "compute_pass", "type": "SDL_GPUComputePass *"}]}, + {"name": "SDL_MapGPUTransferBuffer", "return_type": "void *", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "transfer_buffer", "type": "SDL_GPUTransferBuffer *"}, {"name": "cycle", "type": "bool"}]}, + {"name": "SDL_UnmapGPUTransferBuffer", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "transfer_buffer", "type": "SDL_GPUTransferBuffer *"}]}, + {"name": "SDL_BeginGPUCopyPass", "return_type": "SDL_GPUCopyPass *", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}]}, + {"name": "SDL_UploadToGPUTexture", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}, {"name": "source", "type": "const SDL_GPUTextureTransferInfo *"}, {"name": "destination", "type": "const SDL_GPUTextureRegion *"}, {"name": "cycle", "type": "bool"}]}, + {"name": "SDL_UploadToGPUBuffer", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}, {"name": "source", "type": "const SDL_GPUTransferBufferLocation *"}, {"name": "destination", "type": "const SDL_GPUBufferRegion *"}, {"name": "cycle", "type": "bool"}]}, + {"name": "SDL_CopyGPUTextureToTexture", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}, {"name": "source", "type": "const SDL_GPUTextureLocation *"}, {"name": "destination", "type": "const SDL_GPUTextureLocation *"}, {"name": "w", "type": "Uint32"}, {"name": "h", "type": "Uint32"}, {"name": "d", "type": "Uint32"}, {"name": "cycle", "type": "bool"}]}, + {"name": "SDL_CopyGPUBufferToBuffer", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}, {"name": "source", "type": "const SDL_GPUBufferLocation *"}, {"name": "destination", "type": "const SDL_GPUBufferLocation *"}, {"name": "size", "type": "Uint32"}, {"name": "cycle", "type": "bool"}]}, + {"name": "SDL_DownloadFromGPUTexture", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}, {"name": "source", "type": "const SDL_GPUTextureRegion *"}, {"name": "destination", "type": "const SDL_GPUTextureTransferInfo *"}]}, + {"name": "SDL_DownloadFromGPUBuffer", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}, {"name": "source", "type": "const SDL_GPUBufferRegion *"}, {"name": "destination", "type": "const SDL_GPUTransferBufferLocation *"}]}, + {"name": "SDL_EndGPUCopyPass", "return_type": "void", "parameters": [{"name": "copy_pass", "type": "SDL_GPUCopyPass *"}]}, + {"name": "SDL_GenerateMipmapsForGPUTexture", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "texture", "type": "SDL_GPUTexture *"}]}, + {"name": "SDL_BlitGPUTexture", "return_type": "void", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "info", "type": "const SDL_GPUBlitInfo *"}]}, + {"name": "SDL_WindowSupportsGPUSwapchainComposition", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}, {"name": "swapchain_composition", "type": "SDL_GPUSwapchainComposition"}]}, + {"name": "SDL_WindowSupportsGPUPresentMode", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}, {"name": "present_mode", "type": "SDL_GPUPresentMode"}]}, + {"name": "SDL_ClaimWindowForGPUDevice", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_ReleaseWindowFromGPUDevice", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetGPUSwapchainParameters", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}, {"name": "swapchain_composition", "type": "SDL_GPUSwapchainComposition"}, {"name": "present_mode", "type": "SDL_GPUPresentMode"}]}, + {"name": "SDL_SetGPUAllowedFramesInFlight", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "allowed_frames_in_flight", "type": "Uint32"}]}, + {"name": "SDL_GetGPUSwapchainTextureFormat", "return_type": "SDL_GPUTextureFormat", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_AcquireGPUSwapchainTexture", "return_type": "bool", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "window", "type": "SDL_Window *"}, {"name": "swapchain_texture", "type": "SDL_GPUTexture **"}, {"name": "swapchain_texture_width", "type": "Uint32 *"}, {"name": "swapchain_texture_height", "type": "Uint32 *"}]}, + {"name": "SDL_WaitForGPUSwapchain", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_WaitAndAcquireGPUSwapchainTexture", "return_type": "bool", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}, {"name": "window", "type": "SDL_Window *"}, {"name": "swapchain_texture", "type": "SDL_GPUTexture **"}, {"name": "swapchain_texture_width", "type": "Uint32 *"}, {"name": "swapchain_texture_height", "type": "Uint32 *"}]}, + {"name": "SDL_SubmitGPUCommandBuffer", "return_type": "bool", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}]}, + {"name": "SDL_SubmitGPUCommandBufferAndAcquireFence", "return_type": "SDL_GPUFence *", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}]}, + {"name": "SDL_CancelGPUCommandBuffer", "return_type": "bool", "parameters": [{"name": "command_buffer", "type": "SDL_GPUCommandBuffer *"}]}, + {"name": "SDL_WaitForGPUIdle", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]}, + {"name": "SDL_WaitForGPUFences", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "wait_all", "type": "bool"}, {"name": "fences", "type": "SDL_GPUFence *const *"}, {"name": "num_fences", "type": "Uint32"}]}, + {"name": "SDL_QueryGPUFence", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "fence", "type": "SDL_GPUFence *"}]}, + {"name": "SDL_ReleaseGPUFence", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "fence", "type": "SDL_GPUFence *"}]}, + {"name": "SDL_GPUTextureFormatTexelBlockSize", "return_type": "Uint32", "parameters": [{"name": "format", "type": "SDL_GPUTextureFormat"}]}, + {"name": "SDL_GPUTextureSupportsFormat", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "format", "type": "SDL_GPUTextureFormat"}, {"name": "type", "type": "SDL_GPUTextureType"}, {"name": "usage", "type": "SDL_GPUTextureUsageFlags"}]}, + {"name": "SDL_GPUTextureSupportsSampleCount", "return_type": "bool", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}, {"name": "format", "type": "SDL_GPUTextureFormat"}, {"name": "sample_count", "type": "SDL_GPUSampleCount"}]}, + {"name": "SDL_CalculateGPUTextureFormatSize", "return_type": "Uint32", "parameters": [{"name": "format", "type": "SDL_GPUTextureFormat"}, {"name": "width", "type": "Uint32"}, {"name": "height", "type": "Uint32"}, {"name": "depth_or_layer_count", "type": "Uint32"}]}, + {"name": "SDL_GDKSuspendGPU", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]}, + {"name": "SDL_GDKResumeGPU", "return_type": "void", "parameters": [{"name": "device", "type": "SDL_GPUDevice *"}]} + ] +} diff --git a/lib/sdl3/parser/output/SDL_init.json b/lib/sdl3/parser/output/SDL_init.json new file mode 100644 index 0000000..d0c788c --- /dev/null +++ b/lib/sdl3/parser/output/SDL_init.json @@ -0,0 +1,36 @@ +{ + "header": "SDL_init.h", + "opaque_types": [ + ], + "typedefs": [ + ], + "function_pointers": [ + {"name": "SDL_AppInit_func", "return_type": "SDL_AppResult", "parameters": [{"name": "appstate", "type": "void **"}, {"name": "argc", "type": "int"}, {"name": "argv[]", "type": "char *"}]}, + {"name": "SDL_AppIterate_func", "return_type": "SDL_AppResult", "parameters": [{"name": "appstate", "type": "void *"}]}, + {"name": "SDL_AppEvent_func", "return_type": "SDL_AppResult", "parameters": [{"name": "appstate", "type": "void *"}, {"name": "event", "type": "SDL_Event *"}]}, + {"name": "SDL_AppQuit_func", "return_type": "void", "parameters": [{"name": "appstate", "type": "void *"}, {"name": "result", "type": "SDL_AppResult"}]}, + {"name": "SDL_MainThreadCallback", "return_type": "void", "parameters": [{"name": "userdata", "type": "void *"}]} + ], + "enums": [ + {"name": "SDL_AppResult", "values": []} + ], + "structs": [ + ], + "unions": [ + ], + "flags": [ + {"name": "SDL_InitFlags", "underlying_type": "Uint32", "values": [{"name": "SDL_INIT_AUDIO", "value": "0x00000010u", "comment": "`SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS`"}, {"name": "SDL_INIT_VIDEO", "value": "0x00000020u", "comment": "`SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS`, should be initialized on the main thread"}, {"name": "SDL_INIT_JOYSTICK", "value": "0x00000200u", "comment": "`SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD"}, {"name": "SDL_INIT_HAPTIC", "value": "0x00001000u"}, {"name": "SDL_INIT_GAMEPAD", "value": "0x00002000u", "comment": "`SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK`"}, {"name": "SDL_INIT_EVENTS", "value": "0x00004000u"}, {"name": "SDL_INIT_SENSOR", "value": "0x00008000u", "comment": "`SDL_INIT_SENSOR` implies `SDL_INIT_EVENTS`"}, {"name": "SDL_INIT_CAMERA", "value": "0x00010000u", "comment": "`SDL_INIT_CAMERA` implies `SDL_INIT_EVENTS`"}]} + ], + "functions": [ + {"name": "SDL_Init", "return_type": "bool", "parameters": [{"name": "flags", "type": "SDL_InitFlags"}]}, + {"name": "SDL_InitSubSystem", "return_type": "bool", "parameters": [{"name": "flags", "type": "SDL_InitFlags"}]}, + {"name": "SDL_QuitSubSystem", "return_type": "void", "parameters": [{"name": "flags", "type": "SDL_InitFlags"}]}, + {"name": "SDL_WasInit", "return_type": "SDL_InitFlags", "parameters": [{"name": "flags", "type": "SDL_InitFlags"}]}, + {"name": "SDL_Quit", "return_type": "void", "parameters": []}, + {"name": "SDL_IsMainThread", "return_type": "bool", "parameters": []}, + {"name": "SDL_RunOnMainThread", "return_type": "bool", "parameters": [{"name": "callback", "type": "SDL_MainThreadCallback"}, {"name": "userdata", "type": "void *"}, {"name": "wait_complete", "type": "bool"}]}, + {"name": "SDL_SetAppMetadata", "return_type": "bool", "parameters": [{"name": "appname", "type": "const char *"}, {"name": "appversion", "type": "const char *"}, {"name": "appidentifier", "type": "const char *"}]}, + {"name": "SDL_SetAppMetadataProperty", "return_type": "bool", "parameters": [{"name": "name", "type": "const char *"}, {"name": "value", "type": "const char *"}]}, + {"name": "SDL_GetAppMetadataProperty", "return_type": "const char *", "parameters": [{"name": "name", "type": "const char *"}]} + ] +} diff --git a/lib/sdl3/parser/output/SDL_pixels.h.json b/lib/sdl3/parser/output/SDL_pixels.h.json new file mode 100644 index 0000000..7f89efa --- /dev/null +++ b/lib/sdl3/parser/output/SDL_pixels.h.json @@ -0,0 +1,47 @@ +{ + "header": "SDL_pixels.h", + "opaque_types": [ + ], + "typedefs": [ + ], + "function_pointers": [ + ], + "enums": [ + {"name": "SDL_PixelType", "values": [{"name": "SDL_PIXELTYPE_UNKNOWN"}, {"name": "SDL_PIXELTYPE_INDEX1"}, {"name": "SDL_PIXELTYPE_INDEX4"}, {"name": "SDL_PIXELTYPE_INDEX8"}, {"name": "SDL_PIXELTYPE_PACKED8"}, {"name": "SDL_PIXELTYPE_PACKED16"}, {"name": "SDL_PIXELTYPE_PACKED32"}, {"name": "SDL_PIXELTYPE_ARRAYU8"}, {"name": "SDL_PIXELTYPE_ARRAYU16"}, {"name": "SDL_PIXELTYPE_ARRAYU32"}, {"name": "SDL_PIXELTYPE_ARRAYF16"}, {"name": "SDL_PIXELTYPE_ARRAYF32"}, {"name": "SDL_PIXELTYPE_INDEX2"}]}, + {"name": "SDL_BitmapOrder", "values": [{"name": "SDL_BITMAPORDER_NONE"}, {"name": "SDL_BITMAPORDER_4321"}, {"name": "SDL_BITMAPORDER_1234"}]}, + {"name": "SDL_PackedOrder", "values": [{"name": "SDL_PACKEDORDER_NONE"}, {"name": "SDL_PACKEDORDER_XRGB"}, {"name": "SDL_PACKEDORDER_RGBX"}, {"name": "SDL_PACKEDORDER_ARGB"}, {"name": "SDL_PACKEDORDER_RGBA"}, {"name": "SDL_PACKEDORDER_XBGR"}, {"name": "SDL_PACKEDORDER_BGRX"}, {"name": "SDL_PACKEDORDER_ABGR"}, {"name": "SDL_PACKEDORDER_BGRA"}]}, + {"name": "SDL_ArrayOrder", "values": [{"name": "SDL_ARRAYORDER_NONE"}, {"name": "SDL_ARRAYORDER_RGB"}, {"name": "SDL_ARRAYORDER_RGBA"}, {"name": "SDL_ARRAYORDER_ARGB"}, {"name": "SDL_ARRAYORDER_BGR"}, {"name": "SDL_ARRAYORDER_BGRA"}, {"name": "SDL_ARRAYORDER_ABGR"}]}, + {"name": "SDL_PackedLayout", "values": [{"name": "SDL_PACKEDLAYOUT_NONE"}, {"name": "SDL_PACKEDLAYOUT_332"}, {"name": "SDL_PACKEDLAYOUT_4444"}, {"name": "SDL_PACKEDLAYOUT_1555"}, {"name": "SDL_PACKEDLAYOUT_5551"}, {"name": "SDL_PACKEDLAYOUT_565"}, {"name": "SDL_PACKEDLAYOUT_8888"}, {"name": "SDL_PACKEDLAYOUT_2101010"}, {"name": "SDL_PACKEDLAYOUT_1010102"}]}, + {"name": "SDL_PixelFormat", "values": [{"name": "SDL_PIXELFORMAT_UNKNOWN", "value": "0"}, {"name": "SDL_PIXELFORMAT_INDEX1LSB", "value": "0x11100100u"}, {"name": "SDL_PIXELFORMAT_INDEX1MSB", "value": "0x11200100u"}, {"name": "SDL_PIXELFORMAT_INDEX2LSB", "value": "0x1c100200u"}, {"name": "SDL_PIXELFORMAT_INDEX2MSB", "value": "0x1c200200u"}, {"name": "SDL_PIXELFORMAT_INDEX4LSB", "value": "0x12100400u"}, {"name": "SDL_PIXELFORMAT_INDEX4MSB", "value": "0x12200400u"}, {"name": "SDL_PIXELFORMAT_INDEX8", "value": "0x13000801u"}, {"name": "SDL_PIXELFORMAT_RGB332", "value": "0x14110801u"}, {"name": "SDL_PIXELFORMAT_XRGB4444", "value": "0x15120c02u"}, {"name": "SDL_PIXELFORMAT_XBGR4444", "value": "0x15520c02u"}, {"name": "SDL_PIXELFORMAT_XRGB1555", "value": "0x15130f02u"}, {"name": "SDL_PIXELFORMAT_XBGR1555", "value": "0x15530f02u"}, {"name": "SDL_PIXELFORMAT_ARGB4444", "value": "0x15321002u"}, {"name": "SDL_PIXELFORMAT_RGBA4444", "value": "0x15421002u"}, {"name": "SDL_PIXELFORMAT_ABGR4444", "value": "0x15721002u"}, {"name": "SDL_PIXELFORMAT_BGRA4444", "value": "0x15821002u"}, {"name": "SDL_PIXELFORMAT_ARGB1555", "value": "0x15331002u"}, {"name": "SDL_PIXELFORMAT_RGBA5551", "value": "0x15441002u"}, {"name": "SDL_PIXELFORMAT_ABGR1555", "value": "0x15731002u"}, {"name": "SDL_PIXELFORMAT_BGRA5551", "value": "0x15841002u"}, {"name": "SDL_PIXELFORMAT_RGB565", "value": "0x15151002u"}, {"name": "SDL_PIXELFORMAT_BGR565", "value": "0x15551002u"}, {"name": "SDL_PIXELFORMAT_RGB24", "value": "0x17101803u"}, {"name": "SDL_PIXELFORMAT_BGR24", "value": "0x17401803u"}, {"name": "SDL_PIXELFORMAT_XRGB8888", "value": "0x16161804u"}, {"name": "SDL_PIXELFORMAT_RGBX8888", "value": "0x16261804u"}, {"name": "SDL_PIXELFORMAT_XBGR8888", "value": "0x16561804u"}, {"name": "SDL_PIXELFORMAT_BGRX8888", "value": "0x16661804u"}, {"name": "SDL_PIXELFORMAT_ARGB8888", "value": "0x16362004u"}, {"name": "SDL_PIXELFORMAT_RGBA8888", "value": "0x16462004u"}, {"name": "SDL_PIXELFORMAT_ABGR8888", "value": "0x16762004u"}, {"name": "SDL_PIXELFORMAT_BGRA8888", "value": "0x16862004u"}, {"name": "SDL_PIXELFORMAT_XRGB2101010", "value": "0x16172004u"}, {"name": "SDL_PIXELFORMAT_XBGR2101010", "value": "0x16572004u"}, {"name": "SDL_PIXELFORMAT_ARGB2101010", "value": "0x16372004u"}, {"name": "SDL_PIXELFORMAT_ABGR2101010", "value": "0x16772004u"}, {"name": "SDL_PIXELFORMAT_RGB48", "value": "0x18103006u"}, {"name": "SDL_PIXELFORMAT_BGR48", "value": "0x18403006u"}, {"name": "SDL_PIXELFORMAT_RGBA64", "value": "0x18204008u"}, {"name": "SDL_PIXELFORMAT_ARGB64", "value": "0x18304008u"}, {"name": "SDL_PIXELFORMAT_BGRA64", "value": "0x18504008u"}, {"name": "SDL_PIXELFORMAT_ABGR64", "value": "0x18604008u"}, {"name": "SDL_PIXELFORMAT_RGB48_FLOAT", "value": "0x1a103006u"}, {"name": "SDL_PIXELFORMAT_BGR48_FLOAT", "value": "0x1a403006u"}, {"name": "SDL_PIXELFORMAT_RGBA64_FLOAT", "value": "0x1a204008u"}, {"name": "SDL_PIXELFORMAT_ARGB64_FLOAT", "value": "0x1a304008u"}, {"name": "SDL_PIXELFORMAT_BGRA64_FLOAT", "value": "0x1a504008u"}, {"name": "SDL_PIXELFORMAT_ABGR64_FLOAT", "value": "0x1a604008u"}, {"name": "SDL_PIXELFORMAT_RGB96_FLOAT", "value": "0x1b10600cu"}, {"name": "SDL_PIXELFORMAT_BGR96_FLOAT", "value": "0x1b40600cu"}, {"name": "SDL_PIXELFORMAT_RGBA128_FLOAT", "value": "0x1b208010u"}, {"name": "SDL_PIXELFORMAT_ARGB128_FLOAT", "value": "0x1b308010u"}, {"name": "SDL_PIXELFORMAT_BGRA128_FLOAT", "value": "0x1b508010u"}, {"name": "SDL_PIXELFORMAT_ABGR128_FLOAT", "value": "0x1b608010u"}, {"name": "SDL_PIXELFORMAT_RGBA32", "value": "SDL_PIXELFORMAT_RGBA8888"}, {"name": "SDL_PIXELFORMAT_ARGB32", "value": "SDL_PIXELFORMAT_ARGB8888"}, {"name": "SDL_PIXELFORMAT_BGRA32", "value": "SDL_PIXELFORMAT_BGRA8888"}, {"name": "SDL_PIXELFORMAT_ABGR32", "value": "SDL_PIXELFORMAT_ABGR8888"}, {"name": "SDL_PIXELFORMAT_RGBX32", "value": "SDL_PIXELFORMAT_RGBX8888"}, {"name": "SDL_PIXELFORMAT_XRGB32", "value": "SDL_PIXELFORMAT_XRGB8888"}, {"name": "SDL_PIXELFORMAT_BGRX32", "value": "SDL_PIXELFORMAT_BGRX8888"}, {"name": "SDL_PIXELFORMAT_XBGR32", "value": "SDL_PIXELFORMAT_XBGR8888"}]}, + {"name": "SDL_ColorType", "values": [{"name": "SDL_COLOR_TYPE_UNKNOWN", "value": "0"}, {"name": "SDL_COLOR_TYPE_RGB", "value": "1"}, {"name": "SDL_COLOR_TYPE_YCBCR", "value": "2"}]}, + {"name": "SDL_ColorRange", "values": [{"name": "SDL_COLOR_RANGE_UNKNOWN", "value": "0"}]}, + {"name": "SDL_ColorPrimaries", "values": [{"name": "SDL_COLOR_PRIMARIES_UNKNOWN", "value": "0"}, {"name": "SDL_COLOR_PRIMARIES_UNSPECIFIED", "value": "2"}, {"name": "SDL_COLOR_PRIMARIES_CUSTOM", "value": "31"}]}, + {"name": "SDL_TransferCharacteristics", "values": [{"name": "SDL_TRANSFER_CHARACTERISTICS_UNKNOWN", "value": "0"}, {"name": "SDL_TRANSFER_CHARACTERISTICS_UNSPECIFIED", "value": "2"}, {"name": "SDL_TRANSFER_CHARACTERISTICS_LINEAR", "value": "8"}, {"name": "SDL_TRANSFER_CHARACTERISTICS_LOG100", "value": "9"}, {"name": "SDL_TRANSFER_CHARACTERISTICS_LOG100_SQRT10", "value": "10"}, {"name": "SDL_TRANSFER_CHARACTERISTICS_CUSTOM", "value": "31"}]}, + {"name": "SDL_MatrixCoefficients", "values": [{"name": "SDL_MATRIX_COEFFICIENTS_IDENTITY", "value": "0"}, {"name": "SDL_MATRIX_COEFFICIENTS_UNSPECIFIED", "value": "2"}, {"name": "SDL_MATRIX_COEFFICIENTS_YCGCO", "value": "8"}, {"name": "SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL", "value": "12"}, {"name": "SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL", "value": "13"}, {"name": "SDL_MATRIX_COEFFICIENTS_CUSTOM", "value": "31"}]}, + {"name": "SDL_ChromaLocation", "values": []}, + {"name": "SDL_Colorspace", "values": [{"name": "SDL_COLORSPACE_UNKNOWN", "value": "0"}]} + ], + "structs": [ + {"name": "SDL_Color", "fields": [{"name": "r", "type": "Uint8"}, {"name": "g", "type": "Uint8"}, {"name": "b", "type": "Uint8"}, {"name": "a", "type": "Uint8"}]}, + {"name": "SDL_FColor", "fields": [{"name": "r", "type": "float"}, {"name": "g", "type": "float"}, {"name": "b", "type": "float"}, {"name": "a", "type": "float"}]}, + {"name": "SDL_Palette", "fields": [{"name": "ncolors", "type": "int", "comment": "number of elements in `colors`."}, {"name": "colors", "type": "SDL_Color *", "comment": "an array of colors, `ncolors` long."}, {"name": "version", "type": "Uint32", "comment": "internal use only, do not touch."}, {"name": "refcount", "type": "int", "comment": "internal use only, do not touch."}]}, + {"name": "SDL_PixelFormatDetails", "fields": [{"name": "format", "type": "SDL_PixelFormat"}, {"name": "bits_per_pixel", "type": "Uint8"}, {"name": "bytes_per_pixel", "type": "Uint8"}, {"name": "padding", "type": "Uint8[2]"}, {"name": "Rmask", "type": "Uint32"}, {"name": "Gmask", "type": "Uint32"}, {"name": "Bmask", "type": "Uint32"}, {"name": "Amask", "type": "Uint32"}, {"name": "Rbits", "type": "Uint8"}, {"name": "Gbits", "type": "Uint8"}, {"name": "Bbits", "type": "Uint8"}, {"name": "Abits", "type": "Uint8"}, {"name": "Rshift", "type": "Uint8"}, {"name": "Gshift", "type": "Uint8"}, {"name": "Bshift", "type": "Uint8"}, {"name": "Ashift", "type": "Uint8"}]} + ], + "unions": [ + ], + "flags": [ + ], + "functions": [ + {"name": "SDL_GetPixelFormatName", "return_type": "const char *", "parameters": [{"name": "format", "type": "SDL_PixelFormat"}]}, + {"name": "SDL_GetMasksForPixelFormat", "return_type": "bool", "parameters": [{"name": "format", "type": "SDL_PixelFormat"}, {"name": "bpp", "type": "int *"}, {"name": "Rmask", "type": "Uint32 *"}, {"name": "Gmask", "type": "Uint32 *"}, {"name": "Bmask", "type": "Uint32 *"}, {"name": "Amask", "type": "Uint32 *"}]}, + {"name": "SDL_GetPixelFormatForMasks", "return_type": "SDL_PixelFormat", "parameters": [{"name": "bpp", "type": "int"}, {"name": "Rmask", "type": "Uint32"}, {"name": "Gmask", "type": "Uint32"}, {"name": "Bmask", "type": "Uint32"}, {"name": "Amask", "type": "Uint32"}]}, + {"name": "SDL_GetPixelFormatDetails", "return_type": "const SDL_PixelFormatDetails *", "parameters": [{"name": "format", "type": "SDL_PixelFormat"}]}, + {"name": "SDL_CreatePalette", "return_type": "SDL_Palette *", "parameters": [{"name": "ncolors", "type": "int"}]}, + {"name": "SDL_SetPaletteColors", "return_type": "bool", "parameters": [{"name": "palette", "type": "SDL_Palette *"}, {"name": "colors", "type": "const SDL_Color *"}, {"name": "firstcolor", "type": "int"}, {"name": "ncolors", "type": "int"}]}, + {"name": "SDL_DestroyPalette", "return_type": "void", "parameters": [{"name": "palette", "type": "SDL_Palette *"}]}, + {"name": "SDL_MapRGB", "return_type": "Uint32", "parameters": [{"name": "format", "type": "const SDL_PixelFormatDetails *"}, {"name": "palette", "type": "const SDL_Palette *"}, {"name": "r", "type": "Uint8"}, {"name": "g", "type": "Uint8"}, {"name": "b", "type": "Uint8"}]}, + {"name": "SDL_MapRGBA", "return_type": "Uint32", "parameters": [{"name": "format", "type": "const SDL_PixelFormatDetails *"}, {"name": "palette", "type": "const SDL_Palette *"}, {"name": "r", "type": "Uint8"}, {"name": "g", "type": "Uint8"}, {"name": "b", "type": "Uint8"}, {"name": "a", "type": "Uint8"}]}, + {"name": "SDL_GetRGB", "return_type": "void", "parameters": [{"name": "pixel", "type": "Uint32"}, {"name": "format", "type": "const SDL_PixelFormatDetails *"}, {"name": "palette", "type": "const SDL_Palette *"}, {"name": "r", "type": "Uint8 *"}, {"name": "g", "type": "Uint8 *"}, {"name": "b", "type": "Uint8 *"}]}, + {"name": "SDL_GetRGBA", "return_type": "void", "parameters": [{"name": "pixel", "type": "Uint32"}, {"name": "format", "type": "const SDL_PixelFormatDetails *"}, {"name": "palette", "type": "const SDL_Palette *"}, {"name": "r", "type": "Uint8 *"}, {"name": "g", "type": "Uint8 *"}, {"name": "b", "type": "Uint8 *"}, {"name": "a", "type": "Uint8 *"}]} + ] +} diff --git a/lib/sdl3/parser/output/SDL_rect.h.json b/lib/sdl3/parser/output/SDL_rect.h.json new file mode 100644 index 0000000..d86e27c --- /dev/null +++ b/lib/sdl3/parser/output/SDL_rect.h.json @@ -0,0 +1,33 @@ +{ + "header": "SDL_rect.h", + "opaque_types": [ + ], + "typedefs": [ + ], + "function_pointers": [ + ], + "enums": [ + ], + "structs": [ + {"name": "SDL_Point", "fields": [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}]}, + {"name": "SDL_FPoint", "fields": [{"name": "x", "type": "float"}, {"name": "y", "type": "float"}]}, + {"name": "SDL_Rect", "fields": [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}, {"name": "w", "type": "int"}, {"name": "h", "type": "int"}]}, + {"name": "SDL_FRect", "fields": [{"name": "x", "type": "float"}, {"name": "y", "type": "float"}, {"name": "w", "type": "float"}, {"name": "h", "type": "float"}]} + ], + "unions": [ + ], + "flags": [ + ], + "functions": [ + {"name": "SDL_HasRectIntersection", "return_type": "bool", "parameters": [{"name": "A", "type": "const SDL_Rect *"}, {"name": "B", "type": "const SDL_Rect *"}]}, + {"name": "SDL_GetRectIntersection", "return_type": "bool", "parameters": [{"name": "A", "type": "const SDL_Rect *"}, {"name": "B", "type": "const SDL_Rect *"}, {"name": "result", "type": "SDL_Rect *"}]}, + {"name": "SDL_GetRectUnion", "return_type": "bool", "parameters": [{"name": "A", "type": "const SDL_Rect *"}, {"name": "B", "type": "const SDL_Rect *"}, {"name": "result", "type": "SDL_Rect *"}]}, + {"name": "SDL_GetRectEnclosingPoints", "return_type": "bool", "parameters": [{"name": "points", "type": "const SDL_Point *"}, {"name": "count", "type": "int"}, {"name": "clip", "type": "const SDL_Rect *"}, {"name": "result", "type": "SDL_Rect *"}]}, + {"name": "SDL_GetRectAndLineIntersection", "return_type": "bool", "parameters": [{"name": "rect", "type": "const SDL_Rect *"}, {"name": "X1", "type": "int *"}, {"name": "Y1", "type": "int *"}, {"name": "X2", "type": "int *"}, {"name": "Y2", "type": "int *"}]}, + {"name": "SDL_HasRectIntersectionFloat", "return_type": "bool", "parameters": [{"name": "A", "type": "const SDL_FRect *"}, {"name": "B", "type": "const SDL_FRect *"}]}, + {"name": "SDL_GetRectIntersectionFloat", "return_type": "bool", "parameters": [{"name": "A", "type": "const SDL_FRect *"}, {"name": "B", "type": "const SDL_FRect *"}, {"name": "result", "type": "SDL_FRect *"}]}, + {"name": "SDL_GetRectUnionFloat", "return_type": "bool", "parameters": [{"name": "A", "type": "const SDL_FRect *"}, {"name": "B", "type": "const SDL_FRect *"}, {"name": "result", "type": "SDL_FRect *"}]}, + {"name": "SDL_GetRectEnclosingPointsFloat", "return_type": "bool", "parameters": [{"name": "points", "type": "const SDL_FPoint *"}, {"name": "count", "type": "int"}, {"name": "clip", "type": "const SDL_FRect *"}, {"name": "result", "type": "SDL_FRect *"}]}, + {"name": "SDL_GetRectAndLineIntersectionFloat", "return_type": "bool", "parameters": [{"name": "rect", "type": "const SDL_FRect *"}, {"name": "X1", "type": "float *"}, {"name": "Y1", "type": "float *"}, {"name": "X2", "type": "float *"}, {"name": "Y2", "type": "float *"}]} + ] +} diff --git a/lib/sdl3/parser/output/SDL_video.json b/lib/sdl3/parser/output/SDL_video.json new file mode 100644 index 0000000..37f5f75 --- /dev/null +++ b/lib/sdl3/parser/output/SDL_video.json @@ -0,0 +1,143 @@ +{ + "header": "SDL_video.h", + "opaque_types": [ + {"name": "SDL_DisplayModeData"}, + {"name": "SDL_Window"} + ], + "typedefs": [ + {"name": "SDL_DisplayID", "underlying_type": "Uint32"}, + {"name": "SDL_WindowID", "underlying_type": "Uint32"}, + {"name": "SDL_GLProfile", "underlying_type": "Uint32"}, + {"name": "SDL_GLContextFlag", "underlying_type": "Uint32"}, + {"name": "SDL_GLContextReleaseFlag", "underlying_type": "Uint32"}, + {"name": "SDL_GLContextResetNotification", "underlying_type": "Uint32"} + ], + "function_pointers": [ + ], + "enums": [ + {"name": "SDL_SystemTheme", "values": []}, + {"name": "SDL_DisplayOrientation", "values": []}, + {"name": "SDL_FlashOperation", "values": []}, + {"name": "SDL_HitTestResult", "values": []} + ], + "structs": [ + {"name": "SDL_DisplayMode", "fields": [{"name": "displayID", "type": "SDL_DisplayID", "comment": "the display this mode is associated with"}, {"name": "format", "type": "SDL_PixelFormat", "comment": "pixel format"}, {"name": "w", "type": "int", "comment": "width"}, {"name": "h", "type": "int", "comment": "height"}, {"name": "pixel_density", "type": "float", "comment": "scale converting size to pixels (e.g. a 1920x1080 mode with 2.0 scale would have 3840x2160 pixels)"}, {"name": "refresh_rate", "type": "float", "comment": "refresh rate (or 0.0f for unspecified)"}, {"name": "refresh_rate_numerator", "type": "int", "comment": "precise refresh rate numerator (or 0 for unspecified)"}, {"name": "refresh_rate_denominator", "type": "int", "comment": "precise refresh rate denominator"}, {"name": "internal", "type": "SDL_DisplayModeData *", "comment": "Private"}]}, + {"name": "SDL_GLContextState", "fields": []} + ], + "unions": [ + ], + "flags": [ + {"name": "SDL_WindowFlags", "underlying_type": "Uint64", "values": [{"name": "SDL_WINDOW_FULLSCREEN", "value": "SDL_UINT64_C(0x0000000000000001)", "comment": "window is in fullscreen mode"}, {"name": "SDL_WINDOW_OPENGL", "value": "SDL_UINT64_C(0x0000000000000002)", "comment": "window usable with OpenGL context"}, {"name": "SDL_WINDOW_OCCLUDED", "value": "SDL_UINT64_C(0x0000000000000004)", "comment": "window is occluded"}, {"name": "SDL_WINDOW_HIDDEN", "value": "SDL_UINT64_C(0x0000000000000008)", "comment": "window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow() is required for it to become visible"}, {"name": "SDL_WINDOW_BORDERLESS", "value": "SDL_UINT64_C(0x0000000000000010)", "comment": "no window decoration"}, {"name": "SDL_WINDOW_RESIZABLE", "value": "SDL_UINT64_C(0x0000000000000020)", "comment": "window can be resized"}, {"name": "SDL_WINDOW_MINIMIZED", "value": "SDL_UINT64_C(0x0000000000000040)", "comment": "window is minimized"}, {"name": "SDL_WINDOW_MAXIMIZED", "value": "SDL_UINT64_C(0x0000000000000080)", "comment": "window is maximized"}, {"name": "SDL_WINDOW_MOUSE_GRABBED", "value": "SDL_UINT64_C(0x0000000000000100)", "comment": "window has grabbed mouse input"}, {"name": "SDL_WINDOW_INPUT_FOCUS", "value": "SDL_UINT64_C(0x0000000000000200)", "comment": "window has input focus"}, {"name": "SDL_WINDOW_MOUSE_FOCUS", "value": "SDL_UINT64_C(0x0000000000000400)", "comment": "window has mouse focus"}, {"name": "SDL_WINDOW_EXTERNAL", "value": "SDL_UINT64_C(0x0000000000000800)", "comment": "window not created by SDL"}, {"name": "SDL_WINDOW_MODAL", "value": "SDL_UINT64_C(0x0000000000001000)", "comment": "window is modal"}, {"name": "SDL_WINDOW_HIGH_PIXEL_DENSITY", "value": "SDL_UINT64_C(0x0000000000002000)", "comment": "window uses high pixel density back buffer if possible"}, {"name": "SDL_WINDOW_MOUSE_CAPTURE", "value": "SDL_UINT64_C(0x0000000000004000)", "comment": "window has mouse captured (unrelated to MOUSE_GRABBED)"}, {"name": "SDL_WINDOW_MOUSE_RELATIVE_MODE", "value": "SDL_UINT64_C(0x0000000000008000)", "comment": "window has relative mode enabled"}, {"name": "SDL_WINDOW_ALWAYS_ON_TOP", "value": "SDL_UINT64_C(0x0000000000010000)", "comment": "window should always be above others"}, {"name": "SDL_WINDOW_UTILITY", "value": "SDL_UINT64_C(0x0000000000020000)", "comment": "window should be treated as a utility window, not showing in the task bar and window list"}, {"name": "SDL_WINDOW_TOOLTIP", "value": "SDL_UINT64_C(0x0000000000040000)", "comment": "window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window"}, {"name": "SDL_WINDOW_POPUP_MENU", "value": "SDL_UINT64_C(0x0000000000080000)", "comment": "window should be treated as a popup menu, requires a parent window"}, {"name": "SDL_WINDOW_KEYBOARD_GRABBED", "value": "SDL_UINT64_C(0x0000000000100000)", "comment": "window has grabbed keyboard input"}, {"name": "SDL_WINDOW_VULKAN", "value": "SDL_UINT64_C(0x0000000010000000)", "comment": "window usable for Vulkan surface"}, {"name": "SDL_WINDOW_METAL", "value": "SDL_UINT64_C(0x0000000020000000)", "comment": "window usable for Metal view"}, {"name": "SDL_WINDOW_TRANSPARENT", "value": "SDL_UINT64_C(0x0000000040000000)", "comment": "window with transparent buffer"}, {"name": "SDL_WINDOW_NOT_FOCUSABLE", "value": "SDL_UINT64_C(0x0000000080000000)", "comment": "window should not be focusable"}]} + ], + "functions": [ + {"name": "SDL_GetNumVideoDrivers", "return_type": "int", "parameters": []}, + {"name": "SDL_GetVideoDriver", "return_type": "const char *", "parameters": [{"name": "index", "type": "int"}]}, + {"name": "SDL_GetCurrentVideoDriver", "return_type": "const char *", "parameters": []}, + {"name": "SDL_GetSystemTheme", "return_type": "SDL_SystemTheme", "parameters": []}, + {"name": "SDL_GetDisplays", "return_type": "SDL_DisplayID *", "parameters": [{"name": "count", "type": "int *"}]}, + {"name": "SDL_GetPrimaryDisplay", "return_type": "SDL_DisplayID", "parameters": []}, + {"name": "SDL_GetDisplayProperties", "return_type": "SDL_PropertiesID", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetDisplayName", "return_type": "const char *", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetDisplayBounds", "return_type": "bool", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}, {"name": "rect", "type": "SDL_Rect *"}]}, + {"name": "SDL_GetDisplayUsableBounds", "return_type": "bool", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}, {"name": "rect", "type": "SDL_Rect *"}]}, + {"name": "SDL_GetNaturalDisplayOrientation", "return_type": "SDL_DisplayOrientation", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetCurrentDisplayOrientation", "return_type": "SDL_DisplayOrientation", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetDisplayContentScale", "return_type": "float", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetFullscreenDisplayModes", "return_type": "SDL_DisplayMode **", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}, {"name": "count", "type": "int *"}]}, + {"name": "SDL_GetClosestFullscreenDisplayMode", "return_type": "bool", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}, {"name": "w", "type": "int"}, {"name": "h", "type": "int"}, {"name": "refresh_rate", "type": "float"}, {"name": "include_high_density_modes", "type": "bool"}, {"name": "closest", "type": "SDL_DisplayMode *"}]}, + {"name": "SDL_GetDesktopDisplayMode", "return_type": "const SDL_DisplayMode *", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetCurrentDisplayMode", "return_type": "const SDL_DisplayMode *", "parameters": [{"name": "displayID", "type": "SDL_DisplayID"}]}, + {"name": "SDL_GetDisplayForPoint", "return_type": "SDL_DisplayID", "parameters": [{"name": "point", "type": "const SDL_Point *"}]}, + {"name": "SDL_GetDisplayForRect", "return_type": "SDL_DisplayID", "parameters": [{"name": "rect", "type": "const SDL_Rect *"}]}, + {"name": "SDL_GetDisplayForWindow", "return_type": "SDL_DisplayID", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowPixelDensity", "return_type": "float", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowDisplayScale", "return_type": "float", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowFullscreenMode", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "mode", "type": "const SDL_DisplayMode *"}]}, + {"name": "SDL_GetWindowFullscreenMode", "return_type": "const SDL_DisplayMode *", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowICCProfile", "return_type": "void *", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "size", "type": "size_t *"}]}, + {"name": "SDL_GetWindowPixelFormat", "return_type": "SDL_PixelFormat", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindows", "return_type": "SDL_Window **", "parameters": [{"name": "count", "type": "int *"}]}, + {"name": "SDL_CreateWindow", "return_type": "SDL_Window *", "parameters": [{"name": "title", "type": "const char *"}, {"name": "w", "type": "int"}, {"name": "h", "type": "int"}, {"name": "flags", "type": "SDL_WindowFlags"}]}, + {"name": "SDL_CreatePopupWindow", "return_type": "SDL_Window *", "parameters": [{"name": "parent", "type": "SDL_Window *"}, {"name": "offset_x", "type": "int"}, {"name": "offset_y", "type": "int"}, {"name": "w", "type": "int"}, {"name": "h", "type": "int"}, {"name": "flags", "type": "SDL_WindowFlags"}]}, + {"name": "SDL_CreateWindowWithProperties", "return_type": "SDL_Window *", "parameters": [{"name": "props", "type": "SDL_PropertiesID"}]}, + {"name": "SDL_GetWindowID", "return_type": "SDL_WindowID", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowFromID", "return_type": "SDL_Window *", "parameters": [{"name": "id", "type": "SDL_WindowID"}]}, + {"name": "SDL_GetWindowParent", "return_type": "SDL_Window *", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowProperties", "return_type": "SDL_PropertiesID", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowFlags", "return_type": "SDL_WindowFlags", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowTitle", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "title", "type": "const char *"}]}, + {"name": "SDL_GetWindowTitle", "return_type": "const char *", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowIcon", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "icon", "type": "SDL_Surface *"}]}, + {"name": "SDL_SetWindowPosition", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "x", "type": "int"}, {"name": "y", "type": "int"}]}, + {"name": "SDL_GetWindowPosition", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "x", "type": "int *"}, {"name": "y", "type": "int *"}]}, + {"name": "SDL_SetWindowSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "w", "type": "int"}, {"name": "h", "type": "int"}]}, + {"name": "SDL_GetWindowSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "w", "type": "int *"}, {"name": "h", "type": "int *"}]}, + {"name": "SDL_GetWindowSafeArea", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "rect", "type": "SDL_Rect *"}]}, + {"name": "SDL_SetWindowAspectRatio", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "min_aspect", "type": "float"}, {"name": "max_aspect", "type": "float"}]}, + {"name": "SDL_GetWindowAspectRatio", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "min_aspect", "type": "float *"}, {"name": "max_aspect", "type": "float *"}]}, + {"name": "SDL_GetWindowBordersSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "top", "type": "int *"}, {"name": "left", "type": "int *"}, {"name": "bottom", "type": "int *"}, {"name": "right", "type": "int *"}]}, + {"name": "SDL_GetWindowSizeInPixels", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "w", "type": "int *"}, {"name": "h", "type": "int *"}]}, + {"name": "SDL_SetWindowMinimumSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "min_w", "type": "int"}, {"name": "min_h", "type": "int"}]}, + {"name": "SDL_GetWindowMinimumSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "w", "type": "int *"}, {"name": "h", "type": "int *"}]}, + {"name": "SDL_SetWindowMaximumSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "max_w", "type": "int"}, {"name": "max_h", "type": "int"}]}, + {"name": "SDL_GetWindowMaximumSize", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "w", "type": "int *"}, {"name": "h", "type": "int *"}]}, + {"name": "SDL_SetWindowBordered", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "bordered", "type": "bool"}]}, + {"name": "SDL_SetWindowResizable", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "resizable", "type": "bool"}]}, + {"name": "SDL_SetWindowAlwaysOnTop", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "on_top", "type": "bool"}]}, + {"name": "SDL_ShowWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_HideWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_RaiseWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_MaximizeWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_MinimizeWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_RestoreWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowFullscreen", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "fullscreen", "type": "bool"}]}, + {"name": "SDL_SyncWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_WindowHasSurface", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowSurface", "return_type": "SDL_Surface *", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowSurfaceVSync", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "vsync", "type": "int"}]}, + {"name": "SDL_GetWindowSurfaceVSync", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "vsync", "type": "int *"}]}, + {"name": "SDL_UpdateWindowSurface", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_UpdateWindowSurfaceRects", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "rects", "type": "const SDL_Rect *"}, {"name": "numrects", "type": "int"}]}, + {"name": "SDL_DestroyWindowSurface", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowKeyboardGrab", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "grabbed", "type": "bool"}]}, + {"name": "SDL_SetWindowMouseGrab", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "grabbed", "type": "bool"}]}, + {"name": "SDL_GetWindowKeyboardGrab", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetWindowMouseGrab", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GetGrabbedWindow", "return_type": "SDL_Window *", "parameters": []}, + {"name": "SDL_SetWindowMouseRect", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "rect", "type": "const SDL_Rect *"}]}, + {"name": "SDL_GetWindowMouseRect", "return_type": "const SDL_Rect *", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowOpacity", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "opacity", "type": "float"}]}, + {"name": "SDL_GetWindowOpacity", "return_type": "float", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowParent", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "parent", "type": "SDL_Window *"}]}, + {"name": "SDL_SetWindowModal", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "modal", "type": "bool"}]}, + {"name": "SDL_SetWindowFocusable", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "focusable", "type": "bool"}]}, + {"name": "SDL_ShowWindowSystemMenu", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "x", "type": "int"}, {"name": "y", "type": "int"}]}, + {"name": "SDL_SetWindowHitTest", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "callback", "type": "SDL_HitTest"}, {"name": "callback_data", "type": "void *"}]}, + {"name": "SDL_SetWindowShape", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "shape", "type": "SDL_Surface *"}]}, + {"name": "SDL_FlashWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "operation", "type": "SDL_FlashOperation"}]}, + {"name": "SDL_DestroyWindow", "return_type": "void", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_ScreenSaverEnabled", "return_type": "bool", "parameters": []}, + {"name": "SDL_EnableScreenSaver", "return_type": "bool", "parameters": []}, + {"name": "SDL_DisableScreenSaver", "return_type": "bool", "parameters": []}, + {"name": "SDL_GL_LoadLibrary", "return_type": "bool", "parameters": [{"name": "path", "type": "const char *"}]}, + {"name": "SDL_GL_GetProcAddress", "return_type": "SDL_FunctionPointer", "parameters": [{"name": "proc", "type": "const char *"}]}, + {"name": "SDL_EGL_GetProcAddress", "return_type": "SDL_FunctionPointer", "parameters": [{"name": "proc", "type": "const char *"}]}, + {"name": "SDL_GL_UnloadLibrary", "return_type": "void", "parameters": []}, + {"name": "SDL_GL_ExtensionSupported", "return_type": "bool", "parameters": [{"name": "extension", "type": "const char *"}]}, + {"name": "SDL_GL_ResetAttributes", "return_type": "void", "parameters": []}, + {"name": "SDL_GL_SetAttribute", "return_type": "bool", "parameters": [{"name": "attr", "type": "SDL_GLAttr"}, {"name": "value", "type": "int"}]}, + {"name": "SDL_GL_GetAttribute", "return_type": "bool", "parameters": [{"name": "attr", "type": "SDL_GLAttr"}, {"name": "value", "type": "int *"}]}, + {"name": "SDL_GL_CreateContext", "return_type": "SDL_GLContext", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GL_MakeCurrent", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}, {"name": "context", "type": "SDL_GLContext"}]}, + {"name": "SDL_GL_GetCurrentWindow", "return_type": "SDL_Window *", "parameters": []}, + {"name": "SDL_GL_GetCurrentContext", "return_type": "SDL_GLContext", "parameters": []}, + {"name": "SDL_EGL_GetCurrentDisplay", "return_type": "SDL_EGLDisplay", "parameters": []}, + {"name": "SDL_EGL_GetCurrentConfig", "return_type": "SDL_EGLConfig", "parameters": []}, + {"name": "SDL_EGL_GetWindowSurface", "return_type": "SDL_EGLSurface", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_EGL_SetAttributeCallbacks", "return_type": "void", "parameters": [{"name": "platformAttribCallback", "type": "SDL_EGLAttribArrayCallback"}, {"name": "surfaceAttribCallback", "type": "SDL_EGLIntArrayCallback"}, {"name": "contextAttribCallback", "type": "SDL_EGLIntArrayCallback"}, {"name": "userdata", "type": "void *"}]}, + {"name": "SDL_GL_SetSwapInterval", "return_type": "bool", "parameters": [{"name": "interval", "type": "int"}]}, + {"name": "SDL_GL_GetSwapInterval", "return_type": "bool", "parameters": [{"name": "interval", "type": "int *"}]}, + {"name": "SDL_GL_SwapWindow", "return_type": "bool", "parameters": [{"name": "window", "type": "SDL_Window *"}]}, + {"name": "SDL_GL_DestroyContext", "return_type": "bool", "parameters": [{"name": "context", "type": "SDL_GLContext"}]} + ] +} diff --git a/lib/sdl3/parser/src/json_serializer.zig b/lib/sdl3/parser/src/json_serializer.zig index 36154ac..f747de9 100644 --- a/lib/sdl3/parser/src/json_serializer.zig +++ b/lib/sdl3/parser/src/json_serializer.zig @@ -17,16 +17,16 @@ pub const JsonSerializer = struct { pub fn init(allocator: std.mem.Allocator, header_name: []const u8) JsonSerializer { return .{ .allocator = allocator, - .output = std.ArrayList(u8){}, + .output = .{}, .header_name = header_name, - .opaque_types = std.ArrayList(patterns.OpaqueType){}, - .typedefs = std.ArrayList(patterns.TypedefDecl){}, - .function_pointers = std.ArrayList(patterns.FunctionPointerDecl){}, - .enums = std.ArrayList(patterns.EnumDecl){}, - .structs = std.ArrayList(patterns.StructDecl){}, - .unions = std.ArrayList(patterns.UnionDecl){}, - .flags = std.ArrayList(patterns.FlagDecl){}, - .functions = std.ArrayList(patterns.FunctionDecl){}, + .opaque_types = .{}, + .typedefs = .{}, + .function_pointers = .{}, + .enums = .{}, + .structs = .{}, + .unions = .{}, + .flags = .{}, + .functions = .{}, }; } diff --git a/lib/sdl3/research/parser-implementation-summary.md b/lib/sdl3/research/parser-implementation-summary.md deleted file mode 100644 index eb93d18..0000000 --- a/lib/sdl3/research/parser-implementation-summary.md +++ /dev/null @@ -1,314 +0,0 @@ -# SDL3 Parser Implementation Summary - -## Overview - -Successfully implemented a fully functional C header parser for SDL3 in Zig that automatically generates idiomatic Zig bindings from SDL3's C headers. The parser uses a simplified text-matching approach rather than a full C parser, taking advantage of SDL3's highly regular header structure. - -## Project Structure - -``` -lib/sdl3/parser/ -├── build.zig # Build configuration for parser executable -├── parser.zig # Main entry point (107 lines) -├── patterns.zig # Pattern scanner (700+ lines, 2 tests) -├── naming.zig # Name conversion utilities (130+ lines, 6 tests) -├── types.zig # Type conversion utilities (88 lines, 3 tests) -└── codegen.zig # Code generation (339 lines, 3 tests) - -Total: ~1,364 lines of code, 14 tests (all passing) -``` - -## Features Implemented - -### 1. Pattern Detection - -The parser successfully detects and extracts: - -**Opaque Types** -```c -typedef struct SDL_GPUDevice SDL_GPUDevice; -``` -→ -```zig -pub const GPUDevice = opaque {}; -``` - -**Enums** -```c -typedef enum SDL_GPUPrimitiveType { - SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, - SDL_GPU_PRIMITIVETYPE_LINELIST -} SDL_GPUPrimitiveType; -``` -→ -```zig -pub const GPUPrimitiveType = enum(c_int) { - trianglelist, - linelist, -}; -``` - -**Structs** -```c -typedef struct SDL_GPUBlitInfo { - SDL_GPUBlitRegion source; - SDL_GPUBlitRegion destination; - bool cycle; -} SDL_GPUBlitInfo; -``` -→ -```zig -pub const GPUBlitInfo = extern struct { - source: GPUBlitRegion, - destination: GPUBlitRegion, - cycle: bool, -}; -``` - -**Functions** -```c -extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsShaderFormats( - SDL_GPUShaderFormat format_flags, - const char *name); -``` -→ -```zig -pub inline fn gpuSupportsShaderFormats(format_flags: GPUShaderFormat, name: [*c]const u8) bool { - return c.SDL_GPUSupportsShaderFormats(@bitCast(format_flags), name); -} -``` - -### 2. Name Conversion - -Intelligent naming conventions to match idiomatic Zig style: - -| C Name | Zig Name | Rule | -|--------|----------|------| -| `SDL_GPUDevice` | `GPUDevice` | Type: Remove SDL_ prefix | -| `SDL_CreateGPUDevice` | `createGPUDevice` | Function: Remove SDL_, lowercase first | -| `SDL_GPUSupportsShaderFormats` | `gpuSupportsShaderFormats` | Function: Lowercase leading acronym | -| `SDL_GPU_PRIMITIVETYPE_TRIANGLELIST` | `trianglelist` | Enum value: Remove common prefix, lowercase | - -Key insight: Leading acronyms (GPU, API, etc.) are fully lowercased when at the start of function names. - -### 3. Type Conversion - -Automatic C to Zig type mapping: - -| C Type | Zig Type | -|--------|----------| -| `float` | `f32` | -| `Uint32` | `u32` | -| `bool` | `bool` | -| `const char *` | `[*c]const u8` | -| `void *` | `?*anyopaque` | -| `SDL_GPUDevice *` | `*GPUDevice` | - -### 4. Cast Detection - -Smart cast insertion based on type patterns: - -| Type Pattern | Cast Used | Example | -|--------------|-----------|---------| -| Pointer types | `@ptrCast` | `*GPUDevice` | -| Flags/packed structs | `@bitCast` | `GPUShaderFormat` | -| Enums | `@intFromEnum` | `GPUPrimitiveType` | -| Primitives | None | `bool`, `u32` | - -## Major Bugs Fixed - -### 1. Memory Leaks in scanFunction (FIXED ✓) - -**Problem**: `readLine()` allocations in loop were never freed. - -**Solution**: -```zig -while (!self.isAtEnd()) { - const line = try self.readLine(); - defer self.allocator.free(line); // ← Added defer - // ... use line ... -} -``` - -**Result**: Zero memory leaks detected by GPA. - -### 2. Function Name Conversion (FIXED ✓) - -**Problem**: `SDL_GPUSupportsShaderFormats` became `gPUSupportsShaderFormats` instead of `gpuSupportsShaderFormats`. - -**Solution**: Implemented proper leading acronym detection: -```zig -// Lowercase entire leading acronym until lowercase char found -var i: usize = 0; -while (i < result.len and std.ascii.isUpper(result[i])) : (i += 1) { - if (i > 0 and i + 1 < result.len and std.ascii.isLower(result[i + 1])) { - break; // Keep last uppercase - it starts next word - } - result[i] = std.ascii.toLower(result[i]); -} -``` - -**Result**: Correctly generates `gpuSupportsShaderFormats`, `createGPUDevice`, etc. - -### 3. Enum/Struct Parsing Broken (FIXED ✓) - -**Problem**: `matchPrefix()` consumes input, then `readLine()` reads from wrong position. - -**Before (broken)**: -```zig -if (self.matchPrefix("typedef enum ")) { // pos moves past "typedef enum " - const line = try self.readLine(); // reads "SDL_GPUPrimitiveType {" - var iter = std.mem.tokenizeScalar(u8, line, ' '); - _ = iter.next(); // expects "typedef" - NOT THERE! - _ = iter.next(); // expects "enum" - NOT THERE! -} -``` - -**After (fixed)**: -```zig -if (self.matchPrefix("typedef enum ")) { - const name_start = self.pos; - while (self.pos < self.source.len and self.source[self.pos] != '{') { - self.pos += 1; - } - const name_slice = std.mem.trim(u8, self.source[name_start..self.pos], " \t\n\r"); - var iter = std.mem.tokenizeScalar(u8, name_slice, ' '); - const name = iter.next() orelse return null; // Gets "SDL_GPUPrimitiveType" - const body = try self.readBracedBlock(); // Now positioned at '{' -} -``` - -**Result**: Enums and structs parse correctly. - -### 4. Brace Characters in Output (FIXED ✓) - -**Problem**: `readBracedBlock()` returns full source including `{`, `}`, and typedef name. These appeared as enum values. - -**Solution**: Filter brace lines: -```zig -while (lines.next()) |line| { - const trimmed = std.mem.trim(u8, line, " \t\r"); - if (trimmed.len == 0) continue; - if (std.mem.startsWith(u8, trimmed, "{")) continue; // ← Added - if (std.mem.startsWith(u8, trimmed, "}")) continue; // ← Added - // Parse actual content... -} -``` - -**Result**: Clean enum values and struct fields. - -## Test Results - -All 14 tests passing: - -``` -1/14 codegen.test.generate opaque type...OK -2/14 codegen.test.generate enum...OK -3/14 codegen.test.parse bit position...OK -4/14 patterns.test.scan opaque typedef...OK -5/14 patterns.test.scan function declaration...OK -6/14 naming.test.strip SDL prefix...OK -7/14 naming.test.type name to Zig...OK -8/14 naming.test.function name to Zig...OK -9/14 naming.test.detect common prefix...OK -10/14 naming.test.enum value to Zig...OK -11/14 naming.test.screaming to lower camel...OK -12/14 types.test.convert primitive types...OK -13/14 types.test.convert SDL types...OK -14/14 types.test.convert pointer types...OK -All 14 tests passed. -``` - -## Example Output - -**Input** (`/tmp/test_sdl.h`): -```c -typedef struct SDL_GPUDevice SDL_GPUDevice; - -typedef enum SDL_GPUPrimitiveType { - SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, - SDL_GPU_PRIMITIVETYPE_LINELIST -} SDL_GPUPrimitiveType; - -extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsShaderFormats( - SDL_GPUShaderFormat format_flags, - const char *name); - -extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( - SDL_GPUShaderFormat format_flags, - bool debug_mode, - const char *name); -``` - -**Output**: -```zig -pub const c = @import("c.zig").c; - -pub const GPUDevice = opaque {}; - -pub const GPUPrimitiveType = enum(c_int) { - trianglelist, - linelist, -}; - -pub inline fn gpuSupportsShaderFormats(format_flags: GPUShaderFormat, name: [*c]const u8) bool { - return c.SDL_GPUSupportsShaderFormats(@bitCast(format_flags), name); -} - -pub inline fn createGPUDevice(format_flags: GPUShaderFormat, debug_mode: bool, name: [*c]const u8) *GPUDevice { - return @ptrCast(c.SDL_CreateGPUDevice(@bitCast(format_flags), debug_mode, name)); -} -``` - -**Statistics**: -- Found 4 declarations -- 1 opaque type, 1 enum, 2 functions -- Zero memory leaks -- Valid Zig code ready to compile - -## Lessons Learned - -### Scanner State Management - -The biggest challenge was managing scanner position correctly when using `matchPrefix()` + other position-modifying operations. Key insight: **Don't mix `matchPrefix()` with `readLine()`** - they both move position and expect different starting states. - -### Memory Management - -Zig's explicit allocator pattern catches leaks early. Using `defer` for cleanup is essential, especially in loops where early `break` or `return` can skip manual cleanup. - -### Text Transformation > Full Parsing - -SDL3's headers are extremely regular. A simple text transformation approach (pattern matching + line-by-line parsing) is **significantly simpler** than a full recursive descent parser with semantic analysis. Original plan: 2000+ lines, 10+ modules. Final implementation: ~1400 lines, 4 modules. - -### Zig 0.15 API Changes - -Major changes encountered: -- ArrayList requires allocator for all methods -- Build system uses `root_module` instead of `root_source_file` -- `std.io.getStdOut()` moved to `std.posix.STDOUT_FILENO` -- Bit shift operand types must match exactly (u5 for u32 shifts) - -## Remaining Work - -- [ ] Test flag parsing (#define-based flags) -- [ ] Run on full SDL_gpu.h header -- [ ] Implement doc comment extraction and formatting -- [ ] Handle edge cases (function pointers, varargs, etc.) -- [ ] Performance testing on all 85 SDL3 headers - -## Usage - -```bash -# Build -zig build - -# Parse a header -./zig-cache/o/*/sdl-parser path/to/header.h > output.zig - -# Example -./zig-cache/o/*/sdl-parser ../SDL/include/SDL3/SDL_gpu.h > gpu.zig -``` - -## Conclusion - -Successfully built a working SDL3 header parser in Zig with clean architecture, comprehensive tests, and proper memory management. The simplified approach proved significantly more maintainable than the original full-parser design, demonstrating the value of understanding your input domain before choosing an implementation strategy. diff --git a/lib/sdl3/research/sdl-header-parser.md b/lib/sdl3/research/sdl-header-parser.md deleted file mode 100644 index 0f9d753..0000000 --- a/lib/sdl3/research/sdl-header-parser.md +++ /dev/null @@ -1,1703 +0,0 @@ -# SDL3 Header Parser & Zig Binding Generator - -## Overview - -SDL3's C headers are highly regular and well-structured, making them ideal candidates for automated parsing and Zig binding generation. This document outlines the architecture and implementation plan for a parser that will extract type and function information from SDL3 headers and generate idiomatic Zig bindings. - -## Current State - -The `lib/sdl3/src/` directory contains hand-maintained Zig bindings for SDL3. These bindings demonstrate the target output format that our generator should produce. Key files include: -- `gpu.zig` - Comprehensive GPU API bindings (good reference implementation) -- `video.zig`, `events.zig`, `init.zig` - Other module bindings -- `c.zig` - Direct C imports - -## Goals - -1. **Parse all 85 SDL3 headers** in `SDL/include/SDL3/` -2. **Extract complete type information**: enums, flags, structs, opaque types, functions -3. **Generate idiomatic Zig bindings** matching the style of existing hand-written bindings -4. **Preserve documentation** from C headers in generated Zig files -5. **Support incremental updates** when SDL3 headers change - -## SDL3 Header Patterns - -### 1. Opaque Types - -**C Pattern:** -```c -/** - * An opaque handle representing a GPU device. - * - * \since This struct is available since SDL 3.2.0. - * - * \sa SDL_CreateGPUDevice - * \sa SDL_DestroyGPUDevice - */ -typedef struct SDL_GPUDevice SDL_GPUDevice; -``` - -**Zig Output:** -```zig -pub const GPUDevice = opaque { - // Methods will be added here -}; -``` - -### 2. Enumerations - -**C Pattern:** -```c -/** - * Specifies the primitive topology of a graphics pipeline. - * - * \since This enum is available since SDL 3.2.0. - * - * \sa SDL_CreateGPUGraphicsPipeline - */ -typedef enum SDL_GPUPrimitiveType -{ - SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, /**< A series of separate triangles. */ - SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP, /**< A series of connected triangles. */ - SDL_GPU_PRIMITIVETYPE_LINELIST, /**< A series of separate lines. */ - SDL_GPU_PRIMITIVETYPE_LINESTRIP, /**< A series of connected lines. */ - SDL_GPU_PRIMITIVETYPE_POINTLIST /**< A series of separate points. */ -} SDL_GPUPrimitiveType; -``` - -**Zig Output:** -```zig -pub const GPUPrimitiveType = enum(c_int) { - primitivetypeTrianglelist, //*< A series of separate triangles. */ - primitivetypeTrianglestrip, //*< A series of connected triangles. */ - primitivetypeLinelist, //*< A series of separate lines. */ - primitivetypeLinestrip, //*< A series of connected lines. */ - primitivetypePointlist, //*< A series of separate points. */ -}; -``` - -**Naming Convention:** -- Remove `SDL_GPU_` prefix -- Convert to camelCase starting with lowercase -- Example: `SDL_GPU_PRIMITIVETYPE_TRIANGLELIST` → `primitivetypeTrianglelist` - -### 3. Flag Types (Bitmasks) - -**C Pattern:** -```c -typedef Uint32 SDL_GPUTextureUsageFlags; - -#define SDL_GPU_TEXTUREUSAGE_SAMPLER (1u << 0) /**< Texture supports sampling. */ -#define SDL_GPU_TEXTUREUSAGE_COLOR_TARGET (1u << 1) /**< Texture is a color render target. */ -#define SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET (1u << 2) /**< Texture is a depth stencil target. */ -#define SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ (1u << 3) /**< Texture supports storage reads in graphics stages. */ -#define SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ (1u << 4) /**< Texture supports storage reads in the compute stage. */ -#define SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE (1u << 5) /**< Texture supports storage writes in the compute stage. */ -#define SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE (1u << 6) /**< Texture supports reads and writes in the same compute shader. */ -``` - -**Zig Output:** -```zig -pub const GPUTextureUsageFlags = packed struct(u32) { - textureusageSampler: bool = false, - textureusageColorTarget: bool = false, - textureusageDepthStencilTarget: bool = false, - textureusageGraphicsStorageRead: bool = false, - textureusageComputeStorageRead: bool = false, - textureusageComputeStorageWrite: bool = false, - textureusageComputeStorageSimultaneousReadWrite: bool = false, - pad0: u24 = 0, - rsvd: bool = false, -}; -``` - -**Naming Convention:** -- Remove common prefix (e.g., `SDL_GPU_TEXTUREUSAGE_`) -- Convert to camelCase starting with lowercase -- Add padding fields to reach the backing integer size (u32, u64, etc.) -- Add `rsvd` field as the high bit for future expansion - -### 4. Structures - -**C Pattern:** -```c -/** - * A structure specifying the parameters of a graphics pipeline viewport. - * - * \since This struct is available since SDL 3.2.0. - * - * \sa SDL_SetGPUViewport - */ -typedef struct SDL_GPUViewport -{ - float x; /**< The left offset of the viewport. */ - float y; /**< The top offset of the viewport. */ - float w; /**< The width of the viewport. */ - float h; /**< The height of the viewport. */ - float min_depth; /**< The minimum depth of the viewport. */ - float max_depth; /**< The maximum depth of the viewport. */ -} SDL_GPUViewport; -``` - -**Zig Output:** -```zig -pub const GPUViewport = extern struct { - x: f32, // The left offset of the viewport. - y: f32, // The top offset of the viewport. - w: f32, // The width of the viewport. - h: f32, // The height of the viewport. - min_depth: f32, // The minimum depth of the viewport. - max_depth: f32, // The maximum depth of the viewport. -}; -``` - -**Naming Convention:** -- Keep field names as-is (already snake_case) -- Convert C types to Zig equivalents: - - `float` → `f32` - - `double` → `f64` - - `Uint8` → `u8` - - `Uint16` → `u16` - - `Uint32` → `u32` - - `Uint64` → `u64` - - `Sint8` → `i8` - - `Sint16` → `i16` - - `Sint32` → `i32` - - `Sint64` → `i64` - - `bool` / `SDL_bool` → `bool` - - `size_t` → `usize` - - `int` → `c_int` - - `char` → `u8` (for single chars) or `[*c]const u8` (for strings) - - `void*` → `?*anyopaque` (if nullable) or `*anyopaque` (if non-null) - - `const char*` → `[*c]const u8` - - `T*` (opaque pointer) → `*T` - - `const T*` (opaque pointer) → `*const T` - - `T**` (out parameter) → `[*c]*T` - -### 5. Constants & Large Enums - -Some enums in SDL3 have many values and are better represented as individual constants in Zig. - -**C Pattern:** -```c -typedef enum SDL_EventType -{ - SDL_EVENT_FIRST = 0, /**< Unused (do not remove) */ - - /* Application events */ - SDL_EVENT_QUIT = 0x100, /**< User-requested quit */ - SDL_EVENT_TERMINATING = 0x101, /**< OS is terminating the app */ - // ... many more values -} SDL_EventType; -``` - -**Zig Output (Individual Constants):** -```zig -pub const first: u32 = 0; -pub const quit: u32 = 256; -pub const terminating: u32 = 257; -// ... many more constants -``` - -**Design Decision:** -- Large enums (>20 values) that serve as constant collections → individual constants -- Small enums that represent a closed set of values → Zig enum -- Configuration: Mark certain enums for constant expansion in config - -### 6. Functions - -**C Pattern:** -```c -/** - * Create a GPU context. - * - * \param format_flags a bitflag indicating which shader formats the app can - * provide. - * \param debug_mode enable debug mode properties and validations. - * \param name the preferred GPU driver, or NULL to let SDL pick the optimal - * driver. - * \returns a GPU context on success, or NULL on failure; call SDL_GetError() - * for more information. - * - * \since This function is available since SDL 3.2.0. - * - * \sa SDL_GetGPUDriver - * \sa SDL_DestroyGPUDevice - * \sa SDL_GPUSupportsShaderFormats - */ -extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( - SDL_GPUShaderFormat format_flags, - bool debug_mode, - const char *name); -``` - -**Zig Output (Free Function):** -```zig -// SDL_CreateGPUDevice -pub inline fn createGPUDevice(format_flags: GPUShaderFormat, debug_mode: bool, name: [*c]const u8) *GPUDevice { - return @ptrCast(c.SDL_CreateGPUDevice(@bitCast(format_flags), debug_mode, name)); -} -``` - -**Zig Output (Method on Opaque Type):** -```zig -pub const GPUDevice = opaque { - // SDL_DestroyGPUDevice - pub inline fn destroyGPUDevice(device: *GPUDevice) void { - c.SDL_DestroyGPUDevice(@ptrCast(device)); - } -}; -``` - -**Function Classification Rules:** -1. Functions taking an opaque type pointer as the first parameter → method on that type -2. Functions that create an opaque type → free function (constructor) -3. All other functions → free functions - -**Naming Convention:** -- Remove `SDL_` prefix -- Convert to camelCase -- Example: `SDL_CreateGPUDevice` → `createGPUDevice` -- For methods, keep the full name but it will be called as `device.destroyGPUDevice(device)` - -**Cast Handling in Generated Code:** - -The wrapper functions need to insert appropriate casts: - -1. **Opaque pointers:** Use `@ptrCast` - ```zig - c.SDL_DestroyGPUDevice(@ptrCast(device)) - ``` - -2. **Enums:** Use `@intFromEnum` (Zig → C) or `@enumFromInt` (C → Zig) - ```zig - // Zig to C - c.SDL_Function(@intFromEnum(my_enum)) - - // C to Zig - return @enumFromInt(c.SDL_Function()) - ``` - -3. **Flags (packed structs):** Use `@bitCast` - ```zig - c.SDL_CreateDevice(@bitCast(format_flags)) - ``` - -4. **Primitive types:** Usually no cast needed, but may use `@bitCast` for same-size conversions - ```zig - c.SDL_Function(@bitCast(my_u32)) - ``` - -5. **Return values:** - - Opaque pointers: `@ptrCast` the result - - Enums: `@enumFromInt` the result - - Flags: `@bitCast` the result - - Primitives: direct return - -## Module Dependencies & Header Relationships - -SDL3 headers have dependencies on each other: - -``` -SDL_stdinc.h # Base types (Uint32, Sint32, etc.) - ↓ -SDL_error.h # Error handling - ↓ -SDL_properties.h # Properties system - ↓ -SDL_video.h # Video/window system - ↓ -SDL_gpu.h # GPU rendering (depends on video for SDL_Window) -``` - -**Parsing Strategy:** -1. Parse all headers into a unified AST first -2. Build type dependency graph -3. Resolve cross-header type references -4. Generate modules in dependency order -5. Add imports between generated modules as needed - -**Generated Module Structure:** -```zig -// gpu.zig -pub const c = @import("c.zig").c; -pub const video = @import("video.zig"); // If needed - -// Use video types -pub const Window = video.Window; -``` - -## Simplified Zig Parser Architecture - -### Key Insight: SDL3 Headers Are EXTREMELY Regular - -After analyzing the actual SDL3 headers, they follow **very simple patterns**: - -1. **Opaque types:** `typedef struct SDL_Foo SDL_Foo;` - Single line! -2. **Enums:** `typedef enum SDL_Foo { ... } SDL_Foo;` - Braces are balanced -3. **Structs:** `typedef struct SDL_Foo { ... } SDL_Foo;` - Same as enums -4. **Flags:** `typedef Uint32 SDL_FooFlags;` + `#define SDL_FOO_*` lines following -5. **Functions:** `extern SDL_DECLSPEC Type SDLCALL SDL_Name(...);` - May span lines - -**We don't need:** -- ❌ Full lexer/tokenizer -- ❌ Recursive descent parser -- ❌ Abstract Syntax Tree -- ❌ Symbol tables -- ❌ Type resolution -- ❌ Semantic analysis -- ❌ Following #includes or system headers -- ❌ Complex preprocessor - -**We DO need:** -- ✅ Line-by-line reader with brace tracking -- ✅ Simple pattern matching (regex or string matching) -- ✅ Extract pattern data into structs -- ✅ Direct code generation - -### Simplified Pipeline - -``` -C Header File - ↓ -[1. Pattern Scanner] → Extract Declarations - ↓ (opaque, enum, struct, flags, function) -[2. Data Extraction] → Simple Structs - ↓ (name, fields, values, etc.) -[3. Code Generator] → Zig Source Code - ↓ -Generated Bindings -``` - -**Complexity Reduction:** ~1/5th the original complexity! - -### Simplified Module Structure - -#### `parser.zig` - Main Entry Point & Scanner - -The main file that does pattern scanning and code generation. - -```zig -const std = @import("std"); -const patterns = @import("patterns.zig"); -const codegen = @import("codegen.zig"); - -pub fn main() !void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - // 1. Parse command line arguments - const args = try std.process.argsAlloc(allocator); - - // 2. Read header file - const source = try std.fs.cwd().readFileAlloc(allocator, header_path, 10 * 1024 * 1024); - - // 3. Scan for patterns - const declarations = try patterns.scan(allocator, source); - - // 4. Generate Zig code - const output = try codegen.generate(allocator, declarations); - - // 5. Write output - try std.fs.cwd().writeFile(output_path, output); -} -``` - -**Responsibilities:** -- Command-line argument parsing -- File I/O -- Call scanner and generator -- Memory management (arena allocator) - -#### `patterns.zig` - Pattern Scanner - -Scans the C header and extracts declarations using simple pattern matching. - -```zig -pub const Declaration = union(enum) { - opaque_type: OpaqueType, - enum_decl: EnumDecl, - struct_decl: StructDecl, - flag_decl: FlagDecl, - function_decl: FunctionDecl, -}; - -pub const OpaqueType = struct { - name: []const u8, // SDL_GPUDevice - doc_comment: ?[]const u8, // /** ... */ -}; - -pub const EnumDecl = struct { - name: []const u8, // SDL_GPUPrimitiveType - values: []EnumValue, // List of enum values - doc_comment: ?[]const u8, -}; - -pub const EnumValue = struct { - name: []const u8, // SDL_GPU_PRIMITIVETYPE_TRIANGLELIST - value: ?[]const u8, // Optional explicit value - comment: ?[]const u8, // Inline comment -}; - -pub const StructDecl = struct { - name: []const u8, // SDL_GPUViewport - fields: []FieldDecl, - doc_comment: ?[]const u8, -}; - -pub const FieldDecl = struct { - name: []const u8, // x - type_name: []const u8, // float - comment: ?[]const u8, -}; - -pub const FlagDecl = struct { - name: []const u8, // SDL_GPUTextureUsageFlags - underlying_type: []const u8, // Uint32 - flags: []FlagValue, - doc_comment: ?[]const u8, -}; - -pub const FlagValue = struct { - name: []const u8, // SDL_GPU_TEXTUREUSAGE_SAMPLER - value: []const u8, // (1u << 0) - comment: ?[]const u8, -}; - -pub const FunctionDecl = struct { - name: []const u8, // SDL_CreateGPUDevice - return_type: []const u8, // SDL_GPUDevice * - params: []ParamDecl, - doc_comment: ?[]const u8, -}; - -pub const ParamDecl = struct { - name: []const u8, // format_flags - type_name: []const u8, // SDL_GPUShaderFormat -}; - -pub const Scanner = struct { - source: []const u8, - pos: usize, - - pub fn init(source: []const u8) Scanner { - return .{ .source = source, .pos = 0 }; - } - - pub fn scan(self: *Scanner, allocator: Allocator) ![]Declaration { - var decls = std.ArrayList(Declaration).init(allocator); - - while (!self.isAtEnd()) { - if (try self.scanOpaque()) |opaque| { - try decls.append(.{ .opaque_type = opaque }); - } else if (try self.scanEnum()) |enum_| { - try decls.append(.{ .enum_decl = enum_ }); - } else if (try self.scanStruct()) |struct_| { - try decls.append(.{ .struct_decl = struct_ }); - } else if (try self.scanFlags()) |flags| { - try decls.append(.{ .flag_decl = flags }); - } else if (try self.scanFunction()) |func| { - try decls.append(.{ .function_decl = func }); - } else { - self.skipLine(); - } - } - - return decls.toOwnedSlice(); - } - - fn scanOpaque(self: *Scanner) !?OpaqueType { - // Look for: typedef struct SDL_Foo SDL_Foo; - if (self.matchLine("typedef struct ")) { - // Extract name from "SDL_Foo SDL_Foo;" - // ... - } - return null; - } - - fn scanEnum(self: *Scanner) !?EnumDecl { - // Look for: typedef enum SDL_Foo - // Then collect until } SDL_Foo; - // ... - } - - fn scanStruct(self: *Scanner) !?StructDecl { - // Same as enum but for structs - // ... - } - - fn scanFlags(self: *Scanner) !?FlagDecl { - // Look for: typedef Uint32 SDL_FooFlags; - // Then collect following #define lines - // ... - } - - fn scanFunction(self: *Scanner) !?FunctionDecl { - // Look for: extern SDL_DECLSPEC Type SDLCALL SDL_Name(...); - // May span multiple lines - // ... - } - - // Utility functions - fn matchLine(self: *Scanner, prefix: []const u8) bool { } - fn readUntil(self: *Scanner, terminator: u8) []const u8 { } - fn readBraced(self: *Scanner) []const u8 { } // Read {...} - fn extractDocComment(self: *Scanner) ?[]const u8 { } - fn skipLine(self: *Scanner) void { } - fn isAtEnd(self: *Scanner) bool { } -}; -``` - -**Strategy:** -- Simple line-by-line scanning -- Pattern matching with `std.mem.startsWith` -- Brace counting for `{...}` blocks -- Store raw strings, parse during generation - -#### `naming.zig` - Name Conversion - -Simple string manipulation for name conversion. - -```zig -pub fn stripPrefix(name: []const u8, prefix: []const u8) []const u8 { - if (std.mem.startsWith(u8, name, prefix)) { - return name[prefix.len..]; - } - return name; -} - -pub fn typeNameToZig(c_name: []const u8) []const u8 { - // SDL_GPUDevice -> GPUDevice (just strip SDL_) - return stripPrefix(c_name, "SDL_"); -} - -pub fn functionNameToZig(c_name: []const u8, allocator: Allocator) ![]const u8 { - // SDL_CreateGPUDevice -> createGPUDevice - const without_prefix = stripPrefix(c_name, "SDL_"); - return lowerFirstChar(without_prefix, allocator); -} - -pub fn enumValueToZig(c_name: []const u8, prefix: []const u8, allocator: Allocator) ![]const u8 { - // SDL_GPU_PRIMITIVETYPE_TRIANGLELIST -> primitivetypeTrianglelist - const without_prefix = stripPrefix(c_name, prefix); - return toLowerCamelCase(without_prefix, allocator); -} - -pub fn detectCommonPrefix(names: []const []const u8) []const u8 { - // Find longest common prefix - // SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, SDL_GPU_PRIMITIVETYPE_LINESTRIP - // -> SDL_GPU_PRIMITIVETYPE_ -} - -fn lowerFirstChar(s: []const u8, allocator: Allocator) ![]const u8 { - var result = try allocator.dupe(u8, s); - if (result.len > 0) result[0] = std.ascii.toLower(result[0]); - return result; -} - -fn toLowerCamelCase(s: []const u8, allocator: Allocator) ![]const u8 { - // Convert SCREAMING_SNAKE to lowerCamelCase - // Handle SDL3's conventions -} -``` - -**Convention Rules:** - -| C Pattern | Zig Pattern | Example | -|-----------|-------------|---------| -| `SDL_FooBar` (type) | `FooBar` | `SDL_GPUDevice` → `GPUDevice` | -| `SDL_FooBar` (function) | `fooBar` | `SDL_CreateGPUDevice` → `createGPUDevice` | -| `SDL_FOO_BAR_BAZ` (enum) | `fooBarBaz` | `SDL_GPU_PRIMITIVETYPE_TRIANGLELIST` → `primitivetypeTrianglelist` | -| `SDL_FOO_BAR` (flag) | `fooBar` | `SDL_GPU_TEXTUREUSAGE_SAMPLER` → `textureusageSampler` | - -#### `types.zig` - Type Conversion - -Simple string-based type conversion (no need to parse types fully). - -```zig -pub fn convertType(c_type: []const u8) []const u8 { - // Simple table lookup and string replacement - if (std.mem.eql(u8, c_type, "void")) return "void"; - if (std.mem.eql(u8, c_type, "bool")) return "bool"; - if (std.mem.eql(u8, c_type, "SDL_bool")) return "bool"; - if (std.mem.eql(u8, c_type, "float")) return "f32"; - if (std.mem.eql(u8, c_type, "double")) return "f64"; - if (std.mem.eql(u8, c_type, "char")) return "u8"; - if (std.mem.eql(u8, c_type, "int")) return "c_int"; - if (std.mem.eql(u8, c_type, "Uint8")) return "u8"; - if (std.mem.eql(u8, c_type, "Uint16")) return "u16"; - if (std.mem.eql(u8, c_type, "Uint32")) return "u32"; - if (std.mem.eql(u8, c_type, "Uint64")) return "u64"; - if (std.mem.eql(u8, c_type, "Sint8")) return "i8"; - if (std.mem.eql(u8, c_type, "Sint16")) return "i16"; - if (std.mem.eql(u8, c_type, "Sint32")) return "i32"; - if (std.mem.eql(u8, c_type, "Sint64")) return "i64"; - if (std.mem.eql(u8, c_type, "size_t")) return "usize"; - - // Pointers - simple pattern matching - if (std.mem.eql(u8, c_type, "const char *")) return "[*c]const u8"; - if (std.mem.eql(u8, c_type, "void *")) return "?*anyopaque"; - - // SDL types - just strip SDL_ prefix - if (std.mem.startsWith(u8, c_type, "SDL_")) { - // SDL_GPUDevice * -> *GPUDevice - // SDL_GPUTextureFormat -> GPUTextureFormat - // Handle pointers and const - } - - return c_type; // fallback -} -``` - -**Strategy:** -- Table lookup for primitives -- Pattern matching for pointers -- String replacement for SDL types -- No need to fully parse - SDL types are very regular! - -#### `codegen.zig` - Code Generation - -Direct code generation from extracted declarations. - -```zig -pub const CodeGen = struct { - decls: []Declaration, - allocator: Allocator, - output: std.ArrayList(u8), - - pub fn generate(allocator: Allocator, decls: []Declaration) ![]const u8 { - var gen = CodeGen{ - .decls = decls, - .allocator = allocator, - .output = std.ArrayList(u8).init(allocator), - }; - - try gen.writeHeader(); - - // Generate each declaration - for (decls) |decl| { - switch (decl) { - .opaque_type => |opaque| try gen.writeOpaque(opaque), - .enum_decl => |enum_| try gen.writeEnum(enum_), - .struct_decl => |struct_| try gen.writeStruct(struct_), - .flag_decl => |flags| try gen.writeFlags(flags), - .function_decl => |func| try gen.writeFunction(func), - } - } - - return gen.output.toOwnedSlice(); - } - - fn writeHeader(self: *CodeGen) !void { - try self.output.appendSlice("pub const c = @import(\"c.zig\").c;\n\n"); - } - - fn writeOpaque(self: *CodeGen, opaque: OpaqueType) !void { - // pub const GPUDevice = opaque {}; - try self.output.writer().print("pub const {s} = opaque {{}};\n\n", .{ - naming.typeNameToZig(opaque.name), - }); - } - - fn writeEnum(self: *CodeGen, enum_: EnumDecl) !void { - const zig_name = naming.typeNameToZig(enum_.name); - try self.output.writer().print("pub const {s} = enum(c_int) {{\n", .{zig_name}); - - const prefix = naming.detectCommonPrefix(/* enum values */); - - for (enum_.values) |value| { - const zig_value = try naming.enumValueToZig(value.name, prefix, self.allocator); - if (value.comment) |comment| { - try self.output.writer().print(" {s}, // {s}\n", .{ zig_value, comment }); - } else { - try self.output.writer().print(" {s},\n", .{zig_value}); - } - } - - try self.output.appendSlice("};\n\n"); - } - - fn writeStruct(self: *CodeGen, struct_: StructDecl) !void { - const zig_name = naming.typeNameToZig(struct_.name); - try self.output.writer().print("pub const {s} = extern struct {{\n", .{zig_name}); - - for (struct_.fields) |field| { - const zig_type = types.convertType(field.type_name); - if (field.comment) |comment| { - try self.output.writer().print(" {s}: {s}, // {s}\n", .{ - field.name, zig_type, comment, - }); - } else { - try self.output.writer().print(" {s}: {s},\n", .{ field.name, zig_type }); - } - } - - try self.output.appendSlice("};\n\n"); - } - - fn writeFlags(self: *CodeGen, flags: FlagDecl) !void { - // pub const GPUTextureUsageFlags = packed struct(u32) { - // textureusageSampler: bool = false, - // ... - // }; - // Calculate padding, generate fields - } - - fn writeFunction(self: *CodeGen, func: FunctionDecl) !void { - // Determine if it's a method or free function - const is_method = isMethod(func); - - if (is_method) { - // Will be added to opaque type later (need second pass) - } else { - // Free function - const zig_name = try naming.functionNameToZig(func.name, self.allocator); - // Generate: pub inline fn createGPUDevice(...) ... { c.SDL_CreateGPUDevice(...); } - } - } -}; - -fn isMethod(func: FunctionDecl) bool { - // Check if first parameter is an opaque type - if (func.params.len > 0) { - const first_param_type = func.params[0].type_name; - // Check if it's one of the opaque types - return std.mem.startsWith(u8, first_param_type, "SDL_GPU") and - std.mem.endsWith(u8, first_param_type, " *"); - } - return false; -} -``` - -**Strategy:** -- Direct string generation (no templates needed!) -- Two passes: types first, then group methods with opaque types -- Simple `std.fmt.format` for code generation -- No complex AST traversal - -**Note:** Config can be added later if needed, but start without it for simplicity. - -### Memory Management - -Arena allocation for simplicity: - -```zig -pub fn main() !void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - // Everything freed at once when done -} -``` - -### Testing - -Simple integration tests: - -```zig -test "scan opaque typedef" { - const source = "typedef struct SDL_GPUDevice SDL_GPUDevice;"; - var scanner = patterns.Scanner.init(source); - const decls = try scanner.scan(std.testing.allocator); - try std.testing.expectEqual(@as(usize, 1), decls.len); - try std.testing.expect(decls[0] == .opaque_type); -} - -test "generate enum" { - const enum_decl = EnumDecl{ - .name = "SDL_GPUPrimitiveType", - .values = &[_]EnumValue{ - .{ .name = "SDL_GPU_PRIMITIVETYPE_TRIANGLELIST", .value = null, .comment = null }, - }, - .doc_comment = null, - }; - const output = try codegen.generateEnum(enum_decl, std.testing.allocator); - // Check output matches expected Zig code -} -``` - -### Performance - -**Expected:** -- Parse all 85 headers: < 1 second -- Memory: < 50 MB -- Single-threaded (sufficient for this workload) - -## Parser Architecture - -### Phase 1: Lexical Analysis & Preprocessing - -**Input:** Raw C header files -**Output:** Token stream - -**Tasks:** -1. Remove `SDL_begin_code.h` / `SDL_close_code.h` includes (these are preprocessor magic) -2. Strip out platform-specific `#ifdef` blocks (or handle multiple platform variants) -3. Expand or track `#define` macros (especially for flag values) -4. Tokenize the remaining C code -5. Handle multi-line comments and documentation blocks - -**Challenges:** -- C preprocessor complexity -- Platform-specific code paths -- Macro expansion for flag definitions - -**Approach:** -- Use a simple regex-based preprocessor for well-known patterns -- Or use libclang Python bindings for robust parsing -- Focus on public API headers only (skip internal `_c.h` files) - -### Phase 2: Syntax Analysis & AST Building - -**Input:** Token stream -**Output:** Abstract Syntax Tree (AST) - -**AST Node Types:** -- `OpaqueType` - opaque struct typedefs -- `Enum` - enum definitions with values -- `FlagType` - flag typedef + associated defines -- `Struct` - struct definitions -- `Function` - function declarations -- `Comment` - documentation blocks - -**Key Information to Extract:** - -For each type/function: -- Full C name (e.g., `SDL_GPUDevice`) -- Zig name (e.g., `GPUDevice`) -- Documentation comment -- Source location (file, line number) -- Related items (`\sa` references) -- Version info (`\since`) - -For functions: -- Return type -- Parameter names and types -- Which opaque type it belongs to (if any) -- Const/pointer qualifiers - -For enums: -- Each enumerant name and value -- Inline comments for each value - -For flags: -- Each flag name and bit position -- Backing integer type - -For structs: -- Each field name and type -- Inline comments for each field -- Padding requirements - -### Phase 3: Semantic Analysis - -**Input:** Raw AST -**Output:** Enriched AST with relationships - -**Tasks:** -1. **Type Resolution:** - - Resolve all type references to their definitions - - Handle forward declarations - - Build type dependency graph - -2. **Function Classification:** - - Identify which functions are methods vs. free functions - - Group methods by opaque type - - Detect constructor/destructor patterns - -3. **Documentation Processing:** - - Parse Doxygen tags (`\param`, `\returns`, `\sa`, `\since`) - - Build cross-reference map - - Extract and clean inline comments - -4. **Naming Convention Application:** - - Convert SDL names to Zig names - - Detect and handle naming collisions - - Generate consistent camelCase names - -5. **Module Organization:** - - Determine which Zig file each definition belongs to - - Based on C header name (e.g., `SDL_gpu.h` → `gpu.zig`) - - Handle cross-module dependencies - -### Phase 4: Code Generation - -**Input:** Enriched AST -**Output:** Zig source files - -**Generation Strategy:** - -1. **Header:** -```zig -pub const c = @import("c.zig").c; -pub const PropertiesID = u32; -// Other common imports/aliases -``` - -2. **Type Definitions (Order matters!):** - - First: Flag types (no dependencies) - - Second: Enums (no dependencies) - - Third: Opaque types (empty declarations) - - Fourth: Structs (may reference above types) - -3. **Free Functions:** - - After all types - - Grouped by category - -4. **Opaque Type Methods:** - - Fill in method definitions in opaque types - - Maintain consistent ordering - -**Code Generation Templates:** - -For each AST node type, we need a template. Examples: - -**Enum Template:** -```zig -pub const {ZigName} = enum(c_int) { - {for each value} - {zigValueName}, //{inline comment} - {end for} -}; -``` - -**Flag Template:** -```zig -pub const {ZigName} = packed struct({backingType}) { - {for each flag} - {zigFlagName}: bool = false, - {end for} - {padding fields} - rsvd: bool = false, -}; -``` - -**Struct Template:** -```zig -pub const {ZigName} = extern struct { - {for each field} - {fieldName}: {zigType}, // {inline comment} - {end for} -}; -``` - -**Free Function Template:** -```zig -// {C function name} -pub inline fn {zigFuncName}({params}) {returnType} { - {function body with casts} -} -``` - -**Method Template:** -```zig -// {C function name} -pub inline fn {zigMethodName}({params}) {returnType} { - c.{cFuncName}({casts and calls}); -} -``` - -### Phase 5: Validation & Testing - -**Input:** Generated Zig files -**Output:** Validated, compilable bindings - -**Validation Steps:** - -1. **Compilation Test:** - - Run `zig build` on generated files - - Ensure no syntax errors - - Check type correctness - -2. **API Completeness:** - - Compare generated API surface with C headers - - Ensure no functions/types are missing - - Check for extra/duplicate definitions - -3. **Comparison with Hand-Written:** - - Diff generated `gpu.zig` with existing `src/gpu.zig` - - Verify naming conventions match - - Check structure and organization - -4. **Cross-Reference Validation:** - - Verify all type references are resolvable - - Check method ownership is correct - - Ensure no circular dependencies - -5. **Documentation Check:** - - Verify comments are preserved - - Check for formatting issues - - Validate cross-references - -## Recommended Implementation Milestones - -**Current Status:** ✅ Hello world implemented (`parser.zig` lists all 85 headers) - -### Milestone 1: Pattern Scanner (2-3 days) - -**Goal:** Extract declarations from SDL_gpu.h - -**Scope:** -1. Implement `patterns.zig` with `Scanner` struct -2. Scan for opaque typedefs (simple one-line pattern) -3. Scan for enums (track braces) -4. Scan for structs (track braces) -5. Store declarations in simple structs - -**Deliverable:** -- `patterns.zig` that extracts opaque, enum, and struct from SDL_gpu.h -- Basic tests for each pattern type - -**Complexity:** Low - just string matching and brace counting - -### Milestone 2: Code Generation (2-3 days) - -**Goal:** Generate Zig code for extracted declarations - -**Scope:** -1. Implement `codegen.zig` -2. Implement `naming.zig` for name conversion -3. Implement `types.zig` for type conversion -4. Generate opaque types -5. Generate enums -6. Generate structs - -**Deliverable:** -- Generated Zig code for subset of SDL_gpu.h -- Code compiles with `zig build` -- Matches hand-written style - -**Complexity:** Low - direct string generation - -### Milestone 3: Flags and Functions (2-3 days) - -**Goal:** Complete SDL_gpu.h parsing - -**Scope:** -1. Add flag scanning (typedef + #define lines) -2. Add function scanning -3. Classify functions (method vs. free function) -4. Generate flag types -5. Generate functions and methods - -**Deliverable:** -- Complete `gpu.zig` generation -- All types and functions included -- Compiles and matches hand-written version - -**Complexity:** Medium - function classification logic - -### Milestone 4: Multi-Header Support (1-2 days) - -**Goal:** Generalize to other headers - -**Scope:** -1. Test on SDL_video.h, SDL_events.h, SDL_init.h -2. Handle any new patterns -3. Fix bugs -4. Add integration tests - -**Deliverable:** -- Parser handles all common SDL3 patterns -- Generate bindings for multiple headers -- All generated code compiles - -**Complexity:** Low - SDL headers are very consistent - -### Total Time Estimate - -**2-3 weeks** of focused work (vs. 6-8 weeks with complex architecture) - -**Key Simplifications:** -- No lexer/tokenizer (line-by-line scanning) -- No AST (direct data extraction) -- No semantic analysis (simple pattern matching) -- No complex type system (string conversion) - -## Implementation Plan - -### Stage 1: Prototype Parser (Week 1-2) - -**Goal:** Parse SDL_gpu.h and generate gpu.zig - -**Tasks:** -1. Choose parsing approach (libclang vs. custom parser) -2. Implement basic token scanner -3. Parse enum definitions -4. Parse flag definitions -5. Parse struct definitions -6. Parse opaque types -7. Parse function signatures - -**Deliverable:** Working parser for SDL_gpu.h - -### Stage 2: Code Generator (Week 2-3) - -**Goal:** Generate gpu.zig from parsed data - -**Tasks:** -1. Implement naming convention rules -2. Build type dependency resolver -3. Create code generation templates -4. Implement function classification -5. Add method grouping logic -6. Generate initial gpu.zig - -**Deliverable:** Generated gpu.zig that compiles - -### Stage 3: Refinement (Week 3-4) - -**Goal:** Match hand-written gpu.zig quality - -**Tasks:** -1. Compare generated vs. hand-written -2. Fix naming mismatches -3. Improve comment formatting -4. Adjust code organization -5. Handle edge cases -6. Add manual override system for special cases - -**Deliverable:** Generated gpu.zig identical to hand-written version - -### Stage 4: Generalization (Week 4-6) - -**Goal:** Parse all 85 SDL3 headers - -**Tasks:** -1. Test parser on other headers (video, events, init, etc.) -2. Handle new patterns not seen in gpu.h -3. Implement cross-header type resolution -4. Add module dependency management -5. Handle platform-specific code -6. Create configuration system for header selection - -**Deliverable:** Parser that handles all SDL3 headers - -### Stage 5: Integration & Automation (Week 6-7) - -**Goal:** Integrate into build system - -**Tasks:** -1. Create Zig build step for code generation -2. Add header change detection -3. Implement incremental regeneration -4. Add validation step to build -5. Create documentation generator -6. Write user guide - -**Deliverable:** Automated, maintainable system - -## Technical Decisions - -### Parser Implementation - -**Option A: libclang bindings (C or Zig)** -- ✅ Robust, handles all C syntax -- ✅ Proper preprocessor support -- ✅ Battle-tested -- ❌ External dependency -- ❌ Slower -- ❌ Overkill for regular headers -- ❌ Complex API - -**Option B: Custom Zig parser** -- ✅ Lightweight and fast -- ✅ Tailored to SDL patterns -- ✅ Easy to debug and modify -- ✅ No external dependencies -- ✅ Compiles to single binary -- ✅ Same language as target (Zig → Zig) -- ✅ Can share types with generated code -- ✅ Strong type safety during parsing -- ❌ Need to handle C syntax edge cases -- ❌ Manual preprocessor handling - -**Decision:** **Option B** (custom Zig parser). - -**Rationale:** SDL3 headers are extremely regular. A custom Zig parser lets us exploit this regularity and generate better Zig code. We can handle the preprocessor with simple pattern matching for the common cases. Using Zig gives us strong typing, safety, and performance, and results in a single-binary tool with no external dependencies. - -### Language Choice - -**Zig** - Perfect for this task: -- Strong type system helps model C syntax accurately -- Excellent string processing with `std.mem` -- Arena allocators simplify AST memory management -- Fast compilation and execution -- Same language as output (Zig → Zig) -- Can share common types between parser and generated code -- Single binary deployment -- No runtime dependencies - -### File Organization - -``` -lib/sdl3/ -├── parser/ # Simple parser implementation (Zig) -│ ├── build.zig # Parser build script -│ ├── parser.zig # Main entry point & CLI -│ ├── patterns.zig # Pattern scanner (core logic) -│ ├── codegen.zig # Code generator -│ ├── naming.zig # Name conversion utilities -│ └── types.zig # Type conversion utilities -├── src/ # Hand-written & final bindings (target) -│ ├── gpu.zig # Reference implementation (1,198 lines) -│ ├── video.zig -│ ├── events.zig -│ └── ... -├── SDL/ # SDL3 submodule -│ └── include/SDL3/ # Source C headers (85 files) -└── research/ - └── sdl-header-parser.md # This file -``` - -**Total Modules:** 4 (vs. 10+ in over-engineered approach) -**Total Complexity:** ~1/5th of original plan - -### Configuration System - -Support manual overrides for edge cases: - -**config.py:** -```python -# Functions that should be free functions despite taking opaque pointer first -FREE_FUNCTIONS = [ - 'SDL_SomeSpecialCase', -] - -# Custom type mappings -TYPE_OVERRIDES = { - 'SDL_bool': 'bool', - 'void*': '*anyopaque', -} - -# Headers to skip -SKIP_HEADERS = [ - 'SDL_test_*.h', # Test framework - 'SDL_oldnames.h', # Deprecated -] - -# Custom naming rules -NAMING_OVERRIDES = { - 'SDL_bool': 'bool', -} -``` - -## Parsing Challenges & Solutions - -### Challenge 1: Multi-line Declarations - -C allows declarations to span multiple lines: -```c -extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL -SDL_CreateGPUDevice( - SDL_GPUShaderFormat format_flags, - bool debug_mode, - const char *name); -``` - -**Solution:** Normalize whitespace before parsing, treat newlines as spaces inside declarations. - -### Challenge 2: Documentation Comment Association - -Comments must be correctly associated with the following declaration: -```c -/** - * Creates a device. - */ -typedef struct SDL_GPUDevice SDL_GPUDevice; // This gets the comment -``` - -**Solution:** Track the "pending comment" and attach it to the next declaration. - -### Challenge 3: Macro Values - -Flag values use macros: -```c -#define SDL_GPU_TEXTUREUSAGE_SAMPLER (1u << 0) -``` - -**Solution:** Evaluate simple expressions (bit shifts, arithmetic) during parsing. - -### Challenge 4: Nested Structs - -SDL rarely uses these, but they can appear: -```c -typedef struct SDL_Foo { - struct { - int x, y; - } point; -} SDL_Foo; -``` - -**Solution:** Flatten or generate anonymous struct types as needed. - -### Challenge 5: Function Pointers in Structs - -```c -typedef struct SDL_Foo { - void (*callback)(void *userdata); -} SDL_Foo; -``` - -**Solution:** Convert to Zig function pointer syntax: -```zig -callback: ?*const fn (userdata: ?*anyopaque) callconv(.C) void, -``` - -### Challenge 6: Forward Declarations - -```c -typedef struct SDL_Surface SDL_Surface; // Forward declaration -// ... later ... -typedef struct SDL_Surface { - // actual definition -} SDL_Surface; -``` - -**Solution:** Track forward declarations, replace with full definition when found. - -### Challenge 7: Conditional Compilation - -```c -#ifdef SDL_PLATFORM_WIN32 -typedef HWND SDL_WindowHandle; -#else -typedef void* SDL_WindowHandle; -#endif -``` - -**Solution:** Either: -- Parse all branches and generate conditional Zig code -- Use platform-specific configuration -- Default to most general case - -## Edge Cases & Special Handling - -### 1. Properties API - -SDL3 has a properties system with string constants: -```c -#define SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN "SDL.gpu.device.create.debugmode" -``` - -These should be preserved as string constants in Zig. - -### 2. Callbacks - -Function pointer types need special handling: -```c -typedef void (*SDL_SomeCallback)(void *userdata); -``` - -Map to Zig function pointers: -```zig -pub const SomeCallback = *const fn (userdata: ?*anyopaque) callconv(.C) void; -``` - -### 3. Union Types - -SDL uses unions in some places: -```c -typedef union SDL_Event { - Uint32 type; - SDL_WindowEvent window; -} SDL_Event; -``` - -Map to Zig extern unions: -```zig -pub const Event = extern union { - type: u32, - window: WindowEvent, -}; -``` - -### 4. Variadic Functions - -Some SDL functions are variadic (e.g., `SDL_Log`). These should be marked appropriately or wrapped. - -### 5. Platform-Specific Types - -Handle with conditional compilation: -```zig -pub const WindowsHandle = if (builtin.os.tag == .windows) *c.HWND else *anyopaque; -``` - -### 6. Anonymous Structs/Enums - -These rarely appear in SDL3 public headers but should be handled if encountered. - -## Success Criteria - -The parser/generator is successful when: - -1. ✅ All 85 SDL3 headers can be parsed without errors -2. ✅ Generated Zig code compiles without warnings -3. ✅ Generated API is 100% complete (no missing functions/types) -4. ✅ Generated code matches hand-written style -5. ✅ Documentation is preserved and readable -6. ✅ Build time is reasonable (<5 seconds for full regeneration) -7. ✅ Integration tests pass with generated bindings -8. ✅ Code is maintainable and well-documented - -## Future Enhancements - -### Phase 2 Features - -1. **Multi-language support:** Generate bindings for other languages -2. **Documentation generation:** Create API documentation from parsed data -3. **Test generation:** Auto-generate basic API tests -4. **Type-safe wrappers:** Generate higher-level Zig wrappers with better error handling -5. **Backwards compatibility:** Handle multiple SDL versions - -## Open Questions - -1. **Preprocessor handling:** How much preprocessor complexity do we need to support? - - **Answer:** Start simple, expand as needed - -2. **Manual overrides:** How do we handle cases where generated code isn't quite right? - - **Answer:** Configuration file + ability to exclude certain items from generation - -3. **Version tracking:** How do we track which SDL version we're generating for? - - **Answer:** Parse version from SDL_version.h, embed in generated files - -4. **Breaking changes:** What happens when SDL API changes? - - **Answer:** Regenerate, review diff, update override config if needed - -5. **Testing strategy:** How do we test the generated bindings? - - **Answer:** Compile tests + comparison with hand-written + integration tests - -## Example Workflow - -Here's how the parser would be used in practice: - -```bash -# Build the parser -$ cd lib/sdl3/parser -$ zig build - -# Test it lists headers correctly -$ zig build run -- ../SDL/include/SDL3 -SDL3 Header Parser -================== -Scanning headers in: ../SDL/include/SDL3 - [1] SDL_gpu.h - [2] SDL_video.h - ... -Total headers found: 85 - -# Parse a single header (future) -$ zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output ../src/gpu.zig - -# Parse all headers (future) -$ zig build run -- ../SDL/include/SDL3 --output-dir ../src - -# Compare with hand-written -$ diff ../src/gpu.zig ../src/gpu.zig.backup - -# Build and test the generated bindings -$ cd ../.. && zig build test -``` - -**Recommended Development Workflow:** - -1. **Implement lexer** with comprehensive tests -2. **Implement syntax parser** for basic patterns (enum, struct, function) -3. **Implement code generator** for those patterns -4. **Test on subset of SDL_gpu.h** (see "Recommended First Milestone") -5. **Iterate until output matches** hand-written bindings -6. **Add semantic analysis** (type resolution, function classification) -7. **Extend to full SDL_gpu.h** -8. **Generalize to other headers** one by one -9. **Add config system** for edge cases -10. **Integrate into build system** for automatic regeneration - -## Troubleshooting Guide - -### Problem: Generated code doesn't compile - -**Possible Causes:** -1. Type conversion is wrong (check C type → Zig type mapping) -2. Cast is missing or incorrect (check @ptrCast, @bitCast usage) -3. Missing import (check module dependencies) -4. Struct field alignment issue (use `extern struct`) - -**Solution:** -- Compare with hand-written version -- Check `zig build` error message carefully -- Verify the C type in header matches assumption - -### Problem: Parser fails to extract a declaration - -**Possible Causes:** -1. Multi-line declaration not handled -2. Unexpected syntax/formatting -3. Preprocessor directive interfering -4. Comment breaking parser - -**Solution:** -- Print the problematic line with context -- Check for unusual formatting -- Simplify the declaration in a test case -- Add special handling for this pattern - -### Problem: Generated function doesn't match hand-written - -**Possible Causes:** -1. Function classification is wrong (method vs. free function) -2. Parameter types differ -3. Cast strategy differs -4. Naming convention mismatch - -**Solution:** -- Review function classification rules -- Check parameter type conversions -- Verify cast strategy for each type -- Update naming rules in config - -### Problem: Flag structure has wrong padding - -**Possible Causes:** -1. Bit positions calculated incorrectly -2. Backing type size wrong (u32 vs u64) -3. Missing flags - -**Solution:** -- Verify all flag definitions are found -- Check bit position extraction -- Ensure padding calculation accounts for all bits -- Validate backing type matches typedef - -### Problem: Cross-reference types not found - -**Possible Causes:** -1. Type defined in different header -2. Forward declaration not resolved -3. Module dependency missing - -**Solution:** -- Parse dependent headers first -- Build complete type database -- Add explicit imports in generated code -- Check type dependency graph - -## References - -- SDL3 repository: https://github.com/libsdl-org/SDL -- SDL3 headers: `lib/sdl3/SDL/include/SDL3/` -- Existing bindings: `lib/sdl3/src/` -- Zig documentation: https://ziglang.org/documentation/master/ -- libclang Python: https://libclang.readthedocs.io/ -- C11 Standard: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf -- Zig Language Reference: https://ziglang.org/documentation/master/ - -## Next Steps - -**Current Status:** ✅ Hello world implemented - -### Immediate Next Steps (This Week) - -1. **Implement `patterns.zig`** (2-3 days) - - Create simple scanner that reads line-by-line - - Match pattern: `typedef struct SDL_Foo SDL_Foo;` → opaque - - Match pattern: `typedef enum SDL_Foo {` ... `} SDL_Foo;` → enum - - Match pattern: `typedef struct SDL_Foo {` ... `} SDL_Foo;` → struct - - Store in simple structs (no complex AST) - -2. **Implement `codegen.zig`** + helpers (2-3 days) - - Create `naming.zig` for name conversion (SDL_GPUDevice → GPUDevice) - - Create `types.zig` for type conversion (Uint32 → u32, float → f32) - - Generate Zig code directly from extracted data - - Test on subset of SDL_gpu.h - -3. **Add flags and functions** (2-3 days) - - Parse flag typedefs + #define sequences - - Parse function declarations - - Classify as method or free function (check first param) - - Generate complete gpu.zig - -### Following Week - -4. **Test on other headers** (1-2 days) - - Try SDL_video.h, SDL_events.h - - Fix any new patterns - - Handle edge cases - -5. **Polish and integrate** (1-2 days) - - Clean up code - - Add tests - - Update build system - - Document usage - -**Total: 2-3 weeks** to complete parser - -## Key Takeaways - -1. **SDL3 headers are EXTREMELY regular** - Perfect for simple pattern matching -2. **Don't over-engineer** - Text transformation is sufficient, no need for full parser -3. **Start small** - Get pattern matching working for one header first -4. **Use hand-written as reference** - The existing gpu.zig shows exactly what we want -5. **Iterate quickly** - Scan, generate, compile, compare, fix, repeat -6. **Line-by-line scanning works** - No need for tokenizer/lexer -7. **Direct generation is simpler** - No need for AST, just extract and generate -8. **Simple pattern matching** - `typedef struct SDL_Foo SDL_Foo;` is a one-line pattern -9. **Brace counting is enough** - Track `{` and `}` for multi-line declarations -10. **String conversion for types** - Table lookup, no need to parse type expressions -11. **Function classification is simple** - Check if first param is opaque type -12. **Implementation time: 2-3 weeks** (vs. 6-8 weeks for over-engineered approach) - -## Conclusion - -This plan provides a comprehensive roadmap for creating an SDL3 header parser and Zig binding generator. The regular structure of SDL3 headers makes this an ideal project for automated code generation. By following this plan, we can create maintainable, high-quality Zig bindings that stay synchronized with SDL3 development. - -The project is feasible because: -- **SDL3 headers are EXTREMELY regular** - Simple pattern matching works -- **We have excellent reference implementations** - Hand-written bindings show target output -- **Text transformation is sufficient** - No need for complex parsing -- **The scope is well-defined** - 85 headers, 5-6 simple patterns -- **Zig provides excellent tooling** - String manipulation, arena allocation, fast compilation -- **No external dependencies** - Single binary, easy integration - -With a simplified approach using pattern matching instead of full parsing, this can be completed in **2-3 weeks** of focused work (vs. 6-8 weeks for over-engineered approach). The result will be a maintainable system that generates high-quality Zig bindings automatically. - -### Advantages of Simplified Approach - -1. **Simplicity:** ~500 lines of code vs. 2000+ for full parser -2. **Speed:** Faster to implement and faster to execute -3. **Maintainability:** Easy to understand and modify -4. **Reliability:** Less code = fewer bugs -5. **Sufficiency:** SDL3 headers don't need full C parsing -6. **Quick iteration:** Changes are fast to test - -### Simplified Parser Flow - -``` -C Header File - ↓ -┌──────────────────────────────────┐ -│ patterns.zig (Scanner) │ -│ Line-by-line pattern matching │ -│ - typedef struct SDL_Foo... │ -│ - typedef enum SDL_Foo {... │ -│ - typedef Uint32 SDL_Flags; │ -│ - extern SDL_DECLSPEC... │ -└──────────────────┬───────────────┘ - │ - ▼ - Simple Struct Data - (name, fields, values, etc.) - │ - ▼ -┌──────────────────────────────────┐ -│ codegen.zig │ -│ Direct string generation │ -│ + naming.zig (name conversion) │ -│ + types.zig (type conversion) │ -└──────────────────┬───────────────┘ - │ - ▼ - gpu.zig (output) -``` - -**Complexity:** Very Low - just pattern matching and string generation!