/*
 * Copyright (c) 2004-2008 Derelict Developers
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the names 'Derelict', 'DerelictGL', nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
module derelict.opengl.cgl;

// Original version: 2008-04-03 by Hugues De Keyzer

// Original C headers:
//     OpenGL.h
//     CGLTypes.h
//     CGLCurrent.h
// from /System/Library/Frameworks/OpenGL.framework/Headers from Mac OS X 10.4

version (darwin)
{

private
{
    import derelict.opengl.gltypes;
    import derelict.util.loader;
}

extern (C):

/*
** CGLContext structure.
*/
struct _CGLContextObject {}

struct _CGLPixelFormatObject {}
struct _CGLRendererInfoObject {}
struct _CGLPBufferObject {}

/*
** CGL opaque data.
*/
typedef _CGLContextObject*              CGLContextObj;
typedef _CGLPixelFormatObject*          CGLPixelFormatObj;
typedef _CGLRendererInfoObject*         CGLRendererInfoObj;
typedef _CGLPBufferObject*              CGLPBufferObj;

/*
** Attribute names for CGLChoosePixelFormat and CGLDescribePixelFormat.
*/
enum CGLPixelFormatAttribute
{
	kCGLPFAAllRenderers       =   1,	/* choose from all available renderers          */
	kCGLPFADoubleBuffer       =   5,	/* choose a double buffered pixel format        */
	kCGLPFAStereo             =   6,	/* stereo buffering supported                   */
	kCGLPFAAuxBuffers         =   7,	/* number of aux buffers                        */
	kCGLPFAColorSize          =   8,	/* number of color buffer bits                  */
	kCGLPFAAlphaSize          =  11,	/* number of alpha component bits               */
	kCGLPFADepthSize          =  12,	/* number of depth buffer bits                  */
	kCGLPFAStencilSize        =  13,	/* number of stencil buffer bits                */
	kCGLPFAAccumSize          =  14,	/* number of accum buffer bits                  */
	kCGLPFAMinimumPolicy      =  51,	/* never choose smaller buffers than requested  */
	kCGLPFAMaximumPolicy      =  52,	/* choose largest buffers of type requested     */
	kCGLPFAOffScreen          =  53,	/* choose an off-screen capable renderer        */
	kCGLPFAFullScreen         =  54,	/* choose a full-screen capable renderer        */
	kCGLPFASampleBuffers      =  55,	/* number of multi sample buffers               */
	kCGLPFASamples            =  56,	/* number of samples per multi sample buffer    */
	kCGLPFAAuxDepthStencil    =  57,	/* each aux buffer has its own depth stencil    */
	kCGLPFAColorFloat         =  58,	/* color buffers store floating point pixels    */
	kCGLPFAMultisample        =  59,	/* choose multisampling                         */
	kCGLPFASupersample        =  60,	/* choose supersampling                         */
	kCGLPFASampleAlpha        =  61,	/* request alpha filtering                      */

	kCGLPFARendererID         =  70,	/* request renderer by ID                       */
	kCGLPFASingleRenderer     =  71,	/* choose a single renderer for all screens     */
	kCGLPFANoRecovery         =  72,	/* disable all failure recovery systems         */
	kCGLPFAAccelerated        =  73,	/* choose a hardware accelerated renderer       */
	kCGLPFAClosestPolicy      =  74,	/* choose the closest color buffer to request   */
	kCGLPFARobust             =  75,	/* renderer does not need failure recovery      */
	kCGLPFABackingStore       =  76,	/* back buffer contents are valid after swap    */
	kCGLPFAMPSafe             =  78,	/* renderer is multi-processor safe             */
	kCGLPFAWindow             =  80,	/* can be used to render to an onscreen window  */
	kCGLPFAMultiScreen        =  81,	/* single window can span multiple screens      */
	kCGLPFACompliant          =  83,	/* renderer is opengl compliant                 */
	kCGLPFADisplayMask        =  84,	/* mask limiting supported displays             */
	kCGLPFAPBuffer            =  90,	/* can be used to render to a pbuffer           */
	kCGLPFARemotePBuffer      =  91,	/* can be used to render offline to a pbuffer   */
	kCGLPFAVirtualScreenCount = 128 	/* number of virtual screens in this format     */
}

