/*

Boost Software License - Version 1.0 - August 17th,2003

Permission is hereby granted,free of charge,to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license(the "Software") to use,reproduce,display,distribute,
execute,and transmit the Software,and to prepare derivative works of the
Software,and to permit third-parties to whom the Software is furnished to
do so,all subject to the following:

The copyright notices in the Software and this entire statement,including
the above license grant,this restriction and the following disclaimer,
must be included in all copies of the Software,in whole or in part,and
all derivative works of the Software,unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR
IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE,TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY,WHETHER IN CONTRACT,TORT OR OTHERWISE,
ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

*/
module derelict.sdl2.internal.gpu_types;

import core.stdc.stdarg : va_list;
import derelict.sdl2.internal.sdl_types;

version(DerelictSDL2GPU_UseIntBool)
    alias GPU_bool = int;
else
    alias GPU_bool = bool;

enum GPU_FALSE = 0;
enum GPU_TRUE = 1;

struct GPU_Rect {
    float x, y;
    float w, h;
}

alias GPU_RendererEnum = uint;
enum : uint {
    GPU_RENDERER_UNKNOWN            = 0,
    GPU_RENDERER_OPENGL_1_BASE      = 1,
    GPU_RENDERER_OPENGL_1           = 2,
    GPU_RENDERER_OPENGL_2           = 3,
    GPU_RENDERER_OPENGL_3           = 4,
    GPU_RENDERER_OPENGL_4           = 5,
    GPU_RENDERER_GLES_1             = 11,
    GPU_RENDERER_GLES_2             = 12,
    GPU_RENDERER_GLES_3             = 13,
    GPU_RENDERER_D3D9               = 21,
    GPU_RENDERER_D3D10              = 22,
    GPU_RENDERER_D3D11              = 23,
    GPU_RENDERER_CUSTOM_0           = 1000,
}

struct GPU_RendererID {
    const(char)* name;
    GPU_RendererEnum renderer;
    int major_version;
    int minor_version;
}

alias GPU_BlendFuncEnum = int;
enum {
    GPU_FUNC_ZERO               = 0,
    GPU_FUNC_ONE                = 1,
    GPU_FUNC_SRC_COLOR          = 0x0300,
    GPU_FUNC_DST_COLOR          = 0x0306,
    GPU_FUNC_ONE_MINUS_SRC      = 0x0301,
    GPU_FUNC_ONE_MINUS_DST      = 0x0307,
    GPU_FUNC_SRC_ALPHA          = 0x0302,
    GPU_FUNC_DST_ALPHA          = 0x0304,
    GPU_FUNC_ONE_MINUS_SRC_ALPHA = 0x0303,
    GPU_FUNC_ONE_MINUS_DST_ALPHA = 0x0305,
}

alias GPU_BlendEqEnum = int;
enum {
    GPU_EQ_ADD              = 0x8006,
    GPU_EQ_SUBTRACT         = 0x800A,
    GPU_EQ_REVERSE_SUBRRACT = 0x800B,
}

struct GPU_BlendMode {
    GPU_BlendFuncEnum source_color;
    GPU_BlendFuncEnum dest_color;
    GPU_BlendFuncEnum source_alpha;
    GPU_BlendFuncEnum dest_alpha;
    GPU_BlendEqEnum color_equation;
    GPU_BlendEqEnum alpha_equation;
}

alias GPU_BlendPresetEnum = int;
enum {
    GPU_BLEND_NORMAL                = 0,
    GPU_BLEND_PREMULTIPLIED_ALPHA   = 1,
    GPU_BLEND_MULTIPLY              = 2,
    GPU_BLEND_ADD                   = 3,
    GPU_BLEND_SUBTRACT              = 4,
    GPU_BLEND_MOD_ALPHA             = 5,
    GPU_BLEND_SET_ALPHA             = 6,
    GPU_BLEND_SET                   = 7,
    GPU_BLEND_NORMAL_KEEP_ALPHA     = 8,
    GPU_BLEND_NORMAL_ADD_ALPHA      = 9,
    GPU_BLEND_NORMAL_FACTOR_ALPHA   = 10,
}

