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
26struct 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
34struct TlsData {
35    std::map<int,DisplayInfo> m_map;
36};
37
38static DWORD s_tlsIndex = 0;
39
40static 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
49class WinDisplay{
50public:
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
64void 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
75bool WinDisplay::infoExists(int configurationIndex){
76    return getTLS()->m_map.find(configurationIndex) != getTLS()->m_map.end();
77}
78
79void WinDisplay::setInfo(int configurationIndex,const DisplayInfo& info){
80    getTLS()->m_map[configurationIndex] = info;
81}
82
83struct 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
94static WglExtProcs* s_wglExtProcs = NULL;
95
96class SrfcInfo{
97public:
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();
111private:
112    HWND        m_hwnd;
113    HPBUFFERARB m_pb;
114    HBITMAP     m_bmap;
115    HDC         m_hdc;
116    SurfaceType m_type;
117};
118
119SrfcInfo::SrfcInfo(HBITMAP bmap):m_hwnd(NULL),
120                                 m_pb(NULL),
121                                 m_hdc(NULL),
122                                 m_type(PIXMAP){
123    m_bmap = bmap;
124}
125
126SrfcInfo::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
133SrfcInfo::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
142SrfcInfo::~SrfcInfo(){
143    if(m_type == WINDOW){
144        ReleaseDC(m_hwnd,m_hdc);
145    }
146}
147
148namespace EglOS{
149
150
151
152PROC 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
175LRESULT CALLBACK dummyWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
176{
177    return DefWindowProc(hwnd, uMsg, wParam, lParam);
178}
179
180HWND 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
211EGLNativeInternalDisplayType 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
221EGLNativeInternalDisplayType 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
228static 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}
240void 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
310bool releaseDisplay(EGLNativeInternalDisplayType dpy) {
311    dpy->releaseAll();
312    return true;
313}
314
315void deleteDisplay(EGLNativeInternalDisplayType idpy){
316    if(idpy){
317        delete idpy;
318    }
319}
320
321
322static 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
336EglConfig* 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
406void 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
429bool validNativeDisplay(EGLNativeInternalDisplayType dpy) {
430    return dpy != NULL;
431}
432
433bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeWindowType win) {
434    return IsWindow(win);
435}
436
437bool validNativeWin(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win) {
438    if (!win) return false;
439    return validNativeWin(dpy,win->getHwnd());
440}
441
442bool validNativePixmap(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType pix) {
443    BITMAP bm;
444    if (!pix) return false;
445    return GetObject(pix->getBmap(), sizeof(BITMAP), (LPSTR)&bm);
446}
447
448bool 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
460bool 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
471EGLNativeSurfaceType 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
506bool 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
516EGLNativeContextType 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
540bool destroyContext(EGLNativeInternalDisplayType dpy,EGLNativeContextType ctx) {
541    if(!wglDeleteContext(ctx)) {
542        DWORD err = GetLastError();
543        return false;
544    }
545    return true;
546}
547
548
549bool 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
567void swapBuffers(EGLNativeInternalDisplayType display,EGLNativeSurfaceType srfc){
568    if(srfc && !SwapBuffers(srfc->getDC())) {
569        DWORD err = GetLastError();
570    }
571}
572
573
574void waitNative(){}
575
576void swapInterval(EGLNativeInternalDisplayType dpy,EGLNativeSurfaceType win,int interval) {
577
578    if (s_wglExtProcs->wglSwapIntervalEXT){
579        s_wglExtProcs->wglSwapIntervalEXT(interval);
580    }
581}
582
583EGLNativeSurfaceType createWindowSurface(EGLNativeWindowType wnd){
584    return new SrfcInfo(wnd);
585}
586
587EGLNativeSurfaceType createPixmapSurface(EGLNativePixmapType pix){
588    return new SrfcInfo(pix);
589}
590
591void destroySurface(EGLNativeSurfaceType srfc){
592    delete srfc;
593}
594
595
596};
597