/*
** Property names for CGLDescribeRenderer.
*/
enum CGLRendererProperty
{
	kCGLRPOffScreen           =  53,
	kCGLRPFullScreen          =  54,
	kCGLRPRendererID          =  70,
	kCGLRPAccelerated         =  73,
	kCGLRPRobust              =  75,
	kCGLRPBackingStore        =  76,
	kCGLRPMPSafe              =  78,
	kCGLRPWindow              =  80,
	kCGLRPMultiScreen         =  81,
	kCGLRPCompliant           =  83,
	kCGLRPDisplayMask         =  84,
	kCGLRPBufferModes         = 100,	/* a bitfield of supported buffer modes          */
	kCGLRPColorModes          = 103,	/* a bitfield of supported color buffer formats  */
	kCGLRPAccumModes          = 104,	/* a bitfield of supported accum buffer formats  */
	kCGLRPDepthModes          = 105,	/* a bitfield of supported depth buffer depths   */
	kCGLRPStencilModes        = 106,	/* a bitfield of supported stencil buffer depths */
	kCGLRPMaxAuxBuffers       = 107,	/* maximum number of auxilliary buffers          */
	kCGLRPMaxSampleBuffers    = 108,	/* maximum number of sample buffers              */
	kCGLRPMaxSamples          = 109,	/* maximum number of samples                     */
	kCGLRPSampleModes         = 110,	/* a bitfield of supported sample modes          */
	kCGLRPSampleAlpha         = 111,	/* support for alpha sampling                    */
	kCGLRPVideoMemory         = 120,	/* total video memory                            */
	kCGLRPTextureMemory       = 121,	/* video memory useable for texture storage      */
	kCGLRPGPUVertProcCapable  = 122,	/* renderer capable of GPU vertex processing     */
	kCGLRPGPUFragProcCapable  = 123,	/* renderer capable of GPU fragment processing   */
	kCGLRPRendererCount       = 128 	/* the number of renderers in this renderer info */
}

/*
** Enable names for CGLEnable, CGLDisable, and CGLIsEnabled.
*/
enum CGLContextEnable
{
	kCGLCESwapRectangle    = 201,	/* Enable or disable the swap rectangle          */
	kCGLCESwapLimit        = 203,	/* Enable or disable the swap async limit        */
	kCGLCERasterization    = 221,	/* Enable or disable all rasterization           */
	kCGLCEStateValidation  = 301,	/* Validate state for multi-screen functionality */
	kCGLCESurfaceBackingSize = 305, /* Enable or disable surface backing size override */
	kCGLCEDisplayListOptimization = 307,  /* Ability to turn off display list optimizer */
	kCGLCEMPEngine = 313            /* Enable or disable multi-threaded GL engine    */
}

/*
** Parameter names for CGLSetParameter and CGLGetParameter.
*/
enum CGLContextParameter
{
	kCGLCPSwapRectangle     = 200,  /* 4 params.  Set or get the swap rectangle {x, y, w, h}  */
	kCGLCPSwapInterval      = 222,  /* 1 param.   0 -> Don't sync, n -> Sync every n retrace  */
	kCGLCPDispatchTableSize = 224,  /* 1 param.   Get the dispatch table size                 */
	/* Note: kCGLCPClientStorage is always a pointer-sized parameter, even though the API claims GLint. */
	kCGLCPClientStorage     = 226,  /* 1 param.   Context specific generic storage            */
	kCGLCPSurfaceTexture    = 228,  /* 3 params.  SID, target, internal_format                */
/*  - Used by AGL - */
/*  AGL_STATE_VALIDATION     230    */
/*  AGL_BUFFER_NAME          231    */
/*  AGL_ORDER_CONTEXT_TO_FRONT  232 */
/*  AGL_CONTEXT_SURFACE_ID   233    */
/*  AGL_CONTEXT_DISPLAY_ID   234    */
	kCGLCPSurfaceOrder      = 235,  /* 1 param.   1 -> Above window, -1 -> Below Window       */
	kCGLCPSurfaceOpacity    = 236,  /* 1 param.   1 -> Surface is opaque (default), 0 -> non-opaque */
/*  - Used by AGL - */
/*  AGL_CLIP_REGION          254   */
/*  AGL_FS_CAPTURE_SINGLE    255   */
	kCGLCPSurfaceBackingSize = 304,  	/* 2 params.   Width/height of surface backing size     */
/* AGL_SURFACE_VOLATILE		 306	*/
	kCGLCPSurfaceSurfaceVolatile = 306,	/* 1 param.   Surface volatile state					*/
	kCGLCPReclaimResources		 = 308,	/* 0 params.  */
	kCGLCPCurrentRendererID      = 309,	/* 1 param.   Retrieves the current renderer ID         */
	kCGLCPGPUVertexProcessing	 = 310, /* 1 param.   Currently processing vertices with GPU (get) */
	kCGLCPGPUFragmentProcessing	 = 311, /* 1 param.   Currently processing fragments with GPU (get) */
}