alias GPU_FilterEnum = int;
enum {
    GPU_FILTER_NEAREST = 0,
    GPU_FILTER_LINEAR = 1,
    GPU_FILTER_LINEAR_MIPMAP = 2,
}

alias GPU_SnapEnum = int;
enum {
    GPU_SNAP_NONE = 0,
    GPU_SNAP_POSITION = 1,
    GPU_SNAP_DIMENSIONS = 2,
    GPU_SNAP_POSITION_AND_DIMENSIONS = 3
}

alias GPU_WrapEnum = int;
enum {
    GPU_WRAP_NONE = 0,
    GPU_WRAP_REPEAT = 1,
    GPU_WRAP_MIRRORED = 2
}

alias GPU_FormatEnum = int;
enum {
    GPU_FORMAT_LUMINANCE = 1,
    GPU_FORMAT_LUMINANCE_ALPHA = 2,
    GPU_FORMAT_RGB = 3,
    GPU_FORMAT_RGBA = 4,
    GPU_FORMAT_ALPHA = 5,
    GPU_FORMAT_RG = 6,
    GPU_FORMAT_YCbCr422 = 7,
    GPU_FORMAT_YCbCr420P = 8,
}

alias GPU_FileFormatEnum = int;
enum {
    GPU_FILE_AUTO = 0,
    GPU_FILE_PNG,
    GPU_FILE_BMP,
    GPU_FILE_TGA
}

struct GPU_Image {
    GPU_Renderer* renderer;
    GPU_Target* context_target;
    GPU_Target* target;
    ushort w, h;
    GPU_bool using_virtual_resolution;
    GPU_FormatEnum format;
    int num_layers;
    int bytes_per_pixel;
    ushort base_w, base_h;
    ushort texture_w, texture_h;
    GPU_bool has_mipmaps;
    float anchor_x;
    float anchor_y;
    SDL_Color color;
    GPU_bool use_blending;
    GPU_BlendMode blend_mode;
    GPU_FilterEnum filter_mode;
    GPU_SnapEnum snap_mode;
    GPU_WrapEnum wrap_mode_x;
    GPU_WrapEnum wrap_mode_y;
    void* data;
    int refcount;
    GPU_bool is_alias;
}

struct GPU_Camera {
    float x, y, z;
    float angle;
    float zoom;
}

struct GPU_ShaderBlock {
    int position_loc;
    int texcoord_loc;
    int color_loc;
    int modelViewProjection_loc;
}

enum GPU_MODELVIEW = 0;
enum GPU_PROJECTION = 1;
enum GPU_MATRIX_STACK_MAX = 5;

struct GPU_MatrixStack {
    uint size;
    float[16][GPU_MATRIX_STACK_MAX] matrix;
}

struct GPU_Context {
    void* context;
    GPU_bool failed;
    uint windowID;
    int window_w;
    int window_h;
    int drawable_w;
    int drawable_h;
    int stored_window_w;
    int stored_window_h;
    uint current_shader_program;
    uint default_textured_shader_program;
    uint default_untextured_shader_program;
    GPU_ShaderBlock current_shader_block;
    GPU_ShaderBlock default_textured_shader_block;
    GPU_ShaderBlock default_untextured_shader_block;
    GPU_bool shapes_use_blending;
    GPU_BlendMode shapes_blend_mode;
    float line_thickness;
    GPU_bool use_texturing;
    int matrix_mode;
    GPU_MatrixStack projection_matrix;
    GPU_MatrixStack modelview_matrix;
    void* data;
}

struct GPU_Target {
    GPU_Renderer* renderer;
    GPU_Target* context_target;
    GPU_Image* image;
    void* data;
    ushort w, h;
    GPU_bool using_virtual_resolution;
    ushort base_w, base_h;
    GPU_bool use_clip_rect;
    GPU_Rect clip_rect;
    GPU_bool use_color;
    SDL_Color color;
    GPU_Rect viewport;
    GPU_Camera camera;
    GPU_bool use_camera;
    GPU_Context* context;
    int refcount;
    GPU_bool is_alias;
}

