const std = @import("std");
pub const c = @import("c.zig").c;

pub const FPoint = extern struct {
    x: f32,
    y: f32,
};

pub const FColor = extern struct {
    r: f32,
    g: f32,
    b: f32,
    a: f32,
};

pub const Surface = opaque {
    pub inline fn createSoftwareRenderer(surface: *Surface) ?*Renderer {
        return c.SDL_CreateSoftwareRenderer(surface);
    }
};

pub const PropertiesID = u32;

pub const Window = opaque {
    pub inline fn createRenderer(window: *Window, name: [*c]const u8) ?*Renderer {
        return c.SDL_CreateRenderer(window, name);
    }

    pub inline fn getRenderer(window: *Window) ?*Renderer {
        return c.SDL_GetRenderer(window);
    }
};

pub const FRect = extern struct {
    x: f32,
    y: f32,
    w: f32,
    h: f32,
};

pub const GPUTextureSamplerBinding = extern struct {
    texture: ?*GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER.
    sampler: ?*GPUSampler, // The sampler to bind.
};

pub const GPUSampler = opaque {};

pub const GPUTexture = opaque {};

pub const GPUShader = opaque {};

pub const WindowFlags = packed struct(u64) {
    windowFullscreen: bool = false, // window is in fullscreen mode
    windowOpengl: bool = false, // window usable with OpenGL context
    windowOccluded: bool = false, // window is occluded
    windowHidden: bool = false, // window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow() is required for it to become visible
    windowBorderless: bool = false, // no window decoration
    windowResizable: bool = false, // window can be resized
    windowMinimized: bool = false, // window is minimized
    windowMaximized: bool = false, // window is maximized
    windowMouseGrabbed: bool = false, // window has grabbed mouse input
    windowInputFocus: bool = false, // window has input focus
    windowMouseFocus: bool = false, // window has mouse focus
    windowExternal: bool = false, // window not created by SDL
    windowModal: bool = false, // window is modal
    windowHighPixelDensity: bool = false, // window uses high pixel density back buffer if possible
    windowMouseCapture: bool = false, // window has mouse captured (unrelated to MOUSE_GRABBED)
    windowMouseRelativeMode: bool = false, // window has relative mode enabled
    windowAlwaysOnTop: bool = false, // window should always be above others
    windowUtility: bool = false, // window should be treated as a utility window, not showing in the task bar and window list
    windowTooltip: bool = false, // window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window
    windowPopupMenu: bool = false, // window should be treated as a popup menu, requires a parent window
    windowKeyboardGrabbed: bool = false, // window has grabbed keyboard input
    windowFillDocument: bool = false, // window is in fill-document mode (Emscripten only), since SDL 3.4.0
    windowVulkan: bool = false, // window usable for Vulkan surface
    windowMetal: bool = false, // window usable for Metal view
    windowTransparent: bool = false, // window with transparent buffer
    windowNotFocusable: bool = false, // window should not be focusable
    pad0: u37 = 0,
    rsvd: bool = false,
};

pub const PixelFormat = enum(c_int) {
    pixelformatYv12, //Planar mode: Y + V + U  (3 planes)
    pixelformatIyuv, //Planar mode: Y + U + V  (3 planes)
    pixelformatYuy2, //Packed mode: Y0+U0+Y1+V0 (1 plane)
    pixelformatUyvy, //Packed mode: U0+Y0+V0+Y1 (1 plane)
    pixelformatYvyu, //Packed mode: Y0+V0+Y1+U0 (1 plane)
    pixelformatNv12, //Planar mode: Y + U/V interleaved  (2 planes)
    pixelformatNv21, //Planar mode: Y + V/U interleaved  (2 planes)
    pixelformatP010, //Planar mode: Y + U/V interleaved  (2 planes)
    pixelformatExternalOes, //Android video texture format
    pixelformatMjpg, //Motion JPEG
};

pub const ScaleMode = enum(c_int) {
    scalemodeNearest, //nearest pixel sampling
    scalemodeLinear, //linear filtering
    scalemodePixelart,
};

pub const GPUDevice = opaque {
    pub inline fn createGPURenderer(gpudevice: *GPUDevice, window: ?*Window) ?*Renderer {
        return c.SDL_CreateGPURenderer(gpudevice, window);
    }
};

pub const BlendMode = u32;

pub const Event = extern union {
    _type: u32, // Event type, shared with all events, Uint32 to cover user events which are not in the SDL_EventType enumeration
    common: CommonEvent, // Common event data
    display: DisplayEvent, // Display event data
    window: WindowEvent, // Window event data
    kdevice: KeyboardDeviceEvent, // Keyboard device change event data
    key: KeyboardEvent, // Keyboard event data
    edit: TextEditingEvent, // Text editing event data
    edit_candidates: TextEditingCandidatesEvent, // Text editing candidates event data
    text: TextInputEvent, // Text input event data
    mdevice: MouseDeviceEvent, // Mouse device change event data
    motion: MouseMotionEvent, // Mouse motion event data
    button: MouseButtonEvent, // Mouse button event data
    wheel: MouseWheelEvent, // Mouse wheel event data
    jdevice: JoyDeviceEvent, // Joystick device change event data
    jaxis: JoyAxisEvent, // Joystick axis event data
    jball: JoyBallEvent, // Joystick ball event data
    jhat: JoyHatEvent, // Joystick hat event data
    jbutton: JoyButtonEvent, // Joystick button event data
    jbattery: JoyBatteryEvent, // Joystick battery event data
    gdevice: GamepadDeviceEvent, // Gamepad device event data
    gaxis: GamepadAxisEvent, // Gamepad axis event data
    gbutton: GamepadButtonEvent, // Gamepad button event data
    gtouchpad: GamepadTouchpadEvent, // Gamepad touchpad event data
    gsensor: GamepadSensorEvent, // Gamepad sensor event data
    adevice: AudioDeviceEvent, // Audio device event data
    cdevice: CameraDeviceEvent, // Camera device event data
    sensor: SensorEvent, // Sensor event data
    quit: QuitEvent, // Quit request event data
    user: UserEvent, // Custom event data
    tfinger: TouchFingerEvent, // Touch finger event data
    pinch: PinchFingerEvent, // Pinch event data
    pproximity: PenProximityEvent, // Pen proximity event data
    ptouch: PenTouchEvent, // Pen tip touching event data
    pmotion: PenMotionEvent, // Pen motion event data
    pbutton: PenButtonEvent, // Pen button event data
    paxis: PenAxisEvent, // Pen axis event data
    render: RenderEvent, // Render event data
    drop: DropEvent, // Drag and drop event data
    clipboard: ClipboardEvent, // Clipboard event data
    padding: [128]u8,
};

pub const JoyAxisEvent = extern struct {
    _type: EventType, // SDL_EVENT_JOYSTICK_AXIS_MOTION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    axis: u8, // The joystick axis index
    padding1: u8,
    padding2: u8,
    padding3: u8,
    value: i16, // The axis value (range: -32768 to 32767)
    padding4: u16,
};