/*
** Option names for CGLSetOption and CGLGetOption.
*/
enum CGLGlobalOption
{
	kCGLGOFormatCacheSize  = 501,	/* Set the size of the pixel format cache        */
	kCGLGOClearFormatCache = 502,	/* Reset the pixel format cache if true          */
	kCGLGORetainRenderers  = 503,	/* Whether to retain loaded renderers in memory  */
	kCGLGOResetLibrary     = 504,	/* *** DEPRECATED in MacOS X 10.4 ***            */
	                             	/* Do a soft reset of the CGL library if true    */
	kCGLGOUseErrorHandler  = 505,	/* Call the Core Graphics handler on CGL errors  */
}

/*
** Error return values from CGLGetError.
*/
enum CGLError
{
	kCGLNoError            = 0,     /* no error */
	kCGLBadAttribute       = 10000,	/* invalid pixel format attribute  */
	kCGLBadProperty        = 10001,	/* invalid renderer property       */
	kCGLBadPixelFormat     = 10002,	/* invalid pixel format            */
	kCGLBadRendererInfo    = 10003,	/* invalid renderer info           */
	kCGLBadContext         = 10004,	/* invalid context                 */
	kCGLBadDrawable        = 10005,	/* invalid drawable                */
	kCGLBadDisplay         = 10006,	/* invalid graphics device         */
	kCGLBadState           = 10007,	/* invalid context state           */
	kCGLBadValue           = 10008,	/* invalid numerical value         */
	kCGLBadMatch           = 10009,	/* invalid share context           */
	kCGLBadEnumeration     = 10010,	/* invalid enumerant               */
	kCGLBadOffScreen       = 10011,	/* invalid offscreen drawable      */
	kCGLBadFullScreen      = 10012,	/* invalid offscreen drawable      */
	kCGLBadWindow          = 10013,	/* invalid window                  */
	kCGLBadAddress         = 10014,	/* invalid pointer                 */
	kCGLBadCodeModule      = 10015,	/* invalid code module             */
	kCGLBadAlloc           = 10016,	/* invalid memory allocation       */
	kCGLBadConnection      = 10017 	/* invalid CoreGraphics connection */
}

// Function pointer variables

/*
** Pixel format functions
*/
typedef CGLError                function(CGLPixelFormatAttribute*, CGLPixelFormatObj*, int*)
                            pfCGLChoosePixelFormat;
typedef CGLError                function(CGLPixelFormatObj)
                            pfCGLDestroyPixelFormat;
typedef CGLError                function(CGLPixelFormatObj, int, CGLPixelFormatAttribute, int*)
                            pfCGLDescribePixelFormat;

/*
** Renderer information functions
*/
typedef CGLError                function(uint, CGLRendererInfoObj*, int*)
                            pfCGLQueryRendererInfo;
typedef CGLError                function(CGLRendererInfoObj)
                            pfCGLDestroyRendererInfo;
typedef CGLError                function(CGLRendererInfoObj, int, CGLRendererProperty, int*)
                            pfCGLDescribeRenderer;

/*
** Context functions
*/
typedef CGLError                function(CGLPixelFormatObj, CGLContextObj, CGLContextObj*)
                            pfCGLCreateContext;
typedef CGLError                function(CGLContextObj)
                            pfCGLDestroyContext;
typedef CGLError                function(CGLContextObj, CGLContextObj, uint)
                            pfCGLCopyContext;

/*
** PBuffer functions
*/
// FIXME
// These functions use the AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER macro. See
// <AvailabilityMacros.h>.
version (Mac_OS_X_10_3_and_later)
{
typedef CGLError                function(int, int, uint, uint, int, CGLPBufferObj*)
                            pfCGLCreatePBuffer;

typedef CGLError                function(CGLPBufferObj)
                            pfCGLDestroyPBuffer;

typedef CGLError                function(CGLPBufferObj, int*, int*, uint*, uint*, int*)
                            pfCGLDescribePBuffer;

typedef CGLError                function(CGLContextObj, CGLPBufferObj, uint)
                            pfCGLTexImagePBuffer;
}

/*
** Drawable Functions
*/
typedef CGLError                function(CGLContextObj, int, int, int, void*)
                            pfCGLSetOffScreen;
typedef CGLError                function(CGLContextObj, int*, int*, int*, void **baseaddr)
                            pfCGLGetOffScreen;
