/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "EglOsApi.h"
#include <windows.h>
#include <wingdi.h>
#include <GL/wglext.h>
#include <stdio.h>

#define IS_TRUE(a) \
        if(a != true) return false;


struct DisplayInfo{
    DisplayInfo():dc(NULL),hwnd(NULL),isPixelFormatSet(false){};
    DisplayInfo(HDC hdc,HWND wnd):isPixelFormatSet(false){dc = hdc; hwnd = wnd;};
    HDC  dc;
    HWND hwnd;
    bool isPixelFormatSet;
};

struct TlsData {
    std::map<int,DisplayInfo> m_map;
};

static DWORD s_tlsIndex = 0;

static TlsData *getTLS() {
    TlsData *tls = (TlsData *)TlsGetValue(s_tlsIndex);
    if (!tls) {
        tls = new TlsData();
        TlsSetValue(s_tlsIndex, tls);
    }
    return tls;
}

class WinDisplay{
public:
     typedef enum {
                      DEFAULT_DISPLAY = 0
                  };
     WinDisplay(){};
     DisplayInfo& getInfo(int configurationIndex){ return getTLS()->m_map[configurationIndex];}
     HDC  getDC(int configId){return getTLS()->m_map[configId].dc;}
     void setInfo(int configurationIndex,const DisplayInfo& info);
     bool isPixelFormatSet(int cfgId){ return getTLS()->m_map[cfgId].isPixelFormatSet;}
     void pixelFormatWasSet(int cfgId){getTLS()->m_map[cfgId].isPixelFormatSet = true;}
     bool infoExists(int configurationIndex);
     void releaseAll();
};

void WinDisplay::releaseAll(){
    TlsData * tls = getTLS();
    
    for(std::map<int,DisplayInfo>::iterator it = tls->m_map.begin(); it != tls->m_map.end();it++){
       if((*it).second.hwnd){
           DestroyWindow((*it).second.hwnd);
       }
       DeleteDC((*it).second.dc);
    }
}

bool WinDisplay::infoExists(int configurationIndex){
    return getTLS()->m_map.find(configurationIndex) != getTLS()->m_map.end();
}

void WinDisplay::setInfo(int configurationIndex,const DisplayInfo& info){
    getTLS()->m_map[configurationIndex] = info;
}

struct WglExtProcs{
    PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB;
    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
    PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB;
    PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB;
    PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB;
    PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB;
    PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB;
    PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
};

static WglExtProcs* s_wglExtProcs = NULL;

class SrfcInfo{
public:
    typedef enum {
                 WINDOW  = 0,
                 PBUFFER = 1,
                 PIXMAP  = 2
                 }SurfaceType;
    explicit SrfcInfo(HWND wnd);
    explicit SrfcInfo(HPBUFFERARB pb);
    explicit SrfcInfo(HBITMAP bmap);
    HWND getHwnd(){ return m_hwnd;};
    HDC  getDC(){ return m_hdc;};
    HBITMAP  getBmap(){ return m_bmap;};
    HPBUFFERARB  getPbuffer(){ return m_pb;};
    ~SrfcInfo();
private:
    HWND        m_hwnd;
    HPBUFFERARB m_pb; 
    HBITMAP     m_bmap;
    HDC         m_hdc;
    SurfaceType m_type;
};

SrfcInfo::SrfcInfo(HBITMAP bmap):m_hwnd(NULL),
                                 m_pb(NULL),
                                 m_hdc(NULL),
                                 m_type(PIXMAP){
    m_bmap = bmap;
}

SrfcInfo::SrfcInfo(HWND wnd):m_pb(NULL),
                             m_bmap(NULL),
                             m_type(WINDOW){
    m_hwnd = wnd;
    m_hdc = GetDC(wnd); 
}

SrfcInfo::SrfcInfo(HPBUFFERARB pb):m_hwnd(NULL),
                                   m_bmap(NULL),
                                   m_type(PBUFFER){
    m_pb = pb;
    if(s_wglExtProcs->wglGetPbufferDCARB){
        m_hdc =  s_wglExtProcs->wglGetPbufferDCARB(pb);
    }
}

SrfcInfo::~SrfcInfo(){
    if(m_type == WINDOW){
        ReleaseDC(m_hwnd,m_hdc);
    }
}