pub const UserEvent = extern struct {
    _type: u32, // SDL_EVENT_USER through SDL_EVENT_LAST, Uint32 because these are not in the SDL_EventType enumeration
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The associated window if any
    code: i32, // User defined event code
    data1: ?*anyopaque, // User defined data pointer
    data2: ?*anyopaque, // User defined data pointer
};

pub const PinchFingerEvent = extern struct {
    _type: EventType, // ::SDL_EVENT_PINCH_BEGIN or ::SDL_EVENT_PINCH_UPDATE or ::SDL_EVENT_PINCH_END
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    scale: f32, // The scale change since the last SDL_EVENT_PINCH_UPDATE. Scale < 1 is "zoom out". Scale > 1 is "zoom in".
    windowID: WindowID, // The window underneath the finger, if any
};

pub const MouseMotionEvent = extern struct {
    _type: EventType, // SDL_EVENT_MOUSE_MOTION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with mouse focus, if any
    which: MouseID, // The mouse instance id in relative mode, SDL_TOUCH_MOUSEID for touch events, or 0
    state: MouseButtonFlags, // The current button state
    x: f32, // X coordinate, relative to window
    y: f32, // Y coordinate, relative to window
    xrel: f32, // The relative motion in the X direction
    yrel: f32, // The relative motion in the Y direction
};

pub const CommonEvent = extern struct {
    _type: u32, // Event type, shared with all events, Uint32 to cover user events which are not in the SDL_EventType enumeration
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
};

pub const GamepadButtonEvent = extern struct {
    _type: EventType, // SDL_EVENT_GAMEPAD_BUTTON_DOWN or SDL_EVENT_GAMEPAD_BUTTON_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    button: u8, // The gamepad button (SDL_GamepadButton)
    down: bool, // true if the button is pressed
    padding1: u8,
    padding2: u8,
};

pub const JoyDeviceEvent = extern struct {
    _type: EventType, // SDL_EVENT_JOYSTICK_ADDED or SDL_EVENT_JOYSTICK_REMOVED or SDL_EVENT_JOYSTICK_UPDATE_COMPLETE
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
};

pub const GamepadTouchpadEvent = extern struct {
    _type: EventType, // SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN or SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION or SDL_EVENT_GAMEPAD_TOUCHPAD_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    touchpad: i32, // The index of the touchpad
    finger: i32, // The index of the finger on the touchpad
    x: f32, // Normalized in the range 0...1 with 0 being on the left
    y: f32, // Normalized in the range 0...1 with 0 being at the top
    pressure: f32, // Normalized in the range 0...1
};

pub const GamepadSensorEvent = extern struct {
    _type: EventType, // SDL_EVENT_GAMEPAD_SENSOR_UPDATE
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    sensor: i32, // The type of the sensor, one of the values of SDL_SensorType
    data: [3]f32, // Up to 3 values from the sensor, as defined in SDL_sensor.h
    sensor_timestamp: u64, // The timestamp of the sensor reading in nanoseconds, not necessarily synchronized with the system clock
};

pub const RenderEvent = extern struct {
    _type: EventType, // SDL_EVENT_RENDER_TARGETS_RESET, SDL_EVENT_RENDER_DEVICE_RESET, SDL_EVENT_RENDER_DEVICE_LOST
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window containing the renderer in question.
};

pub const ClipboardEvent = extern struct {
    _type: EventType, // SDL_EVENT_CLIPBOARD_UPDATE
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    owner: bool, // are we owning the clipboard (internal update)
    num_mime_types: i32, // number of mime types
    mime_types: [*c][*c]const u8, // current mime types
};

pub const PenMotionEvent = extern struct {
    _type: EventType, // SDL_EVENT_PEN_MOTION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with pen focus, if any
    which: PenID, // The pen instance id
    pen_state: PenInputFlags, // Complete pen input state at time of event
    x: f32, // X coordinate, relative to window
    y: f32, // Y coordinate, relative to window
};

pub const GamepadAxisEvent = extern struct {
    _type: EventType, // SDL_EVENT_GAMEPAD_AXIS_MOTION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    axis: u8, // The gamepad axis (SDL_GamepadAxis)
    padding1: u8,
    padding2: u8,
    padding3: u8,
    value: i16, // The axis value (range: -32768 to 32767)
    padding4: u16,
};

pub const DisplayEvent = extern struct {
    _type: EventType, // SDL_EVENT_DISPLAY_*
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    displayID: DisplayID, // The associated display
    data1: i32, // event dependent data
    data2: i32, // event dependent data
};

pub const DropEvent = extern struct {
    _type: EventType, // SDL_EVENT_DROP_BEGIN or SDL_EVENT_DROP_FILE or SDL_EVENT_DROP_TEXT or SDL_EVENT_DROP_COMPLETE or SDL_EVENT_DROP_POSITION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window that was dropped on, if any
    x: f32, // X coordinate, relative to window (not on begin)
    y: f32, // Y coordinate, relative to window (not on begin)
    source: [*c]const u8, // The source app that sent this drop event, or NULL if that isn't available
    data: [*c]const u8, // The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events
};

pub const CameraDeviceEvent = extern struct {
    _type: EventType, // SDL_EVENT_CAMERA_DEVICE_ADDED, SDL_EVENT_CAMERA_DEVICE_REMOVED, SDL_EVENT_CAMERA_DEVICE_APPROVED, SDL_EVENT_CAMERA_DEVICE_DENIED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: CameraID, // SDL_CameraID for the device being added or removed or changing
};

pub const KeyboardDeviceEvent = extern struct {
    _type: EventType, // SDL_EVENT_KEYBOARD_ADDED or SDL_EVENT_KEYBOARD_REMOVED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: KeyboardID, // The keyboard instance id
};

pub const JoyBatteryEvent = extern struct {
    _type: EventType, // SDL_EVENT_JOYSTICK_BATTERY_UPDATED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    state: PowerState, // The joystick battery state
    percent: c_int, // The joystick battery percent charge remaining
};

pub const TouchFingerEvent = extern struct {
    _type: EventType, // SDL_EVENT_FINGER_DOWN, SDL_EVENT_FINGER_UP, SDL_EVENT_FINGER_MOTION, or SDL_EVENT_FINGER_CANCELED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    touchID: TouchID, // The touch device id
    fingerID: FingerID,
    x: f32, // Normalized in the range 0...1
    y: f32, // Normalized in the range 0...1
    dx: f32, // Normalized in the range -1...1
    dy: f32, // Normalized in the range -1...1
    pressure: f32, // Normalized in the range 0...1
    windowID: WindowID, // The window underneath the finger, if any
};

pub const SensorEvent = extern struct {
    _type: EventType, // SDL_EVENT_SENSOR_UPDATE
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: SensorID, // The instance ID of the sensor
    data: [6]f32, // Up to 6 values from the sensor - additional values can be queried using SDL_GetSensorData()
    sensor_timestamp: u64, // The timestamp of the sensor reading in nanoseconds, not necessarily synchronized with the system clock
};

pub const TextEditingEvent = extern struct {
    _type: EventType, // SDL_EVENT_TEXT_EDITING
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with keyboard focus, if any
    text: [*c]const u8, // The editing text
    start: i32, // The start cursor of selected editing text, or -1 if not set
    length: i32, // The length of selected editing text, or -1 if not set
};