typedef CGLError                function(CGLContextObj)
                            pfCGLSetFullScreen;

version (Mac_OS_X_10_3_and_later)
{
typedef CGLError                function(CGLContextObj, CGLPBufferObj, uint, int, int)
                            pfCGLSetPBuffer;

typedef CGLError                function(CGLContextObj, CGLPBufferObj*, uint*, int*, int*)
                            pfCGLGetPBuffer;
}

typedef CGLError                function(CGLContextObj)
                            pfCGLClearDrawable;
typedef CGLError                function(CGLContextObj)
                            pfCGLFlushDrawable;

/*
** Per context enables and parameters
*/
typedef CGLError                function(CGLContextObj, CGLContextEnable)
                            pfCGLEnable;
typedef CGLError                function(CGLContextObj, CGLContextEnable)
                            pfCGLDisable;
typedef CGLError                function(CGLContextObj, CGLContextEnable, int*)
                            pfCGLIsEnabled;
typedef CGLError                function(CGLContextObj, CGLContextParameter, int*)
                            pfCGLSetParameter;
typedef CGLError                function(CGLContextObj, CGLContextParameter, int*)
                            pfCGLGetParameter;

/*
** Virtual screen functions
*/
typedef CGLError                function(CGLContextObj, int)
                            pfCGLSetVirtualScreen;
typedef CGLError                function(CGLContextObj, int*)
                            pfCGLGetVirtualScreen;

/*
** Global library options
*/
typedef CGLError                function(CGLGlobalOption, int)
                            pfCGLSetOption;
typedef CGLError                function(CGLGlobalOption, int*)
                            pfCGLGetOption;

/*
** Locking functions
*/
version (Mac_OS_X_10_4_and_later)
{
typedef CGLError                function(CGLContextObj)
                            pfCGLLockContext;

typedef CGLError                function(CGLContextObj)
                            pfCGLUnlockContext;
}

/*
** Version numbers
*/
typedef void                    function(int*, int*)
                            pfCGLGetVersion;

/*
** Convert an error code to a string
*/
typedef const char*             function(CGLError)
                            pfCGLErrorString;

/*
** Current context functions
*/
typedef CGLError                function(CGLContextObj)
                            pfCGLSetCurrentContext;
typedef CGLContextObj           function()
                            pfCGLGetCurrentContext;

/*
** Pixel format functions
*/
pfCGLChoosePixelFormat      CGLChoosePixelFormat;
pfCGLDestroyPixelFormat     CGLDestroyPixelFormat;
pfCGLDescribePixelFormat    CGLDescribePixelFormat;

/*
** Renderer information functions
*/
pfCGLQueryRendererInfo      CGLQueryRendererInfo;
pfCGLDestroyRendererInfo    CGLDestroyRendererInfo;
pfCGLDescribeRenderer       CGLDescribeRenderer;

/*
** Context functions
*/
pfCGLCreateContext          CGLCreateContext;
pfCGLDestroyContext         CGLDestroyContext;
pfCGLCopyContext            CGLCopyContext;

/*
** PBuffer functions
*/
// FIXME
// These functions use the AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER macro. See
// <AvailabilityMacros.h>.
version (Mac_OS_X_10_3_and_later)
{
pfCGLCreatePBuffer          CGLCreatePBuffer;

pfCGLDestroyPBuffer         CGLDestroyPBuffer;

pfCGLDescribePBuffer        CGLDescribePBuffer;

pfCGLTexImagePBuffer        CGLTexImagePBuffer;
}

/*
** Drawable Functions
*/
pfCGLSetOffScreen           CGLSetOffScreen;
pfCGLGetOffScreen           CGLGetOffScreen;
pfCGLSetFullScreen          CGLSetFullScreen;

version (Mac_OS_X_10_3_and_later)
{
pfCGLSetPBuffer             CGLSetPBuffer;

pfCGLGetPBuffer             CGLGetPBuffer;
}

pfCGLClearDrawable          CGLClearDrawable;
pfCGLFlushDrawable          CGLFlushDrawable;

/*
** Per context enables and parameters
*/
pfCGLEnable                 CGLEnable;
pfCGLDisable                CGLDisable;
pfCGLIsEnabled              CGLIsEnabled;
pfCGLSetParameter           CGLSetParameter;
pfCGLGetParameter           CGLGetParameter;

/*
** Virtual screen functions
*/
pfCGLSetVirtualScreen       CGLSetVirtualScreen;
pfCGLGetVirtualScreen       CGLGetVirtualScreen;

