/*
 * Direct3D HAL GLX interface
 *
 * Copyright 2003 TransGaming Technologies, Inc.
 */
#ifndef __WINE_GLX_PRIVATE_H
#define __WINE_GLX_PRIVATE_H
#include "config.h"
#ifdef HAVE_OPENGL
#include "ddrawi.h"

#define CACHESIZE 64 /* at least front + back + 6 cubemap faces = 8, preferably more */

/* with a few exceptions, these are mostly only extensions
 * we need to know about and disable to make the FPS display
 * display properly, the full extension list used for rendering
 * is in dlls/d3dgl/d3dgl_private.h */
#define DD_GL_EXTENSION_LIST \
    DD_GL_EXT(ARB_multitexture), \
    DD_GL_EXT(ARB_texture_cube_map), \
    DD_GL_EXT(ARB_vertex_blend), \
    DD_GL_EXT(ARB_vertex_program), \
    DD_GL_EXT(ARB_fragment_program), \
    DD_GL_EXT(EXT_secondary_color), \
    DD_GL_EXT(EXT_fog_coord), \
    DD_GL_EXT(EXT_vertex_weighting), \
    DD_GL_EXT(EXT_vertex_shader), \
    DD_GL_EXT(NV_vertex_array_range), \
    DD_GL_EXT(NV_register_combiners), \
    DD_GL_EXT(NV_fence), \
    DD_GL_EXT(NV_vertex_array_range2), \
    DD_GL_EXT(NV_vertex_program)

#define DD_GL_EXT(x) x
typedef enum {
  DD_GL_EXTENSION_LIST,
  DD_GL_EXTENSION_COUNT
} DD_GL_ext;
#undef DD_GL_EXT

#define DD_GL_PROC_LIST \
    DD_GL_PROC(PFNGLACTIVETEXTUREARBPROC,glActiveTextureARB) \
    DD_GL_PROC(PFNGLCLIENTACTIVETEXTUREARBPROC,glClientActiveTextureARB) \
    DD_GL_PROC(PFNGLMULTITEXCOORD2FARBPROC,glMultiTexCoord2fARB) \
    DD_GL_PROC(PFNGLSECONDARYCOLOR3UBEXTPROC,glSecondaryColor3ubEXT)

/* vertex buffer implementations */

typedef struct _GLX_D3D_VBUFFER_priv GLX_D3D_VBUFFER_priv;

typedef struct _GLX_D3D_VBUFFER_callbacks
{
    void(*cleanup)();
    GLX_D3D_VBUFFER_priv *(*allocate)(DWORD size, DWORD dwCaps, DWORD dwCaps2);
    void(*free)(GLX_D3D_VBUFFER_priv *);
    void *(*lock)(GLX_D3D_VBUFFER_priv *, DWORD);
    void(*unlock)(GLX_D3D_VBUFFER_priv *);
    void*(*renderptr)(GLX_D3D_VBUFFER_priv *);
    void(*prerender)(GLX_D3D_VBUFFER_priv *);
    void(*postrender)(GLX_D3D_VBUFFER_priv *);
} GLX_D3D_VBUFFER_callbacks;

GLX_D3D_VBUFFER_callbacks *VB_VAR_init(); /* NV_VAR */
GLX_D3D_VBUFFER_callbacks *VB_VBO_init(); /* ARB_VBO */

/* end vb implementations */

typedef struct _D3DTCONTEXT {
  struct _D3DCONTEXT* parent;
  HANDLE	thread;
  GLXContext	ctx;
  GLXContext	save_ctx;
  GLXDrawable	save_draw;
  GLXDrawable	last_draw;
  DWORD		stamp;
  struct _D3DTCONTEXT*	prev;
  struct _D3DTCONTEXT*	next;
} D3DTCONTEXT,*LPD3DTCONTEXT;

typedef struct {
  GLXDrawable draw;
  DWORD flags;
  HBITMAP bmp;
  X11DRV_DIBSECTION *dib;
  BITMAPOBJ *lockedBmp;
  DWORD locks, lockf;
  BOOL rect_lock, rect_area;
  RECTL rect;
} D3DTARGET,*LPD3DTARGET;