pub const JoyHatEvent = extern struct {
    _type: EventType, // SDL_EVENT_JOYSTICK_HAT_MOTION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    hat: u8, // The joystick hat index
    padding1: u8,
    padding2: u8,
};

pub const QuitEvent = extern struct {
    _type: EventType, // SDL_EVENT_QUIT
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
};

pub const PenProximityEvent = extern struct {
    _type: EventType, // SDL_EVENT_PEN_PROXIMITY_IN or SDL_EVENT_PEN_PROXIMITY_OUT
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with pen focus, if any
    which: PenID, // The pen instance id
};

pub const WindowEvent = extern struct {
    _type: EventType, // SDL_EVENT_WINDOW_*
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The associated window
    data1: i32, // event dependent data
    data2: i32, // event dependent data
};

pub const PenTouchEvent = extern struct {
    _type: EventType, // SDL_EVENT_PEN_DOWN or SDL_EVENT_PEN_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with pen focus, if any
    which: PenID, // The pen instance id
    pen_state: PenInputFlags, // Complete pen input state at time of event
    x: f32, // X coordinate, relative to window
    y: f32, // Y coordinate, relative to window
    eraser: bool, // true if eraser end is used (not all pens support this).
    down: bool, // true if the pen is touching or false if the pen is lifted off
};

pub const PenButtonEvent = extern struct {
    _type: EventType, // SDL_EVENT_PEN_BUTTON_DOWN or SDL_EVENT_PEN_BUTTON_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with mouse focus, if any
    which: PenID, // The pen instance id
    pen_state: PenInputFlags, // Complete pen input state at time of event
    x: f32, // X coordinate, relative to window
    y: f32, // Y coordinate, relative to window
    button: u8, // The pen button index (first button is 1).
    down: bool, // true if the button is pressed
};

pub const GamepadDeviceEvent = extern struct {
    _type: EventType, // SDL_EVENT_GAMEPAD_ADDED, SDL_EVENT_GAMEPAD_REMOVED, or SDL_EVENT_GAMEPAD_REMAPPED, SDL_EVENT_GAMEPAD_UPDATE_COMPLETE or SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
};

pub const JoyBallEvent = extern struct {
    _type: EventType, // SDL_EVENT_JOYSTICK_BALL_MOTION
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    ball: u8, // The joystick trackball index
    padding1: u8,
    padding2: u8,
    padding3: u8,
    xrel: i16, // The relative motion in the X direction
    yrel: i16, // The relative motion in the Y direction
};