namespace EglOS{



PROC wglGetExtentionsProcAddress(HDC hdc,const char *extension_name,const char* proc_name)
{
    // this is pointer to function which returns pointer to string with list of all wgl extensions
    PFNWGLGETEXTENSIONSSTRINGARBPROC _wglGetExtensionsStringARB = NULL;

    // determine pointer to wglGetExtensionsStringEXT function
    _wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
    if(!_wglGetExtensionsStringARB){
        fprintf(stderr,"could not get wglGetExtensionsStringARB\n");
        return NULL;
    }

    if (!_wglGetExtensionsStringARB || strstr(_wglGetExtensionsStringARB(hdc), extension_name) == NULL)
    {
        fprintf(stderr,"extension %s was not found\n",extension_name);
        // string was not found
        return NULL;
    }

    // extension is supported
    return wglGetProcAddress(proc_name);
}

LRESULT CALLBACK dummyWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

HWND createDummyWindow(){

    WNDCLASSEX wcx;
    wcx.cbSize = sizeof(wcx);                       // size of structure
    wcx.style =  CS_OWNDC |CS_HREDRAW |CS_VREDRAW;  // redraw if size changes
    wcx.lpfnWndProc = dummyWndProc;                 // points to window procedure
    wcx.cbClsExtra = 0;                             // no extra class memory
    wcx.cbWndExtra = sizeof(void*);                 // save extra window memory, to store VasWindow instance
    wcx.hInstance = NULL;                           // handle to instance
    wcx.hIcon = NULL;                               // predefined app. icon
    wcx.hCursor = NULL;
    wcx.hbrBackground = NULL;                       // no background brush
    wcx.lpszMenuName =  NULL;                       // name of menu resource
    wcx.lpszClassName = "DummyWin";                 // name of window class
    wcx.hIconSm = (HICON) NULL;                     // small class icon

    ATOM winClass = RegisterClassEx(&wcx);
    HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
                               "DummyWin",
                               "Dummy",
                               WS_POPUP,
                               0,
                               0,
                               1,
                               1,
                               NULL,
                               NULL,
                               0,0);
    return hwnd;
}

EGLNativeInternalDisplayType getDefaultDisplay() {
    if (!s_tlsIndex) s_tlsIndex = TlsAlloc();
    WinDisplay* dpy = new WinDisplay();

    HWND hwnd = createDummyWindow();
    HDC  hdc  =  GetDC(hwnd);
    dpy->setInfo(WinDisplay::DEFAULT_DISPLAY,DisplayInfo(hdc,hwnd));
    return static_cast<EGLNativeInternalDisplayType>(dpy);
}

EGLNativeInternalDisplayType getInternalDisplay(EGLNativeDisplayType display){
    if (!s_tlsIndex) s_tlsIndex = TlsAlloc();
    WinDisplay* dpy = new WinDisplay();
    dpy->setInfo(WinDisplay::DEFAULT_DISPLAY,DisplayInfo(display,NULL));
    return dpy;
}