typedef struct _D3DCONTEXT {
  D3DTCONTEXT	p;

  XVisualInfo*	vis;
  DWORD		owner_tid;
  pid_t		owner_unix_tid;
  GLXContext	owner_ctx;
  GLXDrawable	owner_last_draw;
  BOOL		borked, cant_copy;
  int		sync_pipe[2];
  DWORD		refs;
  LPDDRAWI_DDRAWSURFACE_LCL lsurf, zsurf, nsurf;
  LPDDRAWI_DDRAWSURFACE_GBL surf;
  Font		lfont;
  BOOL		in_scene;

  D3DTARGET	cache[CACHESIZE];
  D3DTARGET	zcache[CACHESIZE];
  DWORD		curp;

#define DD_GL_PROC(x,y) x y;
  char gl_ext[DD_GL_EXTENSION_COUNT];
  DD_GL_PROC_LIST
#undef DD_GL_PROC

  GLint		texunits;

  int		glx_major, glx_minor;
  BOOL		glx13, glx13_pbuffers;

  /* GLX 1.3 pbuffer subset */
  GLXFBConfig* (*glXGetFBConfigs)(Display*,int,int*);
  GLXFBConfig* (*glXChooseFBConfig)(Display*,int,const int*,int*);
  int (*glXGetFBConfigAttrib)(Display*,GLXFBConfig,int,int*);
  XVisualInfo* (*glXGetVisualFromFBConfig)(Display*,GLXFBConfig);
  GLXPbuffer (*glXCreatePbuffer)(Display*,GLXFBConfig,const int*);
  void (*glXDestroyPbuffer)(Display*,GLXPbuffer);

  /* SGIX_fbconfig */
  int (*glXGetFBConfigAttribSGIX)(Display*,GLXFBConfig,int,int*);
  GLXFBConfig* (*glXChooseFBConfigSGIX)(Display*,int,const int*,int*);
  GLXPixmap (*glXCreateGLXPixmapWithConfigSGIX)(Display*,GLXFBConfig,Pixmap);
  GLXContext (*glXCreateContextWithConfigSGIX)(Display*,GLXFBConfig,int,GLXContext,Bool);
  XVisualInfo* (*glXGetVisualFromFBConfigSGIX)(Display*,GLXFBConfig);
  GLXFBConfig (*glXGetFBConfigFromVisualSGIX)(Display*,XVisualInfo*);

  /* SGIX_pbuffer */
  GLXPbuffer (*glXCreateGLXPbufferSGIX)(Display*,GLXFBConfig,unsigned int,unsigned int,int*);
  void (*glXDestroyGLXPbufferSGIX)(Display*,GLXPbuffer);
  void (*glXQueryGLXPbufferSGIX)(Display*,GLXPbuffer,int,unsigned int);
  void (*glXSelectEventSGIX)(Display*,GLXDrawable,unsigned long);
  void (*glXGetSelectedEventSGIX)(Display*,GLXDrawable,unsigned long*);

  GLuint hud_font, hud_logo, hud_profile_font;

#ifdef TRANSGAMING_LOGO
  GLuint logo;
  GLuint logo_list;
  DWORD logo_size;
#endif
} D3DCONTEXT,*LPD3DCONTEXT;
typedef const D3DCONTEXT* LPCD3DCONTEXT;

#define FLAG_PIXMAP	0x0001
#define FLAG_CINDIRECT	0x0002
#define FLAG_PINDIRECT	0x0004
#define FLAG_WINDIRECT  0x0008
#define FLAG_PDIRECT	0x0010
#define FLAG_WDIRECT	0x0020
#define FLAG_INDIRECT	(FLAG_PINDIRECT|FLAG_WINDIRECT)
#define FLAG_DIRECT	(FLAG_PDIRECT|FLAG_WDIRECT)
#define FLAG_BACKBUF	0x0040
#define FLAG_FLIPPED	0x0080
#define FLAG_PBUFFER	0x0100
#define FLAG_OFFSCREEN	(FLAG_PIXMAP|FLAG_PBUFFER)
#define FLAG_ZBUFFER	0x0200
#define FLAG_DESTROYED	0x8000

#define FLAG_COMMON	(FLAG_INDIRECT|FLAG_DIRECT|FLAG_ZBUFFER|FLAG_DESTROYED)

#define HAVE_GL_EXT(ctx,ext) ((ctx)->gl_ext[ext])

#define CHECK_GL_ERROR(x) do { GLenum err; err = glGetError(); if (err) ERR("glGetError returns %08x for %s\n", err, x); } while (0)

DWORD X11DRV_GLX_MakeCurrent(LPD3DCONTEXT ctx);
void X11DRV_GLX_FlushCurrent(LPD3DCONTEXT ctx);
BOOL X11DRV_GLX_KillCurrent(LPD3DCONTEXT ctx);

extern void X11DRV_GLX_EB_Init(void);
extern void X11DRV_GLX_EB_Context_Init(void);
extern void X11DRV_GLX_EB_Cleanup(void);

extern BOOL X11DRV_GLX_StartDraw(LPD3DCONTEXT ctx, LPD3DTARGET tgt, GLbitfield mask, GLbitfield client_mask);
extern void X11DRV_GLX_EndDraw(LPD3DCONTEXT ctx, GLbitfield mask, GLbitfield client_mask);

extern DDHAL_DDEXEBUFCALLBACKS X11DRV_GLX_exebufcallbacks;
extern struct GL_D3D_DriverCallbacks X11DRV_GLX_GL_D3D_driver_callbacks;

int X11DRV_GLX_VAR_CreateDriver(LPDDHALINFO info);

extern BOOL X11DRV_GLX_D3dRenderLock(ULONG_PTR dwhContext, BOOL draw, LPBOOL invert);
extern void X11DRV_GLX_D3dRenderUnlock(ULONG_PTR dwhContext, BOOL draw);
extern void X11DRV_GLX_D3dRenderArea(ULONG_PTR dwhContext, LPRECT rect, BOOL clear);

extern void X11DRV_GLX_DisplayFPS(LPD3DCONTEXT ctx, LPD3DTARGET tgt);

#endif /* HAVE_OPENGL */
#endif /* __WINE_GLX_PRIVATE_H */
