Home | History | Annotate | Download | only in EGL
      1 /*
      2 * Copyright (C) 2011 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 #include "EglOsApi.h"
     17 #include <windows.h>
     18 #include <wingdi.h>
     19 #include <GL/wglext.h>
     20 #include <stdio.h>
     21 
     22 #define IS_TRUE(a) \
     23         if(a != true) return NULL;
     24 
     25 struct DisplayInfo{
     26     DisplayInfo():dc(NULL),hwnd(NULL),isPixelFormatSet(false){};
     27     DisplayInfo(HDC hdc,HWND wnd):isPixelFormatSet(false){dc = hdc; hwnd = wnd;};
     28     HDC  dc;
     29     HWND hwnd;
     30     bool isPixelFormatSet;
     31 };
     32 
     33 struct TlsData {
     34     std::map<int,DisplayInfo> m_map;
     35 };
     36 
     37 static DWORD s_tlsIndex = 0;
     38 
     39 static TlsData *getTLS() {
     40     TlsData *tls = (TlsData *)TlsGetValue(s_tlsIndex);
     41     if (!tls) {
     42         tls = new TlsData();
     43         TlsSetValue(s_tlsIndex, tls);
     44     }
     45     return tls;
     46 }
     47 
     48 class WinDisplay{
     49 public:
     50      enum { DEFAULT_DISPLAY = 0 };
     51      WinDisplay(){};
     52      DisplayInfo& getInfo(int configurationIndex){ return getTLS()->m_map[configurationIndex];}
     53      HDC  getDC(int configId){return getTLS()->m_map[configId].dc;}
     54      void setInfo(int configurationIndex,const DisplayInfo& info);
     55      bool isPixelFormatSet(int cfgId){ return getTLS()->m_map[cfgId].isPixelFormatSet;}
     56      void pixelFormatWasSet(int cfgId){getTLS()->m_map[cfgId].isPixelFormatSet = true;}
     57      bool infoExists(int configurationIndex);
     58      void releaseAll();
     59 };
     60 
     61 void WinDisplay::releaseAll(){
     62     TlsData * tls = getTLS();
     63 
     64     for(std::map<int,DisplayInfo>::iterator it = tls->m_map.begin(); it != tls->m_map.end();it++){
     65        if((*it).second.hwnd){
     66            DestroyWindow((*it).second.hwnd);
     67        }
     68        DeleteDC((*it).second.dc);
     69     }
     70 }
     71 
     72 bool WinDisplay::infoExists(int configurationIndex){
     73     return getTLS()->m_map.find(configurationIndex) != getTLS()->m_map.end();
     74 }
     75 
     76 void WinDisplay::setInfo(int configurationIndex,const DisplayInfo& info){
     77     getTLS()->m_map[configurationIndex] = info;
     78 }
     79 
     80 struct WglExtProcs{
     81     PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB;
     82     PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
     83     PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB;
     84     PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB;
     85     PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB;
     86     PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB;
     87     PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB;
     88     PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
     89 };
     90 
     91 static WglExtProcs* s_wglExtProcs = NULL;
     92 
     93 class SrfcInfo{
     94 public:
     95     typedef enum {
     96                  WINDOW  = 0,
     97                  PBUFFER = 1,
     98                  PIXMAP  = 2
     99                  }SurfaceType;
    100     explicit SrfcInfo(HWND wnd);
    101     explicit SrfcInfo(HPBUFFERARB pb);
    102     explicit SrfcInfo(HBITMAP bmap);
    103     HWND getHwnd(){ return m_hwnd;};
    104     HDC  getDC(){ return m_hdc;};
    105     HBITMAP  getBmap(){ return m_bmap;};
    106     HPBUFFERARB  getPbuffer(){ return m_pb;};
    107     ~SrfcInfo();
    108 private:
    109     HWND        m_hwnd;
    110     HPBUFFERARB m_pb;
    111     HBITMAP     m_bmap;
    112     HDC         m_hdc;
    113     SurfaceType m_type;
    114 };
    115 
    116 SrfcInfo::SrfcInfo(HBITMAP bmap):m_hwnd(NULL),
    117                                  m_pb(NULL),
    118                                  m_hdc(NULL),
    119                                  m_type(PIXMAP){
    120     m_bmap = bmap;
    121 }
    122 
    123 SrfcInfo::SrfcInfo(HWND wnd):m_pb(NULL),
    124                              m_bmap(NULL),
    125                              m_type(WINDOW){
    126     m_hwnd = wnd;
    127     m_hdc = GetDC(wnd);
    128 }
    129 
    130 SrfcInfo::SrfcInfo(HPBUFFERARB pb):m_hwnd(NULL),
    131                                    m_bmap(NULL),
    132                                    m_type(PBUFFER){
    133     m_pb = pb;
    134     if(s_wglExtProcs->wglGetPbufferDCARB){
    135         m_hdc =  s_wglExtProcs->wglGetPbufferDCARB(pb);
    136     }
    137 }
    138 
    139 SrfcInfo::~SrfcInfo(){
    140     if(m_type == WINDOW){
    141         ReleaseDC(m_hwnd,m_hdc);
    142     }
    143 }
    144 
    145 namespace EglOS{
    146 
    147 
    148 
    149 PROC wglGetExtentionsProcAddress(HDC hdc,const char *extension_name,const char* proc_name)
    150 {
    151     // this is pointer to function which returns pointer to string with list of all wgl extensions
    152     PFNWGLGETEXTENSIONSSTRINGARBPROC _wglGetExtensionsStringARB = NULL;
    153 
    154     // determine pointer to wglGetExtensionsStringEXT function
    155     _wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
    156     if(!_wglGetExtensionsStringARB){
    157         fprintf(stderr,"could not get wglGetExtensionsStringARB\n");
    158         return NULL;
    159     }
    160 
    161     if (!_wglGetExtensionsStringARB || strstr(_wglGetExtensionsStringARB(hdc), extension_name) == NULL)
    162     {
    163         fprintf(stderr,"extension %s was not found\n",extension_name);
    164         // string was not found
    165         return NULL;
    166     }
    167 
    168     // extension is supported
    169     return wglGetProcAddress(proc_name);
    170 }
    171 
    172 LRESULT CALLBACK dummyWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    173 {
    174     return DefWindowProc(hwnd, uMsg, wParam, lParam);
    175 }
    176 
    177 HWND createDummyWindow(){
    178 
    179     WNDCLASSEX wcx;
    180     wcx.cbSize = sizeof(wcx);                       // size of structure
    181     wcx.style =  CS_OWNDC |CS_HREDRAW |CS_VREDRAW;  // redraw if size changes
    182     wcx.lpfnWndProc = dummyWndProc;                 // points to window procedure
    183     wcx.cbClsExtra = 0;                             // no extra class memory
    184     wcx.cbWndExtra = sizeof(void*);                 // save extra window memory, to store VasWindow instance
    185     wcx.hInstance = NULL;                           // handle to instance
    186     wcx.hIcon = NULL;                               // predefined app. icon
    187     wcx.hCursor = NULL;
    188     wcx.hbrBackground = NULL;                       // no background brush
    189     wcx.lpszMenuName =  NULL;                       // name of menu resource
    190     wcx.lpszClassName = "DummyWin";                 // name of window class
    191     wcx.hIconSm = (HICON) NULL;                     // small class icon
    192 
    193     RegisterClassEx(&wcx);
    194 
    195     HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
    196                                "DummyWin",
    197                                "Dummy",
    198                                WS_POPUP,
    199                                0,
    200                                0,
    201                                1,
    202                                1,
    203                                NULL,
    204                                NULL,
    205                                0,0);
    206     return hwnd;
    207 }
    208 
    209 EGLNativeInternalDisplayType getDefaultDisplay() {
    210     if (!s_tlsIndex) s_tlsIndex = TlsAlloc();
    211     WinDisplay* dpy = new WinDisplay();
    212 
    213     HWND hwnd = createDummyWindow();
    214     HDC  hdc  =  GetDC(hwnd);
    215     dpy->setInfo(WinDisplay::DEFAULT_DISPLAY,DisplayInfo(hdc,hwnd));
    216     return static_cast<EGLNativeInternalDisplayType>(dpy);
    217 }
    218 
    219 EGLNativeInternalDisplayType getInternalDisplay(EGLNativeDisplayType display){
    220     if (!s_tlsIndex) s_tlsIndex = TlsAlloc();
    221     WinDisplay* dpy = new WinDisplay();
    222     dpy->setInfo(WinDisplay::DEFAULT_DISPLAY,DisplayInfo(display,NULL));
    223     return dpy;
    224 }
    225 
    226 static HDC getDummyDC(EGLNativeInternalDisplayType display,int cfgId){
    227 
    228     HDC dpy = NULL;
    229     if(!display->infoExists(cfgId)){
    230         HWND hwnd = createDummyWindow();
    231         dpy  = GetDC(hwnd);
    232         display->setInfo(cfgId,DisplayInfo(dpy,hwnd));
    233     } else {
    234         dpy = display->getDC(cfgId);
    235     }
    236     return dpy;
    237 }
    238 void initPtrToWglFunctions(){
    239     HWND hwnd = createDummyWindow();
    240     HDC dpy =  GetDC(hwnd);
    241     if(!hwnd || !dpy){
    242         fprintf(stderr,"error while getting DC\n");
    243         return;
    244     }
    245     EGLNativeContextType ctx = NULL;
    246     PIXELFORMATDESCRIPTOR pfd = {
    247                                   sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
    248                                   1,                     // version number
    249                                   PFD_DRAW_TO_WINDOW |   // support window
    250                                   PFD_SUPPORT_OPENGL |   // support OpenGL
    251                                   PFD_DOUBLEBUFFER,      // double buffered
    252                                   PFD_TYPE_RGBA,         // RGBA type
    253                                   24,                    // 24-bit color depth
    254                                   0, 0, 0, 0, 0, 0,      // color bits ignored
    255                                   0,                     // no alpha buffer
    256                                   0,                     // shift bit ignored
    257                                   0,                     // no accumulation buffer
    258                                   0, 0, 0, 0,            // accum bits ignored
    259                                   32,                    // 32-bit z-buffer
    260                                   0,                     // no stencil buffer
    261                                   0,                     // no auxiliary buffer
    262                                   PFD_MAIN_PLANE,        // main layer
    263                                   0,                     // reserved
    264                                   0, 0, 0                // layer masks ignored
    265                                  };
    266 
    267     int  iPixelFormat,err;
    268     iPixelFormat = ChoosePixelFormat(dpy, &pfd);
    269     if(iPixelFormat < 0){
    270         fprintf(stderr,"error while choosing pixel format\n");
    271         return;
    272     }
    273     if(!SetPixelFormat(dpy,iPixelFormat,&pfd)){
    274 
    275         int err = GetLastError();
    276         fprintf(stderr,"error while setting pixel format 0x%x\n",err);
    277         return;
    278     }
    279 
    280 
    281     ctx = wglCreateContext(dpy);
    282     if(!ctx){
    283         err =  GetLastError();
    284         fprintf(stderr,"error while creating dummy context %d\n",err);
    285     }
    286     if(!wglMakeCurrent(dpy,ctx)){
    287         err =  GetLastError();
    288         fprintf(stderr,"error while making dummy context current %d\n",err);
    289     }
    290 
    291     if(!s_wglExtProcs){
    292         s_wglExtProcs = new WglExtProcs();
    293         s_wglExtProcs->wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pixel_format","wglGetPixelFormatAttribivARB");
    294         s_wglExtProcs->wglChoosePixelFormatARB      = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pixel_format","wglChoosePixelFormatARB");
    295         s_wglExtProcs->wglCreatePbufferARB          = (PFNWGLCREATEPBUFFERARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglCreatePbufferARB");
    296         s_wglExtProcs->wglReleasePbufferDCARB       = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglReleasePbufferDCARB");
    297         s_wglExtProcs->wglDestroyPbufferARB         = (PFNWGLDESTROYPBUFFERARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglDestroyPbufferARB");
    298         s_wglExtProcs->wglGetPbufferDCARB           = (PFNWGLGETPBUFFERDCARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_pbuffer","wglGetPbufferDCARB");
    299         s_wglExtProcs->wglMakeContextCurrentARB     = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetExtentionsProcAddress(dpy,"WGL_ARB_make_current_read","wglMakeContextCurrentARB");
    300         s_wglExtProcs->wglSwapIntervalEXT           = (PFNWGLSWAPINTERVALEXTPROC)wglGetExtentionsProcAddress(dpy,"WGL_EXT_swap_control","wglSwapIntervalEXT");
    301     }
    302 
    303    wglMakeCurrent(dpy,NULL);
    304    DestroyWindow(hwnd);
    305    DeleteDC(dpy);
    306 }
    307 
    308 bool releaseDisplay(EGLNativeInternalDisplayType dpy) {
    309     dpy->releaseAll();
    310     return true;
    311 }
    312 
    313 void deleteDisplay(EGLNativeInternalDisplayType idpy){
    314     if(idpy){
    315         delete idpy;
    316     }
    317 }
    318 
    319 
    320 static bool initPixelFormat(HDC dc){
    321     PIXELFORMATDESCRIPTOR  pfd;
    322     unsigned int numpf;
    323     int iPixelFormat;
    324 
    325     if(s_wglExtProcs->wglChoosePixelFormatARB) {
    326         int i0 = 0;
    327         float f0 = 0.0f;
    328         return s_wglExtProcs->wglChoosePixelFormatARB(dc,&i0, &f0, 1, &iPixelFormat, &numpf);
    329     } else {
    330         return ChoosePixelFormat(dc,&pfd);
    331     }
    332 }
    333 
    334 EglConfig* pixelFormatToConfig(EGLNativeInternalDisplayType display,int renderableType,EGLNativePixelFormatType* frmt,int index){
    335 
    336     EGLint  red,green,blue,alpha,depth,stencil;
    337     EGLint  supportedSurfaces,visualType,visualId;
    338     EGLint  transparentType,samples;
    339     EGLint  tRed,tGreen,tBlue;
    340     EGLint  pMaxWidth,pMaxHeight,pMaxPixels;
    341     EGLint  level;
    342     EGLint  window,bitmap,pbuffer,transparent;
    343     HDC dpy = getDummyDC(display,WinDisplay::DEFAULT_DISPLAY);
    344 
    345     if(frmt->iPixelType != PFD_TYPE_RGBA) return NULL; // other formats are not supported yet
    346     if(!((frmt->dwFlags & PFD_SUPPORT_OPENGL) && (frmt->dwFlags & PFD_DOUBLEBUFFER))) return NULL; //pixel format does not supports opengl or double buffer
    347     if( 0 != (frmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_NEED_PALETTE )) ) return NULL; //discard generic pixel formats as well as pallete pixel formats
    348 
    349     int attribs [] = {
    350                           WGL_DRAW_TO_WINDOW_ARB,
    351                           WGL_DRAW_TO_BITMAP_ARB,
    352                           WGL_DRAW_TO_PBUFFER_ARB,
    353                           WGL_TRANSPARENT_ARB,
    354                           WGL_TRANSPARENT_RED_VALUE_ARB,
    355                           WGL_TRANSPARENT_GREEN_VALUE_ARB,
    356                           WGL_TRANSPARENT_BLUE_VALUE_ARB
    357                      };
    358 
    359     supportedSurfaces = 0;
    360     if(!s_wglExtProcs->wglGetPixelFormatAttribivARB) return NULL;
    361 
    362     IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[0],&window));
    363     IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[1],&bitmap));
    364     IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[2],&pbuffer));
    365     if(window)  supportedSurfaces |= EGL_WINDOW_BIT;
    366     if(bitmap)  supportedSurfaces |= EGL_PIXMAP_BIT;
    367     if(pbuffer) supportedSurfaces |= EGL_PBUFFER_BIT;
    368 
    369 
    370     if(!supportedSurfaces) return NULL;
    371 
    372     //default values
    373     visualId                  = 0;
    374     visualType                = EGL_NONE;
    375     EGLenum caveat            = EGL_NONE;
    376     EGLBoolean renderable     = EGL_FALSE;
    377     pMaxWidth                 = PBUFFER_MAX_WIDTH;
    378     pMaxHeight                = PBUFFER_MAX_HEIGHT;
    379     pMaxPixels                = PBUFFER_MAX_PIXELS;
    380     samples                   = 0 ;
    381     level                     = 0 ;
    382 
    383     IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[3],&transparent));
    384     if(transparent) {
    385         transparentType = EGL_TRANSPARENT_RGB;
    386         IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[4],&tRed));
    387         IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[5],&tGreen));
    388         IS_TRUE(s_wglExtProcs->wglGetPixelFormatAttribivARB(dpy,index,0,1,&attribs[6],&tBlue));
    389     } else {
    390         transparentType = EGL_NONE;
    391     }
    392 
    393     red     = frmt->cRedBits;
    394     green   = frmt->cGreenBits;
    395     blue    = frmt->cBlueBits;
    396     alpha   = frmt->cAlphaBits;
    397     depth   = frmt->cDepthBits;
    398     stencil = frmt->cStencilBits;
    399     return new EglConfig(red,green,blue,alpha,caveat,(EGLint)index,depth,level,pMaxWidth,pMaxHeight,pMaxPixels,renderable,renderableType,
    400                          visualId,visualType,samples,stencil,supportedSurfaces,transparentType,tRed,tGreen,tBlue,*frmt);
    401 }
    402 
    403 
    404 void queryConfigs(EGLNativeInternalDisplayType display,int renderableType,ConfigsList& listOut) {
    405     PIXELFORMATDESCRIPTOR  pfd;
    406     int  iPixelFormat = 1;
    407     HDC dpy = getDummyDC(display,WinDisplay::DEFAULT_DISPLAY);
    408 
    409     //
    410     // We need to call wglChoosePixelFormat at least once,
    411     // seems that the driver needs to initialize itself.
    412     // do it here during initialization.
    413     //
    414     initPixelFormat(dpy);
    415 
    416     //quering num of formats
    417     int maxFormat = DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd);
    418 
    419     //inserting rest of formats
    420     for(;iPixelFormat <= maxFormat; iPixelFormat++) {
    421          DescribePixelFormat(dpy, iPixelFormat,sizeof(PIXELFORMATDESCRIPTOR), &pfd);
    422          EglConfig* pConfig = pixelFormatToConfig(display,renderableType,&pfd,iPixelFormat);
    423          if(pConfig) listOut.push_back(pConfig);
    424     }
    425 }
    426 
    427 bool validNativeDisplay(EGLNativeInternalDisplayType dpy) {
    428     return dpy != NULL;
    429 }
    430 
    431 bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeWindowType win) {
    432     return IsWindow(win);
    433 }
    434 
    435 bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win) {
    436     if (!win) return false;
    437     return validNativeWin(dpy,win->getHwnd());
    438 }
    439 
    440 bool validNativePixmap(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType pix) {
    441     BITMAP bm;
    442     if (!pix) return false;
    443     return GetObject(pix->getBmap(), sizeof(BITMAP), (LPSTR)&bm);
    444 }
    445 
    446 bool checkWindowPixelFormatMatch(EGLNativeInternalDisplayType dpy,EGLNativeWindowType win,EglConfig* cfg,unsigned int* width,unsigned int* height) {
    447    RECT r;
    448    if(!GetClientRect(win,&r)) return false;
    449    *width  = r.right  - r.left;
    450    *height = r.bottom - r.top;
    451    HDC dc = GetDC(win);
    452    EGLNativePixelFormatType nativeConfig = cfg->nativeConfig();
    453    bool ret = SetPixelFormat(dc,cfg->nativeId(),&nativeConfig);
    454    DeleteDC(dc);
    455    return ret;
    456 }
    457 
    458 bool checkPixmapPixelFormatMatch(EGLNativeInternalDisplayType dpy,EGLNativePixmapType pix,EglConfig* cfg,unsigned int* width,unsigned int* height){
    459 
    460     BITMAP bm;
    461     if(!GetObject(pix, sizeof(BITMAP), (LPSTR)&bm)) return false;
    462 
    463     *width  = bm.bmWidth;
    464     *height = bm.bmHeight;
    465 
    466     return true;
    467 }
    468 
    469 EGLNativeSurfaceType createPbufferSurface(EGLNativeInternalDisplayType display,EglConfig* cfg,EglPbufferSurface* pbSurface) {
    470 
    471 
    472     HDC dpy = getDummyDC(display,cfg->nativeId());
    473     EGLint width,height,largest,texTarget,texFormat;
    474     pbSurface->getDim(&width,&height,&largest);
    475     pbSurface->getTexInfo(&texTarget,&texFormat);
    476 
    477     int wglTexFormat = WGL_NO_TEXTURE_ARB;
    478     int wglTexTarget = (texTarget == EGL_TEXTURE_2D)? WGL_TEXTURE_2D_ARB:
    479                                                       WGL_NO_TEXTURE_ARB;
    480 
    481     switch(texFormat) {
    482     case EGL_TEXTURE_RGB:
    483         wglTexFormat = WGL_TEXTURE_RGB_ARB;
    484         break;
    485     case EGL_TEXTURE_RGBA:
    486         wglTexFormat = WGL_TEXTURE_RGBA_ARB;
    487         break;
    488     }
    489 
    490     int pbAttribs[] = {
    491                        WGL_TEXTURE_TARGET_ARB   ,wglTexTarget,
    492                        WGL_TEXTURE_FORMAT_ARB   ,wglTexFormat,
    493                        0
    494                       };
    495     if(!s_wglExtProcs->wglCreatePbufferARB) return NULL;
    496     EGLNativePbufferType pb = s_wglExtProcs->wglCreatePbufferARB(dpy,cfg->nativeId(),width,height,pbAttribs);
    497     if(!pb) {
    498         GetLastError();
    499         return NULL;
    500     }
    501     return new SrfcInfo(pb);
    502 }
    503 
    504 bool releasePbuffer(EGLNativeInternalDisplayType display,EGLNativeSurfaceType pb) {
    505     if (!pb) return false;
    506     if(!s_wglExtProcs->wglReleasePbufferDCARB || !s_wglExtProcs->wglDestroyPbufferARB) return false;
    507     if(!s_wglExtProcs->wglReleasePbufferDCARB(pb->getPbuffer(),pb->getDC()) || !s_wglExtProcs->wglDestroyPbufferARB(pb->getPbuffer())){
    508         GetLastError();
    509         return false;
    510     }
    511     return true;
    512 }
    513 
    514 EGLNativeContextType createContext(EGLNativeInternalDisplayType display,EglConfig* cfg,EGLNativeContextType sharedContext) {
    515 
    516     EGLNativeContextType ctx = NULL;
    517     HDC  dpy  = getDummyDC(display,cfg->nativeId());
    518 
    519     if(!display->isPixelFormatSet(cfg->nativeId())){
    520         EGLNativePixelFormatType nativeConfig = cfg->nativeConfig();
    521         if(!SetPixelFormat(dpy,cfg->nativeId(),&nativeConfig)){
    522             return NULL;
    523         }
    524         display->pixelFormatWasSet(cfg->nativeId());
    525     }
    526 
    527     ctx = wglCreateContext(dpy);
    528 
    529     if(ctx && sharedContext) {
    530         if(!wglShareLists(sharedContext,ctx)) {
    531             wglDeleteContext(ctx);
    532             return NULL;
    533         }
    534     }
    535     return ctx;
    536 }
    537 
    538 bool destroyContext(EGLNativeInternalDisplayType dpy,EGLNativeContextType ctx) {
    539     if(!wglDeleteContext(ctx)) {
    540         GetLastError();
    541         return false;
    542     }
    543     return true;
    544 }
    545 
    546 
    547 bool makeCurrent(EGLNativeInternalDisplayType display,EglSurface* read,EglSurface* draw,EGLNativeContextType ctx) {
    548 
    549     HDC hdcRead = read ? read->native()->getDC(): NULL;
    550     HDC hdcDraw = draw ? draw->native()->getDC(): NULL;
    551     bool retVal = false;
    552 
    553 
    554     if(hdcRead == hdcDraw){
    555             bool ret =  wglMakeCurrent(hdcDraw,ctx);
    556             return ret;
    557     } else if (!s_wglExtProcs->wglMakeContextCurrentARB ) {
    558         return false;
    559     }
    560     retVal = s_wglExtProcs->wglMakeContextCurrentARB(hdcDraw,hdcRead,ctx);
    561 
    562     return retVal;
    563 }
    564 
    565 void swapBuffers(EGLNativeInternalDisplayType display,EGLNativeSurfaceType srfc){
    566     if(srfc && !SwapBuffers(srfc->getDC())) {
    567         GetLastError();
    568     }
    569 }
    570 
    571 
    572 void waitNative(){}
    573 
    574 void swapInterval(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win,int interval) {
    575 
    576     if (s_wglExtProcs->wglSwapIntervalEXT){
    577         s_wglExtProcs->wglSwapIntervalEXT(interval);
    578     }
    579 }
    580 
    581 EGLNativeSurfaceType createWindowSurface(EGLNativeWindowType wnd){
    582     return new SrfcInfo(wnd);
    583 }
    584 
    585 EGLNativeSurfaceType createPixmapSurface(EGLNativePixmapType pix){
    586     return new SrfcInfo(pix);
    587 }
    588 
    589 void destroySurface(EGLNativeSurfaceType srfc){
    590     delete srfc;
    591 }
    592 
    593 
    594 };
    595