Home | History | Annotate | Download | only in libEGL
      1 //
      2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // libEGL.cpp: Implements the exported EGL functions.
      8 
      9 #include <exception>
     10 
     11 #include "common/debug.h"
     12 #include "common/version.h"
     13 #include "libGLESv2/Context.h"
     14 #include "libGLESv2/Texture.h"
     15 #include "libGLESv2/main.h"
     16 #include "libGLESv2/renderer/SwapChain.h"
     17 
     18 #include "libEGL/main.h"
     19 #include "libEGL/Display.h"
     20 #include "libEGL/Surface.h"
     21 
     22 bool validateDisplay(egl::Display *display)
     23 {
     24     if (display == EGL_NO_DISPLAY)
     25     {
     26         return egl::error(EGL_BAD_DISPLAY, false);
     27     }
     28 
     29     if (!display->isInitialized())
     30     {
     31         return egl::error(EGL_NOT_INITIALIZED, false);
     32     }
     33 
     34     return true;
     35 }
     36 
     37 bool validateConfig(egl::Display *display, EGLConfig config)
     38 {
     39     if (!validateDisplay(display))
     40     {
     41         return false;
     42     }
     43 
     44     if (!display->isValidConfig(config))
     45     {
     46         return egl::error(EGL_BAD_CONFIG, false);
     47     }
     48 
     49     return true;
     50 }
     51 
     52 bool validateContext(egl::Display *display, gl::Context *context)
     53 {
     54     if (!validateDisplay(display))
     55     {
     56         return false;
     57     }
     58 
     59     if (!display->isValidContext(context))
     60     {
     61         return egl::error(EGL_BAD_CONTEXT, false);
     62     }
     63 
     64     return true;
     65 }
     66 
     67 bool validateSurface(egl::Display *display, egl::Surface *surface)
     68 {
     69     if (!validateDisplay(display))
     70     {
     71         return false;
     72     }
     73 
     74     if (!display->isValidSurface(surface))
     75     {
     76         return egl::error(EGL_BAD_SURFACE, false);
     77     }
     78 
     79     return true;
     80 }
     81 
     82 extern "C"
     83 {
     84 EGLint __stdcall eglGetError(void)
     85 {
     86     EVENT("()");
     87 
     88     EGLint error = egl::getCurrentError();
     89 
     90     if (error != EGL_SUCCESS)
     91     {
     92         egl::setCurrentError(EGL_SUCCESS);
     93     }
     94 
     95     return error;
     96 }
     97 
     98 EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
     99 {
    100     EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
    101 
    102     return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
    103 }
    104 
    105 EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
    106 {
    107     EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
    108           platform, native_display, attrib_list);
    109 
    110     switch (platform)
    111     {
    112       case EGL_PLATFORM_ANGLE_ANGLE:
    113         break;
    114 
    115       default:
    116         return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY);
    117     }
    118 
    119     EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
    120 
    121     // Validate the display device context
    122     if (WindowFromDC(displayId) == NULL)
    123     {
    124         return egl::success(EGL_NO_DISPLAY);
    125     }
    126 
    127     EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
    128     if (attrib_list)
    129     {
    130         for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
    131         {
    132             switch (curAttrib[0])
    133             {
    134               case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
    135                 requestedDisplayType = curAttrib[1];
    136                 break;
    137 
    138               default:
    139                 break;
    140             }
    141         }
    142     }
    143 
    144     switch (requestedDisplayType)
    145     {
    146       case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
    147         break;
    148 
    149       case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
    150       case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
    151       case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE:
    152         if (!egl::Display::supportsPlatformD3D())
    153         {
    154             return egl::success(EGL_NO_DISPLAY);
    155         }
    156         break;
    157 
    158       case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
    159       case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
    160         if (!egl::Display::supportsPlatformOpenGL())
    161         {
    162             return egl::success(EGL_NO_DISPLAY);
    163         }
    164         break;
    165 
    166       default:
    167         return egl::success(EGL_NO_DISPLAY);
    168     }
    169 
    170     return egl::Display::getDisplay(displayId, requestedDisplayType);
    171 }
    172 
    173 EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
    174 {
    175     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
    176           dpy, major, minor);
    177 
    178     if (dpy == EGL_NO_DISPLAY)
    179     {
    180         return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
    181     }
    182 
    183     egl::Display *display = static_cast<egl::Display*>(dpy);
    184 
    185     if (!display->initialize())
    186     {
    187         return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
    188     }
    189 
    190     if (major) *major = 1;
    191     if (minor) *minor = 4;
    192 
    193     return egl::success(EGL_TRUE);
    194 }
    195 
    196 EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
    197 {
    198     EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
    199 
    200     if (dpy == EGL_NO_DISPLAY)
    201     {
    202         return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
    203     }
    204 
    205     egl::Display *display = static_cast<egl::Display*>(dpy);
    206 
    207     display->terminate();
    208 
    209     return egl::success(EGL_TRUE);
    210 }
    211 
    212 const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
    213 {
    214     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
    215 
    216     egl::Display *display = static_cast<egl::Display*>(dpy);
    217     if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display))
    218     {
    219         return NULL;
    220     }
    221 
    222     switch (name)
    223     {
    224       case EGL_CLIENT_APIS:
    225         return egl::success("OpenGL_ES");
    226       case EGL_EXTENSIONS:
    227         return egl::success(egl::Display::getExtensionString(display));
    228       case EGL_VENDOR:
    229         return egl::success(display->getVendorString());
    230       case EGL_VERSION:
    231         return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")");
    232       default:
    233         return egl::error(EGL_BAD_PARAMETER, (const char*)NULL);
    234     }
    235 }
    236 
    237 EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    238 {
    239     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
    240           "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
    241           dpy, configs, config_size, num_config);
    242 
    243     egl::Display *display = static_cast<egl::Display*>(dpy);
    244 
    245     if (!validateDisplay(display))
    246     {
    247         return EGL_FALSE;
    248     }
    249 
    250     if (!num_config)
    251     {
    252         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
    253     }
    254 
    255     const EGLint attribList[] =    {EGL_NONE};
    256 
    257     if (!display->getConfigs(configs, attribList, config_size, num_config))
    258     {
    259         return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    260     }
    261 
    262     return egl::success(EGL_TRUE);
    263 }
    264 
    265 EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
    266 {
    267     EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
    268           "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
    269           dpy, attrib_list, configs, config_size, num_config);
    270 
    271     egl::Display *display = static_cast<egl::Display*>(dpy);
    272 
    273     if (!validateDisplay(display))
    274     {
    275         return EGL_FALSE;
    276     }
    277 
    278     if (!num_config)
    279     {
    280         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
    281     }
    282 
    283     const EGLint attribList[] =    {EGL_NONE};
    284 
    285     if (!attrib_list)
    286     {
    287         attrib_list = attribList;
    288     }
    289 
    290     display->getConfigs(configs, attrib_list, config_size, num_config);
    291 
    292     return egl::success(EGL_TRUE);
    293 }
    294 
    295 EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
    296 {
    297     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
    298           dpy, config, attribute, value);
    299 
    300     egl::Display *display = static_cast<egl::Display*>(dpy);
    301 
    302     if (!validateConfig(display, config))
    303     {
    304         return EGL_FALSE;
    305     }
    306 
    307     if (!display->getConfigAttrib(config, attribute, value))
    308     {
    309         return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    310     }
    311 
    312     return egl::success(EGL_TRUE);
    313 }
    314 
    315 EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
    316 {
    317     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
    318           "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
    319 
    320     egl::Display *display = static_cast<egl::Display*>(dpy);
    321 
    322     if (!validateConfig(display, config))
    323     {
    324         return EGL_NO_SURFACE;
    325     }
    326 
    327     HWND window = (HWND)win;
    328 
    329     if (!IsWindow(window))
    330     {
    331         return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
    332     }
    333 
    334     return display->createWindowSurface(window, config, attrib_list);
    335 }
    336 
    337 EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
    338 {
    339     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
    340           dpy, config, attrib_list);
    341 
    342     egl::Display *display = static_cast<egl::Display*>(dpy);
    343 
    344     if (!validateConfig(display, config))
    345     {
    346         return EGL_NO_SURFACE;
    347     }
    348 
    349     return display->createOffscreenSurface(config, NULL, attrib_list);
    350 }
    351 
    352 EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
    353 {
    354     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
    355           "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
    356 
    357     egl::Display *display = static_cast<egl::Display*>(dpy);
    358 
    359     if (!validateConfig(display, config))
    360     {
    361         return EGL_NO_SURFACE;
    362     }
    363 
    364     UNIMPLEMENTED();   // FIXME
    365 
    366     return egl::success(EGL_NO_SURFACE);
    367 }
    368 
    369 EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
    370 {
    371     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
    372 
    373     egl::Display *display = static_cast<egl::Display*>(dpy);
    374     egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
    375 
    376     if (!validateSurface(display, eglSurface))
    377     {
    378         return EGL_FALSE;
    379     }
    380 
    381     if (surface == EGL_NO_SURFACE)
    382     {
    383         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    384     }
    385 
    386     display->destroySurface((egl::Surface*)surface);
    387 
    388     return egl::success(EGL_TRUE);
    389 }
    390 
    391 EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
    392 {
    393     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
    394           dpy, surface, attribute, value);
    395 
    396     egl::Display *display = static_cast<egl::Display*>(dpy);
    397     egl::Surface *eglSurface = (egl::Surface*)surface;
    398 
    399     if (!validateSurface(display, eglSurface))
    400     {
    401         return EGL_FALSE;
    402     }
    403 
    404     if (surface == EGL_NO_SURFACE)
    405     {
    406         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    407     }
    408 
    409     switch (attribute)
    410     {
    411       case EGL_VG_ALPHA_FORMAT:
    412         UNIMPLEMENTED();   // FIXME
    413         break;
    414       case EGL_VG_COLORSPACE:
    415         UNIMPLEMENTED();   // FIXME
    416         break;
    417       case EGL_CONFIG_ID:
    418         *value = eglSurface->getConfigID();
    419         break;
    420       case EGL_HEIGHT:
    421         *value = eglSurface->getHeight();
    422         break;
    423       case EGL_HORIZONTAL_RESOLUTION:
    424         UNIMPLEMENTED();   // FIXME
    425         break;
    426       case EGL_LARGEST_PBUFFER:
    427         UNIMPLEMENTED();   // FIXME
    428         break;
    429       case EGL_MIPMAP_TEXTURE:
    430         UNIMPLEMENTED();   // FIXME
    431         break;
    432       case EGL_MIPMAP_LEVEL:
    433         UNIMPLEMENTED();   // FIXME
    434         break;
    435       case EGL_MULTISAMPLE_RESOLVE:
    436         UNIMPLEMENTED();   // FIXME
    437         break;
    438       case EGL_PIXEL_ASPECT_RATIO:
    439         *value = eglSurface->getPixelAspectRatio();
    440         break;
    441       case EGL_RENDER_BUFFER:
    442         *value = eglSurface->getRenderBuffer();
    443         break;
    444       case EGL_SWAP_BEHAVIOR:
    445         *value = eglSurface->getSwapBehavior();
    446         break;
    447       case EGL_TEXTURE_FORMAT:
    448         *value = eglSurface->getTextureFormat();
    449         break;
    450       case EGL_TEXTURE_TARGET:
    451         *value = eglSurface->getTextureTarget();
    452         break;
    453       case EGL_VERTICAL_RESOLUTION:
    454         UNIMPLEMENTED();   // FIXME
    455         break;
    456       case EGL_WIDTH:
    457         *value = eglSurface->getWidth();
    458         break;
    459       case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
    460         *value = eglSurface->isPostSubBufferSupported();
    461         break;
    462       case EGL_FIXED_SIZE_ANGLE:
    463         *value = eglSurface->isFixedSize();
    464         break;
    465       default:
    466         return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    467     }
    468 
    469     return egl::success(EGL_TRUE);
    470 }
    471 
    472 EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
    473 {
    474     TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
    475           dpy, surface, attribute, value);
    476 
    477     egl::Display *display = static_cast<egl::Display*>(dpy);
    478     egl::Surface *eglSurface = (egl::Surface*)surface;
    479 
    480     if (!validateSurface(display, eglSurface))
    481     {
    482         return EGL_FALSE;
    483     }
    484 
    485     if (surface == EGL_NO_SURFACE)
    486     {
    487         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    488     }
    489 
    490     switch (attribute)
    491     {
    492       case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
    493         {
    494             rx::SwapChain *swapchain = eglSurface->getSwapChain();
    495             *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
    496         }
    497         break;
    498       default:
    499         return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
    500     }
    501 
    502     return egl::success(EGL_TRUE);
    503 }
    504 
    505 EGLBoolean __stdcall eglBindAPI(EGLenum api)
    506 {
    507     EVENT("(EGLenum api = 0x%X)", api);
    508 
    509     switch (api)
    510     {
    511       case EGL_OPENGL_API:
    512       case EGL_OPENVG_API:
    513         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
    514       case EGL_OPENGL_ES_API:
    515         break;
    516       default:
    517         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
    518     }
    519 
    520     egl::setCurrentAPI(api);
    521 
    522     return egl::success(EGL_TRUE);
    523 }
    524 
    525 EGLenum __stdcall eglQueryAPI(void)
    526 {
    527     EVENT("()");
    528 
    529     EGLenum API = egl::getCurrentAPI();
    530 
    531     return egl::success(API);
    532 }
    533 
    534 EGLBoolean __stdcall eglWaitClient(void)
    535 {
    536     EVENT("()");
    537 
    538     UNIMPLEMENTED();   // FIXME
    539 
    540     return egl::success(0);
    541 }
    542 
    543 EGLBoolean __stdcall eglReleaseThread(void)
    544 {
    545     EVENT("()");
    546 
    547     eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
    548 
    549     return egl::success(EGL_TRUE);
    550 }
    551 
    552 EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
    553 {
    554     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
    555           "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
    556           dpy, buftype, buffer, config, attrib_list);
    557 
    558     egl::Display *display = static_cast<egl::Display*>(dpy);
    559 
    560     if (!validateConfig(display, config))
    561     {
    562         return EGL_NO_SURFACE;
    563     }
    564 
    565     if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
    566     {
    567         return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
    568     }
    569 
    570     return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
    571 }
    572 
    573 EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
    574 {
    575     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
    576           dpy, surface, attribute, value);
    577 
    578     egl::Display *display = static_cast<egl::Display*>(dpy);
    579     egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
    580 
    581     if (!validateSurface(display, eglSurface))
    582     {
    583         return EGL_FALSE;
    584     }
    585 
    586     UNIMPLEMENTED();   // FIXME
    587 
    588     return egl::success(EGL_TRUE);
    589 }
    590 
    591 EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    592 {
    593     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
    594 
    595     egl::Display *display = static_cast<egl::Display*>(dpy);
    596     egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
    597 
    598     if (!validateSurface(display, eglSurface))
    599     {
    600         return EGL_FALSE;
    601     }
    602 
    603     if (buffer != EGL_BACK_BUFFER)
    604     {
    605         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
    606     }
    607 
    608     if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
    609     {
    610         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    611     }
    612 
    613     if (eglSurface->getBoundTexture())
    614     {
    615         return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
    616     }
    617 
    618     if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
    619     {
    620         return egl::error(EGL_BAD_MATCH, EGL_FALSE);
    621     }
    622 
    623     if (!glBindTexImage(eglSurface))
    624     {
    625         return egl::error(EGL_BAD_MATCH, EGL_FALSE);
    626     }
    627 
    628     return egl::success(EGL_TRUE);
    629 }
    630 
    631 EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
    632 {
    633     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
    634 
    635     egl::Display *display = static_cast<egl::Display*>(dpy);
    636     egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
    637 
    638     if (!validateSurface(display, eglSurface))
    639     {
    640         return EGL_FALSE;
    641     }
    642 
    643     if (buffer != EGL_BACK_BUFFER)
    644     {
    645         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
    646     }
    647 
    648     if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
    649     {
    650         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    651     }
    652 
    653     if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
    654     {
    655         return egl::error(EGL_BAD_MATCH, EGL_FALSE);
    656     }
    657 
    658     gl::Texture2D *texture = eglSurface->getBoundTexture();
    659 
    660     if (texture)
    661     {
    662         texture->releaseTexImage();
    663     }
    664 
    665     return egl::success(EGL_TRUE);
    666 }
    667 
    668 EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
    669 {
    670     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
    671 
    672     egl::Display *display = static_cast<egl::Display*>(dpy);
    673 
    674     if (!validateDisplay(display))
    675     {
    676         return EGL_FALSE;
    677     }
    678 
    679     egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
    680 
    681     if (draw_surface == NULL)
    682     {
    683         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    684     }
    685 
    686     draw_surface->setSwapInterval(interval);
    687 
    688     return egl::success(EGL_TRUE);
    689 }
    690 
    691 EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
    692 {
    693     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
    694           "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
    695 
    696     // Get the requested client version (default is 1) and check it is 2 or 3.
    697     EGLint client_version = 1;
    698     bool reset_notification = false;
    699     bool robust_access = false;
    700 
    701     if (attrib_list)
    702     {
    703         for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
    704         {
    705             switch (attribute[0])
    706             {
    707               case EGL_CONTEXT_CLIENT_VERSION:
    708                 client_version = attribute[1];
    709                 break;
    710               case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
    711                 if (attribute[1] == EGL_TRUE)
    712                 {
    713                     return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
    714                     // robust_access = true;
    715                 }
    716                 else if (attribute[1] != EGL_FALSE)
    717                     return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
    718                 break;
    719               case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
    720                 if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
    721                     reset_notification = true;
    722                 else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
    723                     return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
    724                 break;
    725               default:
    726                 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
    727             }
    728         }
    729     }
    730 
    731     if (client_version != 2 && client_version != 3)
    732     {
    733         return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
    734     }
    735 
    736     egl::Display *display = static_cast<egl::Display*>(dpy);
    737 
    738     if (share_context)
    739     {
    740         gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
    741 
    742         if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
    743         {
    744             return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
    745         }
    746 
    747         if (sharedGLContext->getClientVersion() != client_version)
    748         {
    749             return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
    750         }
    751 
    752         // Can not share contexts between displays
    753         if (sharedGLContext->getRenderer() != display->getRenderer())
    754         {
    755             return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
    756         }
    757     }
    758 
    759     if (!validateConfig(display, config))
    760     {
    761         return EGL_NO_CONTEXT;
    762     }
    763 
    764     return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
    765 }
    766 
    767 EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
    768 {
    769     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
    770 
    771     egl::Display *display = static_cast<egl::Display*>(dpy);
    772     gl::Context *context = static_cast<gl::Context*>(ctx);
    773 
    774     if (!validateContext(display, context))
    775     {
    776         return EGL_FALSE;
    777     }
    778 
    779     if (ctx == EGL_NO_CONTEXT)
    780     {
    781         return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
    782     }
    783 
    784     display->destroyContext(context);
    785 
    786     return egl::success(EGL_TRUE);
    787 }
    788 
    789 EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
    790 {
    791     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
    792           dpy, draw, read, ctx);
    793 
    794     egl::Display *display = static_cast<egl::Display*>(dpy);
    795     gl::Context *context = static_cast<gl::Context*>(ctx);
    796 
    797     bool noContext = (ctx == EGL_NO_CONTEXT);
    798     bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE);
    799     if (noContext != noSurface)
    800     {
    801         return egl::error(EGL_BAD_MATCH, EGL_FALSE);
    802     }
    803 
    804     if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
    805     {
    806         return EGL_FALSE;
    807     }
    808 
    809     if (dpy != EGL_NO_DISPLAY && display->isInitialized())
    810     {
    811         rx::Renderer *renderer = display->getRenderer();
    812         if (renderer->testDeviceLost(true))
    813         {
    814             return EGL_FALSE;
    815         }
    816 
    817         if (renderer->isDeviceLost())
    818         {
    819             return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
    820         }
    821     }
    822 
    823     if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
    824         (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
    825     {
    826         return EGL_FALSE;
    827     }
    828 
    829     if (draw != read)
    830     {
    831         UNIMPLEMENTED();   // FIXME
    832     }
    833 
    834     egl::setCurrentDisplay(dpy);
    835     egl::setCurrentDrawSurface(draw);
    836     egl::setCurrentReadSurface(read);
    837 
    838     glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
    839 
    840     return egl::success(EGL_TRUE);
    841 }
    842 
    843 EGLContext __stdcall eglGetCurrentContext(void)
    844 {
    845     EVENT("()");
    846 
    847     EGLContext context = glGetCurrentContext();
    848 
    849     return egl::success(context);
    850 }
    851 
    852 EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
    853 {
    854     EVENT("(EGLint readdraw = %d)", readdraw);
    855 
    856     if (readdraw == EGL_READ)
    857     {
    858         EGLSurface read = egl::getCurrentReadSurface();
    859         return egl::success(read);
    860     }
    861     else if (readdraw == EGL_DRAW)
    862     {
    863         EGLSurface draw = egl::getCurrentDrawSurface();
    864         return egl::success(draw);
    865     }
    866     else
    867     {
    868         return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
    869     }
    870 }
    871 
    872 EGLDisplay __stdcall eglGetCurrentDisplay(void)
    873 {
    874     EVENT("()");
    875 
    876     EGLDisplay dpy = egl::getCurrentDisplay();
    877 
    878     return egl::success(dpy);
    879 }
    880 
    881 EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
    882 {
    883     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
    884           dpy, ctx, attribute, value);
    885 
    886     egl::Display *display = static_cast<egl::Display*>(dpy);
    887     gl::Context *context = static_cast<gl::Context*>(ctx);
    888 
    889     if (!validateContext(display, context))
    890     {
    891         return EGL_FALSE;
    892     }
    893 
    894     UNIMPLEMENTED();   // FIXME
    895 
    896     return egl::success(0);
    897 }
    898 
    899 EGLBoolean __stdcall eglWaitGL(void)
    900 {
    901     EVENT("()");
    902 
    903     UNIMPLEMENTED();   // FIXME
    904 
    905     return egl::success(0);
    906 }
    907 
    908 EGLBoolean __stdcall eglWaitNative(EGLint engine)
    909 {
    910     EVENT("(EGLint engine = %d)", engine);
    911 
    912     UNIMPLEMENTED();   // FIXME
    913 
    914     return egl::success(0);
    915 }
    916 
    917 EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
    918 {
    919     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
    920 
    921     egl::Display *display = static_cast<egl::Display*>(dpy);
    922     egl::Surface *eglSurface = (egl::Surface*)surface;
    923 
    924     if (!validateSurface(display, eglSurface))
    925     {
    926         return EGL_FALSE;
    927     }
    928 
    929     if (display->getRenderer()->isDeviceLost())
    930     {
    931         return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
    932     }
    933 
    934     if (surface == EGL_NO_SURFACE)
    935     {
    936         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    937     }
    938 
    939     if (eglSurface->swap())
    940     {
    941         return egl::success(EGL_TRUE);
    942     }
    943 
    944     return EGL_FALSE;
    945 }
    946 
    947 EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
    948 {
    949     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
    950 
    951     egl::Display *display = static_cast<egl::Display*>(dpy);
    952     egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
    953 
    954     if (!validateSurface(display, eglSurface))
    955     {
    956         return EGL_FALSE;
    957     }
    958 
    959     if (display->getRenderer()->isDeviceLost())
    960     {
    961         return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
    962     }
    963 
    964     UNIMPLEMENTED();   // FIXME
    965 
    966     return egl::success(0);
    967 }
    968 
    969 EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
    970 {
    971     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
    972 
    973     if (x < 0 || y < 0 || width < 0 || height < 0)
    974     {
    975         return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
    976     }
    977 
    978     egl::Display *display = static_cast<egl::Display*>(dpy);
    979     egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
    980 
    981     if (!validateSurface(display, eglSurface))
    982     {
    983         return EGL_FALSE;
    984     }
    985 
    986     if (display->getRenderer()->isDeviceLost())
    987     {
    988         return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
    989     }
    990 
    991     if (surface == EGL_NO_SURFACE)
    992     {
    993         return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
    994     }
    995 
    996     if (eglSurface->postSubBuffer(x, y, width, height))
    997     {
    998         return egl::success(EGL_TRUE);
    999     }
   1000 
   1001     return EGL_FALSE;
   1002 }
   1003 
   1004 __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
   1005 {
   1006     EVENT("(const char *procname = \"%s\")", procname);
   1007 
   1008     struct Extension
   1009     {
   1010         const char *name;
   1011         __eglMustCastToProperFunctionPointerType address;
   1012     };
   1013 
   1014     static const Extension eglExtensions[] =
   1015     {
   1016         { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE },
   1017         { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV },
   1018         { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT },
   1019         { "", NULL },
   1020     };
   1021 
   1022     for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++)
   1023     {
   1024         if (strcmp(procname, eglExtensions[ext].name) == 0)
   1025         {
   1026             return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
   1027         }
   1028     }
   1029 
   1030     return glGetProcAddress(procname);
   1031 }
   1032 }
   1033