static HDC getDummyDC(EGLNativeInternalDisplayType display,int cfgId){

    HDC dpy = NULL;
    if(!display->infoExists(cfgId)){
        HWND hwnd = createDummyWindow();
        dpy  = GetDC(hwnd);
        display->setInfo(cfgId,DisplayInfo(dpy,hwnd));
    } else {
        dpy = display->getDC(cfgId);
    }
    return dpy;
}
void initPtrToWglFunctions(){
    HWND hwnd = createDummyWindow();
    HDC dpy =  GetDC(hwnd);
    if(!hwnd || !dpy){
        fprintf(stderr,"error while getting DC\n");
        return;
    }
    EGLNativeContextType ctx = NULL;
    PIXELFORMATDESCRIPTOR pfd = {
                                  sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
                                  1,                     // version number
                                  PFD_DRAW_TO_WINDOW |   // support window
                                  PFD_SUPPORT_OPENGL |   // support OpenGL
                                  PFD_DOUBLEBUFFER,      // double buffered
                                  PFD_TYPE_RGBA,         // RGBA type
                                  24,                    // 24-bit color depth
                                  0, 0, 0, 0, 0, 0,      // color bits ignored
                                  0,                     // no alpha buffer
                                  0,                     // shift bit ignored
                                  0,                     // no accumulation buffer
                                  0, 0, 0, 0,            // accum bits ignored
                                  32,                    // 32-bit z-buffer
                                  0,                     // no stencil buffer
                                  0,                     // no auxiliary buffer
                                  PFD_MAIN_PLANE,        // main layer
                                  0,                     // reserved
                                  0, 0, 0                // layer masks ignored
                                 };

    int  iPixelFormat,err;
    iPixelFormat = ChoosePixelFormat(dpy, &pfd);
    if(iPixelFormat < 0){
        fprintf(stderr,"error while choosing pixel format\n");
        return;
    }
    if(!SetPixelFormat(dpy,iPixelFormat,&pfd)){

        int err = GetLastError();
        fprintf(stderr,"error while setting pixel format 0x%x\n",err);
        return;
    }


    ctx = wglCreateContext(dpy);
    if(!ctx){
        err =  GetLastError();
        fprintf(stderr,"error while creating dummy context %d\n",err);
    }
    if(!wglMakeCurrent(dpy,ctx)){
        err =  GetLastError();
        fprintf(stderr,"error while making dummy context current %d\n",err);
    }

    if(!s_wglExtProcs){
        s_wglExtProcs = new WglExtProcs();
        s_wglExtProcs->wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pixel_format","wglGetPixelFormatAttribivARB");
        s_wglExtProcs->wglChoosePixelFormatARB      = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pixel_format","wglChoosePixelFormatARB");
        s_wglExtProcs->wglCreatePbufferARB          = (PFNWGLCREATEPBUFFERARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglCreatePbufferARB");
        s_wglExtProcs->wglReleasePbufferDCARB       = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglReleasePbufferDCARB");
        s_wglExtProcs->wglDestroyPbufferARB         = (PFNWGLDESTROYPBUFFERARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglDestroyPbufferARB");
        s_wglExtProcs->wglGetPbufferDCARB           = (PFNWGLGETPBUFFERDCARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglGetPbufferDCARB");
        s_wglExtProcs->wglMakeContextCurrentARB     = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_make_current_read","wglMakeContextCurrentARB");
        s_wglExtProcs->wglSwapIntervalEXT           = (PFNWGLSWAPINTERVALEXTPROC)wglGetExtentionsProcAddress(dpy,"WGL_EXT_swap_control","wglSwapIntervalEXT");
    }

   wglMakeCurrent(dpy,NULL);
   DestroyWindow(hwnd);
   DeleteDC(dpy);
}

bool releaseDisplay(EGLNativeInternalDisplayType dpy) {
    dpy->releaseAll();
    return true;
}

void deleteDisplay(EGLNativeInternalDisplayType idpy){
    if(idpy){
        delete idpy;
    }
}


static bool initPixelFormat(HDC dc){
    PIXELFORMATDESCRIPTOR  pfd;
    unsigned int numpf;
    int iPixelFormat;

    if(s_wglExtProcs->wglChoosePixelFormatARB) {
        int i0 = 0;
        float f0 = 0.0f;
        return s_wglExtProcs->wglChoosePixelFormatARB(dc,&i0, &f0, 1, &iPixelFormat, &numpf);
    } else {
        return ChoosePixelFormat(dc,&pfd);
    }
}

EglConfig* pixelFormatToConfig(EGLNativeInternalDisplayType display,int renderableType,EGLNativePixelFormatType* frmt,int index){

    EGLint  red,green,blue,alpha,depth,stencil;
    EGLint  supportedSurfaces,visualType,visualId;
    EGLint  transparentType,samples;
    EGLint  tRed,tGreen,tBlue;
    EGLint  pMaxWidth,pMaxHeight,pMaxPixels;
    EGLint  configId,level;
    EGLint  window,bitmap,pbuffer,transparent;
    HDC dpy = getDummyDC(display,WinDisplay::DEFAULT_DISPLAY);

    if(frmt->iPixelType != PFD_TYPE_RGBA) return NULL; // other formats are not supported yet
    if(!((frmt->dwFlags & PFD_SUPPORT_OPENGL) && (frmt->dwFlags & PFD_DOUBLEBUFFER))) return NULL; //pixel format does not supports opengl or double buffer
    if( 0 != (frmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_NEED_PALETTE )) ) return NULL; //discard generic pixel formats as well as pallete pixel formats

    int attribs [] = {
                          WGL_DRAW_TO_WINDOW_ARB,
                          WGL_DRAW_TO_BITMAP_ARB,
                          WGL_DRAW_TO_PBUFFER_ARB,
                          WGL_TRANSPARENT_ARB,
                          WGL_TRANSPARENT_RED_VALUE_ARB,
                          WGL_TRANSPARENT_GREEN_VALUE_ARB,
                          WGL_TRANSPARENT_BLUE_VALUE_ARB
                     };

    supportedSurfaces = 0;
    if(!s_wglExtProcs->wglGetPixelFormatAttribivARB) return NULL;

    IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[0],&window));
    IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[1],&bitmap));
    IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[2],&pbuffer));
    if(window)  supportedSurfaces |= EGL_WINDOW_BIT;
    if(bitmap)  supportedSurfaces |= EGL_PIXMAP_BIT;
    if(pbuffer) supportedSurfaces |= EGL_PBUFFER_BIT;


    if(!supportedSurfaces) return NULL;

    //default values
    visualId                  = 0;
    visualType                = EGL_NONE;
    EGLenum caveat            = EGL_NONE;
    EGLBoolean renderable     = EGL_FALSE;
    pMaxWidth                 = PBUFFER_MAX_WIDTH;
    pMaxHeight                = PBUFFER_MAX_HEIGHT;
    pMaxPixels                = PBUFFER_MAX_PIXELS;
    samples                   = 0 ;
    level                     = 0 ;

    IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[3],&transparent));
    if(transparent) {
        transparentType = EGL_TRANSPARENT_RGB;
        IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[4],&tRed));
        IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[5],&tGreen));
        IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[6],&tBlue));
    } else {
        transparentType = EGL_NONE;
    }

    red     = frmt->cRedBits;
    green   = frmt->cGreenBits;
    blue    = frmt->cBlueBits;
    alpha   = frmt->cAlphaBits;
    depth   = frmt->cDepthBits;
    stencil = frmt->cStencilBits;
    return new EglConfig(red,green,blue,alpha,caveat,(EGLint)index,depth,level,pMaxWidth,pMaxHeight,pMaxPixels,renderable,renderableType,
                         visualId,visualType,samples,stencil,supportedSurfaces,transparentType,tRed,tGreen,tBlue,*frmt);
}