/*
** Global library options
*/
pfCGLSetOption              CGLSetOption;
pfCGLGetOption              CGLGetOption;

/*
** Locking functions
*/
version (Mac_OS_X_10_4_and_later)
{
pfCGLLockContext            CGLLockContext;

pfCGLUnlockContext          CGLUnlockContext;
}

/*
** Version numbers
*/
pfCGLGetVersion             CGLGetVersion;

/*
** Convert an error code to a string
*/
pfCGLErrorString            CGLErrorString;

/*
** Current context functions
*/
pfCGLSetCurrentContext      CGLSetCurrentContext;
pfCGLGetCurrentContext      CGLGetCurrentContext;

package void loadPlatformGL(SharedLib lib)
{
    bindFunc(CGLSetCurrentContext)("CGLSetCurrentContext", lib);
    bindFunc(CGLGetCurrentContext)("CGLGetCurrentContext", lib);
/*
** Pixel format functions
*/
    bindFunc(CGLChoosePixelFormat)("CGLChoosePixelFormat", lib);
    bindFunc(CGLDestroyPixelFormat)("CGLDestroyPixelFormat", lib);
    bindFunc(CGLDescribePixelFormat)("CGLDescribePixelFormat", lib);

/*
** Renderer information functions
*/
    bindFunc(CGLQueryRendererInfo)("CGLQueryRendererInfo", lib);
    bindFunc(CGLDestroyRendererInfo)("CGLDestroyRendererInfo", lib);
    bindFunc(CGLDescribeRenderer)("CGLDescribeRenderer", lib);

/*
** Context functions
*/
    bindFunc(CGLCreateContext)("CGLCreateContext", lib);
    bindFunc(CGLDestroyContext)("CGLDestroyContext", lib);
    bindFunc(CGLCopyContext)("CGLCopyContext", lib);

/*
** PBuffer functions
*/
// FIXME
// These functions use the AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER macro. See
// <AvailabilityMacros.h>.
version (Mac_OS_X_10_3_and_later)
{
    bindFunc(CGLCreatePBuffer)("CGLCreatePBuffer", lib);

    bindFunc(CGLDestroyPBuffer)("CGLDestroyPBuffer", lib);

    bindFunc(CGLDescribePBuffer)("CGLDescribePBuffer", lib);

    bindFunc(CGLTexImagePBuffer)("CGLTexImagePBuffer", lib);
}

/*
** Drawable Functions
*/
    bindFunc(CGLSetOffScreen)("CGLSetOffScreen", lib);
    bindFunc(CGLGetOffScreen)("CGLGetOffScreen", lib);
    bindFunc(CGLSetFullScreen)("CGLSetFullScreen", lib);

version (Mac_OS_X_10_3_and_later)
{
    bindFunc(CGLSetPBuffer)("CGLSetPBuffer", lib);

    bindFunc(CGLGetPBuffer)("CGLGetPBuffer", lib);
}

    bindFunc(CGLClearDrawable)("CGLClearDrawable", lib);
    bindFunc(CGLFlushDrawable)("CGLFlushDrawable", lib);

/*
** Per context enables and parameters
*/
    bindFunc(CGLEnable)("CGLEnable", lib);
    bindFunc(CGLDisable)("CGLDisable", lib);
    bindFunc(CGLIsEnabled)("CGLIsEnabled", lib);
    bindFunc(CGLSetParameter)("CGLSetParameter", lib);
    bindFunc(CGLGetParameter)("CGLGetParameter", lib);

/*
** Virtual screen functions
*/
    bindFunc(CGLSetVirtualScreen)("CGLSetVirtualScreen", lib);
    bindFunc(CGLGetVirtualScreen)("CGLGetVirtualScreen", lib);

/*
** Global library options
*/
    bindFunc(CGLSetOption)("CGLSetOption", lib);
    bindFunc(CGLGetOption)("CGLGetOption", lib);

/*
** Locking functions
*/
version (Mac_OS_X_10_4_and_later)
{
    bindFunc(CGLLockContext)("CGLLockContext", lib);

    bindFunc(CGLUnlockContext)("CGLUnlockContext", lib);
}

/*
** Version numbers
*/
    bindFunc(CGLGetVersion)("CGLGetVersion", lib);

/*
** Convert an error code to a string
*/
    bindFunc(CGLErrorString)("CGLErrorString", lib);

/*
** Current context functions
*/
    bindFunc(CGLSetCurrentContext)("CGLSetCurrentContext", lib);
    bindFunc(CGLGetCurrentContext)("CGLGetCurrentContext", lib);
}

}   // version(darwin)
