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
25struct 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
33struct TlsData {
34    std::map<int,DisplayInfo> m_map;
35};
36
37static DWORD s_tlsIndex = 0;
38
39static 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
48class WinDisplay{
49public:
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
61void 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
72bool WinDisplay::infoExists(int configurationIndex){
73    return getTLS()->m_map.find(configurationIndex) != getTLS()->m_map.end();
74}
75
76void WinDisplay::setInfo(int configurationIndex,const DisplayInfo& info){
77    getTLS()->m_map[configurationIndex] = info;
78}
79
80struct 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
91static WglExtProcs* s_wglExtProcs = NULL;
92
93class SrfcInfo{
94public:
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();
108private:
109    HWND        m_hwnd;
110    HPBUFFERARB m_pb;
111    HBITMAP     m_bmap;
112    HDC         m_hdc;
113    SurfaceType m_type;
114};
115
116SrfcInfo::SrfcInfo(HBITMAP bmap):m_hwnd(NULL),
117                                 m_pb(NULL),
118                                 m_hdc(NULL),
119                                 m_type(PIXMAP){
120    m_bmap = bmap;
121}
122
123SrfcInfo::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
130SrfcInfo::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
139SrfcInfo::~SrfcInfo(){
140    if(m_type == WINDOW){
141        ReleaseDC(m_hwnd,m_hdc);
142    }
143}
144
145namespace EglOS{
146
147
148
149PROC 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
172LRESULT CALLBACK dummyWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
173{
174    return DefWindowProc(hwnd, uMsg, wParam, lParam);
175}
176
177HWND 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
209EGLNativeInternalDisplayType 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
219EGLNativeInternalDisplayType 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
226static 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}
238void 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
308bool releaseDisplay(EGLNativeInternalDisplayType dpy) {
309    dpy->releaseAll();
310    return true;
311}
312
313void deleteDisplay(EGLNativeInternalDisplayType idpy){
314    if(idpy){
315        delete idpy;
316    }
317}
318
319
320static 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
334EglConfig* 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
404void 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
427bool validNativeDisplay(EGLNativeInternalDisplayType dpy) {
428    return dpy != NULL;
429}
430
431bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeWindowType win) {
432    return IsWindow(win);
433}
434
435bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win) {
436    if (!win) return false;
437    return validNativeWin(dpy,win->getHwnd());
438}
439
440bool validNativePixmap(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType pix) {
441    BITMAP bm;
442    if (!pix) return false;
443    return GetObject(pix->getBmap(), sizeof(BITMAP), (LPSTR)&bm);
444}
445
446bool 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
458bool 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
469EGLNativeSurfaceType 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
504bool 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
514EGLNativeContextType 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
538bool destroyContext(EGLNativeInternalDisplayType dpy,EGLNativeContextType ctx) {
539    if(!wglDeleteContext(ctx)) {
540        GetLastError();
541        return false;
542    }
543    return true;
544}
545
546
547bool 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
565void swapBuffers(EGLNativeInternalDisplayType display,EGLNativeSurfaceType srfc){
566    if(srfc && !SwapBuffers(srfc->getDC())) {
567        GetLastError();
568    }
569}
570
571
572void waitNative(){}
573
574void swapInterval(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win,int interval) {
575
576    if (s_wglExtProcs->wglSwapIntervalEXT){
577        s_wglExtProcs->wglSwapIntervalEXT(interval);
578    }
579}
580
581EGLNativeSurfaceType createWindowSurface(EGLNativeWindowType wnd){
582    return new SrfcInfo(wnd);
583}
584
585EGLNativeSurfaceType createPixmapSurface(EGLNativePixmapType pix){
586    return new SrfcInfo(pix);
587}
588
589void destroySurface(EGLNativeSurfaceType srfc){
590    delete srfc;
591}
592
593
594};
595