├── .github
├── INTEGRATION.md
├── generate-binding-status.sh
├── template.html
├── update-readme.sh
├── validate.sh
└── workflows
│ └── deploy-readme.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── cbits
├── helpers.c
└── stb_image_wrapper.c
├── check-sdl-bindings
├── examples
├── AudioExample.hs
├── CPUInfoExample.hs
├── CameraExample.hs
├── ClipboardExample.hs
├── Content
│ ├── Audio
│ │ └── sound.wav
│ ├── Images
│ │ ├── armadillo.png
│ │ ├── astc
│ │ │ ├── 10x10.astc
│ │ │ ├── 10x5.astc
│ │ │ ├── 10x6.astc
│ │ │ ├── 10x8.astc
│ │ │ ├── 12x10.astc
│ │ │ ├── 12x12.astc
│ │ │ ├── 4x4.astc
│ │ │ ├── 5x4.astc
│ │ │ ├── 5x5.astc
│ │ │ ├── 6x5.astc
│ │ │ ├── 6x6.astc
│ │ │ ├── 8x5.astc
│ │ │ ├── 8x6.astc
│ │ │ └── 8x8.astc
│ │ ├── bcn
│ │ │ ├── BC1.dds
│ │ │ ├── BC1_SRGB.dds
│ │ │ ├── BC2.dds
│ │ │ ├── BC2_SRGB.dds
│ │ │ ├── BC3.dds
│ │ │ ├── BC3_SRGB.dds
│ │ │ ├── BC4.dds
│ │ │ ├── BC5.dds
│ │ │ ├── BC6H_S.dds
│ │ │ ├── BC6H_U.dds
│ │ │ ├── BC7.dds
│ │ │ └── BC7_SRGB.dds
│ │ ├── cube0.bmp
│ │ ├── cube0mip1.bmp
│ │ ├── cube1.bmp
│ │ ├── cube1mip1.bmp
│ │ ├── cube2.bmp
│ │ ├── cube2mip1.bmp
│ │ ├── cube3.bmp
│ │ ├── cube3mip1.bmp
│ │ ├── cube4.bmp
│ │ ├── cube5.bmp
│ │ ├── latency.bmp
│ │ ├── memorial.hdr
│ │ ├── ravioli.bmp
│ │ ├── ravioli_atlas.bmp
│ │ └── ravioli_inverted.bmp
│ └── Shaders
│ │ ├── Compiled
│ │ ├── DXIL
│ │ │ ├── CustomSampling.frag.dxil
│ │ │ ├── DepthOutline.frag.dxil
│ │ │ ├── FillTexture.comp.dxil
│ │ │ ├── Fullscreen.vert.dxil
│ │ │ ├── GradientTexture.comp.dxil
│ │ │ ├── LinearToSRGB.comp.dxil
│ │ │ ├── LinearToST2084.comp.dxil
│ │ │ ├── PositionColor.vert.dxil
│ │ │ ├── PositionColorInstanced.vert.dxil
│ │ │ ├── PositionColorTransform.vert.dxil
│ │ │ ├── PullSpriteBatch.vert.dxil
│ │ │ ├── RawTriangle.vert.dxil
│ │ │ ├── Skybox.frag.dxil
│ │ │ ├── Skybox.vert.dxil
│ │ │ ├── SolidColor.frag.dxil
│ │ │ ├── SolidColorDepth.frag.dxil
│ │ │ ├── SpriteBatch.comp.dxil
│ │ │ ├── TexturedQuad.comp.dxil
│ │ │ ├── TexturedQuad.frag.dxil
│ │ │ ├── TexturedQuad.vert.dxil
│ │ │ ├── TexturedQuadArray.frag.dxil
│ │ │ ├── TexturedQuadColor.frag.dxil
│ │ │ ├── TexturedQuadColorWithMatrix.vert.dxil
│ │ │ ├── TexturedQuadWithMatrix.vert.dxil
│ │ │ ├── TexturedQuadWithMultiplyColor.frag.dxil
│ │ │ ├── ToneMapACES.comp.dxil
│ │ │ ├── ToneMapExtendedReinhardLuminance.comp.dxil
│ │ │ ├── ToneMapHable.comp.dxil
│ │ │ └── ToneMapReinhard.comp.dxil
│ │ ├── MSL
│ │ │ ├── CustomSampling.frag.msl
│ │ │ ├── DepthOutline.frag.msl
│ │ │ ├── FillTexture.comp.msl
│ │ │ ├── Fullscreen.vert.msl
│ │ │ ├── GradientTexture.comp.msl
│ │ │ ├── LinearToSRGB.comp.msl
│ │ │ ├── LinearToST2084.comp.msl
│ │ │ ├── PositionColor.vert.msl
│ │ │ ├── PositionColorInstanced.vert.msl
│ │ │ ├── PositionColorTransform.vert.msl
│ │ │ ├── PullSpriteBatch.vert.msl
│ │ │ ├── RawTriangle.vert.msl
│ │ │ ├── Skybox.frag.msl
│ │ │ ├── Skybox.vert.msl
│ │ │ ├── SolidColor.frag.msl
│ │ │ ├── SolidColorDepth.frag.msl
│ │ │ ├── SpriteBatch.comp.msl
│ │ │ ├── TexturedQuad.comp.msl
│ │ │ ├── TexturedQuad.frag.msl
│ │ │ ├── TexturedQuad.vert.msl
│ │ │ ├── TexturedQuadArray.frag.msl
│ │ │ ├── TexturedQuadColor.frag.msl
│ │ │ ├── TexturedQuadColorWithMatrix.vert.msl
│ │ │ ├── TexturedQuadWithMatrix.vert.msl
│ │ │ ├── TexturedQuadWithMultiplyColor.frag.msl
│ │ │ ├── ToneMapACES.comp.msl
│ │ │ ├── ToneMapExtendedReinhardLuminance.comp.msl
│ │ │ ├── ToneMapHable.comp.msl
│ │ │ └── ToneMapReinhard.comp.msl
│ │ └── SPIRV
│ │ │ ├── CustomSampling.frag.spv
│ │ │ ├── DepthOutline.frag.spv
│ │ │ ├── FillTexture.comp.spv
│ │ │ ├── Fullscreen.vert.spv
│ │ │ ├── GradientTexture.comp.spv
│ │ │ ├── LinearToSRGB.comp.spv
│ │ │ ├── LinearToST2084.comp.spv
│ │ │ ├── PositionColor.vert.spv
│ │ │ ├── PositionColorInstanced.vert.spv
│ │ │ ├── PositionColorTransform.vert.spv
│ │ │ ├── PullSpriteBatch.vert.spv
│ │ │ ├── RawTriangle.vert.spv
│ │ │ ├── Skybox.frag.spv
│ │ │ ├── Skybox.vert.spv
│ │ │ ├── SolidColor.frag.spv
│ │ │ ├── SolidColorDepth.frag.spv
│ │ │ ├── SpriteBatch.comp.spv
│ │ │ ├── TexturedQuad.comp.spv
│ │ │ ├── TexturedQuad.frag.spv
│ │ │ ├── TexturedQuad.vert.spv
│ │ │ ├── TexturedQuadArray.frag.spv
│ │ │ ├── TexturedQuadColor.frag.spv
│ │ │ ├── TexturedQuadColorWithMatrix.vert.spv
│ │ │ ├── TexturedQuadWithMatrix.vert.spv
│ │ │ ├── TexturedQuadWithMultiplyColor.frag.spv
│ │ │ ├── ToneMapACES.comp.spv
│ │ │ ├── ToneMapExtendedReinhardLuminance.comp.spv
│ │ │ ├── ToneMapHable.comp.spv
│ │ │ └── ToneMapReinhard.comp.spv
│ │ └── Source
│ │ ├── CustomSampling.frag.hlsl
│ │ ├── DepthOutline.frag.hlsl
│ │ ├── FillTexture.comp.hlsl
│ │ ├── Fullscreen.vert.hlsl
│ │ ├── GradientTexture.comp.hlsl
│ │ ├── LinearToSRGB.comp.hlsl
│ │ ├── LinearToST2084.comp.hlsl
│ │ ├── PositionColor.vert.hlsl
│ │ ├── PositionColorInstanced.vert.hlsl
│ │ ├── PositionColorTransform.vert.hlsl
│ │ ├── PullSpriteBatch.vert.hlsl
│ │ ├── RawTriangle.vert.hlsl
│ │ ├── Skybox.frag.hlsl
│ │ ├── Skybox.vert.hlsl
│ │ ├── SolidColor.frag.hlsl
│ │ ├── SolidColorDepth.frag.hlsl
│ │ ├── SpriteBatch.comp.hlsl
│ │ ├── TexturedQuad.comp.hlsl
│ │ ├── TexturedQuad.frag.hlsl
│ │ ├── TexturedQuad.vert.hlsl
│ │ ├── TexturedQuadArray.frag.hlsl
│ │ ├── TexturedQuadColor.frag.hlsl
│ │ ├── TexturedQuadColorWithMatrix.vert.hlsl
│ │ ├── TexturedQuadWithMatrix.vert.hlsl
│ │ ├── TexturedQuadWithMultiplyColor.frag.hlsl
│ │ ├── ToneMapACES.comp.hlsl
│ │ ├── ToneMapExtendedReinhardLuminance.comp.hlsl
│ │ ├── ToneMapHable.comp.hlsl
│ │ ├── ToneMapReinhard.comp.hlsl
│ │ └── compile.sh
├── DialogExample.hs
├── EventsExample.hs
├── FilesystemExample.hs
├── GPUAnimatedQuadExample.hs
├── GPUBasicComputeExample.hs
├── GPUClear3DSliceExample.hs
├── GPUClearExample.hs
├── GPUComputeSamplerExample.hs
├── GPUComputeUniformsExample.hs
├── GPUCopyAndReadbackExample.hs
├── GPUCopyConsistencyExample.hs
├── GPUCullExample.hs
├── GPUCustomSamplingExample.hs
├── GPUDrawIndirectExample.hs
├── GPUInstancedExample.hs
├── GPUMultiWindowExample.hs
├── GPURawTriangleExample.hs
├── GPUStencilExample.hs
├── GPUTexturedQuadExample.hs
├── GPUTonemappingExample.hs
├── GPUVertexBufferExample.hs
├── GUIDExample.hs
├── GamepadExample.hs
├── HapticExample.hs
├── HintsExample.hs
├── InitExample.hs
├── LocaleExample.hs
├── MessageBoxExample.hs
├── PlatformExample.hs
├── PowerExample.hs
├── ProcessExample.hs
├── RectExample.hs
├── RenderExample.hs
├── SensorExample.hs
├── StorageExample.hs
├── SystemExample.hsc
├── TimeExample.hs
├── TimerExample.hs
├── TouchDeviceExample.hs
├── TrayExample.hs
└── WAVExample.hs
├── hie.yaml
├── include
├── helpers.h
└── stb_image.h
├── sdl3.cabal
├── src
├── GPUCommon.hs
├── SDL.hs
└── SDL
│ ├── Assert.hsc
│ ├── AsyncIO.hsc
│ ├── Atomic.hs
│ ├── Audio.hsc
│ ├── Bits.hs
│ ├── BlendMode.hsc
│ ├── CPUInfo.hsc
│ ├── Camera.hsc
│ ├── Clipboard.hs
│ ├── Dialog.hsc
│ ├── Endian.hsc
│ ├── Error.hs
│ ├── Events.hsc
│ ├── Filesystem.hsc
│ ├── GPU.hsc
│ ├── GUID.hsc
│ ├── Gamepad.hsc
│ ├── Haptic.hsc
│ ├── Hidapi.hsc
│ ├── Hints.hsc
│ ├── IOStream.hs
│ ├── Init.hsc
│ ├── Joystick.hsc
│ ├── Keyboard.hsc
│ ├── Keycode.hsc
│ ├── LoadSO.hsc
│ ├── Locale.hsc
│ ├── Log.hsc
│ ├── MessageBox.hsc
│ ├── Metal.hsc
│ ├── Misc.hsc
│ ├── Mouse.hsc
│ ├── Mutex.hs
│ ├── Pen.hsc
│ ├── Pixels.hsc
│ ├── Platform.hsc
│ ├── Power.hsc
│ ├── Process.hsc
│ ├── Properties.hs
│ ├── Rect.hsc
│ ├── Render.hsc
│ ├── Scancode.hsc
│ ├── Sensor.hsc
│ ├── Stdinc.hs
│ ├── Storage.hsc
│ ├── Surface.hsc
│ ├── System.hsc
│ ├── Thread.hsc
│ ├── Time.hsc
│ ├── Timer.hsc
│ ├── Touch.hsc
│ ├── Tray.hsc
│ ├── Version.hsc
│ └── Video.hsc
└── test
├── binding-checker.hs
└── validator.md
/.github/generate-binding-status.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Generate SDL3 Binding Status for README
4 | # =======================================
5 | # This script runs the binding checker and generates a status table
6 | # to be included in the README.md file.
7 |
8 | set -e
9 |
10 | echo "Generating SDL3 binding status..." >&2
11 |
12 | # Check if cabal and binding-checker are available
13 | if ! command -v cabal >/dev/null 2>&1; then
14 | echo "Error: cabal not found. Cannot generate binding status." >&2
15 | exit 1
16 | fi
17 |
18 | # Build the binding checker
19 | echo "Building binding checker..." >&2
20 | cabal build exe:binding-checker -f-pkgconfig >/dev/null 2>&1
21 |
22 | # Find SDL3 headers
23 | SDL_PATHS="/usr/local/include/SDL3:/usr/include/SDL3:/opt/homebrew/include/SDL3"
24 | sdl_dir=""
25 |
26 | IFS=':' read -ra PATHS <<< "$SDL_PATHS"
27 | for path in "${PATHS[@]}"; do
28 | if [[ -d "$path" ]]; then
29 | sdl_dir="$path"
30 | break
31 | fi
32 | done
33 |
34 | if [[ -z "$sdl_dir" ]]; then
35 | echo "Error: No SDL3 headers found in standard locations" >&2
36 | echo "Please install SDL3 development files first." >&2
37 | echo "Searched paths: $SDL_PATHS" >&2
38 | exit 1
39 | fi
40 |
41 | # Create temporary directory for results
42 | TEMP_DIR=$(mktemp -d)
43 | trap "rm -rf $TEMP_DIR" EXIT
44 |
45 | # Get list of modules from source directory
46 | modules=()
47 | for file in src/SDL/*.hsc src/SDL/*.hs; do
48 | if [[ -f "$file" ]]; then
49 | basename=$(basename "$file" .hsc)
50 | basename=$(basename "$basename" .hs)
51 | modules+=("$basename")
52 | fi
53 | done
54 |
55 | # Check if we found any modules
56 | if [[ ${#modules[@]} -eq 0 ]]; then
57 | echo "Error: No Haskell binding modules found in src/SDL/" >&2
58 | exit 1
59 | fi
60 |
61 | # Check each module and collect results
62 | echo "Checking bindings for ${#modules[@]} modules..." >&2
63 |
64 | results_file="$TEMP_DIR/results.txt"
65 | total_headers=0
66 | total_broken=0
67 | headers_with_bindings=0
68 | headers_complete=0
69 |
70 | for module in "${modules[@]}"; do
71 | # Convert module name to header name (e.g., "Camera" -> "SDL_camera.h")
72 | module_lower=$(echo "$module" | tr '[:upper:]' '[:lower:]')
73 | header_name="SDL_${module_lower}.h"
74 | header_path="$sdl_dir/$header_name"
75 |
76 | total_headers=$((total_headers + 1))
77 |
78 | # Run binding checker on individual header
79 | if [[ -f "$header_path" ]]; then
80 | if ! output=$(echo "$header_path" | cabal exec -f-pkgconfig binding-checker 2>&1); then
81 | # If binding checker fails, it's a critical error
82 | echo "Error: Binding checker failed for $header_path" >&2
83 | echo "Output: $output" >&2
84 | exit 1
85 | fi
86 | else
87 | # Header doesn't exist, assume no bindings needed
88 | echo "SDL_${module_lower}:❌ No header" >> "$results_file"
89 | continue
90 | fi
91 |
92 | if echo "$output" | grep -q "No binding file found"; then
93 | echo "SDL_${module_lower}:❌ No bindings" >> "$results_file"
94 | elif echo "$output" | grep -q "✓ All bindings OK"; then
95 | echo "SDL_${module_lower}:✅ Complete" >> "$results_file"
96 | headers_complete=$((headers_complete + 1))
97 | headers_with_bindings=$((headers_with_bindings + 1))
98 | elif echo "$output" | grep -q "✗ Found.*broken bindings"; then
99 | count=$(echo "$output" | grep -o "Found [0-9]* broken bindings" | grep -o "[0-9]*" || echo "0")
100 | echo "SDL_${module_lower}:⚠️ $count missing" >> "$results_file"
101 | total_broken=$((total_broken + count))
102 | headers_with_bindings=$((headers_with_bindings + 1))
103 | else
104 | echo "SDL_${module_lower}:❓ Unknown" >> "$results_file"
105 | fi
106 | done
107 |
108 | # Calculate statistics
109 | completion_percentage=0
110 | if [[ $headers_with_bindings -gt 0 ]]; then
111 | completion_percentage=$(( (headers_complete * 100) / headers_with_bindings ))
112 | fi
113 |
114 | # Generate timestamp
115 | timestamp=$(date -u +"%Y-%m-%d %H:%M UTC")
116 |
117 | # Generate the binding status section
118 | echo "## 📊 Binding Status"
119 | echo ""
120 | echo "*Last updated: $timestamp*"
121 | echo ""
122 | echo "### Summary"
123 | echo "- **Total Modules**: $total_headers"
124 | echo "- **Modules with Bindings**: $headers_with_bindings"
125 | echo "- **Complete Bindings**: $headers_complete"
126 | echo "- **Missing Functions**: $total_broken"
127 | echo "- **Completion Rate**: ${completion_percentage}%"
128 | echo ""
129 | echo "### Status by Module"
130 | echo ""
131 | echo "| Module | Status |"
132 | echo "|--------|--------|"
133 |
134 | # Sort results and create simple two-column table
135 | sorted_results=$(sort "$results_file")
136 |
137 | while IFS= read -r line; do
138 | module=$(echo "$line" | cut -d: -f1)
139 | status=$(echo "$line" | cut -d: -f2-)
140 | echo "| \`$module\` | $status |"
141 | done <<< "$sorted_results"
142 |
143 | echo ""
144 | echo "### Legend"
145 | echo "- ✅ **Complete**: All functions from the header are bound"
146 | echo "- ⚠️ **X missing**: Header has bindings but X functions are missing"
147 | echo "- ❌ **No bindings**: No Haskell bindings exist for this header"
148 | echo "- ❓ **Unknown**: Status could not be determined"
149 | echo ""
150 | echo "### Notes"
151 | echo "- Status reflects core SDL3 headers (test/internal headers excluded)"
152 | echo "- Missing function details are available in the \`broken/\` directory after running the binding checker"
153 | echo "- Use \`./check-sdl-bindings -i\` for interactive binding status checking"
154 | echo "- Some modules may intentionally have no bindings if not applicable to Haskell"
155 | echo ""
156 |
157 | echo "Binding status generated successfully! Total: $total_headers modules, $headers_complete complete, $total_broken missing functions" >&2
158 |
--------------------------------------------------------------------------------
/.github/template.html:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 | $title$
18 |
150 |
151 |
152 | $body$
153 |
154 |
155 |
--------------------------------------------------------------------------------
/.github/update-readme.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Update README with SDL3 Binding Status
4 | # ======================================
5 | # This script generates binding status and inserts it into README.md
6 |
7 | set -e
8 |
9 | # Colors for output
10 | RED='\033[0;31m'
11 | GREEN='\033[0;32m'
12 | YELLOW='\033[1;33m'
13 | BLUE='\033[0;34m'
14 | NC='\033[0m' # No Color
15 |
16 | echo "Updating README.md with current binding status..."
17 |
18 | # Pull latest changes from current branch
19 | echo "Pulling latest changes from current branch..."
20 | git pull origin $(git branch --show-current)
21 |
22 | # Extract SDL commit hash from CI workflow
23 | SDL_COMMIT=""
24 | if [[ -f ".github/workflows/deploy-readme.yml" ]]; then
25 | SDL_COMMIT=$(grep -o 'git checkout [a-f0-9]\{40\}' .github/workflows/deploy-readme.yml | cut -d' ' -f3)
26 | fi
27 |
28 | # Check if README.md exists
29 | if [[ ! -f "README.md" ]]; then
30 | echo -e "${RED}Error: README.md not found${NC}"
31 | exit 1
32 | fi
33 |
34 | # Create backup
35 | cp README.md README.md.backup
36 | echo "Created backup: README.md.backup"
37 |
38 | # Generate binding status
39 | echo "Generating binding status..."
40 | binding_status=$(bash .github/generate-binding-status.sh 2>/dev/null)
41 |
42 | # Add SDL commit info to binding status if available
43 | if [[ -n "$SDL_COMMIT" ]]; then
44 | # Insert SDL commit line after the date line
45 | binding_status=$(echo "$binding_status" | sed "/\*Last updated:/a\\
46 | \\
47 | *SDL3 commit: \`$SDL_COMMIT\`*")
48 | fi
49 |
50 | if [[ -z "$binding_status" ]]; then
51 | echo -e "${RED}Error: Failed to generate binding status${NC}"
52 | exit 1
53 | fi
54 |
55 | # Create temporary file for the new README
56 | TEMP_README=$(mktemp)
57 | trap "rm -f $TEMP_README" EXIT
58 |
59 | # Check if binding status section already exists
60 | if grep -q "## 📊 Binding Status" README.md; then
61 | echo "Updating existing binding status section..."
62 |
63 | # Extract content before binding status
64 | sed '/## 📊 Binding Status/,$d' README.md > "$TEMP_README"
65 |
66 | # Add new binding status
67 | echo "$binding_status" >> "$TEMP_README"
68 |
69 | # Find and add content after binding status (if any)
70 | # Look for the next ## section after binding status
71 | in_status=false
72 | found_next=false
73 | while IFS= read -r line; do
74 | if [[ "$line" == "## 📊 Binding Status" ]]; then
75 | in_status=true
76 | continue
77 | elif [[ "$in_status" == true && "$line" =~ ^##[[:space:]] ]]; then
78 | found_next=true
79 | echo "$line" >> "$TEMP_README"
80 | elif [[ "$found_next" == true ]]; then
81 | echo "$line" >> "$TEMP_README"
82 | fi
83 | done < README.md
84 |
85 | else
86 | echo "Adding new binding status section..."
87 |
88 | # Find a good place to insert (after installation, before examples, or at end)
89 | if grep -q "^## " README.md; then
90 | # Find the first occurrence of ## Examples, ## Usage, ## Documentation, or ## Contributing
91 | insert_line=$(grep -n "^## \(Examples\|Usage\|Documentation\|Contributing\|License\)" README.md | head -1 | cut -d: -f1)
92 |
93 | if [[ -n "$insert_line" ]]; then
94 | # Insert before this section
95 | head -n $((insert_line - 1)) README.md > "$TEMP_README"
96 | echo "" >> "$TEMP_README"
97 | echo "$binding_status" >> "$TEMP_README"
98 | echo "" >> "$TEMP_README"
99 | tail -n +$insert_line README.md >> "$TEMP_README"
100 | else
101 | # Append at end
102 | cat README.md > "$TEMP_README"
103 | echo "" >> "$TEMP_README"
104 | echo "$binding_status" >> "$TEMP_README"
105 | fi
106 | else
107 | # No other sections, append at end
108 | cat README.md > "$TEMP_README"
109 | echo "" >> "$TEMP_README"
110 | echo "$binding_status" >> "$TEMP_README"
111 | fi
112 | fi
113 |
114 | # Replace original README with updated version
115 | mv "$TEMP_README" README.md
116 |
117 | echo -e "${GREEN}README.md updated successfully!${NC}"
118 |
119 | # Show what changed
120 | if command -v diff >/dev/null 2>&1; then
121 | echo -e "${BLUE}Changes made:${NC}"
122 | diff README.md.backup README.md || true
123 | else
124 | echo "Updated README.md with binding status"
125 | fi
126 |
127 | # Optional: validate the README still looks good
128 | if command -v wc >/dev/null 2>&1; then
129 | lines=$(wc -l < README.md)
130 | echo "Updated README.md has $lines lines"
131 | fi
132 |
133 | echo -e "${GREEN}README update complete!${NC}"
134 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | dist-*
3 | cabal-dev
4 | *.o
5 | *.hi
6 | *.hie
7 | *.chi
8 | *.chs.h
9 | *.dyn_o
10 | *.dyn_hi
11 | .hpc
12 | .hsenv
13 | .cabal-sandbox/
14 | cabal.sandbox.config
15 | *.prof
16 | *.aux
17 | *.hp
18 | *.eventlog
19 | .stack-work/
20 | cabal.project.local
21 | cabal.project.local~
22 | .HTF/
23 | .ghc.environment.*
24 | .ccls-cache/*
25 |
26 | # Generated directories
27 | broken/
28 |
29 | # Custom directories
30 | sdl/
31 |
32 | # Zed
33 | AGENTS.MD
34 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Revision history for sdl3
2 |
3 | ## 0.1.0.0 -- YYYY-mm-dd
4 |
5 | * First version. Released on an unsuspecting world.
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2025, Kyle Lukaszek
2 |
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above
11 | copyright notice, this list of conditions and the following
12 | disclaimer in the documentation and/or other materials provided
13 | with the distribution.
14 |
15 | * Neither the name of the copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived
17 | from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/cbits/helpers.c:
--------------------------------------------------------------------------------
1 | #include "../include/helpers.h"
2 |
3 | void wrapper_SDL_GUIDToString(Uint8 *guid_data, char *pszGUID, int cbGUID) {
4 | SDL_GUID guid;
5 | memcpy(guid.data, guid_data, 16);
6 | SDL_GUIDToString(guid, pszGUID, cbGUID);
7 | }
8 |
9 | void wrapper_SDL_StringToGUID(const char *pchGUID, Uint8 *guid_data) {
10 | SDL_GUID guid = SDL_StringToGUID(pchGUID);
11 | memcpy(guid_data, guid.data, 16);
12 | }
13 |
--------------------------------------------------------------------------------
/cbits/stb_image_wrapper.c:
--------------------------------------------------------------------------------
1 | // cbits/stb_image_wrapper.c
2 | #include "../include/helpers.h"
3 | #define STB_IMAGE_IMPLEMENTATION
4 | #define STBI_MALLOC SDL_malloc
5 | #define STBI_REALLOC SDL_realloc
6 | #define STBI_FREE SDL_free
7 | #define STBI_ONLY_HDR
8 | #include "../include/stb_image.h"
9 |
10 | // Wrapper function that Haskell will call
11 | // It takes the full path directly.
12 | float* hs_stbi_loadf_wrapper(const char* fullPath, int* pWidth, int* pHeight, int* pChannelsInFile, int desiredChannels) {
13 | return stbi_loadf(fullPath, pWidth, pHeight, pChannelsInFile, desiredChannels);
14 | }
15 |
--------------------------------------------------------------------------------
/examples/AudioExample.hs:
--------------------------------------------------------------------------------
1 | {-|
2 | Module : SDL.Audio
3 | Description : SDL audio functionality
4 | Copyright : (c) Kyle Lukaszek, 2025
5 | License : BSD3
6 |
7 | Plays an 8000Hz tone in F32 format.
8 |
9 | Tested on Linux with Pulse AND Alsa.
10 | Tested on Windows.
11 |
12 | For more details, refer to the official SDL3 documentation:
13 | https://wiki.libsdl.org/SDL3/CategoryAudio
14 | -}
15 |
16 | import Foreign
17 | import Foreign.C
18 | import qualified Data.ByteString as BS
19 | import Data.ByteString.Unsafe (unsafePackCStringLen)
20 | import SDL hiding (sin, round)
21 | import Control.Concurrent (threadDelay)
22 | import Foreign.Marshal.Array (withArray)
23 | import Foreign.Storable (sizeOf)
24 |
25 | -- | Main function to demonstrate SDL audio playback with a 1-second 440 Hz tone
26 | main :: IO ()
27 | main = do
28 | -- Initialize SDL with audio support
29 | sdlInit [SDL_INIT_AUDIO]
30 |
31 | -- Define the audio specification: 32-bit float, 1 channel (mono), 8000 Hz
32 | let spec = SDLAudioSpec SDL_AUDIO_F32 1 8000
33 |
34 | -- Open the default playback device stream with the specified spec and no callback
35 | maybeStream <- sdlOpenAudioDeviceStream SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK (Just spec) Nothing
36 | case maybeStream of
37 | Nothing -> putStrLn "Failed to open audio stream"
38 | Just stream -> do
39 | -- Resume the audio stream to start playback
40 | success <- sdlResumeAudioStreamDevice stream
41 | if not success
42 | then putStrLn "Failed to resume audio stream"
43 | else do
44 | -- Generate 8000 samples (1 second at 8000 Hz) of a 440 Hz sine wave with amplitude 0.5
45 | let samples = [0.5 * sin (2 * pi * 440 * fromIntegral i / 8000) | i <- [0..7999]] :: [Float]
46 |
47 | -- Convert samples to a ByteString and feed them into the audio stream
48 | withArray samples $ \ptr -> do
49 | let len = 8000 * sizeOf (undefined :: Float) -- Total byte length (8000 floats * 4 bytes each)
50 | bs <- unsafePackCStringLen (castPtr ptr, len)
51 | successPut <- sdlPutAudioStreamData stream bs
52 | if not successPut
53 | then putStrLn "Failed to put audio data into stream"
54 | else do
55 | -- Wait 5 seconds to ensure the 1-second tone plays fully
56 | threadDelay (5 * 1000000) -- 5 seconds in microseconds
57 |
58 | -- Clean up by destroying the audio stream (also closes the associated device)
59 | sdlDestroyAudioStream stream
60 | sdlLog "Success!"
61 |
62 | sdlQuit
63 |
--------------------------------------------------------------------------------
/examples/CPUInfoExample.hs:
--------------------------------------------------------------------------------
1 | import SDL
2 |
3 | -- Really simple test.
4 |
5 | main :: IO ()
6 | main = do
7 | cores <- sdlGetNumLogicalCPUCores
8 | hasSSE <- sdlHasSSE
9 | ram <- sdlGetSystemRAM
10 | sdlLog $ "System has " ++ show cores ++ " logical cores"
11 | sdlLog $ "SSE support: " ++ show hasSSE
12 | sdlLog $ "RAM: " ++ show ram ++ " MiB"
13 |
--------------------------------------------------------------------------------
/examples/CameraExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad
5 | import Foreign.Marshal.Alloc (alloca)
6 | import Foreign.Storable (peek)
7 | import System.Exit (exitFailure, exitSuccess)
8 |
9 | main :: IO ()
10 | main = do
11 | -- Check compiled version
12 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
13 | when (sdlVersionAtLeast 3 3 0) $
14 | sdlLog "Compiled with at least SDL 3.3.0"
15 |
16 | -- Get linked version
17 | linkedVersion <- sdlGetVersion
18 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
19 |
20 | -- Initialize SDL with camera subsystem
21 | initSuccess <- sdlInit [SDL_INIT_CAMERA]
22 | unless initSuccess $ do
23 | sdlLog "Failed to initialize SDL with camera support!"
24 | err <- sdlGetError
25 | sdlLog $ "Error: " ++ err
26 | exitFailure
27 |
28 | -- Check initialized subsystems
29 | initializedSystems <- sdlWasInit []
30 | sdlLog "Initialized subsystems:"
31 | mapM_ printSubsystem initializedSystems
32 |
33 | -- List available cameras
34 | sdlLog "Enumerating cameras..."
35 | cameras <- sdlGetCameras
36 | if null cameras
37 | then sdlLog "No cameras found."
38 | else do
39 | sdlLog $ "Found " ++ show (length cameras) ++ " camera(s):"
40 | forM_ cameras $ \camId -> do
41 | mName <- sdlGetCameraName camId
42 | pos <- sdlGetCameraPosition camId
43 | sdlLog $ " - ID: " ++ show camId ++
44 | ", Name: " ++ maybe "Unknown" id mName ++
45 | ", Position: " ++ show pos
46 |
47 | -- Open the first camera
48 | let firstCamera = head cameras
49 | sdlLog $ "Opening camera with ID " ++ show firstCamera ++ "..."
50 | mCamera <- sdlOpenCamera firstCamera Nothing
51 | case mCamera of
52 | Nothing -> do
53 | sdlLog "Failed to open camera!"
54 | err <- sdlGetError
55 | sdlLog $ "Error: " ++ err
56 | Just camera -> do
57 | sdlLog "Camera opened successfully."
58 |
59 | -- Check permission state
60 | permState <- sdlGetCameraPermissionState camera
61 | sdlLog $ "Permission state: " ++
62 | case permState of
63 | 1 -> "Approved"
64 | -1 -> "Denied"
65 | _ -> "Pending"
66 |
67 | -- Get camera format
68 | mFormat <- sdlGetCameraFormat camera
69 | case mFormat of
70 | Nothing -> sdlLog "Failed to get camera format."
71 | Just fmt -> sdlLog $ "Camera format: " ++ show fmt
72 |
73 | -- Close the camera
74 | sdlCloseCamera camera
75 | sdlLog "Camera closed."
76 |
77 | -- Quit SDL
78 | sdlQuit
79 | sdlLog "SDL shutdown complete."
80 | exitSuccess
81 |
82 | -- Helper function to print subsystem names
83 | printSubsystem :: SDLInitFlags -> IO ()
84 | printSubsystem flag = sdlLog $ " - " ++ case flag of
85 | SDL_INIT_AUDIO -> "Audio"
86 | SDL_INIT_VIDEO -> "Video"
87 | SDL_INIT_JOYSTICK -> "Joystick"
88 | SDL_INIT_HAPTIC -> "Haptic"
89 | SDL_INIT_GAMEPAD -> "Gamepad"
90 | SDL_INIT_EVENTS -> "Events"
91 | SDL_INIT_SENSOR -> "Sensor"
92 | SDL_INIT_CAMERA -> "Camera"
93 | _ -> "Unknown subsystem"
94 |
--------------------------------------------------------------------------------
/examples/ClipboardExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad (when, unless)
5 | import System.Exit (exitFailure, exitSuccess)
6 |
7 | main :: IO ()
8 | main = do
9 | -- Initialize SDL with video and events subsystems
10 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
11 | unless initSuccess $ do
12 | sdlLog "Failed to initialize SDL!"
13 | exitFailure
14 |
15 | -- Check initialized subsystems
16 | initializedSystems <- sdlWasInit []
17 | sdlLog "Initialized subsystems:"
18 | mapM_ printSubsystem initializedSystems
19 |
20 | -- Set some text to the clipboard
21 | success <- sdlSetClipboardText "Hello, Clipboard!"
22 | when success $ sdlLog "Successfully set clipboard text"
23 |
24 | -- Check if clipboard has text
25 | hasText <- sdlHasClipboardText
26 | sdlLog $ "Clipboard has text: " ++ show hasText
27 |
28 | -- Retrieve text from clipboard
29 | clipboardContent <- sdlGetClipboardText
30 | case clipboardContent of
31 | Just text -> sdlLog $ "Clipboard contents: " ++ text
32 | Nothing -> sdlLog "Failed to retrieve clipboard text"
33 |
34 | -- Demonstrate primary selection (on systems that support it)
35 | _ <- sdlSetPrimarySelectionText "Primary Selection Text"
36 | primaryText <- sdlGetPrimarySelectionText
37 | case primaryText of
38 | Just text -> sdlLog $ "Primary selection: " ++ text
39 | Nothing -> sdlLog "Failed to retrieve primary selection"
40 |
41 | -- Get clipboard MIME types
42 | mimeTypes <- sdlGetClipboardMimeTypes
43 | sdlLog "Available MIME types:"
44 | mapM_ sdlLog mimeTypes
45 |
46 | sdlQuit
47 | exitSuccess
48 |
49 | -- Helper function to print subsystem names
50 | printSubsystem :: SDLInitFlags -> IO ()
51 | printSubsystem flag = sdlLog $ " - " ++ case flag of
52 | SDL_INIT_AUDIO -> "Audio"
53 | SDL_INIT_VIDEO -> "Video"
54 | SDL_INIT_JOYSTICK -> "Joystick"
55 | SDL_INIT_HAPTIC -> "Haptic"
56 | SDL_INIT_GAMEPAD -> "Gamepad"
57 | SDL_INIT_EVENTS -> "Events"
58 | SDL_INIT_SENSOR -> "Sensor"
59 | SDL_INIT_CAMERA -> "Camera"
60 | _ -> "Unknown subsystem"
61 |
--------------------------------------------------------------------------------
/examples/Content/Audio/sound.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Audio/sound.wav
--------------------------------------------------------------------------------
/examples/Content/Images/armadillo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/armadillo.png
--------------------------------------------------------------------------------
/examples/Content/Images/astc/10x10.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/10x10.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/10x5.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/10x5.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/10x6.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/10x6.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/10x8.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/10x8.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/12x10.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/12x10.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/12x12.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/12x12.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/4x4.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/4x4.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/5x4.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/5x4.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/5x5.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/5x5.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/6x5.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/6x5.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/6x6.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/6x6.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/8x5.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/8x5.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/8x6.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/8x6.astc
--------------------------------------------------------------------------------
/examples/Content/Images/astc/8x8.astc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/astc/8x8.astc
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC1.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC1.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC1_SRGB.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC1_SRGB.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC2.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC2.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC2_SRGB.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC2_SRGB.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC3.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC3.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC3_SRGB.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC3_SRGB.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC4.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC4.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC5.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC5.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC6H_S.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC6H_S.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC6H_U.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC6H_U.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC7.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC7.dds
--------------------------------------------------------------------------------
/examples/Content/Images/bcn/BC7_SRGB.dds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/bcn/BC7_SRGB.dds
--------------------------------------------------------------------------------
/examples/Content/Images/cube0.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube0.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube0mip1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube0mip1.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube1.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube1mip1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube1mip1.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube2.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube2mip1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube2mip1.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube3.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube3.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube3mip1.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube3mip1.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube4.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube4.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/cube5.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/cube5.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/latency.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/latency.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/memorial.hdr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/memorial.hdr
--------------------------------------------------------------------------------
/examples/Content/Images/ravioli.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/ravioli.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/ravioli_atlas.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/ravioli_atlas.bmp
--------------------------------------------------------------------------------
/examples/Content/Images/ravioli_inverted.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Images/ravioli_inverted.bmp
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/CustomSampling.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/CustomSampling.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/DepthOutline.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/DepthOutline.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/FillTexture.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/FillTexture.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/Fullscreen.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/Fullscreen.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/GradientTexture.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/GradientTexture.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/LinearToSRGB.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/LinearToSRGB.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/LinearToST2084.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/LinearToST2084.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/PositionColor.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/PositionColor.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/PositionColorInstanced.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/PositionColorInstanced.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/PositionColorTransform.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/PositionColorTransform.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/PullSpriteBatch.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/PullSpriteBatch.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/RawTriangle.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/RawTriangle.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/Skybox.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/Skybox.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/Skybox.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/Skybox.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/SolidColor.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/SolidColor.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/SolidColorDepth.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/SolidColorDepth.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/SpriteBatch.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/SpriteBatch.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuad.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuad.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuad.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuad.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuad.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuad.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuadArray.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuadArray.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuadColor.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuadColor.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuadColorWithMatrix.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuadColorWithMatrix.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuadWithMatrix.vert.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuadWithMatrix.vert.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/TexturedQuadWithMultiplyColor.frag.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/TexturedQuadWithMultiplyColor.frag.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/ToneMapACES.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/ToneMapACES.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/ToneMapExtendedReinhardLuminance.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/ToneMapExtendedReinhardLuminance.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/ToneMapHable.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/ToneMapHable.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/DXIL/ToneMapReinhard.comp.dxil:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/DXIL/ToneMapReinhard.comp.dxil
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/CustomSampling.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UBO
7 | {
8 | int mode;
9 | };
10 |
11 | struct main0_out
12 | {
13 | float4 out_var_SV_Target0 [[color(0)]];
14 | };
15 |
16 | struct main0_in
17 | {
18 | float2 in_var_TEXCOORD0 [[user(locn0)]];
19 | };
20 |
21 | fragment main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]], texture2d Texture [[texture(0)]])
22 | {
23 | main0_out out = {};
24 | float4 _74;
25 | do
26 | {
27 | uint2 _37 = uint2(Texture.get_width(), Texture.get_height());
28 | int2 _44 = int2(float2(float(_37.x), float(_37.y)) * in.in_var_TEXCOORD0);
29 | float4 _46 = Texture.read(uint2(uint2(_44)), 0u);
30 | if (UBO.mode == 0)
31 | {
32 | _74 = _46;
33 | break;
34 | }
35 | else
36 | {
37 | _74 = ((((_46 * 0.20000000298023223876953125) + (Texture.read(uint2(uint2(_44 + int2(0, 1))), 0u) * 0.20000000298023223876953125)) + (Texture.read(uint2(uint2(_44 + int2(-1, 0))), 0u) * 0.20000000298023223876953125)) + (Texture.read(uint2(uint2(_44 + int2(0, -1))), 0u) * 0.20000000298023223876953125)) + (Texture.read(uint2(uint2(_44 + int2(1, 0))), 0u) * 0.20000000298023223876953125);
38 | break;
39 | }
40 | break; // unreachable workaround
41 | } while(false);
42 | out.out_var_SV_Target0 = _74;
43 | return out;
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/DepthOutline.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_SV_Target0 [[color(0)]];
9 | };
10 |
11 | struct main0_in
12 | {
13 | float2 in_var_TEXCOORD0 [[user(locn0)]];
14 | };
15 |
16 | fragment main0_out main0(main0_in in [[stage_in]], texture2d ColorTexture [[texture(0)]], texture2d DepthTexture [[texture(1)]], sampler ColorSampler [[sampler(0)]], sampler DepthSampler [[sampler(1)]])
17 | {
18 | main0_out out = {};
19 | float4 _38 = ColorTexture.sample(ColorSampler, in.in_var_TEXCOORD0);
20 | float4 _42 = DepthTexture.sample(DepthSampler, in.in_var_TEXCOORD0);
21 | float _43 = _42.x;
22 | uint2 _44 = uint2(DepthTexture.get_width(), DepthTexture.get_height());
23 | float _46 = float(_44.x);
24 | float _48 = float(_44.y);
25 | float2 _50 = float2(1.0 / _46, 0.0);
26 | float2 _58 = float2((-1.0) / _46, 0.0);
27 | float2 _66 = float2(0.0, 1.0 / _48);
28 | float2 _74 = float2(0.0, (-1.0) / _48);
29 | float3 _117 = mix(mix(_38.xyz, float3(0.0), float3(step(0.20000000298023223876953125, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_50 * 2.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_58 * 2.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_66 * 2.0))).x - _43, DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_74 * 2.0))).x - _43)))))), float3(1.0), float3(step(0.20000000298023223876953125, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_50 * 1.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_58 * 1.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_66 * 1.0))).x - _43, DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (_74 * 1.0))).x - _43))))));
30 | out.out_var_SV_Target0 = float4(_117, _38.w);
31 | return out;
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/FillTexture.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d outImage [[texture(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | outImage.write(float4(1.0, 1.0, 0.0, 1.0), uint2(uint2(int2(gl_GlobalInvocationID.xy))));
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/Fullscreen.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float2 out_var_TEXCOORD0 [[user(locn0)]];
9 | float4 gl_Position [[position]];
10 | };
11 |
12 | vertex main0_out main0(uint gl_VertexIndex [[vertex_id]])
13 | {
14 | main0_out out = {};
15 | float2 _30 = float2(float((gl_VertexIndex << 1u) & 2u), float(gl_VertexIndex & 2u));
16 | out.out_var_TEXCOORD0 = _30;
17 | out.gl_Position = float4((_30 * float2(2.0, -2.0)) + float2(-1.0, 1.0), 0.0, 1.0);
18 | return out;
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/GradientTexture.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UBO
7 | {
8 | float ubo_time;
9 | };
10 |
11 | kernel void main0(constant type_UBO& UBO [[buffer(0)]], texture2d OutImage [[texture(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
12 | {
13 | uint2 _34 = uint2(OutImage.get_width(), OutImage.get_height());
14 | float2 _41 = float2(gl_GlobalInvocationID.xy);
15 | OutImage.write(float4(float3(0.5) + (cos((float3(UBO.ubo_time) + (_41 / float2(float(_34.x), float(_34.y))).xyx) + float3(0.0, 2.0, 4.0)) * 0.5), 1.0), uint2(uint2(int2(_41))));
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/LinearToSRGB.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d InImage [[texture(0)]], texture2d OutImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | uint2 _29 = uint2(int2(gl_GlobalInvocationID.xy));
9 | OutImage.write(float4(powr(abs(InImage.read(uint2(_29), 0u).xyz), float3(0.454545438289642333984375)), 1.0), uint2(_29));
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/LinearToST2084.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d InImage [[texture(0)]], texture2d OutImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | uint2 _53 = uint2(int2(gl_GlobalInvocationID.xy));
9 | float4 _55 = InImage.read(uint2(_53), 0u);
10 | float3 _61 = powr(abs(((_55.xyz * float3x3(float3(0.6274039745330810546875, 0.329281985759735107421875, 0.043313600122928619384765625), float3(0.06909699738025665283203125, 0.919539988040924072265625, 0.0113612003624439239501953125), float3(0.01639159955084323883056640625, 0.0880132019519805908203125, 0.895595014095306396484375))) * 200.0) * float3(9.9999997473787516355514526367188e-05)), float3(0.1593017578125));
11 | OutImage.write(float4(powr((float3(0.8359375) + (_61 * 18.8515625)) / (float3(1.0) + (_61 * 18.6875)), float3(78.84375)), _55.w), uint2(_53));
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/PositionColor.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_TEXCOORD0 [[user(locn0)]];
9 | float4 gl_Position [[position]];
10 | };
11 |
12 | struct main0_in
13 | {
14 | float3 in_var_TEXCOORD0 [[attribute(0)]];
15 | float4 in_var_TEXCOORD1 [[attribute(1)]];
16 | };
17 |
18 | vertex main0_out main0(main0_in in [[stage_in]])
19 | {
20 | main0_out out = {};
21 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1;
22 | out.gl_Position = float4(in.in_var_TEXCOORD0, 1.0);
23 | return out;
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/PositionColorInstanced.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_TEXCOORD0 [[user(locn0)]];
9 | float4 gl_Position [[position]];
10 | };
11 |
12 | struct main0_in
13 | {
14 | float3 in_var_TEXCOORD0 [[attribute(0)]];
15 | float4 in_var_TEXCOORD1 [[attribute(1)]];
16 | };
17 |
18 | vertex main0_out main0(main0_in in [[stage_in]], uint gl_InstanceIndex [[instance_id]])
19 | {
20 | main0_out out = {};
21 | float3 _30 = (in.in_var_TEXCOORD0 * 0.25) - float3(0.75, 0.75, 0.0);
22 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1;
23 | out.gl_Position = float4(_30.x + (float(gl_InstanceIndex % 4u) * 0.5), _30.y + (floor(float(gl_InstanceIndex / 4u)) * 0.5), _30.z, 1.0);
24 | return out;
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/PositionColorTransform.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UBO
7 | {
8 | float4x4 transform;
9 | };
10 |
11 | struct main0_out
12 | {
13 | float4 out_var_TEXCOORD0 [[user(locn0)]];
14 | float4 gl_Position [[position]];
15 | };
16 |
17 | struct main0_in
18 | {
19 | float3 in_var_TEXCOORD0 [[attribute(0)]];
20 | float4 in_var_TEXCOORD1 [[attribute(1)]];
21 | };
22 |
23 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]])
24 | {
25 | main0_out out = {};
26 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1;
27 | out.gl_Position = UBO.transform * float4(in.in_var_TEXCOORD0, 1.0);
28 | return out;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/PullSpriteBatch.vert.msl:
--------------------------------------------------------------------------------
1 | #pragma clang diagnostic ignored "-Wmissing-prototypes"
2 | #pragma clang diagnostic ignored "-Wmissing-braces"
3 |
4 | #include
5 | #include
6 |
7 | using namespace metal;
8 |
9 | template
10 | struct spvUnsafeArray
11 | {
12 | T elements[Num ? Num : 1];
13 |
14 | thread T& operator [] (size_t pos) thread
15 | {
16 | return elements[pos];
17 | }
18 | constexpr const thread T& operator [] (size_t pos) const thread
19 | {
20 | return elements[pos];
21 | }
22 |
23 | device T& operator [] (size_t pos) device
24 | {
25 | return elements[pos];
26 | }
27 | constexpr const device T& operator [] (size_t pos) const device
28 | {
29 | return elements[pos];
30 | }
31 |
32 | constexpr const constant T& operator [] (size_t pos) const constant
33 | {
34 | return elements[pos];
35 | }
36 |
37 | threadgroup T& operator [] (size_t pos) threadgroup
38 | {
39 | return elements[pos];
40 | }
41 | constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
42 | {
43 | return elements[pos];
44 | }
45 | };
46 |
47 | struct SpriteData
48 | {
49 | packed_float3 Position;
50 | float Rotation;
51 | float2 Scale;
52 | float2 Padding;
53 | float TexU;
54 | float TexV;
55 | float TexW;
56 | float TexH;
57 | float4 Color;
58 | };
59 |
60 | struct type_StructuredBuffer_SpriteData
61 | {
62 | SpriteData _m0[1];
63 | };
64 |
65 | struct type_UniformBlock
66 | {
67 | float4x4 ViewProjectionMatrix;
68 | };
69 |
70 | constant spvUnsafeArray _46 = spvUnsafeArray({ 0u, 1u, 2u, 3u, 2u, 1u });
71 | constant spvUnsafeArray _51 = spvUnsafeArray({ float2(0.0), float2(1.0, 0.0), float2(0.0, 1.0), float2(1.0) });
72 |
73 | struct main0_out
74 | {
75 | float2 out_var_TEXCOORD0 [[user(locn0)]];
76 | float4 out_var_TEXCOORD1 [[user(locn1)]];
77 | float4 gl_Position [[position]];
78 | };
79 |
80 | vertex main0_out main0(constant type_UniformBlock& UniformBlock [[buffer(0)]], const device type_StructuredBuffer_SpriteData& DataBuffer [[buffer(1)]], uint gl_VertexIndex [[vertex_id]])
81 | {
82 | main0_out out = {};
83 | uint _62 = gl_VertexIndex / 6u;
84 | uint _63 = gl_VertexIndex % 6u;
85 | float _82 = DataBuffer._m0[_62].TexU + DataBuffer._m0[_62].TexW;
86 | float _83 = DataBuffer._m0[_62].TexV + DataBuffer._m0[_62].TexH;
87 | spvUnsafeArray _88 = spvUnsafeArray({ float2(DataBuffer._m0[_62].TexU, DataBuffer._m0[_62].TexV), float2(_82, DataBuffer._m0[_62].TexV), float2(DataBuffer._m0[_62].TexU, _83), float2(_82, _83) });
88 | spvUnsafeArray _60 = _88;
89 | float _89 = cos(DataBuffer._m0[_62].Rotation);
90 | float _90 = sin(DataBuffer._m0[_62].Rotation);
91 | out.out_var_TEXCOORD0 = _60[_46[_63]];
92 | out.out_var_TEXCOORD1 = DataBuffer._m0[_62].Color;
93 | out.gl_Position = UniformBlock.ViewProjectionMatrix * float4((float2x2(float2(_89, _90), float2(-_90, _89)) * (_51[_46[_63]] * DataBuffer._m0[_62].Scale)) + float2(DataBuffer._m0[_62].Position[0], DataBuffer._m0[_62].Position[1]), DataBuffer._m0[_62].Position[2], 1.0);
94 | return out;
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/RawTriangle.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | constant float2 _25 = {};
7 | constant float4 _26 = {};
8 |
9 | struct main0_out
10 | {
11 | float4 out_var_TEXCOORD0 [[user(locn0)]];
12 | float4 gl_Position [[position]];
13 | };
14 |
15 | vertex main0_out main0(uint gl_VertexIndex [[vertex_id]])
16 | {
17 | main0_out out = {};
18 | float4 _47;
19 | float2 _48;
20 | if (gl_VertexIndex == 0u)
21 | {
22 | _47 = float4(1.0, 0.0, 0.0, 1.0);
23 | _48 = float2(-1.0);
24 | }
25 | else
26 | {
27 | float4 _45;
28 | float2 _46;
29 | if (gl_VertexIndex == 1u)
30 | {
31 | _45 = float4(0.0, 1.0, 0.0, 1.0);
32 | _46 = float2(1.0, -1.0);
33 | }
34 | else
35 | {
36 | bool _40 = gl_VertexIndex == 2u;
37 | _45 = select(_26, float4(0.0, 0.0, 1.0, 1.0), bool4(_40));
38 | _46 = select(_25, float2(0.0, 1.0), bool2(_40));
39 | }
40 | _47 = _45;
41 | _48 = _46;
42 | }
43 | out.out_var_TEXCOORD0 = _47;
44 | out.gl_Position = float4(_48, 0.0, 1.0);
45 | return out;
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/Skybox.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_SV_Target0 [[color(0)]];
9 | };
10 |
11 | struct main0_in
12 | {
13 | float3 in_var_TEXCOORD0 [[user(locn0)]];
14 | };
15 |
16 | fragment main0_out main0(main0_in in [[stage_in]], texturecube SkyboxTexture [[texture(0)]], sampler SkyboxSampler [[sampler(0)]])
17 | {
18 | main0_out out = {};
19 | out.out_var_SV_Target0 = SkyboxTexture.sample(SkyboxSampler, in.in_var_TEXCOORD0);
20 | return out;
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/Skybox.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UniformBlock
7 | {
8 | float4x4 MatrixTransform;
9 | };
10 |
11 | struct main0_out
12 | {
13 | float3 out_var_TEXCOORD0 [[user(locn0)]];
14 | float4 gl_Position [[position]];
15 | };
16 |
17 | struct main0_in
18 | {
19 | float3 in_var_TEXCOORD0 [[attribute(0)]];
20 | };
21 |
22 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]])
23 | {
24 | main0_out out = {};
25 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD0;
26 | out.gl_Position = UniformBlock.MatrixTransform * float4(in.in_var_TEXCOORD0, 1.0);
27 | return out;
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/SolidColor.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_SV_Target0 [[color(0)]];
9 | };
10 |
11 | struct main0_in
12 | {
13 | float4 in_var_TEXCOORD0 [[user(locn0)]];
14 | };
15 |
16 | fragment main0_out main0(main0_in in [[stage_in]])
17 | {
18 | main0_out out = {};
19 | out.out_var_SV_Target0 = in.in_var_TEXCOORD0;
20 | return out;
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/SolidColorDepth.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UBO
7 | {
8 | float NearPlane;
9 | float FarPlane;
10 | };
11 |
12 | struct main0_out
13 | {
14 | float4 out_var_SV_Target0 [[color(0)]];
15 | float gl_FragDepth [[depth(any)]];
16 | };
17 |
18 | struct main0_in
19 | {
20 | float4 in_var_TEXCOORD0 [[user(locn0)]];
21 | };
22 |
23 | fragment main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]], float4 gl_FragCoord [[position]])
24 | {
25 | main0_out out = {};
26 | out.out_var_SV_Target0 = in.in_var_TEXCOORD0;
27 | out.gl_FragDepth = (((2.0 * UBO.NearPlane) * UBO.FarPlane) / ((UBO.FarPlane + UBO.NearPlane) - (((gl_FragCoord.z * 2.0) - 1.0) * (UBO.FarPlane - UBO.NearPlane)))) / UBO.FarPlane;
28 | return out;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/SpriteBatch.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct SpriteComputeData
7 | {
8 | packed_float3 Position;
9 | float Rotation;
10 | float2 Scale;
11 | float2 Padding;
12 | float TexU;
13 | float TexV;
14 | float TexW;
15 | float TexH;
16 | float4 Color;
17 | };
18 |
19 | struct type_StructuredBuffer_SpriteComputeData
20 | {
21 | SpriteComputeData _m0[1];
22 | };
23 |
24 | struct SpriteVertex
25 | {
26 | float4 Position;
27 | float2 Texcoord;
28 | float4 Color;
29 | };
30 |
31 | struct type_RWStructuredBuffer_SpriteVertex
32 | {
33 | SpriteVertex _m0[1];
34 | };
35 |
36 | kernel void main0(const device type_StructuredBuffer_SpriteComputeData& ComputeBuffer [[buffer(0)]], device type_RWStructuredBuffer_SpriteVertex& VertexBuffer [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
37 | {
38 | float3 _54 = float3(ComputeBuffer._m0[gl_GlobalInvocationID.x].Position);
39 | float _56 = ComputeBuffer._m0[gl_GlobalInvocationID.x].Rotation;
40 | float2 _58 = ComputeBuffer._m0[gl_GlobalInvocationID.x].Scale;
41 | float _60 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexU;
42 | float _62 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexV;
43 | float _64 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexW;
44 | float _66 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexH;
45 | float4 _68 = ComputeBuffer._m0[gl_GlobalInvocationID.x].Color;
46 | float _74 = cos(_56);
47 | float _75 = sin(_56);
48 | float4x4 _86 = (float4x4(float4(1.0, 0.0, 0.0, 0.0), float4(0.0, 1.0, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(_54, 1.0)) * float4x4(float4(_74, _75, 0.0, 0.0), float4(-_75, _74, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(0.0, 0.0, 0.0, 1.0))) * float4x4(float4(_58.x, 0.0, 0.0, 0.0), float4(0.0, _58.y, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(0.0, 0.0, 0.0, 1.0));
49 | uint _88 = gl_GlobalInvocationID.x * 4u;
50 | VertexBuffer._m0[_88].Position = _86 * float4(0.0, 0.0, 0.0, 1.0);
51 | uint _91 = _88 + 1u;
52 | VertexBuffer._m0[_91].Position = _86 * float4(1.0, 0.0, 0.0, 1.0);
53 | uint _94 = _88 + 2u;
54 | VertexBuffer._m0[_94].Position = _86 * float4(0.0, 1.0, 0.0, 1.0);
55 | uint _97 = _88 + 3u;
56 | VertexBuffer._m0[_97].Position = _86 * float4(1.0, 1.0, 0.0, 1.0);
57 | VertexBuffer._m0[_88].Texcoord = float2(_60, _62);
58 | float _101 = _60 + _64;
59 | VertexBuffer._m0[_91].Texcoord = float2(_101, _62);
60 | float _104 = _62 + _66;
61 | VertexBuffer._m0[_94].Texcoord = float2(_60, _104);
62 | VertexBuffer._m0[_97].Texcoord = float2(_101, _104);
63 | VertexBuffer._m0[_88].Color = _68;
64 | VertexBuffer._m0[_91].Color = _68;
65 | VertexBuffer._m0[_94].Color = _68;
66 | VertexBuffer._m0[_97].Color = _68;
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuad.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UBO
7 | {
8 | float ubo_texcoord_multiplier;
9 | };
10 |
11 | kernel void main0(constant type_UBO& UBO [[buffer(0)]], texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], sampler inImageSampler [[sampler(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
12 | {
13 | uint2 _33 = uint2(inImage.get_width(), inImage.get_height());
14 | int2 _39 = int2(gl_GlobalInvocationID.xy);
15 | outImage.write(inImage.sample(inImageSampler, ((float2(_39) * UBO.ubo_texcoord_multiplier) / float2(float(_33.x), float(_33.y))), level(0.0)), uint2(uint2(_39)));
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuad.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_SV_Target0 [[color(0)]];
9 | };
10 |
11 | struct main0_in
12 | {
13 | float2 in_var_TEXCOORD0 [[user(locn0)]];
14 | };
15 |
16 | fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture [[texture(0)]], sampler Sampler [[sampler(0)]])
17 | {
18 | main0_out out = {};
19 | out.out_var_SV_Target0 = Texture.sample(Sampler, in.in_var_TEXCOORD0);
20 | return out;
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuad.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float2 out_var_TEXCOORD0 [[user(locn0)]];
9 | float4 gl_Position [[position]];
10 | };
11 |
12 | struct main0_in
13 | {
14 | float3 in_var_TEXCOORD0 [[attribute(0)]];
15 | float2 in_var_TEXCOORD1 [[attribute(1)]];
16 | };
17 |
18 | vertex main0_out main0(main0_in in [[stage_in]])
19 | {
20 | main0_out out = {};
21 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1;
22 | out.gl_Position = float4(in.in_var_TEXCOORD0, 1.0);
23 | return out;
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuadArray.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_SV_Target0 [[color(0)]];
9 | };
10 |
11 | struct main0_in
12 | {
13 | float2 in_var_TEXCOORD0 [[user(locn0)]];
14 | };
15 |
16 | fragment main0_out main0(main0_in in [[stage_in]], texture2d_array Texture [[texture(0)]], sampler Sampler [[sampler(0)]])
17 | {
18 | main0_out out = {};
19 | float3 _35 = float3(in.in_var_TEXCOORD0, float(uint(int(in.in_var_TEXCOORD0.y > 0.5))));
20 | out.out_var_SV_Target0 = Texture.sample(Sampler, _35.xy, uint(rint(_35.z)));
21 | return out;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuadColor.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct main0_out
7 | {
8 | float4 out_var_SV_Target0 [[color(0)]];
9 | };
10 |
11 | struct main0_in
12 | {
13 | float2 in_var_TEXCOORD0 [[user(locn0)]];
14 | float4 in_var_TEXCOORD1 [[user(locn1)]];
15 | };
16 |
17 | fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture [[texture(0)]], sampler Sampler [[sampler(0)]])
18 | {
19 | main0_out out = {};
20 | out.out_var_SV_Target0 = in.in_var_TEXCOORD1 * Texture.sample(Sampler, in.in_var_TEXCOORD0);
21 | return out;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuadColorWithMatrix.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UniformBlock
7 | {
8 | float4x4 MatrixTransform;
9 | };
10 |
11 | struct main0_out
12 | {
13 | float2 out_var_TEXCOORD0 [[user(locn0)]];
14 | float4 out_var_TEXCOORD1 [[user(locn1)]];
15 | float4 gl_Position [[position]];
16 | };
17 |
18 | struct main0_in
19 | {
20 | float4 in_var_TEXCOORD0 [[attribute(0)]];
21 | float2 in_var_TEXCOORD1 [[attribute(1)]];
22 | float4 in_var_TEXCOORD2 [[attribute(2)]];
23 | };
24 |
25 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]])
26 | {
27 | main0_out out = {};
28 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1;
29 | out.out_var_TEXCOORD1 = in.in_var_TEXCOORD2;
30 | out.gl_Position = UniformBlock.MatrixTransform * in.in_var_TEXCOORD0;
31 | return out;
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuadWithMatrix.vert.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UniformBlock
7 | {
8 | float4x4 MatrixTransform;
9 | };
10 |
11 | struct main0_out
12 | {
13 | float2 out_var_TEXCOORD0 [[user(locn0)]];
14 | float4 gl_Position [[position]];
15 | };
16 |
17 | struct main0_in
18 | {
19 | float4 in_var_TEXCOORD0 [[attribute(0)]];
20 | float2 in_var_TEXCOORD1 [[attribute(1)]];
21 | };
22 |
23 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]])
24 | {
25 | main0_out out = {};
26 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1;
27 | out.gl_Position = UniformBlock.MatrixTransform * in.in_var_TEXCOORD0;
28 | return out;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/TexturedQuadWithMultiplyColor.frag.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | struct type_UniformBlock
7 | {
8 | float4 MultiplyColor;
9 | };
10 |
11 | struct main0_out
12 | {
13 | float4 out_var_SV_Target0 [[color(0)]];
14 | };
15 |
16 | struct main0_in
17 | {
18 | float2 in_var_TEXCOORD0 [[user(locn0)]];
19 | };
20 |
21 | fragment main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]], texture2d Texture [[texture(0)]], sampler Sampler [[sampler(0)]])
22 | {
23 | main0_out out = {};
24 | out.out_var_SV_Target0 = UniformBlock.MultiplyColor * Texture.sample(Sampler, in.in_var_TEXCOORD0);
25 | return out;
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/ToneMapACES.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | uint2 _62 = uint2(int2(gl_GlobalInvocationID.xy));
9 | float3 _66 = inImage.read(uint2(_62), 0u).xyz * float3x3(float3(0.59719002246856689453125, 0.354579985141754150390625, 0.048229999840259552001953125), float3(0.075999997556209564208984375, 0.908339977264404296875, 0.0156599991023540496826171875), float3(0.0284000001847743988037109375, 0.13382999598979949951171875, 0.837769985198974609375));
10 | outImage.write(float4((((_66 * (_66 + float3(0.02457859925925731658935546875))) - float3(9.0537003416102379560470581054688e-05)) / ((_66 * ((_66 * 0.98372900485992431640625) + float3(0.4329510033130645751953125))) + float3(0.23808099329471588134765625))) * float3x3(float3(1.60475003719329833984375, -0.5310800075531005859375, -0.0736699998378753662109375), float3(-0.10208000242710113525390625, 1.108129978179931640625, -0.00604999996721744537353515625), float3(-0.00326999998651444911956787109375, -0.07276000082492828369140625, 1.0760200023651123046875)), 1.0), uint2(_62));
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/ToneMapExtendedReinhardLuminance.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | uint2 _31 = uint2(int2(gl_GlobalInvocationID.xy));
9 | float3 _34 = inImage.read(uint2(_31), 0u).xyz;
10 | float _35 = dot(_34, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
11 | outImage.write(float4(_34 * (((_35 * (1.0 + (_35 * 2.2818337583885295316576957702637e-06))) / (1.0 + _35)) / _35), 1.0), uint2(_31));
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/ToneMapHable.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | uint2 _40 = uint2(int2(gl_GlobalInvocationID.xy));
9 | float3 _44 = inImage.read(uint2(_40), 0u).xyz * 2.0;
10 | float3 _45 = _44 * 0.1500000059604644775390625;
11 | outImage.write(float4(((((_44 * (_45 + float3(0.0500000007450580596923828125))) + float3(0.0040000001899898052215576171875)) / ((_44 * (_45 + float3(0.5))) + float3(0.060000002384185791015625))) - float3(0.066666662693023681640625)) * float3(1.3790643215179443359375), 1.0), uint2(_40));
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/MSL/ToneMapReinhard.comp.msl:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace metal;
5 |
6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
7 | {
8 | uint2 _27 = uint2(int2(gl_GlobalInvocationID.xy));
9 | float3 _30 = inImage.read(uint2(_27), 0u).xyz;
10 | outImage.write(float4(_30 / (float3(1.0) + _30), 1.0), uint2(_27));
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/CustomSampling.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/CustomSampling.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/DepthOutline.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/DepthOutline.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/FillTexture.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/FillTexture.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/Fullscreen.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/Fullscreen.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/GradientTexture.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/GradientTexture.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/LinearToSRGB.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/LinearToSRGB.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/LinearToST2084.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/LinearToST2084.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/PositionColor.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/PositionColor.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/PositionColorInstanced.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/PositionColorInstanced.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/PositionColorTransform.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/PositionColorTransform.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/PullSpriteBatch.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/PullSpriteBatch.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/RawTriangle.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/RawTriangle.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/Skybox.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/Skybox.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/Skybox.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/Skybox.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/SolidColor.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/SolidColor.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/SolidColorDepth.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/SolidColorDepth.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/SpriteBatch.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/SpriteBatch.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuad.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuad.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuad.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuad.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuad.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuad.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadArray.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadArray.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadColor.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadColor.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadColorWithMatrix.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadColorWithMatrix.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadWithMatrix.vert.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadWithMatrix.vert.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadWithMultiplyColor.frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/TexturedQuadWithMultiplyColor.frag.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/ToneMapACES.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/ToneMapACES.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/ToneMapExtendedReinhardLuminance.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/ToneMapExtendedReinhardLuminance.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/ToneMapHable.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/ToneMapHable.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Compiled/SPIRV/ToneMapReinhard.comp.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klukaszek/sdl3-hs/3dc7e731321ff3f0b97b35f4ae50dc366b65334a/examples/Content/Shaders/Compiled/SPIRV/ToneMapReinhard.comp.spv
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/CustomSampling.frag.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UBO : register(b0, space3)
2 | {
3 | int mode : packoffset(c0);
4 | };
5 |
6 | Texture2D Texture : register(t0, space2);
7 |
8 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0
9 | {
10 | float w, h;
11 | Texture.GetDimensions(w, h);
12 | int2 texelPos = int2(float2(w, h) * TexCoord);
13 | float4 mainTexel = Texture[texelPos];
14 | if (mode == 0)
15 | {
16 | return mainTexel;
17 | }
18 | else
19 | {
20 | float4 bottomTexel = Texture[texelPos + int2(0, 1)];
21 | float4 leftTexel = Texture[texelPos + int2(-1, 0)];
22 | float4 topTexel = Texture[texelPos + int2(0, -1)];
23 | float4 rightTexel = Texture[texelPos + int2(1, 0)];
24 | return ((((mainTexel * 0.2f) + (bottomTexel * 0.2f)) + (leftTexel * 0.20000000298023223876953125f)) + (topTexel * 0.20000000298023223876953125f)) + (rightTexel * 0.2f);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/DepthOutline.frag.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D ColorTexture : register(t0, space2);
2 | SamplerState ColorSampler : register(s0, space2);
3 |
4 | Texture2D DepthTexture : register(t1, space2);
5 | SamplerState DepthSampler : register(s1, space2);
6 |
7 | // Gets the difference between a depth value and adjacent depth pixels
8 | // This is used to detect "edges", where the depth falls off.
9 | float GetDifference(float depth, float2 TexCoord, float distance)
10 | {
11 | float w, h;
12 | DepthTexture.GetDimensions(w, h);
13 |
14 | return
15 | max(DepthTexture.Sample(DepthSampler, TexCoord + float2(1.0 / w, 0) * distance).r - depth,
16 | max(DepthTexture.Sample(DepthSampler, TexCoord + float2(-1.0 / w, 0) * distance).r - depth,
17 | max(DepthTexture.Sample(DepthSampler, TexCoord + float2(0, 1.0 / h) * distance).r - depth,
18 | DepthTexture.Sample(DepthSampler, TexCoord + float2(0, -1.0 / h) * distance).r - depth)));
19 | }
20 |
21 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0
22 | {
23 | // get our color & depth value
24 | float4 color = ColorTexture.Sample(ColorSampler, TexCoord);
25 | float depth = DepthTexture.Sample(DepthSampler, TexCoord).r;
26 |
27 | // get the difference between the edges at 1px and 2px away
28 | float edge = step(0.2, GetDifference(depth, TexCoord, 1.0f));
29 | float edge2 = step(0.2, GetDifference(depth, TexCoord, 2.0f));
30 |
31 | // turn inner edges black
32 | float3 res = lerp(color.rgb, 0, edge2);
33 |
34 | // turn the outer edges white
35 | res = lerp(res, 1, edge);
36 |
37 | // combine results
38 | return float4(res, color.a);
39 | }
40 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/FillTexture.comp.hlsl:
--------------------------------------------------------------------------------
1 | RWTexture2D outImage : register(u0, space1);
2 |
3 | [numthreads(8, 8, 1)]
4 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
5 | {
6 | int2 coord = int2(GlobalInvocationID.xy);
7 | outImage[coord] = float4(1.0f, 1.0f, 0.0f, 1.0f);
8 | }
9 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/Fullscreen.vert.hlsl:
--------------------------------------------------------------------------------
1 | struct Output
2 | {
3 | float2 TexCoord : TEXCOORD0;
4 | float4 Position : SV_Position;
5 | };
6 |
7 | Output main(uint VertexIndex : SV_VertexID)
8 | {
9 | Output output;
10 | output.TexCoord = float2(float((VertexIndex << 1) & 2), float(VertexIndex & 2));
11 | output.Position = float4((output.TexCoord * float2(2.0f, -2.0f)) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
12 | return output;
13 | }
14 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/GradientTexture.comp.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UBO : register(b0, space2)
2 | {
3 | float ubo_time : packoffset(c0);
4 | };
5 |
6 | RWTexture2D OutImage : register(u0, space1);
7 |
8 | uint2 spvImageSize(RWTexture2D Tex, out uint Param)
9 | {
10 | uint2 ret;
11 | Tex.GetDimensions(ret.x, ret.y);
12 | Param = 0u;
13 | return ret;
14 | }
15 |
16 | [numthreads(8, 8, 1)]
17 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
18 | {
19 | float w, h;
20 | OutImage.GetDimensions(w, h);
21 | float2 size = float2(w, h);
22 | float2 coord = float2(GlobalInvocationID.xy);
23 | float2 uv = coord / size;
24 |
25 | float3 col = 0.5f.xxx + (cos((ubo_time.xxx + uv.xyx) + float3(0.0f, 2.0f, 4.0f)) * 0.5f);
26 | OutImage[int2(coord)] = float4(col, 1.0f);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/LinearToSRGB.comp.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D InImage : register(t0, space0);
2 | RWTexture2D OutImage : register(u0, space1);
3 |
4 | float3 LinearToSRGB(float3 color)
5 | {
6 | return pow(abs(color), float(1.0f/2.2f).xxx);
7 | }
8 |
9 | [numthreads(8, 8, 1)]
10 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
11 | {
12 | int2 coord = int2(GlobalInvocationID.xy);
13 | float4 inPixel = InImage[coord];
14 | float3 param = inPixel.xyz;
15 | float3 outColor = LinearToSRGB(param);
16 | OutImage[coord] = float4(outColor, 1.0f);
17 | }
18 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/LinearToST2084.comp.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D InImage : register(t0, space0);
2 | RWTexture2D OutImage : register(u0, space1);
3 |
4 | float3 NormalizeHDRSceneValue(float3 hdrSceneValue, float paperWhiteNits)
5 | {
6 | return (hdrSceneValue * paperWhiteNits) / 10000.0f.xxx;
7 | }
8 |
9 | float3 LinearToST2084(float3 normalizedLinearValue)
10 | {
11 | return pow((0.8359375f.xxx + (pow(abs(normalizedLinearValue), 0.1593017578125f.xxx) * 18.8515625f)) / (1.0f.xxx + (pow(abs(normalizedLinearValue), 0.1593017578125f.xxx) * 18.6875f)), 78.84375f.xxx);
12 | }
13 |
14 | float4 ConvertToHDR10(float4 hdrSceneValue, float paperWhiteNits)
15 | {
16 | float3 rec2020 = mul(float3x3(float3(0.6274039745330810546875f, 0.329281985759735107421875f, 0.043313600122928619384765625f), float3(0.06909699738025665283203125f, 0.919539988040924072265625f, 0.0113612003624439239501953125f), float3(0.01639159955084323883056640625f, 0.0880132019519805908203125f, 0.895595014095306396484375f)), hdrSceneValue.xyz);
17 | float3 normalizedLinearValue = NormalizeHDRSceneValue(rec2020, paperWhiteNits);
18 | float3 HDR10 = LinearToST2084(normalizedLinearValue);
19 | return float4(HDR10, hdrSceneValue.w);
20 | }
21 |
22 | [numthreads(8, 8, 1)]
23 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
24 | {
25 | int2 coord = int2(GlobalInvocationID.xy);
26 | float4 inPixel = InImage[coord];
27 | OutImage[coord] = ConvertToHDR10(inPixel, 200.0f);
28 | }
29 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/PositionColor.vert.hlsl:
--------------------------------------------------------------------------------
1 | struct Input
2 | {
3 | float3 Position : TEXCOORD0;
4 | float4 Color : TEXCOORD1;
5 | };
6 |
7 | struct Output
8 | {
9 | float4 Color : TEXCOORD0;
10 | float4 Position : SV_Position;
11 | };
12 |
13 | Output main(Input input)
14 | {
15 | Output output;
16 | output.Color = input.Color;
17 | output.Position = float4(input.Position, 1.0f);
18 | return output;
19 | }
20 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/PositionColorInstanced.vert.hlsl:
--------------------------------------------------------------------------------
1 | struct Input
2 | {
3 | float3 Position : TEXCOORD0;
4 | float4 Color : TEXCOORD1;
5 | uint InstanceIndex : SV_InstanceID;
6 | };
7 |
8 | struct Output
9 | {
10 | float4 Color : TEXCOORD0;
11 | float4 Position : SV_Position;
12 | };
13 |
14 | Output main(Input input)
15 | {
16 | Output output;
17 | output.Color = input.Color;
18 | float3 pos = (input.Position * 0.25f) - float3(0.75f, 0.75f, 0.0f);
19 | pos.x += (float(input.InstanceIndex % 4) * 0.5f);
20 | pos.y += (floor(float(input.InstanceIndex / 4)) * 0.5f);
21 | output.Position = float4(pos, 1.0f);
22 | return output;
23 | }
24 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/PositionColorTransform.vert.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UBO : register(b0, space1)
2 | {
3 | float4x4 transform : packoffset(c0);
4 | };
5 |
6 | struct Input
7 | {
8 | float3 Position : TEXCOORD0;
9 | float4 Color : TEXCOORD1;
10 | };
11 |
12 | struct Output
13 | {
14 | float4 Color : TEXCOORD0;
15 | float4 Position : SV_Position;
16 | };
17 |
18 | Output main(Input input)
19 | {
20 | Output output;
21 | output.Color = input.Color;
22 | output.Position = mul(transform, float4(input.Position, 1.0f));
23 | return output;
24 | }
25 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/PullSpriteBatch.vert.hlsl:
--------------------------------------------------------------------------------
1 | struct SpriteData
2 | {
3 | float3 Position;
4 | float Rotation;
5 | float2 Scale;
6 | float2 Padding;
7 | float TexU, TexV, TexW, TexH;
8 | float4 Color;
9 | };
10 |
11 | struct Output
12 | {
13 | float2 Texcoord : TEXCOORD0;
14 | float4 Color : TEXCOORD1;
15 | float4 Position : SV_Position;
16 | };
17 |
18 | StructuredBuffer DataBuffer : register(t0, space0);
19 |
20 | cbuffer UniformBlock : register(b0, space1)
21 | {
22 | float4x4 ViewProjectionMatrix : packoffset(c0);
23 | };
24 |
25 | static const uint triangleIndices[6] = {0, 1, 2, 3, 2, 1};
26 | static const float2 vertexPos[4] = {
27 | {0.0f, 0.0f},
28 | {1.0f, 0.0f},
29 | {0.0f, 1.0f},
30 | {1.0f, 1.0f}
31 | };
32 |
33 | Output main(uint id : SV_VertexID)
34 | {
35 | uint spriteIndex = id / 6;
36 | uint vert = triangleIndices[id % 6];
37 | SpriteData sprite = DataBuffer[spriteIndex];
38 |
39 | float2 texcoord[4] = {
40 | {sprite.TexU, sprite.TexV },
41 | {sprite.TexU + sprite.TexW, sprite.TexV },
42 | {sprite.TexU, sprite.TexV + sprite.TexH},
43 | {sprite.TexU + sprite.TexW, sprite.TexV + sprite.TexH}
44 | };
45 |
46 | float c = cos(sprite.Rotation);
47 | float s = sin(sprite.Rotation);
48 |
49 | float2 coord = vertexPos[vert];
50 | coord *= sprite.Scale;
51 | float2x2 rotation = {c, s, -s, c};
52 | coord = mul(coord, rotation);
53 |
54 | float3 coordWithDepth = float3(coord + sprite.Position.xy, sprite.Position.z);
55 |
56 | Output output;
57 |
58 | output.Position = mul(ViewProjectionMatrix, float4(coordWithDepth, 1.0f));
59 | output.Texcoord = texcoord[vert];
60 | output.Color = sprite.Color;
61 |
62 | return output;
63 | }
64 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/RawTriangle.vert.hlsl:
--------------------------------------------------------------------------------
1 | struct Input
2 | {
3 | uint VertexIndex : SV_VertexID;
4 | };
5 |
6 | struct Output
7 | {
8 | float4 Color : TEXCOORD0;
9 | float4 Position : SV_Position;
10 | };
11 |
12 | Output main(Input input)
13 | {
14 | Output output;
15 | float2 pos;
16 | if (input.VertexIndex == 0)
17 | {
18 | pos = (-1.0f).xx;
19 | output.Color = float4(1.0f, 0.0f, 0.0f, 1.0f);
20 | }
21 | else
22 | {
23 | if (input.VertexIndex == 1)
24 | {
25 | pos = float2(1.0f, -1.0f);
26 | output.Color = float4(0.0f, 1.0f, 0.0f, 1.0f);
27 | }
28 | else
29 | {
30 | if (input.VertexIndex == 2)
31 | {
32 | pos = float2(0.0f, 1.0f);
33 | output.Color = float4(0.0f, 0.0f, 1.0f, 1.0f);
34 | }
35 | }
36 | }
37 | output.Position = float4(pos, 0.0f, 1.0f);
38 | return output;
39 | }
40 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/Skybox.frag.hlsl:
--------------------------------------------------------------------------------
1 | TextureCube SkyboxTexture : register(t0, space2);
2 | SamplerState SkyboxSampler : register(s0, space2);
3 |
4 | float4 main(float3 TexCoord : TEXCOORD0) : SV_Target0
5 | {
6 | return SkyboxTexture.Sample(SkyboxSampler, TexCoord);
7 | }
8 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/Skybox.vert.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UniformBlock : register(b0, space1)
2 | {
3 | float4x4 MatrixTransform : packoffset(c0);
4 | };
5 |
6 | struct SPIRV_Cross_Input
7 | {
8 | float3 inTexCoord : TEXCOORD0;
9 | };
10 |
11 | struct Output
12 | {
13 | float3 TexCoord : TEXCOORD0;
14 | float4 Position : SV_Position;
15 | };
16 |
17 | Output main(float3 inTexCoord : TEXCOORD0)
18 | {
19 | Output output;
20 | output.TexCoord = inTexCoord;
21 | output.Position = mul(MatrixTransform, float4(inTexCoord, 1.0));
22 | return output;
23 | }
24 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/SolidColor.frag.hlsl:
--------------------------------------------------------------------------------
1 | float4 main(float4 Color : TEXCOORD0) : SV_Target0
2 | {
3 | return Color;
4 | }
5 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/SolidColorDepth.frag.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UBO : register(b0, space3)
2 | {
3 | float NearPlane;
4 | float FarPlane;
5 | };
6 |
7 | struct Output
8 | {
9 | float4 Color : SV_Target0;
10 | float Depth : SV_Depth;
11 | };
12 |
13 | float LinearizeDepth(float depth, float near, float far)
14 | {
15 | float z = depth * 2.0 - 1.0;
16 | return ((2.0 * near * far) / (far + near - z * (far - near))) / far;
17 | }
18 |
19 | Output main(float4 Color : TEXCOORD0, float4 Position : SV_Position)
20 | {
21 | Output result;
22 | result.Color = Color;
23 | result.Depth = LinearizeDepth(Position.z, NearPlane, FarPlane);
24 | return result;
25 | }
26 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/SpriteBatch.comp.hlsl:
--------------------------------------------------------------------------------
1 | struct SpriteComputeData
2 | {
3 | float3 Position;
4 | float Rotation;
5 | float2 Scale;
6 | float2 Padding;
7 | float TexU, TexV, TexW, TexH;
8 | float4 Color;
9 | };
10 |
11 | struct SpriteVertex
12 | {
13 | float4 Position;
14 | float2 Texcoord;
15 | float4 Color;
16 | };
17 |
18 | StructuredBuffer ComputeBuffer : register(t0, space0);
19 | RWStructuredBuffer VertexBuffer : register(u0, space1);
20 |
21 | [numthreads(64, 1, 1)]
22 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
23 | {
24 | uint n = GlobalInvocationID.x;
25 |
26 | SpriteComputeData sprite = ComputeBuffer[n];
27 |
28 | float4x4 Scale = float4x4(
29 | float4(sprite.Scale.x, 0.0f, 0.0f, 0.0f),
30 | float4(0.0f, sprite.Scale.y, 0.0f, 0.0f),
31 | float4(0.0f, 0.0f, 1.0f, 0.0f),
32 | float4(0.0f, 0.0f, 0.0f, 1.0f)
33 | );
34 |
35 | float c = cos(sprite.Rotation);
36 | float s = sin(sprite.Rotation);
37 |
38 | float4x4 Rotation = float4x4(
39 | float4( c, s, 0.0f, 0.0f),
40 | float4( -s, c, 0.0f, 0.0f),
41 | float4(0.0f, 0.0f, 1.0f, 0.0f),
42 | float4(0.0f, 0.0f, 0.0f, 1.0f)
43 | );
44 |
45 | float4x4 Translation = float4x4(
46 | float4(1.0f, 0.0f, 0.0f, 0.0f),
47 | float4(0.0f, 1.0f, 0.0f, 0.0f),
48 | float4(0.0f, 0.0f, 1.0f, 0.0f),
49 | float4(sprite.Position.x, sprite.Position.y, sprite.Position.z, 1.0f)
50 | );
51 |
52 | float4x4 Model = mul(Scale, mul(Rotation, Translation));
53 |
54 | float4 topLeft = float4(0.0f, 0.0f, 0.0f, 1.0f);
55 | float4 topRight = float4(1.0f, 0.0f, 0.0f, 1.0f);
56 | float4 bottomLeft = float4(0.0f, 1.0f, 0.0f, 1.0f);
57 | float4 bottomRight = float4(1.0f, 1.0f, 0.0f, 1.0f);
58 |
59 | VertexBuffer[n * 4u] .Position = mul(topLeft, Model);
60 | VertexBuffer[n * 4u + 1].Position = mul(topRight, Model);
61 | VertexBuffer[n * 4u + 2].Position = mul(bottomLeft, Model);
62 | VertexBuffer[n * 4u + 3].Position = mul(bottomRight, Model);
63 |
64 | VertexBuffer[n * 4u] .Texcoord = float2(sprite.TexU, sprite.TexV);
65 | VertexBuffer[n * 4u + 1].Texcoord = float2(sprite.TexU + sprite.TexW, sprite.TexV);
66 | VertexBuffer[n * 4u + 2].Texcoord = float2(sprite.TexU, sprite.TexV + sprite.TexH);
67 | VertexBuffer[n * 4u + 3].Texcoord = float2(sprite.TexU + sprite.TexW, sprite.TexV + sprite.TexH);
68 |
69 | VertexBuffer[n * 4u] .Color = sprite.Color;
70 | VertexBuffer[n * 4u + 1].Color = sprite.Color;
71 | VertexBuffer[n * 4u + 2].Color = sprite.Color;
72 | VertexBuffer[n * 4u + 3].Color = sprite.Color;
73 | }
74 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuad.comp.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UBO : register(b0, space2)
2 | {
3 | float ubo_texcoord_multiplier : packoffset(c0);
4 | };
5 |
6 | Texture2D inImage : register(t0, space0);
7 | SamplerState inImageSampler : register(s0, space0);
8 | RWTexture2D outImage : register(u0, space1);
9 |
10 | [numthreads(8, 8, 1)]
11 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
12 | {
13 | float w, h;
14 | inImage.GetDimensions(w, h);
15 | int2 coord = int2(GlobalInvocationID.xy);
16 | float2 texcoord = (float2(coord) * ubo_texcoord_multiplier) / float2(w, h);
17 | float4 inPixel = inImage.SampleLevel(inImageSampler, texcoord, 0.0f);
18 | outImage[coord] = inPixel;
19 | }
20 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuad.frag.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D Texture : register(t0, space2);
2 | SamplerState Sampler : register(s0, space2);
3 |
4 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0
5 | {
6 | return Texture.Sample(Sampler, TexCoord);
7 | }
8 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuad.vert.hlsl:
--------------------------------------------------------------------------------
1 | struct Input
2 | {
3 | float3 Position : TEXCOORD0;
4 | float2 TexCoord : TEXCOORD1;
5 | };
6 |
7 | struct Output
8 | {
9 | float2 TexCoord : TEXCOORD0;
10 | float4 Position : SV_Position;
11 | };
12 |
13 | Output main(Input input)
14 | {
15 | Output output;
16 | output.TexCoord = input.TexCoord;
17 | output.Position = float4(input.Position, 1.0f);
18 | return output;
19 | }
20 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuadArray.frag.hlsl:
--------------------------------------------------------------------------------
1 | Texture2DArray Texture : register(t0, space2);
2 | SamplerState Sampler : register(s0, space2);
3 |
4 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0
5 | {
6 | uint arrayIndex = uint(int(TexCoord.y > 0.5f));
7 | return Texture.Sample(Sampler, float3(TexCoord, float(arrayIndex)));
8 | }
9 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuadColor.frag.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D Texture : register(t0, space2);
2 | SamplerState Sampler : register(s0, space2);
3 |
4 | struct Input
5 | {
6 | float2 TexCoord : TEXCOORD0;
7 | float4 Color : TEXCOORD1;
8 | };
9 |
10 | float4 main(Input input) : SV_Target0
11 | {
12 | return input.Color * Texture.Sample(Sampler, input.TexCoord);
13 | }
14 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuadColorWithMatrix.vert.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UniformBlock : register(b0, space1)
2 | {
3 | float4x4 MatrixTransform : packoffset(c0);
4 | };
5 |
6 | struct Input
7 | {
8 | float4 Position : TEXCOORD0;
9 | float2 TexCoord : TEXCOORD1;
10 | float4 Color : TEXCOORD2;
11 | };
12 |
13 | struct Output
14 | {
15 | float2 TexCoord : TEXCOORD0;
16 | float4 Color : TEXCOORD1;
17 | float4 Position : SV_Position;
18 | };
19 |
20 | Output main(Input input)
21 | {
22 | Output output;
23 | output.TexCoord = input.TexCoord;
24 | output.Color = input.Color;
25 | output.Position = mul(MatrixTransform, input.Position);
26 | return output;
27 | }
28 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuadWithMatrix.vert.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UniformBlock : register(b0, space1)
2 | {
3 | float4x4 MatrixTransform : packoffset(c0);
4 | };
5 |
6 | struct Input
7 | {
8 | float4 Position : TEXCOORD0;
9 | float2 TexCoord : TEXCOORD1;
10 | };
11 |
12 | struct Output
13 | {
14 | float2 TexCoord : TEXCOORD0;
15 | float4 Position : SV_Position;
16 | };
17 |
18 | Output main(Input input)
19 | {
20 | Output output;
21 | output.TexCoord = input.TexCoord;
22 | output.Position = mul(MatrixTransform, input.Position);
23 | return output;
24 | }
25 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/TexturedQuadWithMultiplyColor.frag.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer UniformBlock : register(b0, space3)
2 | {
3 | float4 MultiplyColor : packoffset(c0);
4 | };
5 |
6 | Texture2D Texture : register(t0, space2);
7 | SamplerState Sampler : register(s0, space2);
8 |
9 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0
10 | {
11 | return MultiplyColor * Texture.Sample(Sampler, TexCoord);
12 | }
13 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/ToneMapACES.comp.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D inImage : register(t0, space0);
2 | RWTexture2D outImage : register(u0, space1);
3 |
4 | float3 rtt_and_odt_fit(float3 v)
5 | {
6 | float3 a = (v * (v + 0.0245786f.xxx)) - 0.000090537f.xxx;
7 | float3 b = (v * ((v * 0.983729f) + 0.4329510f.xxx)) + 0.238081f.xxx;
8 | return a / b;
9 | }
10 |
11 | float3 aces_fitted(float3 v)
12 | {
13 | v = mul(float3x3(float3(0.59719f, 0.35458f, 0.04823f), float3(0.07600f, 0.90834f, 0.01566f), float3(0.02840f, 0.13383f, 0.83777f)), v);
14 | v = rtt_and_odt_fit(v);
15 | return mul(float3x3(float3(1.60475f, -0.53108f, -0.07367f), float3(-0.10208f, 1.10813f, -0.00605f), float3(-0.00327f, -0.07276f, 1.07602f)), v);
16 | }
17 |
18 | [numthreads(8, 8, 1)]
19 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
20 | {
21 | int2 coord = int2(GlobalInvocationID.xy);
22 | float4 inPixel = inImage[coord];
23 | float3 outColor = aces_fitted(inPixel.xyz);
24 | outImage[coord] = float4(outColor, 1.0f);
25 | }
26 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/ToneMapExtendedReinhardLuminance.comp.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D inImage : register(t0, space0);
2 | RWTexture2D outImage : register(u0, space1);
3 |
4 | float luminance(float3 v)
5 | {
6 | return dot(v, float3(0.2126f, 0.7152f, 0.0722f));
7 | }
8 |
9 | float3 change_luminance(float3 c_in, float l_out)
10 | {
11 | float l_in = luminance(c_in);
12 | return c_in * (l_out / l_in);
13 | }
14 |
15 | float3 reinhard_extended_luminance(float3 v, float max_white_l)
16 | {
17 | float l_old = luminance(v);
18 | float numerator = l_old * (1.0f + (l_old / (max_white_l * max_white_l)));
19 | float l_new = numerator / (1.0f + l_old);
20 | return change_luminance(v, l_new);
21 | }
22 |
23 | [numthreads(8, 8, 1)]
24 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
25 | {
26 | int2 coord = int2(GlobalInvocationID.xy);
27 | float4 inPixel = inImage[coord];
28 | float3 outColor = reinhard_extended_luminance(inPixel.xyz, 662.0f);
29 | outImage[coord] = float4(outColor, 1.0f);
30 | }
31 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/ToneMapHable.comp.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D inImage : register(t0, space0);
2 | RWTexture2D outImage : register(u0, space1);
3 |
4 | float3 hable_tonemap_partial(float3 x)
5 | {
6 | float A = 0.15f;
7 | float B = 0.50f;
8 | float C = 0.10f;
9 | float D = 0.20f;
10 | float E = 0.02f;
11 | float F = 0.30f;
12 | return (((x * ((x * A) + (C * B).xxx)) + (D * E).xxx) / ((x * ((x * A) + B.xxx)) + (D * F).xxx)) - (E / F).xxx;
13 | }
14 |
15 | float3 hable_filmic(float3 v)
16 | {
17 | float exposure_bias = 2.0f;
18 | float3 curr = hable_tonemap_partial(v * exposure_bias);
19 |
20 | float3 W = 11.2f.xxx;
21 | float3 white_scale = 1.0f.xxx / hable_tonemap_partial(W);
22 | return curr * white_scale;
23 | }
24 |
25 | [numthreads(8, 8, 1)]
26 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
27 | {
28 | int2 coord = int2(GlobalInvocationID.xy);
29 | float4 inPixel = inImage[coord];
30 | float3 outColor = hable_filmic(inPixel.xyz);
31 | outImage[coord] = float4(outColor, 1.0f);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/ToneMapReinhard.comp.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D inImage : register(t0, space0);
2 | RWTexture2D outImage : register(u0, space1);
3 |
4 | float3 reinhard(float3 v)
5 | {
6 | return v / (1.0f.xxx + v);
7 | }
8 |
9 | [numthreads(8, 8, 1)]
10 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
11 | {
12 | int2 coord = int2(GlobalInvocationID.xy);
13 | float4 inPixel = inImage[coord];
14 | float3 outColor = reinhard(inPixel.xyz);
15 | outImage[coord] = float4(outColor, 1.0f);
16 | }
17 |
--------------------------------------------------------------------------------
/examples/Content/Shaders/Source/compile.sh:
--------------------------------------------------------------------------------
1 | # Requires shadercross CLI installed from SDL_shadercross
2 | for filename in *.vert.hlsl; do
3 | if [ -f "$filename" ]; then
4 | shadercross "$filename" -o "../Compiled/SPIRV/${filename/.hlsl/.spv}"
5 | shadercross "$filename" -o "../Compiled/MSL/${filename/.hlsl/.msl}"
6 | shadercross "$filename" -o "../Compiled/DXIL/${filename/.hlsl/.dxil}"
7 | fi
8 | done
9 |
10 | for filename in *.frag.hlsl; do
11 | if [ -f "$filename" ]; then
12 | shadercross "$filename" -o "../Compiled/SPIRV/${filename/.hlsl/.spv}"
13 | shadercross "$filename" -o "../Compiled/MSL/${filename/.hlsl/.msl}"
14 | shadercross "$filename" -o "../Compiled/DXIL/${filename/.hlsl/.dxil}"
15 | fi
16 | done
17 |
18 | for filename in *.comp.hlsl; do
19 | if [ -f "$filename" ]; then
20 | shadercross "$filename" -o "../Compiled/SPIRV/${filename/.hlsl/.spv}"
21 | shadercross "$filename" -o "../Compiled/MSL/${filename/.hlsl/.msl}"
22 | shadercross "$filename" -o "../Compiled/DXIL/${filename/.hlsl/.dxil}"
23 | fi
24 | done
25 |
--------------------------------------------------------------------------------
/examples/DialogExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import Control.Monad
4 | import Foreign.C.String (CString, peekCString, withCString)
5 | import Foreign.C.Types (CBool(..), CInt(..))
6 | import Foreign.Marshal.Array (peekArray0, withArrayLen)
7 | import Foreign.Ptr (FunPtr, Ptr, castPtr, nullPtr)
8 | import Foreign.StablePtr (freeStablePtr, newStablePtr)
9 | import SDL
10 | import System.Exit (exitFailure, exitSuccess)
11 |
12 | main :: IO ()
13 | main = do
14 | -- Initialize SDL
15 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
16 | unless initSuccess $ do
17 | sdlLog "Failed to initialize SDL!"
18 | exitFailure
19 |
20 | -- Create a window for our dialog
21 | maybeWindow <- sdlCreateWindow
22 | "SDL Dialog Example"
23 | 800
24 | 600
25 | [SDL_WINDOW_RESIZABLE]
26 |
27 | case maybeWindow of
28 | Nothing -> do
29 | sdlLog "Failed to create window!"
30 | sdlQuit
31 | exitFailure
32 | Just window -> do
33 | -- Define some file filters
34 | let filters =
35 | [ SDLDialogFileFilter
36 | { filterName = "Text Files"
37 | , filterPattern = "txt;doc;md"
38 | }
39 | , SDLDialogFileFilter
40 | { filterName = "All Files"
41 | , filterPattern = "*"
42 | }
43 | ]
44 |
45 | -- Create our callback function
46 | let dialogCallback :: Ptr () -> Ptr CString -> CInt -> IO ()
47 | dialogCallback userdata filelist filterIndex = do
48 | if filelist == nullPtr
49 | then sdlLog "Dialog was cancelled or error occurred"
50 | else do
51 | -- Get the list of files
52 | files <- peekArray0 nullPtr filelist
53 | fileNames <- mapM peekCString files
54 | sdlLog $ "Selected files (filter index " ++ show filterIndex ++ "):"
55 | mapM_ (sdlLog . (" - " ++)) fileNames
56 |
57 | -- Convert callback to stable pointer for C
58 | callbackPtr <- wrapDialogCallback dialogCallback
59 |
60 | -- Show different types of dialogs
61 | sdlLog "\nShowing Open File Dialog..."
62 | withFilters filters $ \filtersPtr nfilters ->
63 | sdlShowOpenFileDialog
64 | callbackPtr
65 | nullPtr
66 | (Just window)
67 | filtersPtr
68 | (fromIntegral nfilters)
69 | Nothing
70 | True
71 |
72 | sdlLog "\nShowing Save File Dialog..."
73 | withFilters filters $ \filtersPtr nfilters ->
74 | sdlShowSaveFileDialog
75 | callbackPtr
76 | nullPtr
77 | (Just window)
78 | filtersPtr
79 | (fromIntegral nfilters)
80 | Nothing
81 |
82 | sdlLog "\nShowing Folder Dialog..."
83 | sdlShowOpenFolderDialog
84 | callbackPtr
85 | nullPtr
86 | (Just window)
87 | Nothing
88 | False
89 |
90 | -- Show a dialog with custom properties
91 | sdlLog "\nShowing Custom Dialog..."
92 | props <- sdlCreateProperties
93 |
94 | -- Set some custom properties
95 | sdlSetStringProperty props sdlPropFileDialogTitleString "Select a File"
96 | sdlSetStringProperty props sdlPropFileDialogAcceptString "Choose"
97 | sdlSetStringProperty props sdlPropFileDialogCancelString "Never Mind"
98 |
99 | sdlShowFileDialogWithProperties
100 | SDL_FILEDIALOG_OPENFILE
101 | callbackPtr
102 | nullPtr
103 | props
104 |
105 | -- -- Event loop to keep program alive
106 | -- let eventLoop = do
107 | -- sdlPumpEvents -- Process events
108 | -- threadDelay 100000 -- Small delay to prevent CPU spinning
109 | -- -- You might want to add a way to exit the loop
110 | -- -- For example, checking for a quit event or after all dialogs are done
111 | -- eventLoop
112 |
113 | -- -- Run the event loop
114 | -- sdlLog "Running event loop... (Press Ctrl+C to exit)"
115 | -- eventLoop `finally` do
116 | -- -- Cleanup
117 | sdlDestroyProperties props
118 | sdlDestroyWindow window
119 | sdlQuit
120 | exitSuccess
121 |
122 | -- Helper function to manage filter array lifecycle
123 | withFilters ::
124 | [SDLDialogFileFilter] ->
125 | (Ptr SDLDialogFileFilter -> CInt -> IO a) ->
126 | IO a
127 | withFilters filters action =
128 | withArrayLen filters $ \len filtersPtr ->
129 | action filtersPtr (fromIntegral len)
130 |
131 | -- | Type for the dialog callback function
132 | type DialogCallback = Ptr () -> Ptr CString -> CInt -> IO ()
133 |
134 | -- | Foreign wrapper for the callback
135 | foreign import ccall "wrapper"
136 | wrapDialogCallback :: DialogCallback -> IO (FunPtr DialogCallback)
137 |
--------------------------------------------------------------------------------
/examples/EventsExample.hs:
--------------------------------------------------------------------------------
1 | {-|
2 | Example : SDL.Events
3 | Description : SDL Window and Keyboard Event Example
4 | Copyright : (c) Kyle Lukaszek, 2025
5 | License : BSD3
6 | |-}
7 |
8 | module Main where
9 |
10 | import SDL
11 | import Control.Monad (unless, when)
12 | import System.Exit (exitFailure, exitSuccess)
13 | import Foreign.Ptr (nullPtr)
14 | import Data.IORef
15 | import Data.Word (Word32, Word64)
16 | import Text.Printf (printf)
17 |
18 | main :: IO ()
19 | main = do
20 | -- Check compiled version
21 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
22 | when (sdlVersionAtLeast 3 3 0) $ sdlLog "Compiled with at least SDL 3.3.0"
23 |
24 | -- Get linked version
25 | linkedVersion <- sdlGetVersion
26 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
27 |
28 | -- Initialize SDL
29 | initSuccess <- sdlInit [SDL_INIT_VIDEO, SDL_INIT_EVENTS]
30 | unless initSuccess $ do
31 | sdlLog "Failed to initialize SDL!"
32 | exitFailure
33 |
34 | -- Check initialized subsystems
35 | initializedSystems <- sdlWasInit []
36 | sdlLog "Initialized subsystems:"
37 | mapM_ printSubsystem initializedSystems
38 |
39 | -- Create a window
40 | window <- sdlCreateWindow "SDL3 Haskell Event Loop" 800 600 [SDL_WINDOW_RESIZABLE]
41 | case window of
42 | Nothing -> do
43 | sdlLog "Failed to create window!"
44 | sdlQuit
45 | exitFailure
46 | Just win -> do
47 | sdlLog "Window created successfully!"
48 |
49 | -- Start event loop with initial time
50 | startTime <- sdlGetPerformanceCounter
51 | freq <- sdlGetPerformanceFrequency
52 | deltaTimeRef <- newIORef 0.0
53 | eventLoop win startTime freq deltaTimeRef
54 |
55 | -- Cleanup
56 | sdlDestroyWindow win
57 | sdlLog "Window destroyed."
58 |
59 | sdlLog "Shutting down SDL..."
60 | sdlQuit
61 | sdlLog "Application terminated successfully"
62 | exitSuccess
63 |
64 | -- | Main event loop that tracks FPS and processes events
65 | eventLoop :: SDLWindow -> Word64 -> Word64 -> IORef Double -> IO ()
66 | eventLoop window lastTime freq deltaTimeRef = do
67 | currentTime <- sdlGetPerformanceCounter
68 | let deltaTime = fromIntegral (currentTime - lastTime) / fromIntegral freq * 1000.0
69 |
70 | -- Store the new deltaTime
71 | writeIORef deltaTimeRef deltaTime
72 |
73 | -- Event handling
74 | sdlPumpEvents
75 | maybeEvent <- sdlPollEvent
76 | shouldQuit <- case maybeEvent of
77 | Nothing -> return False
78 | Just event -> handleEvent event deltaTimeRef
79 |
80 | unless shouldQuit $ eventLoop window currentTime freq deltaTimeRef
81 |
82 | -- | Handle SDL events
83 | handleEvent :: SDLEvent -> IORef Double -> IO Bool
84 | handleEvent event deltaTimeRef = case event of
85 | SDLEventQuit _ -> do
86 | sdlLog "Quit event received."
87 | return True
88 | SDLEventKeyboard (SDLKeyboardEvent _ _ _ _ scancode _ _ _ down _) | down -> do
89 | deltaTime <- readIORef deltaTimeRef -- Read delta time
90 | sdlLog $ printf "Key event received. Delta Time: %.3f ms" deltaTime
91 | return $ scancode == SDL_SCANCODE_Q
92 | _ -> return False
93 |
94 | -- Helper function to print subsystem names
95 | printSubsystem :: SDLInitFlags -> IO ()
96 | printSubsystem flag = sdlLog $ " - " ++ case flag of
97 | SDL_INIT_AUDIO -> "Audio"
98 | SDL_INIT_VIDEO -> "Video"
99 | SDL_INIT_JOYSTICK -> "Joystick"
100 | SDL_INIT_HAPTIC -> "Haptic"
101 | SDL_INIT_GAMEPAD -> "Gamepad"
102 | SDL_INIT_EVENTS -> "Events"
103 | SDL_INIT_SENSOR -> "Sensor"
104 | SDL_INIT_CAMERA -> "Camera"
105 | _ -> "Unknown subsystem"
106 |
107 | -- Function to log the frame time in milliseconds with decimal precision
108 | logFrameTime :: Double -> IO ()
109 | logFrameTime frameTime = sdlLog $ printf "Frame time: %.4f ms" frameTime
110 |
111 |
--------------------------------------------------------------------------------
/examples/FilesystemExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad (unless, when)
5 | import System.Exit (exitFailure, exitSuccess)
6 | import Foreign.Ptr (nullPtr)
7 |
8 | main :: IO ()
9 | main = do
10 | -- Initialize SDL with basic subsystems
11 | initSuccess <- sdlInit [SDL_INIT_VIDEO, SDL_INIT_EVENTS]
12 | unless initSuccess $ do
13 | sdlLog "Failed to initialize SDL!"
14 | exitFailure
15 |
16 | -- Set basic app metadata
17 | appMetadataSuccess <- sdlSetAppMetadata
18 | "SDL Filesystem Demo"
19 | "1.0.0"
20 | "com.example.filesystemdemo"
21 | unless appMetadataSuccess $ do
22 | sdlLog "Failed to set app metadata!"
23 |
24 | -- Get and print the base path
25 | basePath <- sdlGetBasePath
26 | sdlLog $ "Base Path: " ++ maybe "Not available" id basePath
27 |
28 | -- Get and print the preferences path
29 | prefPath <- sdlGetPrefPath "ExampleOrg" "FilesystemDemo"
30 | case prefPath of
31 | Nothing -> sdlLog "Failed to get preferences path!"
32 | Just path -> do
33 | sdlLog $ "Preferences Path: " ++ path
34 |
35 | -- Create a test directory in the preferences path
36 | let testDir = path ++ "test_dir"
37 | dirCreated <- sdlCreateDirectory testDir
38 | sdlLog $ "Created test directory: " ++ show dirCreated
39 |
40 | -- List contents of the preferences path
41 | dirContents <- sdlGlobDirectory path Nothing (SDLGlobFlags 0)
42 | sdlLog "Contents of preferences path:"
43 | case dirContents of
44 | Nothing -> sdlLog " Failed to list directory contents!"
45 | Just contents -> mapM_ (sdlLog . (" - " ++)) contents
46 |
47 | -- Get and print the user's Documents folder
48 | docsPath <- sdlGetUserFolder SDL_FOLDER_DOCUMENTS
49 | sdlLog $ "Documents Path: " ++ maybe "Not available" id docsPath
50 |
51 | -- Clean up and quit
52 | sdlQuit
53 | sdlLog "Application terminated successfully"
54 | exitSuccess
55 |
56 | -- Helper function to print subsystem names
57 | printSubsystem :: SDLInitFlags -> IO ()
58 | printSubsystem flag = sdlLog $ " - " ++ case flag of
59 | SDL_INIT_AUDIO -> "Audio"
60 | SDL_INIT_VIDEO -> "Video"
61 | SDL_INIT_JOYSTICK -> "Joystick"
62 | SDL_INIT_HAPTIC -> "Haptic"
63 | SDL_INIT_GAMEPAD -> "Gamepad"
64 | SDL_INIT_EVENTS -> "Events"
65 | SDL_INIT_SENSOR -> "Sensor"
66 | SDL_INIT_CAMERA -> "Camera"
67 | _ -> "Unknown subsystem"
68 |
--------------------------------------------------------------------------------
/examples/GUIDExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import SDL.GUID
5 | import Control.Monad
6 | import System.Exit (exitFailure, exitSuccess)
7 | import Foreign.Ptr (nullPtr)
8 | import Data.Word (Word8)
9 | import Data.Maybe (fromMaybe)
10 |
11 | main :: IO ()
12 | main = do
13 | -- Basic SDL initialization from your example
14 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
15 | when (sdlVersionAtLeast 3 3 0) $
16 | sdlLog "Compiled with at least SDL 3.3.0"
17 |
18 | linkedVersion <- sdlGetVersion
19 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
20 |
21 | revision <- sdlGetRevision
22 | sdlLog $ "SDL Revision: " ++ revision
23 |
24 | initSuccess <- sdlInit [SDL_INIT_VIDEO, SDL_INIT_GAMEPAD]
25 | unless initSuccess $ do
26 | sdlLog "Failed to initialize SDL!"
27 | exitFailure
28 |
29 | -- GUID example section
30 | sdlLog "\n=== GUID Example ==="
31 |
32 | -- Create a sample GUID (normally this would come from an SDL input device)
33 | let sampleBytes = take 16 $ cycle [0x12, 0x34, 0x56, 0x78] :: [Word8]
34 | sampleGUID = SDLGUID sampleBytes
35 |
36 | sdlLog "Original GUID bytes:"
37 | print $ unSDLGUID sampleGUID
38 |
39 | -- Convert GUID to string
40 | guidStr <- sdlGUIDToString sampleGUID
41 | sdlLog $ "GUID as string: " ++ guidStr
42 |
43 | -- Convert string back to GUID
44 | guidBack <- sdlStringToGUID guidStr
45 | sdlLog "Converted back to GUID bytes:"
46 | print $ unSDLGUID guidBack
47 |
48 | -- Verify roundtrip conversion
49 | let isMatch = unSDLGUID sampleGUID == unSDLGUID guidBack
50 | sdlLog $ "Roundtrip conversion successful: " ++ show isMatch
51 |
52 | -- Example with an invalid string
53 | sdlLog "\nTesting with invalid GUID string:"
54 | invalidGuid <- sdlStringToGUID "not-a-valid-guid"
55 | sdlLog "Result of invalid string conversion:"
56 | print $ unSDLGUID invalidGuid
57 |
58 | -- Clean up
59 | sdlLog "\nShutting down SDL..."
60 | sdlQuit
61 |
62 | sdlLog "Application terminated successfully"
63 | exitSuccess
64 |
65 | -- Helper function to print subsystem names
66 | printSubsystem :: SDLInitFlags -> IO ()
67 | printSubsystem flag = sdlLog $ " - " ++ case flag of
68 | SDL_INIT_AUDIO -> "Audio"
69 | SDL_INIT_VIDEO -> "Video"
70 | SDL_INIT_JOYSTICK -> "Joystick"
71 | SDL_INIT_HAPTIC -> "Haptic"
72 | SDL_INIT_GAMEPAD -> "Gamepad"
73 | SDL_INIT_EVENTS -> "Events"
74 | SDL_INIT_SENSOR -> "Sensor"
75 | SDL_INIT_CAMERA -> "Camera"
76 | _ -> "Unknown subsystem"
77 |
--------------------------------------------------------------------------------
/examples/HintsExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad
5 | import Foreign.Marshal.Alloc (alloca, mallocBytes)
6 | import Foreign.Storable (poke, peek)
7 | import System.Exit (exitFailure, exitSuccess)
8 |
9 | -- Check power state
10 | main :: IO ()
11 | main = do
12 | -- Check compiled version
13 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
14 | when (sdlVersionAtLeast 3 3 0) $
15 | sdlLog "Compiled with at least SDL 3.3.0"
16 |
17 | -- Get linked version
18 | linkedVersion <- sdlGetVersion
19 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
20 |
21 | -- Get revision
22 | revision <- sdlGetRevision
23 | sdlLog $ "SDL Revision: " ++ revision
24 |
25 | -- Set a hint before initialization
26 | sdlLog "Setting hint SDL_VIDEO_ALLOW_SCREENSAVER to enable screensaver..."
27 | success <- sdlSetHint sdlHintVideoAllowScreensaver "1"
28 | if success
29 | then sdlLog "Hint set successfully."
30 | else do
31 | sdlLog "Failed to set hint!"
32 | err <- sdlGetError
33 | sdlLog $ "Error: " ++ err
34 |
35 |
36 | -- Initialize SDL with video and events subsystems
37 | initSuccess <- sdlInit [SDL_INIT_VIDEO, SDL_INIT_EVENTS]
38 | unless initSuccess $ do
39 | sdlLog "Failed to initialize SDL!"
40 | exitFailure
41 |
42 | -- Check initialized subsystems
43 | initializedSystems <- sdlWasInit []
44 | sdlLog "Initialized subsystems:"
45 | mapM_ printSubsystem initializedSystems
46 |
47 | -- Query the hint
48 | mHintValue <- sdlGetHint sdlHintVideoAllowScreensaver
49 | sdlLog $ "SDL_VIDEO_ALLOW_SCREENSAVER value: " ++ maybe "Not set" id mHintValue
50 |
51 | sdlQuit
52 |
53 | -- Helper function to print subsystem names
54 | printSubsystem :: SDLInitFlags -> IO ()
55 | printSubsystem flag = sdlLog $ " - " ++ case flag of
56 | SDL_INIT_AUDIO -> "Audio"
57 | SDL_INIT_VIDEO -> "Video"
58 | SDL_INIT_JOYSTICK -> "Joystick"
59 | SDL_INIT_HAPTIC -> "Haptic"
60 | SDL_INIT_GAMEPAD -> "Gamepad"
61 | SDL_INIT_EVENTS -> "Events"
62 | SDL_INIT_SENSOR -> "Sensor"
63 | SDL_INIT_CAMERA -> "Camera"
64 | _ -> "Unknown subsystem"
65 |
--------------------------------------------------------------------------------
/examples/InitExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad
5 | import System.Exit (exitFailure, exitSuccess)
6 | import Foreign.Ptr (nullPtr)
7 |
8 | main :: IO ()
9 | main = do
10 | -- Check compiled version
11 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
12 | when (sdlVersionAtLeast 3 3 0) $
13 | sdlLog "Compiled with at least SDL 3.3.0"
14 |
15 | -- Get linked version
16 | linkedVersion <- sdlGetVersion
17 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
18 |
19 | -- Get revision
20 | revision <- sdlGetRevision
21 | sdlLog $ "SDL Revision: " ++ revision
22 |
23 | -- Set some basic metadata about our application
24 | appMetadataSuccess <- sdlSetAppMetadata
25 | "SDL3 Haskell!"
26 | "1.0.0"
27 | "com.example.sdlapp"
28 |
29 | unless appMetadataSuccess $ do
30 | sdlLog "Failed to set app metadata!"
31 |
32 | -- Add some additional metadata
33 | _ <- sdlSetAppMetadataProperty propAppMetadataCreator "Kyle Lukaszek"
34 | _ <- sdlSetAppMetadataProperty propAppMetadataCopyright "Copyright (c) 2025"
35 | _ <- sdlSetAppMetadataProperty propAppMetadataType "Demo"
36 |
37 | -- Print some metadata to verify it was set
38 | name <- sdlGetAppMetadataProperty propAppMetadataName
39 | sdlLog $ "App Name: " ++ maybe "Not set" id name
40 |
41 | -- Initialize SDL with video and events subsystems
42 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
43 |
44 | unless initSuccess $ do
45 | sdlLog "Failed to initialize SDL!"
46 | exitFailure
47 |
48 | -- Check what subsystems are initialized
49 | initializedSystems <- sdlWasInit []
50 | sdlLog "Initialized subsystems:"
51 | mapM_ printSubsystem initializedSystems
52 |
53 | sdlLog "Would create window here..."
54 | sdlLog "Application running..."
55 |
56 | -- For the main thread callback, use a simpler callback
57 | -- that doesn't try to print to avoid potential issues
58 | isMain <- sdlIsMainThread
59 | sdlLog $ "Are we on the main thread? " ++ show isMain
60 |
61 | -- If we're already on the main thread, running on main thread is redundant
62 | -- but we'll do it for demonstration
63 | if isMain
64 | then sdlLog "Already on main thread, calling directly:"
65 | else sdlLog "Running callback on main thread:"
66 |
67 | -- Use the simpler callback that doesn't do IO operations
68 | _ <- sdlRunOnMainThread (\_ -> pure ()) nullPtr True
69 | sdlLog "Callback completed"
70 |
71 | sdlLog "Shutting down SDL..."
72 | sdlQuit
73 |
74 | sdlLog "Application terminated successfully"
75 | exitSuccess
76 |
77 | -- Helper function to print subsystem names
78 | printSubsystem :: SDLInitFlags -> IO ()
79 | printSubsystem flag = sdlLog $ " - " ++ case flag of
80 | SDL_INIT_AUDIO -> "Audio"
81 | SDL_INIT_VIDEO -> "Video"
82 | SDL_INIT_JOYSTICK -> "Joystick"
83 | SDL_INIT_HAPTIC -> "Haptic"
84 | SDL_INIT_GAMEPAD -> "Gamepad"
85 | SDL_INIT_EVENTS -> "Events"
86 | SDL_INIT_SENSOR -> "Sensor"
87 | SDL_INIT_CAMERA -> "Camera"
88 | _ -> "Unknown subsystem"
89 |
--------------------------------------------------------------------------------
/examples/LocaleExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Foreign.C.Types (CInt(..))
5 | import Control.Monad (unless)
6 |
7 | main :: IO ()
8 | main = do
9 | -- Initialize SDL
10 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
11 | unless initSuccess $ do
12 | sdlLog "Failed to initialize SDL"
13 | return ()
14 |
15 | -- Get preferred locales
16 | locales <- sdlGetPreferredLocales
17 |
18 | -- Print the results
19 | sdlLog "User's preferred locales:"
20 | mapM_ printLocale locales
21 |
22 | -- Clean up
23 | sdlQuit
24 |
25 | -- Helper function to print a locale in a readable format
26 | printLocale :: SDLLocale -> IO ()
27 | printLocale (SDLLocale lang country) = do
28 | let countryStr = maybe "" (", " ++) country
29 | sdlLog $ "Language: " ++ lang ++ countryStr
30 |
--------------------------------------------------------------------------------
/examples/MessageBoxExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Foreign.C.Types (CInt)
5 | import Control.Monad (unless)
6 | import Data.Bits (zeroBits)
7 | import System.Exit (exitFailure, exitSuccess)
8 |
9 | main :: IO ()
10 | main = do
11 | -- Initialize SDL
12 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
13 | unless initSuccess $ do
14 | sdlLog "Failed to initialize SDL!"
15 | exitFailure
16 |
17 | -- Create a window for our dialog
18 | maybeWindow <- sdlCreateWindow
19 | "SDL Dialog Example"
20 | 800
21 | 600
22 | [SDL_WINDOW_RESIZABLE]
23 |
24 | sdlLog "SDL Initialized. Testing message boxes..."
25 |
26 | -- Simple information message box
27 | res1 <- showMessageBox "Info" "This is an information message box." maybeWindow [SDL_MESSAGEBOX_INFORMATION]
28 | sdlLog $ "User clicked: " ++ show res1
29 |
30 | -- Warning message box
31 | res2 <- showMessageBox "Warning" "This is a warning message box." maybeWindow [SDL_MESSAGEBOX_WARNING]
32 | sdlLog $ "User clicked: " ++ show res2
33 |
34 | -- Error message box
35 | res3 <- showMessageBox "Error" "This is an error message box." maybeWindow [SDL_MESSAGEBOX_ERROR]
36 | sdlLog $ "User clicked: " ++ show res3
37 |
38 | -- Message box with custom buttons
39 | res4 <- showCustomMessageBox "Custom" "Choose an option:" maybeWindow [("OK", 1), ("Cancel", 2)]
40 | sdlLog $ "User clicked: " ++ show res4
41 |
42 | -- Shutdown SDL
43 | sdlLog "Shutting down SDL..."
44 | sdlQuit
45 | sdlLog "Test completed."
46 | exitSuccess
47 |
48 | -- Function to show a standard message box
49 | showMessageBox :: String -> String -> Maybe SDLWindow -> [SDLMessageBoxFlags] -> IO (Maybe Int)
50 | showMessageBox title msg window msgType = do
51 | let msgBoxData = SDLMessageBoxData
52 | { messageBoxFlags = msgType
53 | , messageBoxWindow = window
54 | , messageBoxTitle = title
55 | , messageBoxMessage = msg
56 | , messageBoxButtons = []
57 | , messageBoxColorScheme = Nothing
58 | }
59 | sdlShowMessageBox msgBoxData
60 |
61 | -- Function to show a custom message box with buttons
62 | showCustomMessageBox :: String -> String -> Maybe SDLWindow -> [(String, CInt)] -> IO (Maybe Int)
63 | showCustomMessageBox title msg window buttons = do
64 | let buttonData = [ SDLMessageBoxButtonData zeroBits bid txt | (txt, bid) <- buttons ]
65 | msgBoxData = SDLMessageBoxData
66 | { messageBoxFlags = [SDL_MESSAGEBOX_INFORMATION]
67 | , messageBoxWindow = window
68 | , messageBoxTitle = title
69 | , messageBoxMessage = msg
70 | , messageBoxButtons = buttonData
71 | , messageBoxColorScheme = Nothing
72 | }
73 | sdlShowMessageBox msgBoxData
74 |
--------------------------------------------------------------------------------
/examples/PlatformExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad (when)
5 |
6 | main :: IO ()
7 | main = do
8 | platform <- sdlGetPlatform
9 | sdlLog $ "Running on platform: " ++ platform
10 |
11 | -- Check compile-time platform constants
12 | when sdlPlatformWindows $
13 | sdlLog "Compiled for Windows"
14 |
15 | when sdlPlatformLinux $
16 | sdlLog "Compiled for Linux"
17 |
18 | when sdlPlatformMacOS $
19 | sdlLog "Compiled for macOS"
20 |
--------------------------------------------------------------------------------
/examples/PowerExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad
5 | import Foreign.Marshal.Alloc (alloca, mallocBytes)
6 | import Foreign.Storable (poke, peek)
7 | import System.Exit (exitFailure, exitSuccess)
8 |
9 | -- Check power state
10 | main :: IO ()
11 | main = do
12 | -- Check compiled version
13 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
14 | when (sdlVersionAtLeast 3 3 0) $
15 | sdlLog "Compiled with at least SDL 3.3.0"
16 |
17 | -- Get linked version
18 | linkedVersion <- sdlGetVersion
19 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
20 |
21 | -- Get revision
22 | revision <- sdlGetRevision
23 | sdlLog $ "SDL Revision: " ++ revision
24 |
25 | -- Set a hint before initialization
26 | sdlLog "Setting hint SDL_VIDEO_ALLOW_SCREENSAVER to enable screensaver..."
27 | success <- sdlSetHint sdlHintVideoAllowScreensaver "1"
28 | if success
29 | then sdlLog "Hint set successfully."
30 | else do
31 | sdlLog "Failed to set hint!"
32 | err <- sdlGetError
33 | sdlLog $ "Error: " ++ err
34 |
35 | -- Query the hint
36 | mHintValue <- sdlGetHint sdlHintVideoAllowScreensaver
37 | sdlLog $ "SDL_VIDEO_ALLOW_SCREENSAVER value: " ++ maybe "Not set" id mHintValue
38 |
39 | -- Initialize SDL with video and events subsystems
40 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
41 | unless initSuccess $ do
42 | sdlLog "Failed to initialize SDL!"
43 | exitFailure
44 |
45 | -- Check initialized subsystems
46 | initializedSystems <- sdlWasInit []
47 | sdlLog "Initialized subsystems:"
48 | mapM_ printSubsystem initializedSystems
49 |
50 | sdlLog "Checking power state..."
51 | alloca $ \secondsPtr ->
52 | alloca $ \percentPtr -> do
53 | mState <- sdlGetPowerInfo (Just secondsPtr) (Just percentPtr)
54 | case mState of
55 | Nothing -> do
56 | sdlLog "Failed to get power info!"
57 | err <- sdlGetError
58 | sdlLog $ "Error: " ++ err
59 | Just state -> do
60 | seconds <- peek secondsPtr
61 | percent <- peek percentPtr
62 | sdlLog $ "Power State: " ++ show state
63 | sdlLog $ "Seconds remaining: " ++ (if seconds == -1 then "Unknown" else show seconds)
64 | sdlLog $ "Percent remaining: " ++ (if percent == -1 then "Unknown" else show percent ++ "%")
65 |
66 | sdlQuit
67 |
68 | -- Helper function to print subsystem names
69 | printSubsystem :: SDLInitFlags -> IO ()
70 | printSubsystem flag = sdlLog $ " - " ++ case flag of
71 | SDL_INIT_AUDIO -> "Audio"
72 | SDL_INIT_VIDEO -> "Video"
73 | SDL_INIT_JOYSTICK -> "Joystick"
74 | SDL_INIT_HAPTIC -> "Haptic"
75 | SDL_INIT_GAMEPAD -> "Gamepad"
76 | SDL_INIT_EVENTS -> "Events"
77 | SDL_INIT_SENSOR -> "Sensor"
78 | SDL_INIT_CAMERA -> "Camera"
79 | _ -> "Unknown subsystem"
80 |
81 |
--------------------------------------------------------------------------------
/examples/ProcessExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad (unless)
5 | import System.Exit (exitFailure, exitSuccess)
6 |
7 | main :: IO ()
8 | main = do
9 | -- Initialize SDL
10 | initSuccess <- sdlInit []
11 | unless initSuccess $ do
12 | sdlLog "Failed to initialize SDL!"
13 | exitFailure
14 |
15 | -- Create a process to run 'ls' (or 'dir' on Windows)
16 | let args = ["ls", "-l"] -- Use "dir" on Windows
17 | process <- sdlCreateProcess args True -- Pipe stdio
18 | case process of
19 | Nothing -> do
20 | sdlLog "Failed to create process!"
21 | sdlQuit
22 | exitFailure
23 | Just proc -> do
24 | -- Read process output
25 | output <- sdlReadProcess proc
26 | case output of
27 | Nothing -> sdlLog "Failed to read process output!"
28 | Just (out, exitcode) -> do
29 | sdlLog $ "Process output:\n" ++ out
30 | sdlLog $ "Exit code: " ++ show exitcode
31 |
32 | -- Clean up
33 | sdlDestroyProcess proc
34 |
35 | -- Shutdown SDL
36 | sdlQuit
37 | sdlLog "Application terminated successfully"
38 | exitSuccess
39 |
--------------------------------------------------------------------------------
/examples/RectExample.hs:
--------------------------------------------------------------------------------
1 | import Foreign.Marshal.Utils (with)
2 | import SDL
3 |
4 |
5 | main :: IO ()
6 | main = do
7 | let rect1 = SDLRect 0 0 10 10
8 | rect2 = SDLRect 5 5 10 10
9 | point = SDLPoint 5 5
10 |
11 | sdlLog $ "GamepadType" ++ show SDL_GAMEPAD_TYPE_UNKNOWN
12 | sdlLog $ "Point in rect1: " ++ show (sdlPointInRect point rect1)
13 | sdlLog $ "Rect1 empty: " ++ show (sdlRectEmpty rect1)
14 | sdlLog $ "Rects equal: " ++ show (sdlRectsEqual rect1 rect2)
15 |
16 | -- Cast our rectangles to pointers and pass them to the sdlHasRectIntersection function
17 | intersects <- with rect1 $ \rect1Ptr ->
18 | with rect2 $ \rect2Ptr ->
19 | sdlHasRectIntersection rect1Ptr rect2Ptr
20 | sdlLog $ "Rectangles intersect: " ++ show intersects
21 |
--------------------------------------------------------------------------------
/examples/SensorExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad
5 | import System.Exit (exitFailure, exitSuccess)
6 | import Foreign.Ptr (nullPtr)
7 |
8 | main :: IO ()
9 | main = do
10 | -- Initialize SDL with sensor subsystem
11 | initSuccess <- sdlInit [SDL_INIT_SENSOR]
12 |
13 | unless initSuccess $ do
14 | sdlLog "Failed to initialize SDL with sensor support!"
15 | exitFailure
16 |
17 | sdlLog "SDL initialized with sensor support"
18 |
19 | -- Get list of available sensors
20 | maybeSensors <- sdlGetSensors
21 | case maybeSensors of
22 | Nothing -> do
23 | sdlLog "No sensors found or error occurred"
24 | cleanupAndExit
25 | Just sensorIds -> do
26 | sdlLog $ "Found " ++ show (length sensorIds) ++ " sensor(s)"
27 |
28 | -- Process each sensor
29 | forM_ sensorIds $ \sensorId -> do
30 | sdlLog $ "\nProcessing sensor ID: " ++ show sensorId
31 |
32 | -- Get sensor name
33 | maybeName <- sdlGetSensorNameForID sensorId
34 | sdlLog $ "Name: " ++ maybe "Unknown" id maybeName
35 |
36 | -- Get sensor type
37 | sensorType <- sdlGetSensorTypeForID sensorId
38 | sdlLog $ "Type: " ++ show sensorType
39 |
40 | -- Open the sensor
41 | maybeSensor <- sdlOpenSensor sensorId
42 | case maybeSensor of
43 | Nothing -> sdlLog "Failed to open sensor"
44 | Just sensor -> do
45 | sdlLog "Successfully opened sensor"
46 |
47 | -- Get some sensor data (assuming 3 values for accel/gyro)
48 | maybeData <- sdlGetSensorData sensor 3
49 | case maybeData of
50 | Nothing -> sdlLog "Failed to get sensor data"
51 | Just values -> do
52 | sdlLog "Sensor data:"
53 | case sensorType of
54 | SDL_SENSOR_ACCEL -> do
55 | sdlLog $ "X acceleration: " ++ show (values !! 0) ++ " m/s²"
56 | sdlLog $ "Y acceleration: " ++ show (values !! 1) ++ " m/s²"
57 | sdlLog $ "Z acceleration: " ++ show (values !! 2) ++ " m/s²"
58 | SDL_SENSOR_GYRO -> do
59 | sdlLog $ "X rotation: " ++ show (values !! 0) ++ " rad/s"
60 | sdlLog $ "Y rotation: " ++ show (values !! 1) ++ " rad/s"
61 | sdlLog $ "Z rotation: " ++ show (values !! 2) ++ " rad/s"
62 | _ -> sdlLog $ "Raw values: " ++ show values
63 |
64 | -- Close the sensor
65 | sdlCloseSensor sensor
66 | sdlLog "Sensor closed"
67 |
68 | cleanupAndExit
69 |
70 | -- Helper function to cleanup and exit
71 | cleanupAndExit :: IO ()
72 | cleanupAndExit = do
73 | sdlLog "\nShutting down SDL..."
74 | sdlQuit
75 | sdlLog "Application terminated successfully"
76 | exitSuccess
77 |
78 | -- Helper function to display sensor type
79 | showSensorType :: SDLSensorType -> String
80 | showSensorType t = case t of
81 | SDL_SENSOR_INVALID -> "Invalid"
82 | SDL_SENSOR_UNKNOWN -> "Unknown"
83 | SDL_SENSOR_ACCEL -> "Accelerometer"
84 | SDL_SENSOR_GYRO -> "Gyroscope"
85 | SDL_SENSOR_ACCEL_L -> "Left Joy-Con Accelerometer"
86 | SDL_SENSOR_GYRO_L -> "Left Joy-Con Gyroscope"
87 | SDL_SENSOR_ACCEL_R -> "Right Joy-Con Accelerometer"
88 | SDL_SENSOR_GYRO_R -> "Right Joy-Con Gyroscope"
89 |
--------------------------------------------------------------------------------
/examples/StorageExample.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import SDL
4 | import Control.Monad
5 | import System.Exit (exitFailure, exitSuccess)
6 | import Foreign.Ptr (Ptr, nullPtr, castPtr)
7 | import Foreign.C.Types
8 | import Foreign.C.String (CString, withCString, peekCString)
9 | import Foreign.Marshal.Alloc (alloca, mallocBytes)
10 | import Foreign.Marshal.Array (copyArray)
11 | import Foreign.Storable (poke, peek)
12 | import Data.Word (Word64)
13 |
14 | main :: IO ()
15 | main = do
16 | -- Check compiled version
17 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
18 | when (sdlVersionAtLeast 3 3 0) $
19 | sdlLog "Compiled with at least SDL 3.3.0"
20 |
21 | -- Get linked version
22 | linkedVersion <- sdlGetVersion
23 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
24 |
25 | -- Get revision
26 | revision <- sdlGetRevision
27 | sdlLog $ "SDL Revision: " ++ revision
28 |
29 | -- Initialize SDL with video and events subsystems
30 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
31 | unless initSuccess $ do
32 | sdlLog "Failed to initialize SDL!"
33 | exitFailure
34 |
35 | -- Check initialized subsystems
36 | initializedSystems <- sdlWasInit []
37 | sdlLog "Initialized subsystems:"
38 | mapM_ printSubsystem initializedSystems
39 |
40 | -- Open user storage
41 | sdlLog "Opening user storage..."
42 | mStorage <- sdlOpenUserStorage "example.org" "StorageDemo" 0
43 | case mStorage of
44 | Nothing -> do
45 | sdlLog "Failed to open user storage!"
46 | sdlQuit
47 | exitFailure
48 | Just storage -> do
49 | sdlLog "User storage opened successfully."
50 |
51 | -- Wait for storage to be ready
52 | waitForStorageReady storage
53 |
54 | -- Write a test file
55 | writeTestFile storage
56 |
57 | -- Read the test file back
58 | readTestFile storage
59 |
60 | -- Enumerate directory contents
61 | listDirectory storage
62 |
63 | -- Close storage
64 | sdlLog "Closing storage..."
65 | success <- sdlCloseStorage storage
66 | unless success $ sdlLog "Failed to close storage cleanly!"
67 |
68 | -- Clean up and quit
69 | sdlLog "Shutting down SDL..."
70 | sdlQuit
71 |
72 | sdlLog "Application terminated successfully"
73 | exitSuccess
74 |
75 | -- Helper to wait for storage to be ready
76 | waitForStorageReady :: Ptr SDLStorage -> IO ()
77 | waitForStorageReady storage = do
78 | sdlLog "Waiting for storage to be ready..."
79 | let checkReady = do
80 | ready <- sdlStorageReady storage
81 | unless ready $ do
82 | sdlDelay 1
83 | checkReady
84 | checkReady
85 | sdlLog "Storage is ready."
86 |
87 | -- Write a test file
88 | writeTestFile :: Ptr SDLStorage -> IO ()
89 | writeTestFile storage = do
90 | sdlLog "Writing test file..."
91 | let content = "Hello, SDL Storage!"
92 | len = fromIntegral (length content) :: Word64
93 | contentPtr <- mallocBytes (fromIntegral len)
94 | withCString content $ \cstr -> do
95 | copyArray contentPtr cstr (fromIntegral len)
96 | success <- sdlWriteStorageFile storage "test.txt" (castPtr contentPtr) len
97 | free contentPtr -- Use Haskell's free for mallocBytes
98 | if success
99 | then sdlLog "Successfully wrote test.txt"
100 | else do
101 | sdlLog "Failed to write test.txt!"
102 | err <- sdlGetError
103 | sdlLog $ "Error: " ++ err
104 |
105 | -- Read the test file back
106 | readTestFile :: Ptr SDLStorage -> IO ()
107 | readTestFile storage = do
108 | sdlLog "Reading test file..."
109 | mSize <- sdlGetStorageFileSize storage "test.txt"
110 | case mSize of
111 | Nothing -> do
112 | sdlLog "Failed to get size of test.txt!"
113 | err <- sdlGetError
114 | sdlLog $ "Error: " ++ err
115 | Just size -> do
116 | buffer <- mallocBytes (fromIntegral size)
117 | success <- sdlReadStorageFile storage "test.txt" buffer size
118 | if success
119 | then do
120 | content <- peekCString (castPtr buffer)
121 | sdlLog $ "Read from test.txt: " ++ content
122 | else do
123 | sdlLog "Failed to read test.txt!"
124 | err <- sdlGetError
125 | sdlLog $ "Error: " ++ err
126 | free buffer -- Use Haskell's free for mallocBytes
127 |
128 | -- List directory contents
129 | listDirectory :: Ptr SDLStorage -> IO ()
130 | listDirectory storage = do
131 | sdlLog "Listing directory contents..."
132 | let callback :: Ptr () -> CString -> CString -> IO SDLEnumerationResult
133 | callback _ path name = do
134 | pathStr <- peekCString path
135 | nameStr <- peekCString name
136 | sdlLog $ " - " ++ pathStr ++ "/" ++ nameStr
137 | return SDL_ENUM_SUCCESS
138 | success <- sdlEnumerateStorageDirectory storage Nothing callback nullPtr
139 | unless success $ do
140 | sdlLog "Failed to enumerate directory!"
141 | err <- sdlGetError
142 | sdlLog $ "Error: " ++ err
143 |
144 | -- Helper function to print subsystem names
145 | printSubsystem :: SDLInitFlags -> IO ()
146 | printSubsystem flag = sdlLog $ " - " ++ case flag of
147 | SDL_INIT_AUDIO -> "Audio"
148 | SDL_INIT_VIDEO -> "Video"
149 | SDL_INIT_JOYSTICK -> "Joystick"
150 | SDL_INIT_HAPTIC -> "Haptic"
151 | SDL_INIT_GAMEPAD -> "Gamepad"
152 | SDL_INIT_EVENTS -> "Events"
153 | SDL_INIT_SENSOR -> "Sensor"
154 | SDL_INIT_CAMERA -> "Camera"
155 | _ -> "Unknown subsystem"
156 |
--------------------------------------------------------------------------------
/examples/SystemExample.hsc:
--------------------------------------------------------------------------------
1 | import SDL
2 | import Control.Monad (unless)
3 | import System.Exit (exitFailure)
4 |
5 | main :: IO ()
6 | main = do
7 | -- Initialize SDL
8 | initSuccess <- sdlInit [SDL_INIT_VIDEO]
9 | unless initSuccess $ do
10 | sdlLog "Failed to initialize SDL!"
11 | exitFailure
12 |
13 | #ifdef SDL_PLATFORM_ANDROID
14 | -- Check if running on a Chromebook
15 | isChromebook <- sdlIsChromebook
16 | sdlLog $ "Running on Chromebook: " ++ show isChromebook
17 |
18 | -- Show a toast notification
19 | success <- sdlShowAndroidToast "Hello from Haskell!" 1 (-1) 0 0
20 | sdlLog $ "Toast shown: " ++ show success
21 | #endif
22 |
23 | -- Check device type
24 | isTablet <- sdlIsTablet
25 | isTV <- sdlIsTV
26 | sdlLog $ "Device type - Tablet: " ++ show isTablet ++ ", TV: " ++ show isTV
27 |
28 | -- Check sandbox environment
29 | sandbox <- sdlGetSandbox
30 | sdlLog $ "Sandbox environment: " ++ show sandbox
31 |
32 | case sandbox of
33 | SDLSandboxNone -> sdlLog " → Running without sandbox (normal for development)"
34 | SDLSandboxMacOS -> sdlLog " → Running in macOS App Sandbox (Mac App Store app)"
35 | SDLSandboxFlatpak -> sdlLog " → Running in Flatpak sandbox"
36 | SDLSandboxSnap -> sdlLog " → Running in Snap package sandbox"
37 | SDLSandboxUnknownContainer -> sdlLog " → Running in unknown container"
38 |
39 | -- Clean up
40 | sdlQuit
41 | sdlLog "System example completed successfully"
42 |
--------------------------------------------------------------------------------
/examples/TimeExample.hs:
--------------------------------------------------------------------------------
1 | import SDL
2 |
3 | main :: IO ()
4 | main = do
5 | -- Get current time
6 | maybeTicks <- sdlGetCurrentTime
7 | case maybeTicks of
8 | Just ticks -> do
9 | sdlLog $ "Current ticks: " ++ show ticks
10 | maybeDt <- sdlTimeToDateTime ticks True
11 | sdlLog $ "Local DateTime: " ++ show maybeDt
12 | Nothing -> sdlLog "Failed to get current time"
13 |
14 | -- Get locale preferences
15 | maybePrefs <- sdlGetDateTimeLocalePreferences
16 | sdlLog $ "Locale Preferences: " ++ show maybePrefs
17 |
18 | -- Example date calculation
19 | days <- sdlGetDaysInMonth 2025 3
20 | sdlLog $ "Days in March 2025: " ++ show days
21 |
--------------------------------------------------------------------------------
/examples/TimerExample.hs:
--------------------------------------------------------------------------------
1 | import Control.Monad (when)
2 | import Foreign.Ptr (nullPtr)
3 | import SDL
4 |
5 | main :: IO ()
6 | main = do
7 | -- Measure elapsed time
8 | start <- sdlGetTicks
9 | sdlDelay 1000 -- Wait 1 second
10 | end <- sdlGetTicks
11 | sdlLog $ "Elapsed time: " ++ show (end - start) ++ " ms"
12 |
13 | -- Add a timer callback
14 | let callback :: SDLTimerCallback
15 | callback _ timerID interval = do
16 | sdlLog $ "Timer " ++ show timerID ++ " fired after " ++ show interval ++ " ms"
17 | return 0 -- Stop the timer after one run
18 | timerID <- sdlAddTimer 500 callback nullPtr
19 | when (timerID /= 0) $ do
20 | sdlLog $ "Timer added with ID: " ++ show timerID
21 | sdlDelay 1000 -- Wait to see the timer fire
22 | sdlRemoveTimer timerID >>= print
23 |
--------------------------------------------------------------------------------
/examples/TouchDeviceExample.hs:
--------------------------------------------------------------------------------
1 | import SDL
2 | import Foreign.Ptr (nullPtr)
3 |
4 | main :: IO ()
5 | main = do
6 | devices <- sdlGetTouchDevices
7 | sdlLog $ "Touch Devices: " ++ show devices
8 | case devices of
9 | (touchID:_) -> do
10 | name <- sdlGetTouchDeviceName touchID
11 | sdlLog $ "Device Name: " ++ show name
12 | devType <- sdlGetTouchDeviceType touchID
13 | sdlLog $ "Device Type: " ++ show devType
14 | fingers <- sdlGetTouchFingers touchID
15 | sdlLog $ "Active Fingers: " ++ show fingers
16 | _ -> sdlLog "No touch devices found."
17 |
--------------------------------------------------------------------------------
/examples/TrayExample.hs:
--------------------------------------------------------------------------------
1 | -- examples/TrayExample.hs
2 |
3 | import Control.Concurrent (threadDelay)
4 | import Control.Monad (unless, when)
5 | import Data.IORef
6 | import Foreign.Ptr (nullPtr)
7 | import Foreign.Storable (peek)
8 | import SDL
9 | import System.Exit (exitFailure, exitSuccess)
10 |
11 | main :: IO ()
12 | main = do
13 | -- Check compiled version
14 | sdlLog $ "Compiled SDL Version: " ++ show sdlVersion
15 | when (sdlVersionAtLeast 3 3 0) $ sdlLog "Compiled with at least SDL 3.3.0"
16 |
17 | -- Get linked version
18 | linkedVersion <- sdlGetVersion
19 | sdlLog $ "Linked SDL Version: " ++ show linkedVersion
20 |
21 | -- Initialize SDL with video and events subsystems
22 | initSuccess <- sdlInit [SDL_INIT_VIDEO, SDL_INIT_EVENTS]
23 | unless initSuccess $ do
24 | err <- sdlGetError
25 | sdlLog $ "Failed to initialize SDL: " ++ err
26 | exitFailure
27 |
28 | -- Check what subsystems are initialized
29 | initializedSystems <- sdlWasInit []
30 | sdlLog "Initialized subsystems:"
31 | mapM_ printSubsystem initializedSystems
32 |
33 | -- Load the tray icon
34 | mSurfacePtr <- sdlLoadBMP "examples/Content/Images/ravioli.bmp"
35 | case mSurfacePtr of
36 | Nothing -> do
37 | err <- sdlGetError
38 | sdlLog $ "Failed to load ravioli.bmp: " ++ err
39 | sdlQuit
40 | exitFailure
41 | Just surfacePtr -> do
42 | -- Inspect the surface
43 | surface <- peek surfacePtr
44 | sdlLog $ "Surface details: " ++ show surface
45 |
46 | -- Create the tray
47 | mTray <- sdlCreateTray (Just surfacePtr) (Just "SDL3 Haskell Tray Example")
48 | case mTray of
49 | Nothing -> do
50 | err <- sdlGetError
51 | sdlLog $ "Failed to create tray: " ++ err
52 | sdlDestroySurface surfacePtr
53 | sdlQuit
54 | exitFailure
55 | Just tray -> do
56 | sdlSetTrayIcon tray (Just surfacePtr)
57 | sdlSetTrayTooltip tray (Just "SDL3 Haskell Tray Example - Use menu to quit")
58 |
59 | -- Create a quit flag that can be shared between callbacks and main loop
60 | quitFlag <- newIORef False
61 |
62 | -- Create a simple menu for the tray
63 | mMenu <- sdlCreateTrayMenu tray
64 | case mMenu of
65 | Nothing -> do
66 | err <- sdlGetError
67 | sdlLog $ "Failed to create tray menu: " ++ err
68 | Just menu -> do
69 | -- Add menu entries
70 | mEntry1 <- sdlInsertTrayEntryAt menu 0 (Just "Hello from Haskell!") SDL_TRAYENTRY_BUTTON
71 | case mEntry1 of
72 | Nothing -> do
73 | err <- sdlGetError
74 | sdlLog $ "Failed to create menu entry 1: " ++ err
75 | Just entry1 -> do
76 | sdlLog "Menu entry 1 created successfully"
77 | sdlSetTrayEntryCallback entry1 (Just (helloCallback, nullPtr))
78 |
79 | -- Add a separator and quit entry
80 | mEntry2 <- sdlInsertTrayEntryAt menu 1 (Just "Quit Application") SDL_TRAYENTRY_BUTTON
81 | case mEntry2 of
82 | Nothing -> do
83 | err <- sdlGetError
84 | sdlLog $ "Failed to create menu entry 2: " ++ err
85 | Just entry2 -> do
86 | sdlLog "Menu entry 2 created successfully"
87 | -- Pass the quit flag to the callback
88 | sdlSetTrayEntryCallback entry2 (Just (quitCallback quitFlag, nullPtr))
89 |
90 | -- Update the trays to ensure changes are reflected
91 | sdlUpdateTrays
92 |
93 | sdlLog "Tray created with menu. Try right-clicking the tray icon to see the menu."
94 | sdlLog "Use the 'Quit Application' menu item to exit."
95 |
96 | -- Start simple event loop
97 | eventLoop tray quitFlag
98 |
99 | -- Cleanup
100 | sdlDestroyTray tray
101 | sdlDestroySurface surfacePtr
102 | sdlLog "Tray destroyed."
103 |
104 | sdlLog "Shutting down SDL..."
105 | sdlQuit
106 | sdlLog "Application terminated successfully"
107 | exitSuccess
108 |
109 | -- | Simple event loop that checks for quit flag and SDL quit events
110 | eventLoop :: SDLTray -> IORef Bool -> IO ()
111 | eventLoop tray quitFlag = do
112 | -- Check if quit was requested from tray menu
113 | shouldQuit <- readIORef quitFlag
114 |
115 | if shouldQuit
116 | then do
117 | sdlLog "Quit requested from tray menu."
118 | return ()
119 | else do
120 | -- Check for SDL quit events (like Ctrl+C)
121 | sdlPumpEvents
122 | maybeEvent <- sdlPollEvent
123 | case maybeEvent of
124 | Just (SDLEventQuit _) -> do
125 | sdlLog "SDL quit event received."
126 | return ()
127 | _ -> do
128 | -- Sleep for a short time to avoid busy waiting
129 | threadDelay 100000 -- 100ms
130 | eventLoop tray quitFlag
131 |
132 | -- Simple callback for menu entry clicks
133 | helloCallback :: SDLTrayCallback
134 | helloCallback _ _ = do
135 | sdlLog "Hello menu entry clicked!"
136 |
137 | -- Quit callback for menu entry clicks
138 | quitCallback :: IORef Bool -> SDLTrayCallback
139 | quitCallback quitFlag _ _ = do
140 | sdlLog "Quit menu entry clicked - quitting application!"
141 | writeIORef quitFlag True
142 |
143 | -- Helper function to print subsystem names
144 | printSubsystem :: SDLInitFlags -> IO ()
145 | printSubsystem flag =
146 | sdlLog $
147 | " - " ++ case flag of
148 | SDL_INIT_AUDIO -> "Audio"
149 | SDL_INIT_VIDEO -> "Video"
150 | SDL_INIT_JOYSTICK -> "Joystick"
151 | SDL_INIT_HAPTIC -> "Haptic"
152 | SDL_INIT_GAMEPAD -> "Gamepad"
153 | SDL_INIT_EVENTS -> "Events"
154 | SDL_INIT_SENSOR -> "Sensor"
155 | SDL_INIT_CAMERA -> "Camera"
156 | _ -> "Unknown subsystem"
157 |
--------------------------------------------------------------------------------
/hie.yaml:
--------------------------------------------------------------------------------
1 | cradle:
2 | cabal:
3 | - path: "./src"
4 | component: "lib:sdl3"
5 | - path: "./examples/AudioExample.hs"
6 | component: "exe:audio"
7 | - path: "./examples/CameraExample.hs"
8 | component: "exe:camera"
9 | - path: "./examples/ClipboardExample.hs"
10 | component: "exe:clipboard"
11 | - path: "./examples/CPUInfoExample.hs"
12 | component: "exe:cpu-info"
13 | - path: "./examples/DialogExample.hs"
14 | component: "exe:dialog"
15 | - path: "./examples/EventsExample.hs"
16 | component: "exe:events"
17 | - path: "./examples/FilesystemExample.hs"
18 | component: "exe:filesystem"
19 | - path: "./examples/GamepadExample.hs"
20 | component: "exe:gamepad"
21 | - path: "./examples/GPUBasicComputeExample.hs"
22 | component: "exe:gpu-basiccompute"
23 | - path: "./examples/GPUClearExample.hs"
24 | component: "exe:gpu-clear"
25 | - path: "./examples/GPUClear3DSliceExample.hs"
26 | component: "exe:gpu-clear3dslice"
27 | - path: "./examples/GPUComputeUniformsExample.hs"
28 | component: "exe:gpu-computeuniforms"
29 | - path: "./examples/GPUCopyConsistencyExample.hs"
30 | component: "exe:gpu-copyconsistency"
31 | - path: "./examples/GPUCopyAndReadbackExample.hs"
32 | component: "exe:gpu-copyreadback"
33 | - path: "./examples/GPUCullExample.hs"
34 | component: "exe:gpu-cull"
35 | - path: "./examples/GPUComputeSamplerExample.hs"
36 | component: "exe:gpu-computesampler"
37 | - path: "./examples/GPUCustomSamplingExample.hs"
38 | component: "exe:gpu-customsampling"
39 | - path: "./examples/GPUDrawIndirectExample.hs"
40 | component: "exe:gpu-drawindirect"
41 | - path: "./examples/GPUInstancedExample.hs"
42 | component: "exe:gpu-instanced"
43 | - path: "./examples/GPUMultiWindowExample.hs"
44 | component: "exe:gpu-multiwindow"
45 | - path: "./examples/GPUStencilExample.hs"
46 | component: "exe:gpu-stencil"
47 | - path: "./examples/GPUAnimatedQuadExample.hs"
48 | component: "exe:gpu-animatedquad"
49 | - path: "./examples/GPUTexturedQuadExample.hs"
50 | component: "exe:gpu-texturedquad"
51 | - path: "./examples/GPUTonemappingExample.hs"
52 | component: "exe:gpu-tonemapping"
53 | - path: "./examples/GPURawTriangleExample.hs"
54 | component: "exe:gpu-triangle"
55 | - path: "./examples/GPUVertexBufferExample.hs"
56 | component: "exe:gpu-vbuf"
57 | - path: "./examples/GUIDExample.hs"
58 | component: "exe:guid"
59 | - path: "./examples/HapticExample.hs"
60 | component: "exe:haptic"
61 | - path: "./examples/HintsExample.hs"
62 | component: "exe:hints"
63 | - path: "./examples/InitExample.hs"
64 | component: "exe:init"
65 | - path: "./examples/LocaleExample.hs"
66 | component: "exe:locale"
67 | - path: "./examples/MessageBoxExample.hs"
68 | component: "exe:messagebox"
69 | - path: "./examples/PlatformExample.hs"
70 | component: "exe:platform"
71 | - path: "./examples/PowerExample.hs"
72 | component: "exe:power"
73 | - path: "./examples/ProcessExample.hs"
74 | component: "exe:process"
75 | - path: "./examples/RectExample.hs"
76 | component: "exe:rect"
77 | - path: "./examples/RenderExample.hs"
78 | component: "exe:render"
79 | - path: "./examples/SensorExample.hs"
80 | component: "exe:sensor"
81 | - path: "./examples/StorageExample.hs"
82 | component: "exe:storage"
83 | - path: "./examples/SystemExample.hs"
84 | component: "exe:system"
85 | - path: "./examples/TimeExample.hs"
86 | component: "exe:time"
87 | - path: "./examples/TimerExample.hs"
88 | component: "exe:timer"
89 | - path: "./examples/TouchDeviceExample.hs"
90 | component: "exe:touch-device"
91 | - path: "./examples/TrayExample.hs"
92 | component: "exe:tray"
93 | - path: "./examples/WAVExample.hs"
94 | component: "exe:wav"
95 | - path: "./test/binding-checker.hs"
96 | component: "exe:binding-checker"
97 |
--------------------------------------------------------------------------------
/include/helpers.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | void wrapper_SDL_GUIDToString(Uint8 *guid_data, char *pszGUID, int cbGUID);
4 | void wrapper_SDL_StringToGUID(const char *pchGUID, Uint8 *guid_data);
5 |
6 |
--------------------------------------------------------------------------------
/src/SDL.hs:
--------------------------------------------------------------------------------
1 | -- Main module
2 | module SDL
3 | ( module SDL.Assert,
4 | module SDL.AsyncIO,
5 | module SDL.Atomic,
6 | module SDL.Audio,
7 | module SDL.Bits,
8 | module SDL.BlendMode,
9 | module SDL.Camera,
10 | module SDL.Clipboard,
11 | module SDL.CPUInfo,
12 | module SDL.Dialog,
13 | module SDL.Endian,
14 | module SDL.Error,
15 | module SDL.Events,
16 | module SDL.Filesystem,
17 | module SDL.Gamepad,
18 | module SDL.GPU,
19 | module SDL.GUID,
20 | module SDL.Haptic,
21 | module SDL.Hidapi,
22 | module SDL.Hints,
23 | module SDL.IOStream,
24 | module SDL.Init,
25 | module SDL.Joystick,
26 | module SDL.Keyboard,
27 | module SDL.Keycode,
28 | module SDL.Locale,
29 | module SDL.LoadSO,
30 | module SDL.Log,
31 | module SDL.MessageBox,
32 | module SDL.Metal,
33 | module SDL.Misc,
34 | module SDL.Mouse,
35 | module SDL.Mutex,
36 | module SDL.Pen,
37 | module SDL.Pixels,
38 | module SDL.Platform,
39 | module SDL.Power,
40 | module SDL.Process,
41 | module SDL.Properties,
42 | module SDL.Rect,
43 | module SDL.Render,
44 | module SDL.Scancode,
45 | module SDL.Sensor,
46 | module SDL.Stdinc,
47 | module SDL.Storage,
48 | module SDL.Surface,
49 | module SDL.System,
50 | module SDL.Thread,
51 | module SDL.Time,
52 | module SDL.Timer,
53 | module SDL.Touch,
54 | module SDL.Tray,
55 | module SDL.Version,
56 | module SDL.Video,
57 | )
58 | where
59 |
60 | import SDL.Assert
61 | import SDL.AsyncIO
62 | import SDL.Atomic
63 | import SDL.Audio
64 | import SDL.Bits
65 | import SDL.BlendMode
66 | import SDL.CPUInfo
67 | import SDL.Camera
68 | import SDL.Clipboard
69 | import SDL.Dialog
70 | import SDL.Endian
71 | import SDL.Error
72 | import SDL.Events
73 | import SDL.Filesystem
74 | import SDL.GPU
75 | import SDL.GUID
76 | import SDL.Gamepad
77 | import SDL.Haptic
78 | import SDL.Hidapi
79 | import SDL.Hints
80 | import SDL.IOStream
81 | import SDL.Init
82 | import SDL.Joystick
83 | import SDL.Keyboard
84 | import SDL.Keycode
85 | import SDL.LoadSO
86 | import SDL.Locale
87 | import SDL.Log
88 | import SDL.MessageBox
89 | import SDL.Metal
90 | import SDL.Misc
91 | import SDL.Mouse
92 | import SDL.Mutex
93 | import SDL.Pen
94 | import SDL.Pixels
95 | import SDL.Platform
96 | import SDL.Power
97 | import SDL.Process
98 | import SDL.Properties
99 | import SDL.Rect
100 | import SDL.Render
101 | import SDL.Scancode
102 | import SDL.Sensor
103 | import SDL.Stdinc
104 | import SDL.Storage
105 | import SDL.Surface
106 | import SDL.System
107 | import SDL.Thread
108 | import SDL.Time
109 | import SDL.Timer
110 | import SDL.Touch
111 | import SDL.Tray
112 | import SDL.Version
113 | import SDL.Video
114 |
--------------------------------------------------------------------------------
/src/SDL/Assert.hsc:
--------------------------------------------------------------------------------
1 | {-|
2 | Module : SDL.Assert
3 | Description : Bindings to SDL assertion functionality
4 | Copyright : (c) Kyle Lukaszek, 2025
5 | License : BSD3
6 |
7 | This module provides Haskell bindings to the SDL assertion functionality.
8 | SDL assertions operate like your usual assert macro, but with additional features.
9 | -}
10 |
11 | module SDL.Assert
12 | (
13 | -- * Types
14 | SDLAssertState(..)
15 | , SDLAssertData(..)
16 | , SDLAssertionHandler
17 |
18 | -- * Functions
19 | , sdlReportAssertion
20 | , sdlSetAssertionHandler
21 | , sdlGetDefaultAssertionHandler
22 | , sdlGetAssertionHandler
23 | , sdlGetAssertionReport
24 | , sdlResetAssertionReport
25 |
26 | -- * Assertion macros (as functions in Haskell)
27 | , sdlAssert
28 | , sdlAssertRelease
29 | , sdlAssertParanoid
30 | , sdlAssertAlways
31 | , sdlTriggerBreakpoint
32 |
33 | -- * Constants
34 | , sdlAssertLevel
35 | ) where
36 |
37 | import Foreign.Ptr
38 | import Foreign.C.Types
39 | import Foreign.C.String
40 | import Control.Monad
41 | import SDL.Stdinc (SDLBool)
42 |
43 | -- | Possible outcomes from a triggered assertion
44 | data SDLAssertState =
45 | SDL_ASSERTION_RETRY -- ^ Retry the assert immediately
46 | | SDL_ASSERTION_BREAK -- ^ Make the debugger trigger a breakpoint
47 | | SDL_ASSERTION_ABORT -- ^ Terminate the program
48 | | SDL_ASSERTION_IGNORE -- ^ Ignore the assert
49 | | SDL_ASSERTION_ALWAYS_IGNORE -- ^ Ignore the assert from now on
50 | deriving (Eq, Show, Enum)
51 |
52 | -- | Information about an assertion failure
53 | data SDLAssertData = SDLAssertData {
54 | alwaysIgnore :: Bool, -- ^ true if app should always continue when assertion is triggered
55 | triggerCount :: Word, -- ^ Number of times this assertion has been triggered
56 | condition :: String, -- ^ A string of this assert's test code
57 | filename :: String, -- ^ The source file where this assert lives
58 | linenum :: Int, -- ^ The line in `filename` where this assert lives
59 | function :: String, -- ^ The name of the function where this assert lives
60 | next :: Maybe SDLAssertData -- ^ next item in the linked list
61 | }
62 |
63 | -- | Foreign representation of the SDLAssertData structure
64 | data SDLAssertDataFFI
65 |
66 | -- | Callback type for custom assertion handlers
67 | type SDLAssertionHandler = Ptr SDLAssertDataFFI -> Ptr () -> IO CInt
68 |
69 | -- | The level of assertion aggressiveness
70 | sdlAssertLevel :: Int
71 | #ifdef DEBUG
72 | sdlAssertLevel = 2 -- Debug settings
73 | #else
74 | sdlAssertLevel = 1 -- Release settings
75 | #endif
76 |
77 | -- | Report an assertion failure
78 | foreign import ccall unsafe "SDL_ReportAssertion"
79 | sdlReportAssertion :: Ptr SDLAssertDataFFI -> CString -> CString -> CInt -> IO CInt
80 |
81 | -- | Set an application-defined assertion handler
82 | foreign import ccall unsafe "SDL_SetAssertionHandler"
83 | sdlSetAssertionHandler :: FunPtr SDLAssertionHandler -> Ptr () -> IO ()
84 |
85 | -- | Get the default assertion handler
86 | foreign import ccall unsafe "SDL_GetDefaultAssertionHandler"
87 | sdlGetDefaultAssertionHandler :: IO (FunPtr SDLAssertionHandler)
88 |
89 | -- | Get the current assertion handler
90 | foreign import ccall unsafe "SDL_GetAssertionHandler"
91 | sdlGetAssertionHandler :: Ptr (Ptr ()) -> IO (FunPtr SDLAssertionHandler)
92 |
93 | -- | Get a list of all assertion failures
94 | foreign import ccall unsafe "SDL_GetAssertionReport"
95 | sdlGetAssertionReport :: IO (Ptr SDLAssertDataFFI)
96 |
97 | -- | Clear the list of all assertion failures
98 | foreign import ccall unsafe "SDL_ResetAssertionReport"
99 | sdlResetAssertionReport :: IO ()
100 |
101 | -- | Attempt to tell an attached debugger to pause
102 | foreign import ccall unsafe "SDL_TriggerBreakpoint"
103 | sdlTriggerBreakpoint :: IO ()
104 |
105 | -- | Implementation for SDL_assert as a Haskell function
106 | --
107 | -- The original C macro uses compile-time magic to enable/disable assertions,
108 | -- but in Haskell we need to use runtime checking.
109 | sdlAssert :: Bool -> IO ()
110 | #if defined(DEBUG) || (sdlAssertLevel >= 2)
111 | sdlAssert condition = unless condition $ sdlAssertHelper "assertion failed"
112 | #else
113 | sdlAssert _ = return ()
114 | #endif
115 |
116 | -- | Implementation for SDL_assert_release as a Haskell function
117 | sdlAssertRelease :: Bool -> IO ()
118 | #if (sdlAssertLevel >= 1)
119 | sdlAssertRelease condition = unless condition $ sdlAssertHelper "release assertion failed"
120 | #else
121 | sdlAssertRelease _ = return ()
122 | #endif
123 |
124 | -- | Implementation for SDL_assert_paranoid as a Haskell function
125 | sdlAssertParanoid :: Bool -> IO ()
126 | #if (sdlAssertLevel >= 3)
127 | sdlAssertParanoid condition = unless condition $ sdlAssertHelper "paranoid assertion failed"
128 | #else
129 | sdlAssertParanoid _ = return ()
130 | #endif
131 |
132 | -- | Implementation for SDL_assert_always as a Haskell function
133 | sdlAssertAlways :: Bool -> IO ()
134 | sdlAssertAlways condition = unless condition $ sdlAssertHelper "assertion failed"
135 |
136 | -- | Helper function for assertion implementations
137 | sdlAssertHelper :: String -> IO ()
138 | sdlAssertHelper msg = do
139 | putStrLn $ "SDL assertion: " ++ msg
140 | sdlTriggerBreakpoint
141 |
--------------------------------------------------------------------------------
/src/SDL/AsyncIO.hsc:
--------------------------------------------------------------------------------
1 | {-|
2 | Module : SDL.AsyncIO
3 | Description : Bindings to SDL asynchronous I/O functionality
4 | Copyright : (c) Kyle Lukaszek, 2025
5 | License : BS3
6 |
7 | This module provides Haskell bindings to SDL's asynchronous I/O functionality.
8 | SDL offers a way to perform I/O asynchronously, allowing an app to read
9 | or write files without waiting for data to actually transfer.
10 | -}
11 |
12 | module SDL.AsyncIO
13 | (
14 | -- * Types
15 | SDLAsyncIO
16 | , SDLAsyncIOTaskType(..)
17 | , SDLAsyncIOResult(..)
18 | , SDLAsyncIOOutcome(..)
19 | , SDLAsyncIOQueue
20 |
21 | -- * Functions
22 | , sdlAsyncIOFromFile
23 | , sdlGetAsyncIOSize
24 | , sdlReadAsyncIO
25 | , sdlWriteAsyncIO
26 | , sdlCloseAsyncIO
27 | , sdlCreateAsyncIOQueue
28 | , sdlDestroyAsyncIOQueue
29 | , sdlGetAsyncIOResult
30 | , sdlWaitAsyncIOResult
31 | , sdlSignalAsyncIOQueue
32 | , sdlLoadFileAsync
33 | ) where
34 |
35 | import Foreign.Ptr
36 | import Foreign.C.Types
37 | import Foreign.C.String
38 | import SDL.Stdinc (SDLBool)
39 | import Data.Word
40 | import Data.Int
41 |
42 | -- | The asynchronous I/O operation structure.
43 | data SDLAsyncIO = SDLAsyncIO
44 |
45 | -- | Types of asynchronous I/O tasks.
46 | data SDLAsyncIOTaskType =
47 | SDL_ASYNCIO_TASK_READ -- ^ A read operation.
48 | | SDL_ASYNCIO_TASK_WRITE -- ^ A write operation.
49 | | SDL_ASYNCIO_TASK_CLOSE -- ^ A close operation.
50 | deriving (Eq, Show, Enum)
51 |
52 | -- | Possible outcomes of an asynchronous I/O task.
53 | data SDLAsyncIOResult =
54 | SDL_ASYNCIO_COMPLETE -- ^ Request was completed without error
55 | | SDL_ASYNCIO_FAILURE -- ^ Request failed for some reason; check SDL_GetError()!
56 | | SDL_ASYNCIO_CANCELED -- ^ Request was canceled before completing.
57 | deriving (Eq, Show, Enum)
58 |
59 | -- | Information about a completed asynchronous I/O request.
60 | data SDLAsyncIOOutcome = SDL_AsyncIOOutcome
61 | { asyncio :: Ptr SDLAsyncIO -- ^ What generated this task. This pointer will be invalid if it was closed!
62 | , taskType :: SDLAsyncIOTaskType -- ^ What sort of task was this? Read, write, etc?
63 | , result :: SDLAsyncIOResult -- ^ The result of the work (success, failure, cancellation).
64 | , buffer :: Ptr () -- ^ Buffer where data was read/written.
65 | , offset :: Word64 -- ^ Offset in the SDL_AsyncIO where data was read/written.
66 | , bytesRequested :: Word64 -- ^ Number of bytes the task was to read/write.
67 | , bytesTransferred :: Word64 -- ^ Actual number of bytes that were read/written.
68 | , userdata :: Ptr () -- ^ Pointer provided by the app when starting the task
69 | }
70 |
71 | -- | A queue of completed asynchronous I/O tasks.
72 | data SDLAsyncIOQueue
73 |
74 | -- Foreign structure for SDL_AsyncIOOutcome
75 | data SDLAsyncIOOutcomeFFI
76 |
77 | -- | Create a new SDL_AsyncIO object for reading from and/or writing to a named file.
78 | foreign import ccall unsafe "SDL_AsyncIOFromFile"
79 | sdlAsyncIOFromFile :: CString -> CString -> IO (Ptr SDLAsyncIO)
80 |
81 | -- | Get the size of the data stream in an SDL_AsyncIO.
82 | foreign import ccall unsafe "SDL_GetAsyncIOSize"
83 | sdlGetAsyncIOSize :: Ptr SDLAsyncIO -> IO Int64
84 |
85 | -- | Start an async read.
86 | foreign import ccall unsafe "SDL_ReadAsyncIO"
87 | sdlReadAsyncIO :: Ptr SDLAsyncIO -> Ptr () -> Word64 -> Word64 -> Ptr SDLAsyncIOQueue -> Ptr () -> IO SDLBool
88 |
89 | -- | Start an async write.
90 | foreign import ccall unsafe "SDL_WriteAsyncIO"
91 | sdlWriteAsyncIO :: Ptr SDLAsyncIO -> Ptr () -> Word64 -> Word64 -> Ptr SDLAsyncIOQueue -> Ptr () -> IO SDLBool
92 |
93 | -- | Close and free any allocated resources for an async I/O object.
94 | foreign import ccall unsafe "SDL_CloseAsyncIO"
95 | sdlCloseAsyncIO :: Ptr SDLAsyncIO -> SDLBool -> Ptr SDLAsyncIOQueue -> Ptr () -> IO SDLBool
96 |
97 | -- | Create a task queue for tracking multiple I/O operations.
98 | foreign import ccall unsafe "SDL_CreateAsyncIOQueue"
99 | sdlCreateAsyncIOQueue :: IO (Ptr SDLAsyncIOQueue)
100 |
101 | -- | Destroy a previously-created async I/O task queue.
102 | foreign import ccall unsafe "SDL_DestroyAsyncIOQueue"
103 | sdlDestroyAsyncIOQueue :: Ptr SDLAsyncIOQueue -> IO ()
104 |
105 | -- | Query an async I/O task queue for completed tasks.
106 | foreign import ccall unsafe "SDL_GetAsyncIOResult"
107 | sdlGetAsyncIOResult :: Ptr SDLAsyncIOQueue -> Ptr SDLAsyncIOOutcomeFFI -> IO SDLBool
108 |
109 | -- | Block until an async I/O task queue has a completed task.
110 | foreign import ccall unsafe "SDL_WaitAsyncIOResult"
111 | sdlWaitAsyncIOResult :: Ptr SDLAsyncIOQueue -> Ptr SDLAsyncIOOutcomeFFI -> Int32 -> IO SDLBool
112 |
113 | -- | Wake up any threads that are blocking in SDL_WaitAsyncIOResult().
114 | foreign import ccall unsafe "SDL_SignalAsyncIOQueue"
115 | sdlSignalAsyncIOQueue :: Ptr SDLAsyncIOQueue -> IO ()
116 |
117 | -- | Load all the data from a file path, asynchronously.
118 | foreign import ccall unsafe "SDL_LoadFileAsync"
119 | sdlLoadFileAsync :: CString -> Ptr SDLAsyncIOQueue -> Ptr () -> IO SDLBool
120 |
--------------------------------------------------------------------------------
/src/SDL/Bits.hs:
--------------------------------------------------------------------------------
1 | {-|
2 | Module : SDL.Bits
3 | Description : Bit manipulation functions
4 | Copyright : (c) Kyle Lukaszek, 2025
5 | License : BSD3
6 |
7 | Functions for fiddling with bits and bitmasks.
8 | -}
9 |
10 | module SDL.Bits
11 | ( -- * Bit Manipulation Functions
12 | sdlMostSignificantBitIndex32
13 | , sdlHasExactlyOneBitSet32
14 | ) where
15 |
16 | import Data.Word
17 | import Data.Bits
18 |
19 | -- | Get the index of the most significant (set) bit in a 32-bit number.
20 | --
21 | -- Result is undefined when called with 0. This operation can also be stated
22 | -- as "count leading zeroes" and "log base 2".
23 | --
24 | -- The function returns -1 if the input value is 0.
25 | --
26 | -- @since 3.2.0
27 | sdlMostSignificantBitIndex32 :: Word32 -> Int
28 | sdlMostSignificantBitIndex32 0 = -1
29 | sdlMostSignificantBitIndex32 x = go x 0
30 | where
31 | go :: Word32 -> Int -> Int
32 | go 0 _ = -1
33 | go 1 acc = acc
34 | go n acc = go (n `shiftR` 1) (acc + 1)
35 |
36 | -- | Determine if a unsigned 32-bit value has exactly one bit set.
37 | --
38 | -- If there are no bits set (x is zero), or more than one bit set, this
39 | -- returns False. If any one bit is exclusively set, this returns True.
40 | --
41 | -- @since 3.2.0
42 | sdlHasExactlyOneBitSet32 :: Word32 -> Bool
43 | sdlHasExactlyOneBitSet32 0 = False
44 | sdlHasExactlyOneBitSet32 x = x .&. (x - 1) == 0
45 |
--------------------------------------------------------------------------------
/src/SDL/CPUInfo.hsc:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE CPP #-}
2 | {-# LANGUAGE ForeignFunctionInterface #-}
3 |
4 | #include
5 |
6 | {-|
7 | Module : SDL.CPUInfo
8 | Description : CPU feature detection for SDL
9 | Copyright : (c) Kyle Lukaszek, 2025
10 | License : BSD3
11 |
12 | This module provides bindings to SDL's CPU information and feature detection functionality.
13 | It allows checking for various SIMD instruction sets and getting information about the system's
14 | CPU configuration.
15 |
16 | The CPU instruction set checks are available on all platforms, though they'll return False
17 | when checking for features that aren't applicable to the current CPU architecture
18 | (e.g., checking for SSE on ARM or NEON on x86).
19 | -}
20 |
21 | module SDL.CPUInfo
22 | ( -- * Constants
23 | sdlCachelineSize
24 |
25 | -- * CPU Information
26 | , sdlGetNumLogicalCPUCores
27 | , sdlGetCPUCacheLineSize
28 | , sdlGetSystemRAM
29 | , sdlGetSIMDAlignment
30 |
31 | -- * CPU Feature Detection
32 | -- ** PowerPC Features
33 | , sdlHasAltiVec
34 |
35 | -- ** x86 Features
36 | , sdlHasMMX
37 | , sdlHasSSE
38 | , sdlHasSSE2
39 | , sdlHasSSE3
40 | , sdlHasSSE41
41 | , sdlHasSSE42
42 | , sdlHasAVX
43 | , sdlHasAVX2
44 | , sdlHasAVX512F
45 |
46 | -- ** ARM Features
47 | , sdlHasARMSIMD
48 | , sdlHasNEON
49 |
50 | -- ** LOONGARCH Features
51 | , sdlHasLSX
52 | , sdlHasLASX
53 | ) where
54 |
55 | import Foreign.C.Types
56 | import Data.Word
57 | import Data.Int
58 |
59 | -- | A guess for the cacheline size used for padding.
60 | -- Most x86 processors have a 64 byte cache line.
61 | -- 64-bit PowerPC processors have a 128 byte cache line.
62 | -- We use the larger value to be generally safe.
63 | sdlCachelineSize :: Int
64 | sdlCachelineSize = #{const SDL_CACHELINE_SIZE}
65 |
66 | -- | Get the number of logical CPU cores available.
67 | foreign import ccall "SDL_GetNumLogicalCPUCores"
68 | sdlGetNumLogicalCPUCores :: IO CInt
69 |
70 | -- | Get the L1 cache line size of the CPU in bytes.
71 | foreign import ccall "SDL_GetCPUCacheLineSize"
72 | sdlGetCPUCacheLineSize :: IO CInt
73 |
74 | -- | Check if the CPU has AltiVec features (PowerPC).
75 | foreign import ccall "SDL_HasAltiVec"
76 | sdlHasAltiVec :: IO Bool
77 |
78 | -- | Check if the CPU has MMX features (x86).
79 | foreign import ccall "SDL_HasMMX"
80 | sdlHasMMX :: IO Bool
81 |
82 | -- | Check if the CPU has SSE features (x86).
83 | foreign import ccall "SDL_HasSSE"
84 | sdlHasSSE :: IO Bool
85 |
86 | -- | Check if the CPU has SSE2 features (x86).
87 | foreign import ccall "SDL_HasSSE2"
88 | sdlHasSSE2 :: IO Bool
89 |
90 | -- | Check if the CPU has SSE3 features (x86).
91 | foreign import ccall "SDL_HasSSE3"
92 | sdlHasSSE3 :: IO Bool
93 |
94 | -- | Check if the CPU has SSE4.1 features (x86).
95 | foreign import ccall "SDL_HasSSE41"
96 | sdlHasSSE41 :: IO Bool
97 |
98 | -- | Check if the CPU has SSE4.2 features (x86).
99 | foreign import ccall "SDL_HasSSE42"
100 | sdlHasSSE42 :: IO Bool
101 |
102 | -- | Check if the CPU has AVX features (x86).
103 | foreign import ccall "SDL_HasAVX"
104 | sdlHasAVX :: IO Bool
105 |
106 | -- | Check if the CPU has AVX2 features (x86).
107 | foreign import ccall "SDL_HasAVX2"
108 | sdlHasAVX2 :: IO Bool
109 |
110 | -- | Check if the CPU has AVX-512F (foundation) features (x86).
111 | foreign import ccall "SDL_HasAVX512F"
112 | sdlHasAVX512F :: IO Bool
113 |
114 | -- | Check if the CPU has ARM SIMD (ARMv6) features.
115 | foreign import ccall "SDL_HasARMSIMD"
116 | sdlHasARMSIMD :: IO Bool
117 |
118 | -- | Check if the CPU has NEON (ARM SIMD) features.
119 | foreign import ccall "SDL_HasNEON"
120 | sdlHasNEON :: IO Bool
121 |
122 | -- | Check if the CPU has LSX (LOONGARCH SIMD) features.
123 | foreign import ccall "SDL_HasLSX"
124 | sdlHasLSX :: IO Bool
125 |
126 | -- | Check if the CPU has LASX (LOONGARCH SIMD) features.
127 | foreign import ccall "SDL_HasLASX"
128 | sdlHasLASX :: IO Bool
129 |
130 | -- | Get the amount of RAM configured in the system in MiB.
131 | foreign import ccall "SDL_GetSystemRAM"
132 | sdlGetSystemRAM :: IO CInt
133 |
134 | -- | Get the alignment needed for SIMD allocations on this system.
135 | foreign import ccall "SDL_GetSIMDAlignment"
136 | sdlGetSIMDAlignment :: IO #{type size_t}
137 |
--------------------------------------------------------------------------------
/src/SDL/Endian.hsc:
--------------------------------------------------------------------------------
1 | {-|
2 | Module : SDL.Endian
3 | Description : Byte order conversion functions
4 | Copyright : (c) Kyle Lukaszek, 2025
5 | License : BSD3
6 |
7 | Functions for converting values between different byte orders.
8 | -}
9 |
10 | {-# LANGUAGE CPP #-}
11 |
12 | module SDL.Endian
13 | ( -- * Endianness Constants
14 | sdlLilEndian
15 | , sdlBigEndian
16 | , sdlByteOrder
17 | , sdlFloatWordOrder
18 | -- * Byte Swapping Functions
19 | , sdlSwap16
20 | , sdlSwap32
21 | , sdlSwap64
22 | , sdlSwapFloat
23 | -- * Endian Conversion Macros
24 | , sdlSwap16LE
25 | , sdlSwap32LE
26 | , sdlSwap64LE
27 | , sdlSwapFloatLE
28 | , sdlSwap16BE
29 | , sdlSwap32BE
30 | , sdlSwap64BE
31 | , sdlSwapFloatBE
32 | ) where
33 |
34 | import Foreign.C.Types
35 | import Data.Word
36 | import Data.Bits
37 | import Unsafe.Coerce (unsafeCoerce)
38 |
39 | -- | Represents little-endian byte order
40 | sdlLilEndian :: Int
41 | sdlLilEndian = 1234
42 |
43 | -- | Represents big-endian byte order
44 | sdlBigEndian :: Int
45 | sdlBigEndian = 4321
46 |
47 | {-|
48 | Indicates the byte order of the current system.
49 | Will be either 'sdlLilEndian' or 'sdlBigEndian'.
50 | -}
51 | -- This should be set based on architecture, but for now we'll default to little endian
52 | -- which is the most common
53 | sdlByteOrder :: Int
54 | #if defined(WORDS_BIGENDIAN)
55 | sdlByteOrder = sdlBigEndian
56 | #else
57 | sdlByteOrder = sdlLilEndian
58 | #endif
59 |
60 | {-|
61 | Indicates the floating point word order of the current system.
62 | Will be either 'sdlLilEndian' or 'sdlBigEndian'.
63 | -}
64 | -- Usually this follows the general system byte order
65 | sdlFloatWordOrder :: Int
66 | sdlFloatWordOrder = sdlByteOrder
67 |
68 | -- | Swaps the byte order of a 16-bit integer
69 | sdlSwap16 :: Word16 -> Word16
70 | sdlSwap16 x = (x `shiftL` 8) .|. (x `shiftR` 8)
71 |
72 | -- | Swaps the byte order of a 32-bit integer
73 | sdlSwap32 :: Word32 -> Word32
74 | sdlSwap32 x =
75 | ((x `shiftL` 24) .|.
76 | ((x `shiftL` 8) .&. 0x00FF0000) .|.
77 | ((x `shiftR` 8) .&. 0x0000FF00) .|.
78 | (x `shiftR` 24))
79 |
80 | -- | Swaps the byte order of a 64-bit integer
81 | sdlSwap64 :: Word64 -> Word64
82 | sdlSwap64 x =
83 | let hi = fromIntegral (x .&. 0xFFFFFFFF) :: Word32
84 | lo = fromIntegral (x `shiftR` 32) :: Word32
85 | swappedHi = sdlSwap32 hi
86 | swappedLo = sdlSwap32 lo
87 | in (fromIntegral swappedHi `shiftL` 32) .|. fromIntegral swappedLo
88 |
89 | -- | Swaps the byte order of a floating point number
90 | sdlSwapFloat :: Float -> Float
91 | sdlSwapFloat x =
92 | let bits = floatToWord x
93 | swapped = sdlSwap32 bits
94 | in wordToFloat swapped
95 | where
96 | floatToWord :: Float -> Word32
97 | floatToWord = unsafeCoerce
98 |
99 | wordToFloat :: Word32 -> Float
100 | wordToFloat = unsafeCoerce
101 |
102 | -- Little endian to native conversion functions
103 | sdlSwap16LE :: Word16 -> Word16
104 | #if defined(WORDS_BIGENDIAN)
105 | sdlSwap16LE = sdlSwap16
106 | #else
107 | sdlSwap16LE x = x
108 | #endif
109 |
110 | sdlSwap32LE :: Word32 -> Word32
111 | #if defined(WORDS_BIGENDIAN)
112 | sdlSwap32LE = sdlSwap32
113 | #else
114 | sdlSwap32LE x = x
115 | #endif
116 |
117 | sdlSwap64LE :: Word64 -> Word64
118 | #if defined(WORDS_BIGENDIAN)
119 | sdlSwap64LE = sdlSwap64
120 | #else
121 | sdlSwap64LE x = x
122 | #endif
123 |
124 | sdlSwapFloatLE :: Float -> Float
125 | #if defined(WORDS_BIGENDIAN)
126 | sdlSwapFloatLE = sdlSwapFloat
127 | #else
128 | sdlSwapFloatLE x = x
129 | #endif
130 |
131 | -- Big endian to native conversion functions
132 | sdlSwap16BE :: Word16 -> Word16
133 | #if defined(WORDS_BIGENDIAN)
134 | sdlSwap16BE x = x
135 | #else
136 | sdlSwap16BE = sdlSwap16
137 | #endif
138 |
139 | sdlSwap32BE :: Word32 -> Word32
140 | #if defined(WORDS_BIGENDIAN)
141 | sdlSwap32BE x = x
142 | #else
143 | sdlSwap32BE = sdlSwap32
144 | #endif
145 |
146 | sdlSwap64BE :: Word64 -> Word64
147 | #if defined(WORDS_BIGENDIAN)
148 | sdlSwap64BE x = x
149 | #else
150 | sdlSwap64BE = sdlSwap64
151 | #endif
152 |
153 | sdlSwapFloatBE :: Float -> Float
154 | #if defined(WORDS_BIGENDIAN)
155 | sdlSwapFloatBE x = x
156 | #else
157 | sdlSwapFloatBE = sdlSwapFloat
158 | #endif
159 |
--------------------------------------------------------------------------------
/src/SDL/Error.hs:
--------------------------------------------------------------------------------
1 | {-|
2 | Module : SDL.Error
3 | Description : Simple error message routines for SDL
4 | Copyright : (c) Kyle Lukaszek
5 | License : BSD3
6 |
7 | Simple error message routines for SDL.
8 |
9 | Most apps will interface with these APIs in exactly one function: when almost any SDL function
10 | call reports failure, you can get a human-readable string of the problem from 'sdlGetError'.
11 |
12 | These strings are maintained per-thread, and apps are welcome to set their own errors, which is
13 | popular when building libraries on top of SDL for other apps to consume. These strings are set
14 | by calling 'sdlSetError'.
15 | -}
16 |
17 | module SDL.Error
18 | ( -- * Error Handling Functions
19 | sdlSetError
20 | , sdlSetErrorV
21 | , sdlOutOfMemory
22 | , sdlGetError
23 | , sdlClearError
24 | -- * Internal Error Macros
25 | , sdlUnsupported
26 | , sdlInvalidParamError
27 | ) where
28 |
29 | import Foreign.C.String (CString, withCString, peekCString)
30 | import Foreign.C.Types (CBool(..))
31 | import Control.Monad (void)
32 | import Data.Bool (bool)
33 |
34 | -- | Set the SDL error message for the current thread.
35 | --
36 | -- Calling this function will replace any previous error message that was set.
37 | --
38 | -- This function always returns False, since SDL frequently uses False to signify a failing result.
39 | --
40 | -- @since 3.2.0
41 | foreign import ccall "SDL_SetError" sdlSetError :: CString -> IO CBool
42 |
43 | -- | Set the SDL error message for the current thread.
44 | --
45 | -- Calling this function will replace any previous error message that was set.
46 | --
47 | -- @since 3.2.0
48 | foreign import ccall "SDL_SetErrorV" sdlSetErrorV :: CString -> IO CBool
49 |
50 | -- | Set an error indicating that memory allocation failed.
51 | --
52 | -- This function does not do any memory allocation.
53 | --
54 | -- @since 3.2.0
55 | foreign import ccall "SDL_OutOfMemory" sdlOutOfMemory :: IO CBool
56 |
57 | -- | Retrieve a message about the last error that occurred on the current thread.
58 | --
59 | -- It is possible for multiple errors to occur before calling 'sdlGetError'.
60 | -- Only the last error is returned.
61 | --
62 | -- The message is only applicable when an SDL function has signaled an error.
63 | -- You must check the return values of SDL function calls to determine when to
64 | -- appropriately call 'sdlGetError'. You should not use the results of
65 | -- 'sdlGetError' to decide if an error has occurred! Sometimes SDL will set
66 | -- an error string even when reporting success.
67 | --
68 | -- SDL will not clear the error string for successful API calls. You must
69 | -- check return values for failure cases before you can assume the error
70 | -- string applies.
71 | --
72 | -- Error strings are set per-thread, so an error set in a different thread
73 | -- will not interfere with the current thread's operation.
74 | --
75 | -- The returned value is a thread-local string which will remain valid until
76 | -- the current thread's error string is changed. The caller should make a copy
77 | -- if the value is needed after the next SDL API call.
78 | --
79 | -- @since 3.2.0
80 | sdlGetError :: IO String
81 | sdlGetError = do
82 | cstr <- sdlGetErrorRaw
83 | peekCString cstr
84 |
85 | -- | Raw C function for SDL_GetError
86 | foreign import ccall "SDL_GetError" sdlGetErrorRaw :: IO CString
87 |
88 | -- | Clear any previous error message for this thread.
89 | --
90 | -- @since 3.2.0
91 | sdlClearError :: IO Bool
92 | sdlClearError = fmap cboolToBool sdlClearErrorRaw
93 | where
94 | cboolToBool :: CBool -> Bool
95 | cboolToBool (CBool 0) = False
96 | cboolToBool _ = True
97 |
98 | -- | Raw C function for SDL_ClearError
99 | foreign import ccall "SDL_ClearError" sdlClearErrorRaw :: IO CBool
100 |
101 | -- | A standard error message for unsupported operations.
102 | --
103 | -- This is a convenience function that sets the error message to
104 | -- "That operation is not supported".
105 | --
106 | -- @since 3.2.0
107 | sdlUnsupported :: IO Bool
108 | sdlUnsupported = withCString "That operation is not supported" $ \cstr -> do
109 | CBool val <- sdlSetError cstr
110 | return (val /= 0)
111 |
112 | -- | A standard error message for invalid parameters.
113 | --
114 | -- This is a convenience function that sets the error message to
115 | -- "Parameter 'param' is invalid", where param is the provided string.
116 | --
117 | -- @since 3.2.0
118 | sdlInvalidParamError :: String -> IO Bool
119 | sdlInvalidParamError param =
120 | withCString ("Parameter '" ++ param ++ "' is invalid") $ \cstr -> do
121 | CBool val <- sdlSetError cstr
122 | return (val /= 0)
123 |
--------------------------------------------------------------------------------
/src/SDL/GUID.hsc:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ForeignFunctionInterface #-}
2 |
3 | {-|
4 | Module : SDL.Guid
5 | Description : SDL GUID functions for working with globally unique identifiers
6 | Copyright : Kyle Lukaszek, 2025
7 | License : BSD3
8 |
9 | This module provides bindings to the SDL3 GUID functions, allowing Haskell applications
10 | to work with 128-bit globally unique identifiers (GUIDs) used to identify input devices
11 | across runs of SDL programs on the same platform.
12 |
13 | The GUID functionality allows conversion between binary GUID structures and their
14 | ASCII string representations.
15 | -}
16 |
17 | module SDL.GUID
18 | ( -- * Types
19 | SDLGUID(..)
20 |
21 | -- * GUID Operations
22 | , sdlGUIDToString
23 | , sdlStringToGUID
24 | ) where
25 |
26 | import System.IO
27 | import Foreign
28 | import Foreign.C.Types
29 | import Foreign.C.String
30 | import Data.Word
31 | import Control.Monad
32 |
33 | #include
34 |
35 | -- Define the proper structure for SDL_GUID to match C declaration
36 | data SDL_GUID = SDL_GUID
37 | { guidData :: [Word8] -- 16-byte array
38 | } deriving (Show, Eq)
39 |
40 | -- Create a newtype for easier manipulation in Haskell
41 | newtype SDLGUID = SDLGUID { unSDLGUID :: [Word8] }
42 | deriving (Show, Eq)
43 |
44 | -- Define the storable instance for SDL_GUID to properly handle marshalling
45 | instance Storable SDLGUID where
46 | sizeOf _ = 16 -- Size of the SDL_GUID struct (16 bytes)
47 | alignment _ = alignment (undefined :: Word8)
48 |
49 | peek ptr = do
50 | bytes <- peekArray 16 (castPtr ptr)
51 | return $ SDLGUID bytes
52 |
53 | poke ptr (SDLGUID bytes) = do
54 | pokeArray (castPtr ptr) (take 16 $ bytes ++ repeat 0)
55 |
56 | -- Foreign declarations around wrappers
57 | foreign import ccall safe "wrapper_SDL_GUIDToString" sdlGUIDToStringRaw ::
58 | Ptr Word8 -> CString -> CInt -> IO ()
59 | foreign import ccall safe "wrapper_SDL_StringToGUID" sdlStringToGUIDRaw ::
60 | CString -> Ptr Word8 -> IO ()
61 |
62 | -- Convert our SDLGUID to string
63 | sdlGUIDToString :: SDLGUID -> IO String
64 | sdlGUIDToString (SDLGUID bytes) = do
65 | let guidBytes = take 16 $ bytes ++ repeat 0 -- Ensure we have exactly 16 bytes
66 |
67 | withArray guidBytes $ \guidPtr -> do
68 | -- Allocate a buffer for the string (33 bytes as specified in the SDL docs)
69 | allocaArray 33 $ \strPtr -> do
70 | -- Call the SDL wrapper function
71 | sdlGUIDToStringRaw guidPtr strPtr 33
72 | -- Convert the result to a Haskell String
73 | peekCString strPtr
74 |
75 | -- Convert a string to our SDLGUID
76 | sdlStringToGUID :: String -> IO SDLGUID
77 | sdlStringToGUID str = do
78 | -- Allocate space for the GUID data (16 bytes)
79 | allocaArray 16 $ \guidPtr -> do
80 | -- Convert our string to C string and call SDL wrapper function
81 | withCString str $ \strPtr -> do
82 | sdlStringToGUIDRaw strPtr guidPtr
83 | -- Read the bytes back
84 | bytes <- peekArray 16 guidPtr
85 | return $ SDLGUID bytes
86 |
87 |
--------------------------------------------------------------------------------
/src/SDL/LoadSO.hsc:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ForeignFunctionInterface #-}
2 | {-|
3 | Module : SDL.LoadSO
4 | Description : SDL shared object loading utilities
5 | Copyright : (c) Kyle Lukaszek, 2025
6 | License : BS3
7 |
8 | System-dependent library loading routines for working with shared objects
9 | (DLLs on Windows, shared libraries on Linux, etc.).
10 | -}
11 |
12 | module SDL.LoadSO
13 | ( -- * Types
14 | SDLSharedObject
15 | , SDLFunctionPointer
16 |
17 | -- * Functions
18 | , sdlLoadObject
19 | , sdlLoadFunction
20 | , sdlUnloadObject
21 | ) where
22 |
23 | #include
24 |
25 | import Foreign.C.Types (CInt)
26 | import Foreign.Ptr (Ptr, nullPtr, FunPtr, nullFunPtr)
27 | import Foreign.C.String (CString, withCString)
28 |
29 | -- | Opaque type representing a loaded shared object
30 | data SDLSharedObject
31 |
32 | -- | Type alias for function pointers loaded from shared objects
33 | type SDLFunctionPointer = FunPtr ()
34 |
35 | -- | Dynamically load a shared object
36 | foreign import ccall "SDL_LoadObject"
37 | sdlLoadObjectRaw :: CString -> IO (Ptr SDLSharedObject)
38 |
39 | sdlLoadObject :: String -> IO (Maybe (Ptr SDLSharedObject))
40 | sdlLoadObject sofile = withCString sofile $ \cstr -> do
41 | handle <- sdlLoadObjectRaw cstr
42 | return $ if handle == nullPtr
43 | then Nothing
44 | else Just handle
45 |
46 | -- | Look up a function in a shared object
47 | foreign import ccall "SDL_LoadFunction"
48 | sdlLoadFunctionRaw :: Ptr SDLSharedObject -> CString -> IO SDLFunctionPointer
49 |
50 | sdlLoadFunction :: Ptr SDLSharedObject -> String -> IO (Maybe SDLFunctionPointer)
51 | sdlLoadFunction handle name = withCString name $ \cstr -> do
52 | ptr <- sdlLoadFunctionRaw handle cstr
53 | return $ if ptr == nullFunPtr
54 | then Nothing
55 | else Just ptr
56 |
57 | -- | Unload a shared object
58 | foreign import ccall "SDL_UnloadObject"
59 | sdlUnloadObject :: Ptr SDLSharedObject -> IO ()
60 |
--------------------------------------------------------------------------------
/src/SDL/Locale.hsc:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ForeignFunctionInterface #-}
2 | {-|
3 | Module : SDL.Locale - SDL Locale
4 | Description : SDL locale services
5 | Copyright : (c) Kyle Lukaszek, 2025
6 | Starting new chunk from module SDL.Log
7 | License : BSD3
8 | Description : Provides access to user's preferred locales (language and country)
9 | -}
10 |
11 | module SDL.Locale
12 | ( -- * Types
13 | SDLLocale(..)
14 |
15 | -- * Functions
16 | , sdlGetPreferredLocales
17 | ) where
18 |
19 | #include
20 |
21 | import Foreign.C.Types (CInt(..))
22 | import Foreign.Ptr (Ptr, nullPtr)
23 | import Foreign.C.String (peekCString)
24 | import Foreign.Marshal.Alloc (free, alloca)
25 | import Foreign.Storable (Storable(..))
26 | import Foreign.Marshal.Array (peekArray, advancePtr)
27 |
28 | -- | Represents a locale with language and optional country code
29 | data SDLLocale = SDLLocale
30 | { language :: String -- ^ ISO-639 language code (e.g., "en")
31 | , country :: Maybe String -- ^ ISO-3166 country code (e.g., "US"), or Nothing
32 | } deriving (Eq, Show)
33 |
34 | instance Storable SDLLocale where
35 | sizeOf _ = #size SDL_Locale
36 | alignment _ = #alignment SDL_Locale
37 | peek ptr = do
38 | lang <- peekCString =<< (#peek SDL_Locale, language) ptr
39 | countryPtr <- (#peek SDL_Locale, country) ptr
40 | country <- if countryPtr == nullPtr
41 | then return Nothing
42 | else Just <$> peekCString countryPtr
43 | return $ SDLLocale lang country
44 | poke _ _ = error "SDLLocale.poke not implemented" -- Not needed for this use case
45 |
46 | -- | Get the user's preferred locales
47 | foreign import ccall "SDL_GetPreferredLocales"
48 | sdlGetPreferredLocalesRaw :: Ptr CInt -> IO (Ptr (Ptr SDLLocale))
49 |
50 | sdlGetPreferredLocales :: IO [SDLLocale]
51 | sdlGetPreferredLocales = alloca $ \countPtr -> do
52 | poke countPtr 0
53 | localePtrs <- sdlGetPreferredLocalesRaw countPtr
54 | if localePtrs == nullPtr
55 | then return []
56 | else do
57 | count <- peek countPtr
58 | locales <- peekArray (fromIntegral count) localePtrs
59 | mapM peek locales <* free localePtrs
60 |
--------------------------------------------------------------------------------
/src/SDL/Metal.hsc:
--------------------------------------------------------------------------------
1 | -- SDL/Metal.hsc
2 | {-# LANGUAGE ForeignFunctionInterface #-}
3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} -- Keep if SDLMetalView needs it later
4 |
5 | {-|
6 | Module : SDL.Metal
7 | Description : SDL Metal layer and view creation functions
8 | Copyright : Kyle Lukaszek, 2025
9 | License : BSD3
10 |
11 | This module provides bindings to the SDL3 Metal API, allowing Haskell applications
12 | to create Metal layers and views on SDL windows for Apple platforms (macOS, iOS, tvOS).
13 | These functions are useful for specific OS-level integration tasks with Metal.
14 |
15 | Note: On macOS, SDL does not automatically associate a MTLDevice with the CAMetalLayer;
16 | this must be handled in user code.
17 | -}
18 |
19 | module SDL.Metal
20 | ( -- * Types
21 | SDLMetalView(..)
22 |
23 | -- * Metal Support Functions
24 | , sdlMetalCreateView
25 | , sdlMetalDestroyView
26 | , sdlMetalGetLayer
27 | ) where
28 |
29 | import Foreign hiding (void) -- Avoid hiding void from Prelude if Ptr () is okay
30 | import Foreign.C.Types
31 | import SDL.Video (SDLWindow(..)) -- Import the newtype
32 |
33 | #include
34 |
35 | -- | A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS).
36 | -- Using Ptr () as the C API returns void*.
37 | newtype SDLMetalView = SDLMetalView (Ptr ())
38 | deriving (Show, Eq)
39 |
40 | -- | Raw C binding for SDL_Metal_CreateView
41 | foreign import ccall unsafe "SDL_Metal_CreateView"
42 | sdlMetalCreateViewRaw :: Ptr SDLWindow -> IO (Ptr ()) -- Use Ptr SDL_Window
43 |
44 | -- | Create a CAMetalLayer-backed NSView/UIView and attach it to the specified window.
45 | -- Returns Nothing if creation fails.
46 | sdlMetalCreateView :: SDLWindow -> IO (Maybe SDLMetalView)
47 | sdlMetalCreateView (SDLWindow windowPtr) = do -- Unpack SDLWindow
48 | view <- sdlMetalCreateViewRaw windowPtr -- Pass unwrapped Ptr SDL_Window
49 | if view == nullPtr
50 | then return Nothing
51 | else return $ Just $ SDLMetalView view
52 |
53 | -- | Raw C binding for SDL_Metal_DestroyView
54 | foreign import ccall unsafe "SDL_Metal_DestroyView"
55 | sdlMetalDestroyViewRaw :: Ptr () -> IO ()
56 |
57 | -- | Destroy an existing SDL_MetalView object.
58 | -- Should be called before destroying the associated window if created after window creation.
59 | sdlMetalDestroyView :: SDLMetalView -> IO ()
60 | sdlMetalDestroyView (SDLMetalView view) = sdlMetalDestroyViewRaw view
61 |
62 | -- | Raw C binding for SDL_Metal_GetLayer
63 | foreign import ccall unsafe "SDL_Metal_GetLayer"
64 | sdlMetalGetLayerRaw :: Ptr () -> IO (Ptr ())
65 |
66 | -- | Get a pointer to the backing CAMetalLayer for the given view.
67 | -- Returns Nothing if the layer cannot be retrieved.
68 | sdlMetalGetLayer :: SDLMetalView -> IO (Maybe (Ptr ()))
69 | sdlMetalGetLayer (SDLMetalView view) = do
70 | layer <- sdlMetalGetLayerRaw view
71 | if layer == nullPtr
72 | then return Nothing
73 | else return $ Just layer
74 |
--------------------------------------------------------------------------------
/src/SDL/Misc.hsc:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ForeignFunctionInterface #-}
2 |
3 | {-|
4 | Module : SDL.Misc
5 | Description : Miscellaneous SDL functions
6 | Copyright : Kyle Lukaszek, 2025
7 | License : BSD3
8 |
9 | This module provides bindings to SDL3 API functions that don't fit elsewhere,
10 | such as opening URLs in the system browser.
11 | -}
12 |
13 | module SDL.Misc
14 | ( -- * URL Handling
15 | sdlOpenURL
16 | ) where
17 |
18 | import Foreign
19 | import Foreign.C.Types
20 | import Foreign.C.String
21 | import Data.Word
22 | import Data.Int
23 | import Control.Monad
24 |
25 | import SDL.Stdinc
26 | import SDL.Error
27 |
28 | #include
29 |
30 | -- | Open a URL/URI in the browser or other appropriate external application.
31 | foreign import ccall "SDL_OpenURL" sdlOpenURLRaw :: CString -> IO Bool
32 |
33 | -- | Open a URL/URI in the browser or other appropriate external application.
34 | -- This high-level function wraps the SDL_OpenURL C function, converting the
35 | -- Haskell String to a C string and handling errors appropriately.
36 | sdlOpenURL :: String -> IO Bool
37 | sdlOpenURL url = withCString url sdlOpenURLRaw
38 |
--------------------------------------------------------------------------------
/src/SDL/Pen.hsc:
--------------------------------------------------------------------------------
1 | -- SDL/Pen.hsc
2 | {-# LANGUAGE ForeignFunctionInterface #-}
3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4 | {-# LANGUAGE PatternSynonyms #-}
5 | {-# LANGUAGE DerivingStrategies #-}
6 |
7 | -- |
8 | -- Module : SDL.Pen
9 | -- Description : SDL pen event handling functions
10 | -- Copyright : Kyle Lukaszek, 2025
11 | -- License : BSD3
12 | --
13 | -- This module provides bindings to the SDL3 pen API, allowing Haskell applications
14 | -- to handle pressure-sensitive pen input (stylus and/or eraser) for devices such as
15 | -- drawing tablets and suitably equipped mobile/tablet devices.
16 | --
17 | -- To use these functions, SDL must be initialized and the application should handle
18 | -- SDL_EVENT_PEN_* events.
19 |
20 | #include
21 |
22 | module SDL.Pen
23 | ( -- * Types
24 | SDLPenID
25 | , SDLPenInputFlags(..)
26 | , SDLPenAxis(..)
27 |
28 | -- * Constants / Patterns
29 | , pattern SDL_PEN_MOUSEID
30 | , pattern SDL_PEN_TOUCHID
31 | , pattern SDL_PEN_INPUT_DOWN
32 | , pattern SDL_PEN_INPUT_BUTTON_1
33 | , pattern SDL_PEN_INPUT_BUTTON_2
34 | , pattern SDL_PEN_INPUT_BUTTON_3
35 | , pattern SDL_PEN_INPUT_BUTTON_4
36 | , pattern SDL_PEN_INPUT_BUTTON_5
37 | , pattern SDL_PEN_INPUT_ERASER_TIP
38 | , pattern SDL_PEN_AXIS_PRESSURE
39 | , pattern SDL_PEN_AXIS_XTILT
40 | , pattern SDL_PEN_AXIS_YTILT
41 | , pattern SDL_PEN_AXIS_DISTANCE
42 | , pattern SDL_PEN_AXIS_ROTATION
43 | , pattern SDL_PEN_AXIS_SLIDER
44 | , pattern SDL_PEN_AXIS_TANGENTIAL_PRESSURE
45 | , pattern SDL_PEN_AXIS_COUNT
46 | ) where
47 |
48 | import Foreign (Ptr, FunPtr, nullPtr, nullFunPtr)
49 | import Foreign.C.Types (CInt(..))
50 | import Foreign.Storable (Storable)
51 | import Data.Word (Word32, Word64)
52 | import Data.Bits (Bits, (.|.))
53 | import SDL.Mouse (SDLMouseID) -- Assuming SDLMouseID is Word32 or similar
54 | import SDL.Touch (SDLTouchID) -- Assuming SDLTouchID is Word64 or similar
55 |
56 | -- | SDL pen instance ID.
57 | -- Zero signifies an invalid/null device.
58 | -- Using a type alias as it's just an identifier.
59 | type SDLPenID = Word32
60 |
61 | -- | Pen input flags as reported in pen events' pen_state field.
62 | -- Wraps a Word32 as the C #defines are flags (bitmasks).
63 | newtype SDLPenInputFlags = SDLPenInputFlags Word32
64 | deriving newtype (Show, Eq, Bits, Num, Storable) -- Added Num for convenience with bitwise OR
65 |
66 | pattern SDL_PEN_INPUT_DOWN :: SDLPenInputFlags
67 | pattern SDL_PEN_INPUT_DOWN = SDLPenInputFlags #{const SDL_PEN_INPUT_DOWN}
68 | pattern SDL_PEN_INPUT_BUTTON_1 :: SDLPenInputFlags
69 | pattern SDL_PEN_INPUT_BUTTON_1 = SDLPenInputFlags #{const SDL_PEN_INPUT_BUTTON_1}
70 | pattern SDL_PEN_INPUT_BUTTON_2 :: SDLPenInputFlags
71 | pattern SDL_PEN_INPUT_BUTTON_2 = SDLPenInputFlags #{const SDL_PEN_INPUT_BUTTON_2}
72 | pattern SDL_PEN_INPUT_BUTTON_3 :: SDLPenInputFlags
73 | pattern SDL_PEN_INPUT_BUTTON_3 = SDLPenInputFlags #{const SDL_PEN_INPUT_BUTTON_3}
74 | pattern SDL_PEN_INPUT_BUTTON_4 :: SDLPenInputFlags
75 | pattern SDL_PEN_INPUT_BUTTON_4 = SDLPenInputFlags #{const SDL_PEN_INPUT_BUTTON_4}
76 | pattern SDL_PEN_INPUT_BUTTON_5 :: SDLPenInputFlags
77 | pattern SDL_PEN_INPUT_BUTTON_5 = SDLPenInputFlags #{const SDL_PEN_INPUT_BUTTON_5}
78 | pattern SDL_PEN_INPUT_ERASER_TIP :: SDLPenInputFlags
79 | pattern SDL_PEN_INPUT_ERASER_TIP = SDLPenInputFlags #{const SDL_PEN_INPUT_ERASER_TIP}
80 |
81 | -- | Pen axis indices for SDL_PenAxisEvent.
82 | -- Wraps CInt as the C type is a standard enum.
83 | newtype SDLPenAxis = SDLPenAxis CInt
84 | deriving newtype (Show, Eq, Ord, Storable, Enum)
85 |
86 | pattern SDL_PEN_AXIS_PRESSURE :: SDLPenAxis
87 | pattern SDL_PEN_AXIS_PRESSURE = SDLPenAxis #{const SDL_PEN_AXIS_PRESSURE}
88 | pattern SDL_PEN_AXIS_XTILT :: SDLPenAxis
89 | pattern SDL_PEN_AXIS_XTILT = SDLPenAxis #{const SDL_PEN_AXIS_XTILT}
90 | pattern SDL_PEN_AXIS_YTILT :: SDLPenAxis
91 | pattern SDL_PEN_AXIS_YTILT = SDLPenAxis #{const SDL_PEN_AXIS_YTILT}
92 | pattern SDL_PEN_AXIS_DISTANCE :: SDLPenAxis
93 | pattern SDL_PEN_AXIS_DISTANCE = SDLPenAxis #{const SDL_PEN_AXIS_DISTANCE}
94 | pattern SDL_PEN_AXIS_ROTATION :: SDLPenAxis
95 | pattern SDL_PEN_AXIS_ROTATION = SDLPenAxis #{const SDL_PEN_AXIS_ROTATION}
96 | pattern SDL_PEN_AXIS_SLIDER :: SDLPenAxis
97 | pattern SDL_PEN_AXIS_SLIDER = SDLPenAxis #{const SDL_PEN_AXIS_SLIDER}
98 | pattern SDL_PEN_AXIS_TANGENTIAL_PRESSURE :: SDLPenAxis
99 | pattern SDL_PEN_AXIS_TANGENTIAL_PRESSURE = SDLPenAxis #{const SDL_PEN_AXIS_TANGENTIAL_PRESSURE}
100 | pattern SDL_PEN_AXIS_COUNT :: SDLPenAxis
101 | pattern SDL_PEN_AXIS_COUNT = SDLPenAxis #{const SDL_PEN_AXIS_COUNT}
102 |
103 | -- | Mouse ID for mouse events simulated with pen input.
104 | pattern SDL_PEN_MOUSEID :: SDLMouseID
105 | pattern SDL_PEN_MOUSEID = #{const SDL_PEN_MOUSEID}
106 |
107 | -- | Touch ID for touch events simulated with pen input.
108 | pattern SDL_PEN_TOUCHID :: SDLTouchID
109 | pattern SDL_PEN_TOUCHID = #{const SDL_PEN_TOUCHID}
110 |
--------------------------------------------------------------------------------
/src/SDL/Power.hsc:
--------------------------------------------------------------------------------
1 | -- SDL/Power.hsc
2 | {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3 | {-# LANGUAGE PatternSynonyms #-}
4 | {-# LANGUAGE DerivingStrategies #-}
5 | {-# LANGUAGE ForeignFunctionInterface #-}
6 |
7 | -- |
8 | -- Module : SDL.Power
9 | -- Description : Power management functions for SDL3.
10 | -- Copyright : (c) Kyle Lukaszek, 2025
11 | -- License : BSD3
12 | --
13 | -- This module provides Haskell bindings to the SDL3 power management functionality.
14 |
15 | #include
16 |
17 | module SDL.Power
18 | (
19 | -- * Types
20 | SDLPowerState(..)
21 |
22 | -- * Patterns / Constants
23 | , pattern SDL_POWERSTATE_ERROR
24 | , pattern SDL_POWERSTATE_UNKNOWN
25 | , pattern SDL_POWERSTATE_ON_BATTERY
26 | , pattern SDL_POWERSTATE_NO_BATTERY
27 | , pattern SDL_POWERSTATE_CHARGING
28 | , pattern SDL_POWERSTATE_CHARGED
29 |
30 | -- * Functions
31 | , sdlGetPowerInfo
32 | ) where
33 |
34 | import Foreign (Ptr, Storable, nullPtr)
35 | import Foreign.C.Types (CInt(..))
36 |
37 | -- | The basic state for the system's power supply.
38 | newtype SDLPowerState = SDLPowerState CInt
39 | deriving newtype (Eq, Ord, Storable, Enum) -- Deriving common instances
40 |
41 | -- Define pattern synonyms using the C constants
42 | pattern SDL_POWERSTATE_ERROR :: SDLPowerState
43 | pattern SDL_POWERSTATE_ERROR = SDLPowerState (#{const SDL_POWERSTATE_ERROR})
44 | pattern SDL_POWERSTATE_UNKNOWN :: SDLPowerState
45 | pattern SDL_POWERSTATE_UNKNOWN = SDLPowerState #{const SDL_POWERSTATE_UNKNOWN}
46 | pattern SDL_POWERSTATE_ON_BATTERY :: SDLPowerState
47 | pattern SDL_POWERSTATE_ON_BATTERY = SDLPowerState #{const SDL_POWERSTATE_ON_BATTERY}
48 | pattern SDL_POWERSTATE_NO_BATTERY :: SDLPowerState
49 | pattern SDL_POWERSTATE_NO_BATTERY = SDLPowerState #{const SDL_POWERSTATE_NO_BATTERY}
50 | pattern SDL_POWERSTATE_CHARGING :: SDLPowerState
51 | pattern SDL_POWERSTATE_CHARGING = SDLPowerState #{const SDL_POWERSTATE_CHARGING}
52 | pattern SDL_POWERSTATE_CHARGED :: SDLPowerState
53 | pattern SDL_POWERSTATE_CHARGED = SDLPowerState #{const SDL_POWERSTATE_CHARGED}
54 |
55 | -- Provide a more informative Show instance using patterns
56 | instance Show SDLPowerState where
57 | show ps
58 | | ps == SDL_POWERSTATE_ERROR = "SDL_POWERSTATE_ERROR"
59 | | ps == SDL_POWERSTATE_UNKNOWN = "SDL_POWERSTATE_UNKNOWN"
60 | | ps == SDL_POWERSTATE_ON_BATTERY = "SDL_POWERSTATE_ON_BATTERY"
61 | | ps == SDL_POWERSTATE_NO_BATTERY = "SDL_POWERSTATE_NO_BATTERY"
62 | | ps == SDL_POWERSTATE_CHARGING = "SDL_POWERSTATE_CHARGING"
63 | | ps == SDL_POWERSTATE_CHARGED = "SDL_POWERSTATE_CHARGED"
64 | | otherwise = "SDLPowerState " ++ show n -- Fallback
65 | where (SDLPowerState n) = ps -- Unpack for the fallback case
66 |
67 | -- FFI Import using c_ prefix convention
68 | foreign import ccall unsafe "SDL_GetPowerInfo"
69 | c_sdlGetPowerInfo :: Ptr CInt -> Ptr CInt -> IO CInt -- Return raw CInt
70 |
71 | -- Haskell Wrapper
72 | -- | Get the current power supply details.
73 | -- Returns the power state and optionally fills in seconds and percent of battery life remaining.
74 | -- Passing Nothing for the Ptr arguments means you don't want that value.
75 | -- Returns Nothing if SDL reports an error state.
76 | sdlGetPowerInfo :: Maybe (Ptr CInt) {-^ Pointer to store seconds remaining, or Nothing -} ->
77 | Maybe (Ptr CInt) {-^ Pointer to store percentage remaining, or Nothing -} ->
78 | IO (Maybe SDLPowerState) {-^ Power state, or Nothing on error -}
79 | sdlGetPowerInfo mSecondsPtr mPercentPtr = do
80 | let secPtr = maybe nullPtr id mSecondsPtr
81 | pctPtr = maybe nullPtr id mPercentPtr
82 | stateCInt <- c_sdlGetPowerInfo secPtr pctPtr
83 | let state = toEnum (fromIntegral stateCInt) :: SDLPowerState
84 | return $ if state == SDL_POWERSTATE_ERROR then Nothing else Just state
85 |
--------------------------------------------------------------------------------
/src/SDL/Version.hsc:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ForeignFunctionInterface #-}
2 | {-|
3 | Module : SDL.Version
4 | Description : SDL version querying and management
5 | Copyright : (c) Kyle Lukaszek, 2025
6 | License : BSD3
7 |
8 | SDL provides functionality to query the current SDL version, both as headers
9 | the application was compiled against and as a library the application is linked to.
10 |
11 | This module allows you to access the compile-time version of SDL through constants
12 | and macros, as well as retrieve the runtime version and revision of the linked SDL
13 | library. This is particularly useful when linking dynamically to SDL, where the
14 | linked library version might differ from the version used at compile time.
15 |
16 | The version information can be used to ensure compatibility or to log details for
17 | debugging purposes.
18 | -}
19 |
20 | module SDL.Version
21 | ( -- * Version Constants
22 | sdlMajorVersion
23 | , sdlMinorVersion
24 | , sdlMicroVersion
25 | , sdlVersion
26 | , sdlVersionAtLeast
27 |
28 | -- * Version Functions
29 | , sdlGetVersion
30 | , sdlGetRevision
31 | ) where
32 |
33 | #include
34 |
35 | import Foreign.C.Types
36 | import Foreign.C.String (CString, peekCString)
37 | import Data.Word (Word32)
38 |
39 | -- | The current major version of SDL headers (SDL_MAJOR_VERSION).
40 | sdlMajorVersion :: Int
41 | sdlMajorVersion = #const SDL_MAJOR_VERSION
42 |
43 | -- | The current minor version of SDL headers (SDL_MINOR_VERSION).
44 | sdlMinorVersion :: Int
45 | sdlMinorVersion = #const SDL_MINOR_VERSION
46 |
47 | -- | The current micro (patchlevel) version of SDL headers (SDL_MICRO_VERSION).
48 | sdlMicroVersion :: Int
49 | sdlMicroVersion = #const SDL_MICRO_VERSION
50 |
51 | -- | Turns the version numbers into a numeric value (SDL_VERSIONNUM).
52 | -- For example, (1, 2, 3) becomes 1002003.
53 | sdlVersionNum :: Int -> Int -> Int -> Int
54 | sdlVersionNum major minor patch = major * 1000000 + minor * 1000 + patch
55 |
56 | -- | The version number for the current SDL version (SDL_VERSION).
57 | sdlVersion :: Int
58 | sdlVersion = sdlVersionNum sdlMajorVersion sdlMinorVersion sdlMicroVersion
59 |
60 | -- | Evaluates to True if compiled with SDL at least X.Y.Z (SDL_VERSION_ATLEAST).
61 | sdlVersionAtLeast :: Int -> Int -> Int -> Bool
62 | sdlVersionAtLeast x y z = sdlVersion >= sdlVersionNum x y z
63 |
64 | -- | Get the version of SDL that is linked against your program.
65 | --
66 | -- This function returns the version as a single integer (e.g., 3003000 for 3.3.0).
67 | -- It corresponds to SDL_GetVersion in the C API.
68 | --
69 | -- Since this function is available since SDL 3.2.0.
70 | foreign import ccall "SDL_GetVersion"
71 | sdlGetVersion :: IO CInt
72 |
73 | -- | Get the code revision of SDL that is linked against your program.
74 | --
75 | -- Returns an arbitrary string uniquely identifying the exact revision of the SDL library in use.
76 | -- Corresponds to SDL_GetRevision in the C API.
77 | --
78 | -- Since this function is available since SDL 3.2.0.
79 | foreign import ccall "SDL_GetRevision"
80 | sdlGetRevisionRaw :: IO CString
81 |
82 | -- | Haskell wrapper for SDL_GetRevision to return a String.
83 | sdlGetRevision :: IO String
84 | sdlGetRevision = sdlGetRevisionRaw >>= peekCString
85 |
--------------------------------------------------------------------------------