alias GPU_FeatureEnum = int;
enum {
    GPU_FEATURE_NON_POWER_OF_TWO        = 0x1,
    GPU_FEATURE_RENDER_TARGETS          = 0x2,
    GPU_FEATURE_BLEND_EQUATIONS         = 0x4,
    GPU_FEATURE_BLEND_FUNC_SEPARATE     = 0x8,
    GPU_FEATURE_BLEND_EQUATIONS_SEPARATE = 0x10,
    GPU_FEATURE_GL_BGR                  = 0x20,
    GPU_FEATURE_GL_BGRA                 = 0x40,
    GPU_FEATURE_GL_ABGR                 = 0x80,
    GPU_FEATURE_VERTEX_SHADER           = 0x100,
    GPU_FEATURE_FRAGMENT_SHADER         = 0x200,
    GPU_FEATURE_PIXEL_SHADER            = 0x200,
    GPU_FEATURE_GEOMETRY_SHADER         = 0x400,
    GPU_FEATURE_WRAP_REPEAT_MIRRORED    = 0x800,
}

alias GPU_WindowFlagEnum = uint;
alias GPU_InitFlagEnum = uint;
enum : uint {
    GPU_INIT_ENABLE_VSYNC               = 0x1,
    GPU_INIT_DISABLE_VSYNC              = 0x2,
    GPU_INIT_DISABLE_DOUBLE_BUFFER      = 0x4,
    GPU_INIT_DISABLE_AUTO_VIRTUAL_RESOLUTION = 0x8,
    GPU_INIT_REQUEST_COMPATIBILITY_PROFILE = 0x10,
}

enum GPU_DEFAULT_INIT_FLAGS = 0;
enum uint GPU_NONE = 0;

alias GPU_BatchFlagEnum = uint;
enum : uint {
    GPU_BATCH_XY        = 0x1,
    GPU_BATCH_XYZ       = 0x2,
    GPU_BATCH_ST        = 0x4,
    GPU_BATCH_RGB       = 0x8,
    GPU_BATCH_RGBA      = 0x10,
    GPU_BATCH_RGB8      = 0x20,
    GPU_BATCH_RGBA8     = 0x40,
    GPU_BATCH_XY_ST     = GPU_BATCH_XY | GPU_BATCH_ST,
    GPU_BATCH_XYZ_ST    = GPU_BATCH_XYZ | GPU_BATCH_ST,
    GPU_BATCH_XY_RGB    = GPU_BATCH_XY | GPU_BATCH_RGB,
    GPU_BATCH_XYZ_RGB   = GPU_BATCH_XYZ | GPU_BATCH_RGB,
    GPU_BATCH_XY_RGBA   = GPU_BATCH_XY | GPU_BATCH_RGBA,
    GPU_BATCH_XYZ_RGBA  = GPU_BATCH_XYZ | GPU_BATCH_RGBA,
    GPU_BATCH_XY_ST_RGBA = GPU_BATCH_XY | GPU_BATCH_ST | GPU_BATCH_RGBA,
    GPU_BATCH_XYZ_ST_RGBA = GPU_BATCH_XYZ | GPU_BATCH_ST | GPU_BATCH_RGBA,
    GPU_BATCH_XY_RGB8   = GPU_BATCH_XY | GPU_BATCH_RGB8,
    GPU_BATCH_XYZ_RGB8  = GPU_BATCH_XYZ | GPU_BATCH_RGB8,
    GPU_BATCH_XY_RGBA8  = GPU_BATCH_XY | GPU_BATCH_RGBA8,
    GPU_BATCH_XYZ_RGBA8 = GPU_BATCH_XYZ | GPU_BATCH_RGBA8,
    GPU_BATCH_XY_ST_RGBA8 = GPU_BATCH_XY | GPU_BATCH_ST | GPU_BATCH_RGBA8,
    GPU_BATCH_XYZ_ST_RGBA8 = GPU_BATCH_XYZ | GPU_BATCH_ST | GPU_BATCH_RGBA8,
}