void queryConfigs(EGLNativeInternalDisplayType display,int renderableType,ConfigsList& listOut) {
    PIXELFORMATDESCRIPTOR  pfd;
    int  iPixelFormat = 1;
    HDC dpy = getDummyDC(display,WinDisplay::DEFAULT_DISPLAY);

    //
    // We need to call wglChoosePixelFormat at least once,
    // seems that the driver needs to initialize itself.
    // do it here during initialization.
    //
    initPixelFormat(dpy);

    //quering num of formats
    int nFormats = DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd);

    //inserting rest of formats
    for(iPixelFormat;iPixelFormat < nFormats; iPixelFormat++) {
         DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd);
         EglConfig* pConfig = pixelFormatToConfig(display,renderableType,&pfd,iPixelFormat);
         if(pConfig) listOut.push_back(pConfig);
    }
}

bool validNativeDisplay(EGLNativeInternalDisplayType dpy) {
    return dpy != NULL;
}

bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeWindowType win) {
    return IsWindow(win);
}

bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win) {
    if (!win) return false;
    return validNativeWin(dpy,win->getHwnd());
}

bool validNativePixmap(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType pix) {
    BITMAP bm;
    if (!pix) return false;
    return GetObject(pix->getBmap(), sizeof(BITMAP), (LPSTR)&bm);
}

bool checkWindowPixelFormatMatch(EGLNativeInternalDisplayType dpy,EGLNativeWindowType win,EglConfig* cfg,unsigned int* width,unsigned int* height) {
   RECT r;
   if(!GetClientRect(win,&r)) return false;
   *width  = r.right  - r.left;
   *height = r.bottom - r.top;
   HDC dc = GetDC(win);
   EGLNativePixelFormatType nativeConfig = cfg->nativeConfig();
   bool ret = SetPixelFormat(dc,cfg->nativeId(),&nativeConfig);
   DeleteDC(dc);
   return ret;
}

bool checkPixmapPixelFormatMatch(EGLNativeInternalDisplayType dpy,EGLNativePixmapType pix,EglConfig* cfg,unsigned int* width,unsigned int* height){

    BITMAP bm;
    if(!GetObject(pix, sizeof(BITMAP), (LPSTR)&bm)) return false;

    *width  = bm.bmWidth;
    *height = bm.bmHeight;

    return true;
}