pub const AudioDeviceEvent = extern struct {
    _type: EventType, // SDL_EVENT_AUDIO_DEVICE_ADDED, or SDL_EVENT_AUDIO_DEVICE_REMOVED, or SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: AudioDeviceID, // SDL_AudioDeviceID for the device being added or removed or changing
    recording: bool, // false if a playback device, true if a recording device.
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub const MouseWheelEvent = extern struct {
    _type: EventType, // SDL_EVENT_MOUSE_WHEEL
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with mouse focus, if any
    which: MouseID, // The mouse instance id in relative mode or 0
    x: f32, // The amount scrolled horizontally, positive to the right and negative to the left
    y: f32, // The amount scrolled vertically, positive away from the user and negative toward the user
    direction: MouseWheelDirection, // Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back
    mouse_x: f32, // X coordinate, relative to window
    mouse_y: f32, // Y coordinate, relative to window
    integer_x: i32, // The amount scrolled horizontally, accumulated to whole scroll "ticks" (added in 3.2.12)
    integer_y: i32, // The amount scrolled vertically, accumulated to whole scroll "ticks" (added in 3.2.12)
};

pub const PenAxisEvent = extern struct {
    _type: EventType, // SDL_EVENT_PEN_AXIS
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with pen focus, if any
    which: PenID, // The pen instance id
    pen_state: PenInputFlags, // Complete pen input state at time of event
    x: f32, // X coordinate, relative to window
    y: f32, // Y coordinate, relative to window
    axis: PenAxis, // Axis that has changed
    value: f32, // New value of axis
};

pub const MouseDeviceEvent = extern struct {
    _type: EventType, // SDL_EVENT_MOUSE_ADDED or SDL_EVENT_MOUSE_REMOVED
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: MouseID, // The mouse instance id
};

pub const JoyButtonEvent = extern struct {
    _type: EventType, // SDL_EVENT_JOYSTICK_BUTTON_DOWN or SDL_EVENT_JOYSTICK_BUTTON_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    which: JoystickID, // The joystick instance id
    button: u8, // The joystick button index
    down: bool, // true if the button is pressed
    padding1: u8,
    padding2: u8,
};

pub const MouseButtonEvent = extern struct {
    _type: EventType, // SDL_EVENT_MOUSE_BUTTON_DOWN or SDL_EVENT_MOUSE_BUTTON_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with mouse focus, if any
    which: MouseID, // The mouse instance id in relative mode, SDL_TOUCH_MOUSEID for touch events, or 0
    button: u8, // The mouse button index
    down: bool, // true if the button is pressed
    clicks: u8, // 1 for single-click, 2 for double-click, etc.
    padding: u8,
    x: f32, // X coordinate, relative to window
    y: f32, // Y coordinate, relative to window
};

pub const KeyboardEvent = extern struct {
    _type: EventType, // SDL_EVENT_KEY_DOWN or SDL_EVENT_KEY_UP
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with keyboard focus, if any
    which: KeyboardID, // The keyboard instance id, or 0 if unknown or virtual
    scancode: Scancode, // SDL physical key code
    key: Keycode, // SDL virtual key code
    mod: Keymod, // current key modifiers
    raw: u16, // The platform dependent scancode for this event
    down: bool, // true if the key is pressed
    repeat: bool, // true if this is a key repeat
};

pub const TextEditingCandidatesEvent = extern struct {
    _type: EventType, // SDL_EVENT_TEXT_EDITING_CANDIDATES
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with keyboard focus, if any
    candidates: [*c]const [*c]const u8, // The list of candidates, or NULL if there are no candidates available
    num_candidates: i32, // The number of strings in `candidates`
    selected_candidate: i32, // The index of the selected candidate, or -1 if no candidate is selected
    horizontal: bool, // true if the list is horizontal, false if it's vertical
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub const TextInputEvent = extern struct {
    _type: EventType, // SDL_EVENT_TEXT_INPUT
    reserved: u32,
    timestamp: u64, // In nanoseconds, populated using SDL_GetTicksNS()
    windowID: WindowID, // The window with keyboard focus, if any
    text: [*c]const u8, // The input text, UTF-8 encoded
};

pub const EventType = enum(c_int) {
    eventFirst, //Unused (do not remove)
    eventQuit, //User-requested quit
    eventTerminating,
    eventLowMemory,
    eventWillEnterBackground,
    eventDidEnterBackground,
    eventWillEnterForeground,
    eventDidEnterForeground,
    eventLocaleChanged, //The user's locale preferences have changed.
    eventSystemThemeChanged, //The system theme changed
    eventDisplayOrientation, //Display orientation has changed to data1
    eventDisplayAdded, //Display has been added to the system
    eventDisplayRemoved, //Display has been removed from the system
    eventDisplayMoved, //Display has changed position
    eventDisplayDesktopModeChanged, //Display has changed desktop mode
    eventDisplayCurrentModeChanged, //Display has changed current mode
    eventDisplayContentScaleChanged, //Display has changed content scale
    eventDisplayUsableBoundsChanged, //Display has changed usable bounds
    eventWindowShown, //Window has been shown
    eventWindowHidden, //Window has been hidden
    eventWindowExposed,
    eventWindowMoved, //Window has been moved to data1, data2
    eventWindowResized, //Window has been resized to data1xdata2
    eventWindowPixelSizeChanged, //The pixel size of the window has changed to data1xdata2
    eventWindowMetalViewResized, //The pixel size of a Metal view associated with the window has changed
    eventWindowMinimized, //Window has been minimized
    eventWindowMaximized, //Window has been maximized
    eventWindowRestored, //Window has been restored to normal size and position
    eventWindowMouseEnter, //Window has gained mouse focus
    eventWindowMouseLeave, //Window has lost mouse focus
    eventWindowFocusGained, //Window has gained keyboard focus
    eventWindowFocusLost, //Window has lost keyboard focus
    eventWindowCloseRequested, //The window manager requests that the window be closed
    eventWindowHitTest, //Window had a hit test that wasn't SDL_HITTEST_NORMAL
    eventWindowIccprofChanged, //The ICC profile of the window's display has changed
    eventWindowDisplayChanged, //Window has been moved to display data1
    eventWindowDisplayScaleChanged, //Window display scale has been changed
    eventWindowSafeAreaChanged, //The window safe area has been changed
    eventWindowOccluded, //The window has been occluded
    eventWindowEnterFullscreen, //The window has entered fullscreen mode
    eventWindowLeaveFullscreen, //The window has left fullscreen mode
    eventWindowDestroyed,
    eventWindowHdrStateChanged, //Window HDR properties have changed
    eventKeyDown, //Key pressed
    eventKeyUp, //Key released
    eventTextEditing, //Keyboard text editing (composition)
    eventTextInput, //Keyboard text input
    eventKeymapChanged,
    eventKeyboardAdded, //A new keyboard has been inserted into the system
    eventKeyboardRemoved, //A keyboard has been removed
    eventTextEditingCandidates, //Keyboard text editing candidates
    eventScreenKeyboardShown, //The on-screen keyboard has been shown
    eventScreenKeyboardHidden, //The on-screen keyboard has been hidden
    eventMouseMotion, //Mouse moved
    eventMouseButtonDown, //Mouse button pressed
    eventMouseButtonUp, //Mouse button released
    eventMouseWheel, //Mouse wheel motion
    eventMouseAdded, //A new mouse has been inserted into the system
    eventMouseRemoved, //A mouse has been removed
    eventJoystickAxisMotion, //Joystick axis motion
    eventJoystickBallMotion, //Joystick trackball motion
    eventJoystickHatMotion, //Joystick hat position change
    eventJoystickButtonDown, //Joystick button pressed
    eventJoystickButtonUp, //Joystick button released
    eventJoystickAdded, //A new joystick has been inserted into the system
    eventJoystickRemoved, //An opened joystick has been removed
    eventJoystickBatteryUpdated, //Joystick battery level change
    eventJoystickUpdateComplete, //Joystick update is complete
    eventGamepadAxisMotion, //Gamepad axis motion
    eventGamepadButtonDown, //Gamepad button pressed
    eventGamepadButtonUp, //Gamepad button released
    eventGamepadAdded, //A new gamepad has been inserted into the system
    eventGamepadRemoved, //A gamepad has been removed
    eventGamepadRemapped, //The gamepad mapping was updated
    eventGamepadTouchpadDown, //Gamepad touchpad was touched
    eventGamepadTouchpadMotion, //Gamepad touchpad finger was moved
    eventGamepadTouchpadUp, //Gamepad touchpad finger was lifted
    eventGamepadSensorUpdate, //Gamepad sensor was updated
    eventGamepadUpdateComplete, //Gamepad update is complete
    eventGamepadSteamHandleUpdated, //Gamepad Steam handle has changed
    eventFingerUp,
    eventFingerMotion,
    eventFingerCanceled,
    eventPinchBegin, //Pinch gesture started
    eventPinchUpdate, //Pinch gesture updated
    eventPinchEnd, //Pinch gesture ended
    eventClipboardUpdate, //The clipboard changed
    eventDropFile, //The system requests a file open
    eventDropText, //text/plain drag-and-drop event
    eventDropBegin, //A new set of drops is beginning (NULL filename)
    eventDropComplete, //Current set of drops is now complete (NULL filename)
    eventDropPosition, //Position while moving over the window
    eventAudioDeviceAdded, //A new audio device is available
    eventAudioDeviceRemoved, //An audio device has been removed.
    eventAudioDeviceFormatChanged, //An audio device's format has been changed by the system.
    eventSensorUpdate, //A sensor was updated
    eventPenProximityIn, //Pressure-sensitive pen has become available
    eventPenProximityOut, //Pressure-sensitive pen has become unavailable
    eventPenDown, //Pressure-sensitive pen touched drawing surface
    eventPenUp, //Pressure-sensitive pen stopped touching drawing surface
    eventPenButtonDown, //Pressure-sensitive pen button pressed
    eventPenButtonUp, //Pressure-sensitive pen button released
    eventPenMotion, //Pressure-sensitive pen is moving on the tablet
    eventPenAxis, //Pressure-sensitive pen angle/pressure/etc changed
    eventCameraDeviceAdded, //A new camera device is available
    eventCameraDeviceRemoved, //A camera device has been removed.
    eventCameraDeviceApproved, //A camera device has been approved for use by the user.
    eventCameraDeviceDenied, //A camera device has been denied for use by the user.
    eventRenderTargetsReset, //The render targets have been reset and their contents need to be updated
    eventRenderDeviceReset, //The device has been reset and all textures need to be recreated
    eventRenderDeviceLost, //The device has been lost and can't be recovered.
    eventPrivate1,
    eventPrivate2,
    eventPrivate3,
    eventPollSentinel, //Signals the end of an event poll cycle
};

pub const JoystickID = u32;

pub const WindowID = u32;

pub const MouseID = u32;

pub const MouseButtonFlags = packed struct(u32) {
    buttonLeft: bool = false,
    buttonMiddle: bool = false,
    buttonX1: bool = false,
    pad0: u28 = 0,
    rsvd: bool = false,
};

pub const PenInputFlags = packed struct(u32) {
    penInputDown: bool = false, // pen is pressed down
    penInputButton1: bool = false, // button 1 is pressed
    penInputButton2: bool = false, // button 2 is pressed
    penInputButton3: bool = false, // button 3 is pressed
    penInputButton4: bool = false, // button 4 is pressed
    penInputButton5: bool = false, // button 5 is pressed
    penInputEraserTip: bool = false, // eraser tip is used
    penInputInProximity: bool = false, // pen is in proximity (since SDL 3.4.0)
    pad0: u23 = 0,
    rsvd: bool = false,
};

pub const PenID = u32;

pub const DisplayID = u32;

pub const CameraID = u32;

pub const KeyboardID = u32;

pub const PowerState = enum(c_int) {
    powerstateError, //error determining power status
    powerstateUnknown, //cannot determine power status
    powerstateOnBattery, //Not plugged in, running on the battery
    powerstateNoBattery, //Plugged in, no battery available
    powerstateCharging, //Plugged in, charging battery
    powerstateCharged,
};

pub const TouchID = u64;

pub const FingerID = u64;

pub const SensorID = u32;

pub const AudioDeviceID = u32;

pub const MouseWheelDirection = enum(c_int) {
    mousewheelNormal, //The scroll direction is normal
    mousewheelFlipped, //The scroll direction is flipped / natural
};

pub const PenAxis = enum(c_int) {
    penAxisPressure, //Pen pressure.  Unidirectional: 0 to 1.0
    penAxisXtilt, //Pen horizontal tilt angle.  Bidirectional: -90.0 to 90.0 (left-to-right).
    penAxisYtilt, //Pen vertical tilt angle.  Bidirectional: -90.0 to 90.0 (top-to-down).
    penAxisDistance, //Pen distance to drawing surface.  Unidirectional: 0.0 to 1.0
    penAxisRotation, //Pen barrel rotation.  Bidirectional: -180 to 179.9 (clockwise, 0 is facing up, -180.0 is facing down).
    penAxisSlider, //Pen finger wheel or slider (e.g., Airbrush Pen).  Unidirectional: 0 to 1.0
    penAxisTangentialPressure, //Pressure from squeezing the pen ("barrel pressure").
    penAxisCount, //Total known pen axis types in this version of SDL. This number may grow in future releases!
};

pub const Scancode = enum(c_int) {
    scancodeBackslash,
    scancodeNonushash,
    scancodeGrave,
    scancodeInsert,
    scancodeNumlockclear,
    scancodeNonusbackslash,
    scancodeApplication, //windows contextual menu, compose
    scancodePower,
    scancodeHelp, //AL Integrated Help Center
    scancodeMenu, //Menu (show menu)
    scancodeStop, //AC Stop
    scancodeAgain, //AC Redo/Repeat
    scancodeUndo, //AC Undo
    scancodeCut, //AC Cut
    scancodeCopy, //AC Copy
    scancodePaste, //AC Paste
    scancodeFind, //AC Find
    scancodeInternational1,
    scancodeInternational3, //Yen
    scancodeLang1, //Hangul/English toggle
    scancodeLang2, //Hanja conversion
    scancodeLang3, //Katakana
    scancodeLang4, //Hiragana
    scancodeLang5, //Zenkaku/Hankaku
    scancodeLang6, //reserved
    scancodeLang7, //reserved
    scancodeLang8, //reserved
    scancodeLang9, //reserved
    scancodeAlterase, //Erase-Eaze
    scancodeCancel, //AC Cancel
    scancodeLalt, //alt, option
    scancodeLgui, //windows, command (apple), meta
    scancodeRalt, //alt gr, option
    scancodeRgui, //windows, command (apple), meta
    scancodeMode,
    scancodeSleep, //Sleep
    scancodeWake, //Wake
    scancodeChannelIncrement, //Channel Increment
    scancodeChannelDecrement, //Channel Decrement
    scancodeMediaPlay, //Play
    scancodeMediaPause, //Pause
    scancodeMediaRecord, //Record
    scancodeMediaFastForward, //Fast Forward
    scancodeMediaRewind, //Rewind
    scancodeMediaNextTrack, //Next Track
    scancodeMediaPreviousTrack, //Previous Track
    scancodeMediaStop, //Stop
    scancodeMediaEject, //Eject
    scancodeMediaPlayPause, //Play / Pause
    scancodeMediaSelect,
    scancodeAcNew, //AC New
    scancodeAcOpen, //AC Open
    scancodeAcClose, //AC Close
    scancodeAcExit, //AC Exit
    scancodeAcSave, //AC Save
    scancodeAcPrint, //AC Print
    scancodeAcProperties, //AC Properties
    scancodeAcSearch, //AC Search
    scancodeAcHome, //AC Home
    scancodeAcBack, //AC Back
    scancodeAcForward, //AC Forward
    scancodeAcStop, //AC Stop
    scancodeAcRefresh, //AC Refresh
    scancodeAcBookmarks, //AC Bookmarks
    scancodeSoftleft,
    scancodeSoftright,
    scancodeCall, //Used for accepting phone calls.
    scancodeEndcall, //Used for rejecting phone calls.
    scancodeReserved, //400-500 reserved for dynamic keycodes
    scancodeCount,
};

pub const Keymod = u16;

pub const Keycode = u32;

pub const FlipMode = enum(c_int) {
    flipNone, //Do not flip
    flipHorizontal, //flip horizontally
    flipVertical, //flip vertically
    flipHorizontalAndVertical, //flip horizontally and vertically (not a diagonal flip)
};

pub const GPUBuffer = opaque {};

pub const Rect = extern struct {
    x: c_int,
    y: c_int,
    w: c_int,
    h: c_int,
};

pub const Palette = extern struct {
    ncolors: c_int, // number of elements in `colors`.
    colors: ?*Color, // an array of colors, `ncolors` long.
    version: u32, // internal use only, do not touch.
    refcount: c_int, // internal use only, do not touch.
};

pub const Color = extern struct {
    r: u8,
    g: u8,
    b: u8,
    a: u8,
};

pub const Vertex = extern struct {
    position: FPoint, // Vertex position, in SDL_Renderer coordinates
    color: FColor, // Vertex color
    tex_coord: FPoint, // Normalized texture coordinates, if needed
};

pub const TextureAccess = enum(c_int) {
    textureaccessStatic, //Changes rarely, not lockable
    textureaccessStreaming, //Changes frequently, lockable
    textureaccessTarget, //Texture can be used as a render target
};

pub const TextureAddressMode = enum(c_int) {
    textureAddressAuto, //Wrapping is enabled if texture coordinates are outside [0, 1], this is the default
    textureAddressClamp, //Texture coordinates are clamped to the [0, 1] range
    textureAddressWrap, //The texture is repeated (tiled)
};

pub const RendererLogicalPresentation = enum(c_int) {
    logicalPresentationDisabled, //There is no logical size in effect
    logicalPresentationStretch, //The rendered content is stretched to the output resolution
    logicalPresentationLetterbox, //The rendered content is fit to the largest dimension and the other dimension is letterboxed with the clear color
    logicalPresentationOverscan, //The rendered content is fit to the smallest dimension and the other dimension extends beyond the output bounds
    logicalPresentationIntegerScale, //The rendered content is scaled up by integer multiples to fit the output resolution
};

pub const Renderer = opaque {
    pub inline fn getGPURendererDevice(renderer: *Renderer) ?*GPUDevice {
        return c.SDL_GetGPURendererDevice(renderer);
    }

    pub inline fn getRenderWindow(renderer: *Renderer) ?*Window {
        return c.SDL_GetRenderWindow(renderer);
    }

    pub inline fn getRendererName(renderer: *Renderer) [*c]const u8 {
        return c.SDL_GetRendererName(renderer);
    }

    pub inline fn getRendererProperties(renderer: *Renderer) PropertiesID {
        return c.SDL_GetRendererProperties(renderer);
    }

    pub inline fn getRenderOutputSize(renderer: *Renderer, w: *c_int, h: *c_int) bool {
        return c.SDL_GetRenderOutputSize(renderer, @ptrCast(w), @ptrCast(h));
    }

    pub inline fn getCurrentRenderOutputSize(renderer: *Renderer, w: *c_int, h: *c_int) bool {
        return c.SDL_GetCurrentRenderOutputSize(renderer, @ptrCast(w), @ptrCast(h));
    }

    pub inline fn createTexture(renderer: *Renderer, format: PixelFormat, access: TextureAccess, w: c_int, h: c_int) ?*Texture {
        return c.SDL_CreateTexture(renderer, @bitCast(format), access, w, h);
    }

    pub inline fn createTextureFromSurface(renderer: *Renderer, surface: ?*Surface) ?*Texture {
        return c.SDL_CreateTextureFromSurface(renderer, surface);
    }

    pub inline fn createTextureWithProperties(renderer: *Renderer, props: PropertiesID) ?*Texture {
        return c.SDL_CreateTextureWithProperties(renderer, props);
    }

    pub inline fn setRenderTarget(renderer: *Renderer, texture: ?*Texture) bool {
        return c.SDL_SetRenderTarget(renderer, texture);
    }

    pub inline fn getRenderTarget(renderer: *Renderer) ?*Texture {
        return c.SDL_GetRenderTarget(renderer);
    }

    pub inline fn setRenderLogicalPresentation(renderer: *Renderer, w: c_int, h: c_int, mode: RendererLogicalPresentation) bool {
        return c.SDL_SetRenderLogicalPresentation(renderer, w, h, mode);
    }

    pub inline fn getRenderLogicalPresentation(renderer: *Renderer, w: *c_int, h: *c_int, mode: ?*RendererLogicalPresentation) bool {
        return c.SDL_GetRenderLogicalPresentation(renderer, @ptrCast(w), @ptrCast(h), mode);
    }

    pub inline fn getRenderLogicalPresentationRect(renderer: *Renderer, rect: ?*FRect) bool {
        return c.SDL_GetRenderLogicalPresentationRect(renderer, rect);
    }

    pub inline fn renderCoordinatesFromWindow(renderer: *Renderer, window_x: f32, window_y: f32, x: *f32, y: *f32) bool {
        return c.SDL_RenderCoordinatesFromWindow(renderer, window_x, window_y, @ptrCast(x), @ptrCast(y));
    }

    pub inline fn renderCoordinatesToWindow(renderer: *Renderer, x: f32, y: f32, window_x: *f32, window_y: *f32) bool {
        return c.SDL_RenderCoordinatesToWindow(renderer, x, y, @ptrCast(window_x), @ptrCast(window_y));
    }

    pub inline fn convertEventToRenderCoordinates(renderer: *Renderer, event: ?*Event) bool {
        return c.SDL_ConvertEventToRenderCoordinates(renderer, event);
    }

    pub inline fn setRenderViewport(renderer: *Renderer, rect: *const Rect) bool {
        return c.SDL_SetRenderViewport(renderer, @ptrCast(rect));
    }

    pub inline fn getRenderViewport(renderer: *Renderer, rect: ?*Rect) bool {
        return c.SDL_GetRenderViewport(renderer, rect);
    }

    pub inline fn renderViewportSet(renderer: *Renderer) bool {
        return c.SDL_RenderViewportSet(renderer);
    }

    pub inline fn getRenderSafeArea(renderer: *Renderer, rect: ?*Rect) bool {
        return c.SDL_GetRenderSafeArea(renderer, rect);
    }

    pub inline fn setRenderClipRect(renderer: *Renderer, rect: *const Rect) bool {
        return c.SDL_SetRenderClipRect(renderer, @ptrCast(rect));
    }

    pub inline fn getRenderClipRect(renderer: *Renderer, rect: ?*Rect) bool {
        return c.SDL_GetRenderClipRect(renderer, rect);
    }

    pub inline fn renderClipEnabled(renderer: *Renderer) bool {
        return c.SDL_RenderClipEnabled(renderer);
    }

    pub inline fn setRenderScale(renderer: *Renderer, scaleX: f32, scaleY: f32) bool {
        return c.SDL_SetRenderScale(renderer, scaleX, scaleY);
    }

    pub inline fn getRenderScale(renderer: *Renderer, scaleX: *f32, scaleY: *f32) bool {
        return c.SDL_GetRenderScale(renderer, @ptrCast(scaleX), @ptrCast(scaleY));
    }

    pub inline fn setRenderDrawColor(renderer: *Renderer, r: u8, g: u8, b: u8, a: u8) bool {
        return c.SDL_SetRenderDrawColor(renderer, r, g, b, a);
    }

    pub inline fn setRenderDrawColorFloat(renderer: *Renderer, r: f32, g: f32, b: f32, a: f32) bool {
        return c.SDL_SetRenderDrawColorFloat(renderer, r, g, b, a);
    }

    pub inline fn getRenderDrawColor(renderer: *Renderer, r: [*c]u8, g: [*c]u8, b: [*c]u8, a: [*c]u8) bool {
        return c.SDL_GetRenderDrawColor(renderer, r, g, b, a);
    }

    pub inline fn getRenderDrawColorFloat(renderer: *Renderer, r: *f32, g: *f32, b: *f32, a: *f32) bool {
        return c.SDL_GetRenderDrawColorFloat(renderer, @ptrCast(r), @ptrCast(g), @ptrCast(b), @ptrCast(a));
    }

    pub inline fn setRenderColorScale(renderer: *Renderer, scale: f32) bool {
        return c.SDL_SetRenderColorScale(renderer, scale);
    }

    pub inline fn getRenderColorScale(renderer: *Renderer, scale: *f32) bool {
        return c.SDL_GetRenderColorScale(renderer, @ptrCast(scale));
    }

    pub inline fn setRenderDrawBlendMode(renderer: *Renderer, blendMode: BlendMode) bool {
        return c.SDL_SetRenderDrawBlendMode(renderer, @intFromEnum(blendMode));
    }

    pub inline fn getRenderDrawBlendMode(renderer: *Renderer, blendMode: ?*BlendMode) bool {
        return c.SDL_GetRenderDrawBlendMode(renderer, @intFromEnum(blendMode));
    }

    pub inline fn renderClear(renderer: *Renderer) bool {
        return c.SDL_RenderClear(renderer);
    }

    pub inline fn renderPoint(renderer: *Renderer, x: f32, y: f32) bool {
        return c.SDL_RenderPoint(renderer, x, y);
    }

    pub inline fn renderPoints(renderer: *Renderer, points: *const FPoint, count: c_int) bool {
        return c.SDL_RenderPoints(renderer, @ptrCast(points), count);
    }

    pub inline fn renderLine(renderer: *Renderer, x1: f32, y1: f32, x2: f32, y2: f32) bool {
        return c.SDL_RenderLine(renderer, x1, y1, x2, y2);
    }

    pub inline fn renderLines(renderer: *Renderer, points: *const FPoint, count: c_int) bool {
        return c.SDL_RenderLines(renderer, @ptrCast(points), count);
    }

    pub inline fn renderRect(renderer: *Renderer, rect: *const FRect) bool {
        return c.SDL_RenderRect(renderer, @ptrCast(rect));
    }

    pub inline fn renderRects(renderer: *Renderer, rects: *const FRect, count: c_int) bool {
        return c.SDL_RenderRects(renderer, @ptrCast(rects), count);
    }

    pub inline fn renderFillRect(renderer: *Renderer, rect: *const FRect) bool {
        return c.SDL_RenderFillRect(renderer, @ptrCast(rect));
    }

    pub inline fn renderFillRects(renderer: *Renderer, rects: *const FRect, count: c_int) bool {
        return c.SDL_RenderFillRects(renderer, @ptrCast(rects), count);
    }

    pub inline fn renderTexture(renderer: *Renderer, texture: ?*Texture, srcrect: *const FRect, dstrect: *const FRect) bool {
        return c.SDL_RenderTexture(renderer, texture, @ptrCast(srcrect), @ptrCast(dstrect));
    }

    pub inline fn renderTextureRotated(renderer: *Renderer, texture: ?*Texture, srcrect: *const FRect, dstrect: *const FRect, angle: f64, center: *const FPoint, flip: FlipMode) bool {
        return c.SDL_RenderTextureRotated(renderer, texture, @ptrCast(srcrect), @ptrCast(dstrect), angle, @ptrCast(center), @intFromEnum(flip));
    }

    pub inline fn renderTextureAffine(renderer: *Renderer, texture: ?*Texture, srcrect: *const FRect, origin: *const FPoint, right: *const FPoint, down: *const FPoint) bool {
        return c.SDL_RenderTextureAffine(renderer, texture, @ptrCast(srcrect), @ptrCast(origin), @ptrCast(right), @ptrCast(down));
    }

    pub inline fn renderTextureTiled(renderer: *Renderer, texture: ?*Texture, srcrect: *const FRect, scale: f32, dstrect: *const FRect) bool {
        return c.SDL_RenderTextureTiled(renderer, texture, @ptrCast(srcrect), scale, @ptrCast(dstrect));
    }

    pub inline fn renderTexture9Grid(renderer: *Renderer, texture: ?*Texture, srcrect: *const FRect, left_width: f32, right_width: f32, top_height: f32, bottom_height: f32, scale: f32, dstrect: *const FRect) bool {
        return c.SDL_RenderTexture9Grid(renderer, texture, @ptrCast(srcrect), left_width, right_width, top_height, bottom_height, scale, @ptrCast(dstrect));
    }

    pub inline fn renderTexture9GridTiled(renderer: *Renderer, texture: ?*Texture, srcrect: *const FRect, left_width: f32, right_width: f32, top_height: f32, bottom_height: f32, scale: f32, dstrect: *const FRect, tileScale: f32) bool {
        return c.SDL_RenderTexture9GridTiled(renderer, texture, @ptrCast(srcrect), left_width, right_width, top_height, bottom_height, scale, @ptrCast(dstrect), tileScale);
    }

    pub inline fn renderGeometry(renderer: *Renderer, texture: ?*Texture, vertices: *const Vertex, num_vertices: c_int, indices: [*c]const c_int, num_indices: c_int) bool {
        return c.SDL_RenderGeometry(renderer, texture, @ptrCast(vertices), num_vertices, indices, num_indices);
    }

    pub inline fn renderGeometryRaw(renderer: *Renderer, texture: ?*Texture, xy: *const f32, xy_stride: c_int, color: *const FColor, color_stride: c_int, uv: *const f32, uv_stride: c_int, num_vertices: c_int, indices: ?*const anyopaque, num_indices: c_int, size_indices: c_int) bool {
        return c.SDL_RenderGeometryRaw(renderer, texture, @ptrCast(xy), xy_stride, @ptrCast(color), color_stride, @ptrCast(uv), uv_stride, num_vertices, indices, num_indices, size_indices);
    }

    pub inline fn setRenderTextureAddressMode(renderer: *Renderer, u_mode: TextureAddressMode, v_mode: TextureAddressMode) bool {
        return c.SDL_SetRenderTextureAddressMode(renderer, @intFromEnum(u_mode), @intFromEnum(v_mode));
    }

    pub inline fn getRenderTextureAddressMode(renderer: *Renderer, u_mode: ?*TextureAddressMode, v_mode: ?*TextureAddressMode) bool {
        return c.SDL_GetRenderTextureAddressMode(renderer, @intFromEnum(u_mode), @intFromEnum(v_mode));
    }

    pub inline fn renderReadPixels(renderer: *Renderer, rect: *const Rect) ?*Surface {
        return c.SDL_RenderReadPixels(renderer, @ptrCast(rect));
    }

    pub inline fn renderPresent(renderer: *Renderer) bool {
        return c.SDL_RenderPresent(renderer);
    }

    pub inline fn destroyRenderer(renderer: *Renderer) void {
        return c.SDL_DestroyRenderer(renderer);
    }

    pub inline fn flushRenderer(renderer: *Renderer) bool {
        return c.SDL_FlushRenderer(renderer);
    }

    pub inline fn getRenderMetalLayer(renderer: *Renderer) ?*anyopaque {
        return c.SDL_GetRenderMetalLayer(renderer);
    }

    pub inline fn getRenderMetalCommandEncoder(renderer: *Renderer) ?*anyopaque {
        return c.SDL_GetRenderMetalCommandEncoder(renderer);
    }

    pub inline fn addVulkanRenderSemaphores(renderer: *Renderer, wait_stage_mask: u32, wait_semaphore: i64, signal_semaphore: i64) bool {
        return c.SDL_AddVulkanRenderSemaphores(renderer, wait_stage_mask, wait_semaphore, signal_semaphore);
    }

    pub inline fn setRenderVSync(renderer: *Renderer, vsync: c_int) bool {
        return c.SDL_SetRenderVSync(renderer, vsync);
    }

    pub inline fn getRenderVSync(renderer: *Renderer, vsync: *c_int) bool {
        return c.SDL_GetRenderVSync(renderer, @ptrCast(vsync));
    }

    pub inline fn renderDebugText(renderer: *Renderer, x: f32, y: f32, str: [*c]const u8) bool {
        return c.SDL_RenderDebugText(renderer, x, y, str);
    }

    pub inline fn setDefaultTextureScaleMode(renderer: *Renderer, scale_mode: ScaleMode) bool {
        return c.SDL_SetDefaultTextureScaleMode(renderer, @intFromEnum(scale_mode));
    }

    pub inline fn getDefaultTextureScaleMode(renderer: *Renderer, scale_mode: ?*ScaleMode) bool {
        return c.SDL_GetDefaultTextureScaleMode(renderer, @intFromEnum(scale_mode));
    }

    pub inline fn createGPURenderState(renderer: *Renderer, createinfo: ?*GPURenderStateCreateInfo) ?*GPURenderState {
        return c.SDL_CreateGPURenderState(renderer, createinfo);
    }

    pub inline fn setGPURenderState(renderer: *Renderer, state: ?*GPURenderState) bool {
        return c.SDL_SetGPURenderState(renderer, state);
    }
};

pub const Texture = opaque {
    pub inline fn getTextureProperties(texture: *Texture) PropertiesID {
        return c.SDL_GetTextureProperties(texture);
    }

    pub inline fn getRendererFromTexture(texture: *Texture) ?*Renderer {
        return c.SDL_GetRendererFromTexture(texture);
    }

    pub inline fn getTextureSize(texture: *Texture, w: *f32, h: *f32) bool {
        return c.SDL_GetTextureSize(texture, @ptrCast(w), @ptrCast(h));
    }

    pub inline fn setTexturePalette(texture: *Texture, palette: ?*Palette) bool {
        return c.SDL_SetTexturePalette(texture, palette);
    }

    pub inline fn getTexturePalette(texture: *Texture) ?*Palette {
        return c.SDL_GetTexturePalette(texture);
    }

    pub inline fn setTextureColorMod(texture: *Texture, r: u8, g: u8, b: u8) bool {
        return c.SDL_SetTextureColorMod(texture, r, g, b);
    }

    pub inline fn setTextureColorModFloat(texture: *Texture, r: f32, g: f32, b: f32) bool {
        return c.SDL_SetTextureColorModFloat(texture, r, g, b);
    }

    pub inline fn getTextureColorMod(texture: *Texture, r: [*c]u8, g: [*c]u8, b: [*c]u8) bool {
        return c.SDL_GetTextureColorMod(texture, r, g, b);
    }

    pub inline fn getTextureColorModFloat(texture: *Texture, r: *f32, g: *f32, b: *f32) bool {
        return c.SDL_GetTextureColorModFloat(texture, @ptrCast(r), @ptrCast(g), @ptrCast(b));
    }

    pub inline fn setTextureAlphaMod(texture: *Texture, alpha: u8) bool {
        return c.SDL_SetTextureAlphaMod(texture, alpha);
    }

    pub inline fn setTextureAlphaModFloat(texture: *Texture, alpha: f32) bool {
        return c.SDL_SetTextureAlphaModFloat(texture, alpha);
    }

    pub inline fn getTextureAlphaMod(texture: *Texture, alpha: [*c]u8) bool {
        return c.SDL_GetTextureAlphaMod(texture, alpha);
    }

    pub inline fn getTextureAlphaModFloat(texture: *Texture, alpha: *f32) bool {
        return c.SDL_GetTextureAlphaModFloat(texture, @ptrCast(alpha));
    }

    pub inline fn setTextureBlendMode(texture: *Texture, blendMode: BlendMode) bool {
        return c.SDL_SetTextureBlendMode(texture, @intFromEnum(blendMode));
    }

    pub inline fn getTextureBlendMode(texture: *Texture, blendMode: ?*BlendMode) bool {
        return c.SDL_GetTextureBlendMode(texture, @intFromEnum(blendMode));
    }

    pub inline fn setTextureScaleMode(texture: *Texture, scaleMode: ScaleMode) bool {
        return c.SDL_SetTextureScaleMode(texture, @intFromEnum(scaleMode));
    }

    pub inline fn getTextureScaleMode(texture: *Texture, scaleMode: ?*ScaleMode) bool {
        return c.SDL_GetTextureScaleMode(texture, @intFromEnum(scaleMode));
    }

    pub inline fn updateTexture(texture: *Texture, rect: *const Rect, pixels: ?*const anyopaque, pitch: c_int) bool {
        return c.SDL_UpdateTexture(texture, @ptrCast(rect), pixels, pitch);
    }

    pub inline fn updateYUVTexture(texture: *Texture, rect: *const Rect, Yplane: [*c]const u8, Ypitch: c_int, Uplane: [*c]const u8, Upitch: c_int, Vplane: [*c]const u8, Vpitch: c_int) bool {
        return c.SDL_UpdateYUVTexture(texture, @ptrCast(rect), Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
    }

    pub inline fn updateNVTexture(texture: *Texture, rect: *const Rect, Yplane: [*c]const u8, Ypitch: c_int, UVplane: [*c]const u8, UVpitch: c_int) bool {
        return c.SDL_UpdateNVTexture(texture, @ptrCast(rect), Yplane, Ypitch, UVplane, UVpitch);
    }

    pub inline fn lockTexture(texture: *Texture, rect: *const Rect, pixels: [*c]?*anyopaque, pitch: *c_int) bool {
        return c.SDL_LockTexture(texture, @ptrCast(rect), pixels, @ptrCast(pitch));
    }

    pub inline fn lockTextureToSurface(texture: *Texture, rect: *const Rect, surface: [*c][*c]Surface) bool {
        return c.SDL_LockTextureToSurface(texture, @ptrCast(rect), surface);
    }

    pub inline fn unlockTexture(texture: *Texture) void {
        return c.SDL_UnlockTexture(texture);
    }

    pub inline fn destroyTexture(texture: *Texture) void {
        return c.SDL_DestroyTexture(texture);
    }
};

pub inline fn getNumRenderDrivers() c_int {
    return c.SDL_GetNumRenderDrivers();
}

pub inline fn getRenderDriver(index: c_int) [*c]const u8 {
    return c.SDL_GetRenderDriver(index);
}

pub inline fn createWindowAndRenderer(title: [*c]const u8, width: c_int, height: c_int, window_flags: WindowFlags, window: [*c][*c]Window, renderer: [*c][*c]Renderer) bool {
    return c.SDL_CreateWindowAndRenderer(title, width, height, @bitCast(window_flags), window, renderer);
}

pub inline fn createRendererWithProperties(props: PropertiesID) ?*Renderer {
    return c.SDL_CreateRendererWithProperties(props);
}

pub const GPURenderStateCreateInfo = extern struct {
    fragment_shader: ?*GPUShader, // The fragment shader to use when this render state is active
    num_sampler_bindings: i32, // The number of additional fragment samplers to bind when this render state is active
    sampler_bindings: *const GPUTextureSamplerBinding, // Additional fragment samplers to bind when this render state is active
    num_storage_textures: i32, // The number of storage textures to bind when this render state is active
    storage_textures: [*c]*const GPUTexture, // Storage textures to bind when this render state is active
    num_storage_buffers: i32, // The number of storage buffers to bind when this render state is active
    storage_buffers: [*c]*const GPUBuffer, // Storage buffers to bind when this render state is active
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPURenderState = opaque {
    pub inline fn setGPURenderStateFragmentUniforms(gpurenderstate: *GPURenderState, slot_index: u32, data: ?*const anyopaque, length: u32) bool {
        return c.SDL_SetGPURenderStateFragmentUniforms(gpurenderstate, slot_index, data, length);
    }

    pub inline fn destroyGPURenderState(gpurenderstate: *GPURenderState) void {
        return c.SDL_DestroyGPURenderState(gpurenderstate);
    }
};
