2019-09-16 17:35:04 +00:00
# pragma once
# include <stdlib.h>
# include <algorithm>
2019-09-16 20:56:48 +00:00
# include <vector>
2019-09-17 17:03:42 +00:00
# include <map>
2019-09-16 21:28:26 +00:00
# include "gl_samplers.h"
2019-09-17 17:03:42 +00:00
# include "gl_hwtexture.h"
2019-10-05 10:28:08 +00:00
# include "gl_renderstate.h"
2019-10-04 16:12:03 +00:00
# include "matrix.h"
2019-10-06 17:32:35 +00:00
# include "palentry.h"
2019-11-05 22:35:38 +00:00
# include "renderstyle.h"
2019-09-16 20:56:48 +00:00
class FSamplerManager ;
2019-10-05 10:28:08 +00:00
class FShader ;
class PolymostShader ;
2019-10-05 11:09:15 +00:00
class SurfaceShader ;
2019-10-05 19:59:03 +00:00
class FTexture ;
2019-10-06 19:15:53 +00:00
class GLInstance ;
2019-11-06 22:40:10 +00:00
class F2DDrawer ;
2019-11-10 20:11:17 +00:00
struct palette_t ;
2020-01-02 22:56:35 +00:00
extern int xdim , ydim ;
2019-10-06 19:15:53 +00:00
struct PaletteData
{
int32_t crc32 ;
PalEntry colors [ 256 ] ;
2019-10-06 22:07:45 +00:00
bool shadesdone ;
2019-10-07 20:11:09 +00:00
int whiteindex , blackindex ;
2019-10-06 19:15:53 +00:00
FHardwareTexture * paltexture ;
} ;
2019-10-06 22:07:45 +00:00
struct PalShade
{
int palindex ;
float mulshade , addshade ;
} ;
struct PalswapData
{
int32_t crc32 ;
2019-11-15 19:51:02 +00:00
bool isbright ;
2019-10-06 22:34:15 +00:00
const uint8_t * lookup ; // points to the original data. This is static so no need to copy
2019-10-07 23:08:08 +00:00
FHardwareTexture * swaptexture ;
2019-10-19 13:52:46 +00:00
PalEntry fadeColor ;
2019-11-15 19:51:02 +00:00
uint8_t brightcolors [ 255 ] ;
2019-10-06 22:07:45 +00:00
} ;
enum
{
PALSWAP_TEXTURE_SIZE = 2048
} ;
2019-10-06 19:15:53 +00:00
class PaletteManager
{
// The current engine limit is 256 palettes and 256 palswaps.
uint32_t palettemap [ 256 ] = { } ;
uint32_t palswapmap [ 256 ] = { } ;
2019-10-06 22:34:15 +00:00
float addshade [ 256 ] = { } ;
float mulshade [ 256 ] = { } ;
2019-10-06 19:15:53 +00:00
uint32_t lastindex = ~ 0u ;
2019-10-07 23:08:08 +00:00
uint32_t lastsindex = ~ 0u ;
2019-10-06 22:34:15 +00:00
int numshades = 1 ;
2019-10-06 19:15:53 +00:00
// All data is being stored in contiguous blocks that can be used as uniform buffers as-is.
TArray < PaletteData > palettes ;
2019-10-06 22:07:45 +00:00
TArray < PalswapData > palswaps ;
2019-10-17 22:20:27 +00:00
TMap < int , int > swappedpalmap ;
2019-10-06 22:07:45 +00:00
FHardwareTexture * palswapTexture = nullptr ;
2019-10-06 19:15:53 +00:00
GLInstance * const inst ;
//OpenGLRenderer::GLDataBuffer* palswapBuffer = nullptr;
2019-11-10 20:11:17 +00:00
unsigned FindPalswap ( const uint8_t * paldata , palette_t & fadecolor ) ;
2019-10-06 19:15:53 +00:00
public :
PaletteManager ( GLInstance * inst_ ) : inst ( inst_ )
{ }
~ PaletteManager ( ) ;
void DeleteAll ( ) ;
2019-11-06 22:40:10 +00:00
void DeleteAllTextures ( ) ;
2019-10-19 20:46:37 +00:00
void SetPalette ( int index , const uint8_t * data ) ;
2019-11-10 20:11:17 +00:00
void SetPalswapData ( int index , const uint8_t * data , int numshades , palette_t & fadecolor ) ;
2019-10-06 19:15:53 +00:00
void BindPalette ( int index ) ;
2019-10-07 23:08:08 +00:00
void BindPalswap ( int index ) ;
2019-10-17 18:29:58 +00:00
int ActivePalswap ( ) const { return lastsindex ; }
2019-12-25 13:13:15 +00:00
int LookupPalette ( int palette , int palswap , bool brightmap , bool nontransparent255 = false ) ;
2019-10-18 09:37:07 +00:00
const PalEntry * GetPaletteData ( int palid ) const { return palettes [ palid ] . colors ; }
2019-11-05 22:35:38 +00:00
unsigned FindPalette ( const uint8_t * paldata ) ;
2019-10-06 19:15:53 +00:00
} ;
2019-09-16 17:35:04 +00:00
2019-10-04 19:13:04 +00:00
struct glinfo_t {
float maxanisotropy ;
} ;
2019-09-16 17:35:04 +00:00
struct BaseVertex
{
float x , y , z ;
float u , v ;
void SetVertex ( float _x , float _y , float _z = 0 )
{
x = _x ;
y = _y ;
z = _z ;
}
void SetTexCoord ( float _u = 0 , float _v = 0 )
{
u = _u ;
v = _v ;
}
2019-09-16 19:08:42 +00:00
void Set ( float _x , float _y , float _z = 0 , float _u = 0 , float _v = 0 )
{
x = _x ;
y = _y ;
z = _z ;
u = _u ;
v = _v ;
}
2019-09-16 17:35:04 +00:00
} ;
enum EDrawType
{
DT_TRIANGLES ,
DT_TRIANGLE_STRIP ,
DT_TRIANGLE_FAN ,
DT_LINES
} ;
2019-10-04 16:12:03 +00:00
enum EMatrixType
{
2019-10-05 10:28:08 +00:00
Matrix_View ,
2019-10-04 16:12:03 +00:00
Matrix_Projection ,
Matrix_ModelView ,
2019-10-06 08:19:51 +00:00
Matrix_Detail ,
2019-10-10 17:40:33 +00:00
Matrix_Texture ,
2019-10-05 10:28:08 +00:00
// These are the only ones being used.
2019-10-04 16:12:03 +00:00
NUMMATRICES
} ;
enum ECull
{
Cull_None ,
Cull_Front ,
Cull_Back
} ;
2019-10-04 16:44:16 +00:00
enum EDepthFunc
{
Depth_Always ,
Depth_Less ,
Depth_Equal ,
Depth_LessEqual
} ;
2019-10-04 19:13:04 +00:00
enum EWinding
{
Winding_CCW ,
Winding_CW
} ;
2019-10-17 22:20:27 +00:00
enum ETexType
{
TT_INDEXED ,
TT_TRUECOLOR ,
2019-10-18 09:37:07 +00:00
TT_HICREPLACE ,
TT_BRIGHTMAP
2019-10-17 22:20:27 +00:00
} ;
2019-11-07 19:31:16 +00:00
struct ImDrawData ;
2019-11-10 20:11:17 +00:00
struct palette_t ;
2019-12-31 21:53:03 +00:00
extern float shadediv [ 256 ] ;
2019-11-07 19:31:16 +00:00
2020-01-03 09:09:38 +00:00
struct GLState
{
int Flags = STF_COLORMASK | STF_DEPTHMASK ;
FRenderStyle Style { } ;
2020-01-03 10:43:44 +00:00
int DepthFunc = - 1 ;
2020-01-03 09:09:38 +00:00
} ;
2019-09-16 17:35:04 +00:00
class GLInstance
{
2019-09-17 17:03:42 +00:00
enum
{
MAX_TEXTURES = 15 , // slot 15 is used internally and not available.
THCACHESIZE = 200 ,
} ;
2019-09-16 20:56:48 +00:00
std : : vector < BaseVertex > Buffer ; // cheap-ass implementation. The primary purpose is to get the GL accesses out of polymost.cpp, not writing something performant right away.
2019-09-17 17:03:42 +00:00
unsigned int LastBoundTextures [ MAX_TEXTURES ] ;
unsigned TextureHandleCache [ THCACHESIZE ] ;
int currentindex = THCACHESIZE ;
2019-10-04 16:12:03 +00:00
int maxTextureSize ;
2019-10-06 19:15:53 +00:00
PaletteManager palmanager ;
2019-10-06 22:07:45 +00:00
int lastPalswapIndex = - 1 ;
2019-10-10 19:24:09 +00:00
FHardwareTexture * texv ;
2019-10-17 18:29:58 +00:00
FTexture * currentTexture = nullptr ;
2019-10-17 22:20:27 +00:00
int TextureType ;
int MatrixChange = 0 ;
2019-12-25 13:13:15 +00:00
bool g_nontransparent255 = false ; // Ugh... This is for movie playback and needs to be maintained as global state.
2020-01-03 09:09:38 +00:00
// Cached GL state.
GLState lastState ;
2019-10-06 22:07:45 +00:00
2019-11-05 22:35:38 +00:00
IVertexBuffer * LastVertexBuffer = nullptr ;
int LastVB_Offset [ 2 ] = { } ;
IIndexBuffer * LastIndexBuffer = nullptr ;
2019-10-06 22:07:45 +00:00
2019-10-04 16:12:03 +00:00
VSMatrix matrices [ NUMMATRICES ] ;
2019-10-05 10:28:08 +00:00
PolymostRenderState renderState ;
FShader * activeShader ;
PolymostShader * polymostShader ;
2019-10-05 11:09:15 +00:00
SurfaceShader * surfaceShader ;
2019-10-05 11:38:02 +00:00
FShader * vpxShader ;
2019-09-17 17:03:42 +00:00
2019-09-16 17:35:04 +00:00
public :
2019-10-04 19:13:04 +00:00
glinfo_t glinfo ;
2019-09-16 20:56:48 +00:00
FSamplerManager * mSamplers ;
2019-11-07 19:31:16 +00:00
void Init ( int y ) ;
2019-10-04 16:12:03 +00:00
void InitGLState ( int fogmode , int multisample ) ;
2019-10-05 10:28:08 +00:00
void LoadPolymostShader ( ) ;
2019-10-05 11:09:15 +00:00
void LoadSurfaceShader ( ) ;
void LoadVPXShader ( ) ;
2019-11-06 22:40:10 +00:00
void Draw2D ( F2DDrawer * drawer ) ;
2019-11-07 19:31:16 +00:00
void DrawImGui ( ImDrawData * ) ;
2019-10-04 16:12:03 +00:00
2019-09-16 20:56:48 +00:00
void Deinit ( ) ;
2019-09-17 17:03:42 +00:00
static int GetTexDimension ( int value )
{
//if (value > gl.max_texturesize) return gl.max_texturesize;
return value ;
}
2019-09-16 17:35:04 +00:00
2019-10-06 19:15:53 +00:00
GLInstance ( ) ;
2019-09-16 17:35:04 +00:00
std : : pair < size_t , BaseVertex * > AllocVertices ( size_t num ) ;
void Draw ( EDrawType type , size_t start , size_t count ) ;
2019-09-18 18:44:21 +00:00
FHardwareTexture * NewTexture ( ) ;
void BindTexture ( int texunit , FHardwareTexture * texid , int sampler = NoSampler ) ;
2019-09-17 17:03:42 +00:00
void UnbindTexture ( int texunit ) ;
void UnbindAllTextures ( ) ;
2019-12-25 13:13:15 +00:00
void EnableNonTransparent255 ( bool on )
{
g_nontransparent255 = on ;
}
2019-11-05 22:35:38 +00:00
void SetVertexBuffer ( IVertexBuffer * vb , int offset1 , int offset2 )
{
renderState . VertexBuffer = vb ;
renderState . VB_Offset [ 0 ] = offset1 ;
renderState . VB_Offset [ 1 ] = offset2 ;
}
void SetIndexBuffer ( IIndexBuffer * vb )
{
renderState . IndexBuffer = vb ;
}
2019-12-26 16:42:45 +00:00
void ClearBufferState ( )
{
SetVertexBuffer ( nullptr , 0 , 0 ) ;
SetIndexBuffer ( nullptr ) ;
// Invalidate the pointers as well to make sure that if another buffer with the same address is used it actually gets bound.
LastVertexBuffer = ( IVertexBuffer * ) ~ intptr_t ( 0 ) ;
LastIndexBuffer = ( IIndexBuffer * ) ~ intptr_t ( 0 ) ;
}
2019-10-04 16:12:03 +00:00
const VSMatrix & GetMatrix ( int num )
{
return matrices [ num ] ;
}
void SetMatrix ( int num , const VSMatrix * mat ) ;
void SetMatrix ( int num , const float * mat )
{
SetMatrix ( num , reinterpret_cast < const VSMatrix * > ( mat ) ) ;
}
2019-10-04 16:44:16 +00:00
2019-10-05 10:28:08 +00:00
void SetPolymostShader ( ) ;
2019-10-05 11:09:15 +00:00
void SetSurfaceShader ( ) ;
2019-10-05 11:38:02 +00:00
void SetVPXShader ( ) ;
2019-10-06 19:15:53 +00:00
void SetPalette ( int palette ) ;
2019-10-17 22:20:27 +00:00
bool ApplyTextureProps ( FTexture * tex , int pal ) ;
2019-10-17 18:29:58 +00:00
void RestoreTextureProps ( ) ;
2019-10-04 19:13:04 +00:00
void ReadPixels ( int w , int h , uint8_t * buffer ) ;
2019-10-05 10:28:08 +00:00
2019-10-19 20:46:37 +00:00
void SetPaletteData ( int index , const uint8_t * data )
2019-10-06 19:15:53 +00:00
{
2019-10-19 20:46:37 +00:00
palmanager . SetPalette ( index , data ) ;
2019-10-06 19:15:53 +00:00
}
2019-11-10 20:11:17 +00:00
void SetPalswapData ( int index , const uint8_t * data , int numshades , palette_t & fadecolor )
2019-10-06 22:07:45 +00:00
{
2019-11-10 20:11:17 +00:00
palmanager . SetPalswapData ( index , data , numshades , fadecolor ) ;
2019-10-06 22:07:45 +00:00
}
void SetPalswap ( int index ) ;
2019-10-05 10:28:08 +00:00
int GetClamp ( )
{
2019-10-19 20:46:37 +00:00
return 0 ; // int(renderState.Clamp[0] + 2 * renderState.Clamp[1]);
2019-10-05 10:28:08 +00:00
}
void SetClamp ( int clamp )
{
2019-10-19 20:46:37 +00:00
// This option is totally pointless and should be removed.
//renderState.Clamp[0] = clamp & 1;
//renderState.Clamp[1] = !!(clamp & 2);
2019-10-05 10:28:08 +00:00
}
void SetShade ( int32_t shade , int numshades )
{
renderState . Shade = shade ;
renderState . NumShades = numshades ;
2019-10-19 23:14:48 +00:00
}
2019-10-05 10:28:08 +00:00
void SetVisibility ( float visibility , float fviewingrange )
{
2019-10-19 23:14:48 +00:00
renderState . VisFactor = visibility * fviewingrange * ( 1.f / ( 64.f * 65536.f ) ) ;
2019-10-05 10:28:08 +00:00
}
2020-01-02 22:22:59 +00:00
void EnableBlend ( bool on )
{
if ( on ) renderState . StateFlags | = STF_BLEND ;
else renderState . StateFlags & = ~ STF_BLEND ;
}
void EnableDepthTest ( bool on )
{
if ( on ) renderState . StateFlags | = STF_DEPTHTEST ;
else renderState . StateFlags & = ~ STF_DEPTHTEST ;
}
void EnableMultisampling ( bool on )
{
if ( on ) renderState . StateFlags | = STF_MULTISAMPLE ;
else renderState . StateFlags & = ~ STF_MULTISAMPLE ;
}
void EnableStencilWrite ( int value )
{
renderState . StateFlags | = STF_STENCILWRITE ;
renderState . StateFlags & = ~ STF_STENCILTEST ;
}
void EnableStencilTest ( int value )
{
renderState . StateFlags & = ~ STF_STENCILWRITE ;
renderState . StateFlags | = STF_STENCILTEST ;
}
void DisableStencil ( )
{
renderState . StateFlags & = ~ ( STF_STENCILWRITE | STF_STENCILTEST ) ;
}
void SetCull ( int type , int winding = Winding_CW )
{
renderState . StateFlags & = ~ ( STF_CULLCCW | STF_CULLCW ) ;
if ( type ! = Cull_None )
{
if ( winding = = Winding_CW ) renderState . StateFlags | = STF_CULLCW ;
else renderState . StateFlags | = STF_CULLCCW ;
}
}
void SetColorMask ( bool on )
{
if ( on ) renderState . StateFlags | = STF_COLORMASK ;
else renderState . StateFlags & = ~ STF_COLORMASK ;
}
void SetDepthMask ( bool on )
{
if ( on ) renderState . StateFlags | = STF_DEPTHMASK ;
else renderState . StateFlags & = ~ STF_DEPTHMASK ;
}
void SetWireframe ( bool on )
{
if ( on ) renderState . StateFlags | = STF_WIREFRAME ;
else renderState . StateFlags & = ~ STF_WIREFRAME ;
}
2020-01-02 22:56:35 +00:00
void ClearScreen ( PalEntry pe , bool depth )
{
renderState . ClearColor = pe ;
renderState . StateFlags | = STF_CLEARCOLOR ;
if ( depth ) renderState . StateFlags | = STF_CLEARDEPTH ;
}
2020-01-03 09:48:01 +00:00
void SetViewport ( int x , int y , int w , int h )
{
renderState . vp_x = ( short ) x ;
renderState . vp_y = ( short ) y ;
renderState . vp_w = ( short ) w ;
renderState . vp_h = ( short ) h ;
renderState . StateFlags | = STF_VIEWPORTSET ;
}
void SetScissor ( int x1 , int y1 , int x2 , int y2 )
{
renderState . sc_x = ( short ) x1 ;
renderState . sc_y = ( short ) y1 ;
renderState . sc_w = ( short ) x2 ;
renderState . sc_h = ( short ) y2 ;
renderState . StateFlags | = STF_SCISSORSET ;
}
void DisableScissor ( )
{
renderState . sc_x = - 1 ;
renderState . StateFlags | = STF_SCISSORSET ;
}
2020-01-03 10:43:44 +00:00
void SetDepthFunc ( int func )
{
renderState . DepthFunc = func ;
}
2020-01-03 09:48:01 +00:00
2020-01-02 22:56:35 +00:00
void ClearScreen ( PalEntry pe )
{
//twod->Clear();
SetViewport ( 0 , 0 , xdim , ydim ) ;
ClearScreen ( pe , false ) ;
}
void ClearDepth ( )
{
renderState . StateFlags | = STF_CLEARDEPTH ;
}
2020-01-02 22:22:59 +00:00
2020-01-03 09:09:38 +00:00
void SetRenderStyle ( FRenderStyle style )
{
renderState . Style = style ;
}
2020-01-03 10:43:44 +00:00
void SetColor ( float r , float g , float b , float a = 1.f )
{
renderState . Color [ 0 ] = r ;
renderState . Color [ 1 ] = g ;
renderState . Color [ 2 ] = b ;
renderState . Color [ 3 ] = a ;
}
void SetColorub ( uint8_t r , uint8_t g , uint8_t b , uint8_t a = 255 )
{
SetColor ( r * ( 1 / 255.f ) , g * ( 1 / 255.f ) , b * ( 1 / 255.f ) , a * ( 1 / 255.f ) ) ;
}
2019-10-19 20:46:37 +00:00
void UseColorOnly ( bool yes )
{
if ( yes ) renderState . Flags | = RF_ColorOnly ;
else renderState . Flags & = ~ RF_ColorOnly ;
}
void UseDetailMapping ( bool yes )
{
if ( yes ) renderState . Flags | = RF_DetailMapping ;
else renderState . Flags & = ~ RF_DetailMapping ;
}
void UseGlowMapping ( bool yes )
2019-10-05 10:28:08 +00:00
{
2019-10-19 20:46:37 +00:00
if ( yes ) renderState . Flags | = RF_GlowMapping ;
else renderState . Flags & = ~ RF_GlowMapping ;
2019-10-05 10:28:08 +00:00
}
2019-10-19 20:46:37 +00:00
void UseBrightmaps ( bool yes )
2019-10-05 10:28:08 +00:00
{
2019-10-19 20:46:37 +00:00
if ( yes ) renderState . Flags | = RF_Brightmapping ;
else renderState . Flags & = ~ RF_Brightmapping ;
2019-10-05 10:28:08 +00:00
}
2019-10-19 20:46:37 +00:00
void SetNpotEmulation ( bool yes , float factor , float xOffset )
2019-10-05 10:28:08 +00:00
{
2019-10-19 20:46:37 +00:00
if ( yes )
{
renderState . Flags | = RF_NPOTEmulation ;
renderState . NPOTEmulationFactor = factor ;
renderState . NPOTEmulationXOffset = xOffset ;
}
else renderState . Flags & = ~ RF_NPOTEmulation ;
2019-10-05 10:28:08 +00:00
}
2019-10-19 20:46:37 +00:00
void SetShadeInterpolate ( int32_t yes )
2019-10-05 10:28:08 +00:00
{
2019-10-19 20:46:37 +00:00
if ( yes ) renderState . Flags | = RF_ShadeInterpolate ;
else renderState . Flags & = ~ RF_ShadeInterpolate ;
2019-10-05 10:28:08 +00:00
}
2019-10-19 20:46:37 +00:00
void SetFadeColor ( PalEntry color )
{
renderState . FogColor = color ;
} ;
void SetFadeDisable ( bool yes )
2019-10-05 10:28:08 +00:00
{
2019-10-19 22:45:47 +00:00
if ( yes ) renderState . Flags | = RF_FogDisabled ;
2019-10-19 20:46:37 +00:00
else renderState . Flags & = ~ RF_FogDisabled ;
2019-10-05 10:28:08 +00:00
}
void SetBrightness ( int brightness )
{
renderState . Brightness = 8.f / ( brightness + 8.f ) ;
}
2019-10-06 10:42:35 +00:00
2019-10-17 18:29:58 +00:00
void SetTinting ( int flags , PalEntry color , PalEntry modulateColor )
2019-10-09 22:07:45 +00:00
{
// not yet implemented.
}
2019-10-17 18:29:58 +00:00
void SetBasepalTint ( PalEntry color )
{
// not yet implemented - only relevant for hires replacements.
}
2019-11-05 22:35:38 +00:00
int GetPaletteIndex ( PalEntry * palette )
{
return palmanager . FindPalette ( ( uint8_t * ) palette ) ;
}
2019-11-10 09:01:31 +00:00
void EnableAlphaTest ( bool on )
{
renderState . AlphaTest = on ;
}
void SetAlphaThreshold ( float al )
{
renderState . AlphaThreshold = al ;
}
2020-01-03 09:09:38 +00:00
2019-10-17 22:20:27 +00:00
FHardwareTexture * CreateIndexedTexture ( FTexture * tex ) ;
2019-10-19 21:14:36 +00:00
FHardwareTexture * CreateTrueColorTexture ( FTexture * tex , int palid , bool checkfulltransparency = false , bool rgb8bit = false ) ;
2019-10-17 22:20:27 +00:00
FHardwareTexture * LoadTexture ( FTexture * tex , int texturetype , int palid ) ;
2019-10-19 08:21:07 +00:00
bool SetTextureInternal ( int globalpicnum , FTexture * tex , int palette , int method , int sampleroverride , float xpanning , float ypanning , FTexture * det , float detscale , FTexture * glow ) ;
2019-10-18 12:04:32 +00:00
2019-11-05 22:35:38 +00:00
bool SetNamedTexture ( FTexture * tex , int palette , int sampleroverride ) ;
2019-10-18 12:04:32 +00:00
2019-10-19 08:21:07 +00:00
bool SetTexture ( int globalpicnum , FTexture * tex , int palette , int method , int sampleroverride )
2019-10-18 12:04:32 +00:00
{
2019-10-19 08:21:07 +00:00
return SetTextureInternal ( globalpicnum , tex , palette , method , sampleroverride , 0 , 0 , nullptr , 1 , nullptr ) ;
2019-10-18 12:04:32 +00:00
}
bool SetModelTexture ( FTexture * tex , int palette , float xpanning , float ypanning , FTexture * det , float detscale , FTexture * glow )
{
2019-10-19 08:21:07 +00:00
return SetTextureInternal ( - 1 , tex , palette , 8 /*DAMETH_MODEL*/ , - 1 , xpanning , ypanning , det , detscale , glow ) ;
2019-10-18 12:04:32 +00:00
}
2019-09-16 17:35:04 +00:00
} ;
2019-10-04 16:12:03 +00:00
extern GLInstance GLInterface ;