EGLNativeSurfaceType createPbufferSurface(EGLNativeInternalDisplayType display,EglConfig* cfg,EglPbufferSurface* pbSurface) {


    HDC dpy = getDummyDC(display,cfg->nativeId());
    EGLint width,height,largest,texTarget,texFormat;
    pbSurface->getDim(&width,&height,&largest);
    pbSurface->getTexInfo(&texTarget,&texFormat);

    int wglTexFormat = WGL_NO_TEXTURE_ARB;
    int wglTexTarget = (texTarget == EGL_TEXTURE_2D)? WGL_TEXTURE_2D_ARB:
                                                      WGL_NO_TEXTURE_ARB;

    switch(texFormat) {
    case EGL_TEXTURE_RGB:
        wglTexFormat = WGL_TEXTURE_RGB_ARB;
        break;
    case EGL_TEXTURE_RGBA:
        wglTexFormat = WGL_TEXTURE_RGBA_ARB;
        break;
    }

    int pbAttribs[] = {
                       WGL_TEXTURE_TARGET_ARB   ,wglTexTarget,
                       WGL_TEXTURE_FORMAT_ARB   ,wglTexFormat,
                       0
                      };
    if(!s_wglExtProcs->wglCreatePbufferARB) return NULL;
    EGLNativePbufferType pb = s_wglExtProcs->wglCreatePbufferARB(dpy,cfg->nativeId(),width,height,pbAttribs);
    if(!pb) {
        DWORD err = GetLastError();
        return NULL;
    }
    return new SrfcInfo(pb);
}

bool releasePbuffer(EGLNativeInternalDisplayType display,EGLNativeSurfaceType pb) {
    if (!pb) return false;
    if(!s_wglExtProcs->wglReleasePbufferDCARB || !s_wglExtProcs->wglDestroyPbufferARB) return false;
    if(!s_wglExtProcs->wglReleasePbufferDCARB(pb->getPbuffer(),pb->getDC()) || !s_wglExtProcs->wglDestroyPbufferARB(pb->getPbuffer())){
        DWORD err = GetLastError();
        return false;
    }
    return true;
}

EGLNativeContextType createContext(EGLNativeInternalDisplayType display,EglConfig* cfg,EGLNativeContextType sharedContext) {

    EGLNativeContextType ctx = NULL;
    HDC  dpy  = getDummyDC(display,cfg->nativeId());

    if(!display->isPixelFormatSet(cfg->nativeId())){
        EGLNativePixelFormatType nativeConfig = cfg->nativeConfig();
        if(!SetPixelFormat(dpy,cfg->nativeId(),&nativeConfig)){
            return NULL;
        }
        display->pixelFormatWasSet(cfg->nativeId());
    }

    ctx = wglCreateContext(dpy);

    if(ctx && sharedContext) {
        if(!wglShareLists(sharedContext,ctx)) {
            wglDeleteContext(ctx);
            return NULL;
        }
    }
    return ctx;
}

bool destroyContext(EGLNativeInternalDisplayType dpy,EGLNativeContextType ctx) {
    if(!wglDeleteContext(ctx)) {
        DWORD err = GetLastError();
        return false;
    }
    return true;
}


bool makeCurrent(EGLNativeInternalDisplayType display,EglSurface* read,EglSurface* draw,EGLNativeContextType ctx) {

    HDC hdcRead = read ? read->native()->getDC(): NULL;
    HDC hdcDraw = draw ? draw->native()->getDC(): NULL;
    bool retVal = false;


    if(hdcRead == hdcDraw){
            bool ret =  wglMakeCurrent(hdcDraw,ctx);
            return ret;
    } else if (!s_wglExtProcs->wglMakeContextCurrentARB ) {
        return false;
    }
    retVal = s_wglExtProcs->wglMakeContextCurrentARB(hdcDraw,hdcRead,ctx);

    return retVal;
}

void swapBuffers(EGLNativeInternalDisplayType display,EGLNativeSurfaceType srfc){
    if(srfc && !SwapBuffers(srfc->getDC())) {
        DWORD err = GetLastError();
    }
}


void waitNative(){}

void swapInterval(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win,int interval) {

    if (s_wglExtProcs->wglSwapIntervalEXT){
        s_wglExtProcs->wglSwapIntervalEXT(interval);
    }
}

EGLNativeSurfaceType createWindowSurface(EGLNativeWindowType wnd){
    return new SrfcInfo(wnd);
}

EGLNativeSurfaceType createPixmapSurface(EGLNativePixmapType pix){
    return new SrfcInfo(pix);
}

void destroySurface(EGLNativeSurfaceType srfc){
    delete srfc;
}


};