alias GPU_FlipEnum = uint;
enum : uint {
    GPU_FLIP_NONE       = 0x0,
    GPU_FLIP_HORIZONTAL = 0x1,
    GPU_FLIP_VERTICAL   = 0x2,
}

alias GPU_TypeEnum = uint;
enum : uint {
    GPU_TYPE_BYTE           = 0x1400,
    GPU_TYPE_UNSIGNED_BYTE  = 0x1401,
    GPU_TYPE_SHORT          = 0x1402,
    GPU_TYPE_UNSIGNED_SHORT = 0x1403,
    GPU_TYPE_INT            = 0x1404,
    GPU_TYPE_UNSIGNED_INT   = 0x1405,
    GPU_TYPE_FLOAT          = 0x1406,
    GPU_TYPE_DOUBLE         = 0x140A,
}

alias GPU_ShaderEnum = int;
enum {
    GPU_VERTEX_SHADER = 0,
    GPU_FRAGMENT_SHADER = 1,
    GPU_PIXEL_SHADER = 1,
    GPU_GEOMETRY_SHADER = 2,
}

alias GPU_ShaderLanguageEnum = int;
enum {
    GPU_LANGUAGE_NONE = 0,
    GPU_LANGUAGE_ARB_ASSEMBLY = 1,
    GPU_LANGUAGE_GLSL = 2,
    GPU_LANGUAGE_GLSLES = 3,
    GPU_LANGUAGE_HLSL = 4,
    GPU_LANGUAGE_CG = 5,
}

struct GPU_AttributeFormat {
    GPU_bool is_per_sprite;
    int num_elems_per_value;
    GPU_TypeEnum type;
    GPU_bool normalize;
    int stride_bytes;
    int offset_bytes;
}

struct GPU_Attribute {
    int location;
    void* values;
    GPU_AttributeFormat format;
}

struct GPU_AttributeSource {
    GPU_bool enabled;
    int num_values;
    void* next_value;
    int per_vertex_storage_stride_bytes;
    int per_vertex_storage_offset_bytes;
    int per_vertex_storage_size;
    void* per_vertex_storage;
    GPU_Attribute attribute;
}

alias GPU_ErrorEnum = int;
enum {
    GPU_ERROR_NONE = 0,
    GPU_ERROR_BACKEND_ERROR = 1,
    GPU_ERROR_DATA_ERROR = 2,
    GPU_ERROR_USER_ERROR = 3,
    GPU_ERROR_UNSUPPORTED_FUNCTION = 4,
    GPU_ERROR_NULL_ARGUMENT = 5,
    GPU_ERROR_FILE_NOT_FOUND = 6,
}

struct GPU_ErrorObject {
    char* function_;
    GPU_ErrorEnum error;
    char* details;
}

alias GPU_DebugLevelEnum = int;
enum {
    GPU_DEBUG_LEVEL_0 = 0,
    GPU_DEBUG_LEVEL_1 = 1,
    GPU_DEBUG_LEVEL_2 = 2,
    GPU_DEBUG_LEVEL_3 = 3,
    GPU_DEBUG_LEVEL_MAX = 3,
}

alias GPU_LogLevelEnum = int;
enum {
    GPU_LOG_INFO = 0,
    GPU_LOG_WARNING,
    GPU_LOG_ERROR,
}

struct GPU_RendererImpl;
struct GPU_Renderer {
    GPU_RendererID id;
    GPU_RendererID requested_id;
    GPU_WindowFlagEnum SDL_init_flags;
    GPU_InitFlagEnum GPU_init_flags;
    GPU_ShaderLanguageEnum shader_language;
    int min_shader_version;
    int max_shader_version;
    GPU_FeatureEnum enabled_features;
    GPU_Target* current_context_target;
    GPU_bool coordinate_mode;
    float default_image_anchor_x;
    float default_image_anchor_y;
    GPU_RendererImpl* impl;
}

extern(C) nothrow {
    alias LogCallback = int function(GPU_LogLevelEnum,const(char)*,va_list);
    alias RendererConstructor = GPU_Renderer* function(GPU_RendererID);
    alias RendererDestructor = void function(GPU_Renderer*);
}