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