hostsupport/hostopenvg/src/src/riMiniEGL.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /*------------------------------------------------------------------------
       
     2  *
       
     3  * EGL 1.3
       
     4  * -------
       
     5  *
       
     6  * Copyright (c) 2007 The Khronos Group Inc.
       
     7  * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     8  *
       
     9  * Permission is hereby granted, free of charge, to any person obtaining a
       
    10  * copy of this software and /or associated documentation files
       
    11  * (the "Materials "), to deal in the Materials without restriction,
       
    12  * including without limitation the rights to use, copy, modify, merge,
       
    13  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
    14  * and to permit persons to whom the Materials are furnished to do so,
       
    15  * subject to the following conditions:
       
    16  *
       
    17  * The above copyright notice and this permission notice shall be included
       
    18  * in all copies or substantial portions of the Materials.
       
    19  *
       
    20  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    26  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    27  *
       
    28  *//**
       
    29  * \file
       
    30  * \brief	Simple implementation of EGL 1.3
       
    31  * \note	caveats:
       
    32             - always renders into the backbuffer and blits it to window (no single buffered rendering)
       
    33             - no native Windows or Mac OS X pixmap support
       
    34             - no power management events
       
    35             - no support for swap interval
       
    36  * \todo	what happens in egl functions when eglTerminate has been called but the context and surface are still in use?
       
    37  * \todo	OSDeinitMutex should be called in case getEGL fails.
       
    38  *//*-------------------------------------------------------------------*/
       
    39 
       
    40 #include "EGL/egl.h"
       
    41 #include "openvg.h"
       
    42 #include "riArray.h"
       
    43 #include "riMath.h"
       
    44 #include "riContext.h"
       
    45 #include "riImage.h"
       
    46 
       
    47 #include "riEGLOS.h"
       
    48 
       
    49 // Temp: A blitter is kept in the egl context for surface copies, but it will
       
    50 // be placed into the EGL to VG interface in the future.
       
    51 #ifndef __SFDYNAMICBLITTER_H
       
    52 #   include "sfDynamicBlitter.h"
       
    53 #endif
       
    54 
       
    55 
       
    56 //==============================================================================================
       
    57 
       
    58 namespace OpenVGRI
       
    59 {
       
    60 
       
    61 #if 0
       
    62 void* OSGetCurrentThreadID(void);
       
    63 void OSAcquireMutex(void);
       
    64 void OSReleaseMutex(void);
       
    65 void OSDeinitMutex(void);
       
    66 
       
    67 EGLDisplay OSGetDisplay(EGLNativeDisplayType display_id);
       
    68 void* OSCreateWindowContext(EGLNativeWindowType window);
       
    69 void OSDestroyWindowContext(void* context);
       
    70 bool OSIsWindow(const void* context);
       
    71 void OSGetWindowSize(const void* context, int& width, int& height);
       
    72 void OSBlitToWindow(void* context, const Drawable* drawable);
       
    73 #else
       
    74 
       
    75 
       
    76 #endif
       
    77 
       
    78 /*-------------------------------------------------------------------*//*!
       
    79 * \brief
       
    80 * \param
       
    81 * \return
       
    82 * \note
       
    83 *//*-------------------------------------------------------------------*/
       
    84 
       
    85 class RIEGLConfig
       
    86 {
       
    87 public:
       
    88     RIEGLConfig() : m_desc(Color::formatToDescriptor(VG_sRGBA_8888)), m_configID(0)	{}
       
    89     ~RIEGLConfig()							{}
       
    90     void		set(int r, int g, int b, int a, int l, int bpp, int samples, int maskBits, int ID)
       
    91     {
       
    92         Color::Shape shape;
       
    93         m_desc.redBits = r;
       
    94         m_desc.greenBits = g;
       
    95         m_desc.blueBits = b;
       
    96         m_desc.alphaBits = a;
       
    97         m_desc.luminanceBits = l;
       
    98 #if !defined(_WIN32) && 0
       
    99         m_desc.alphaShift = 0;
       
   100         m_desc.luminanceShift = 0;
       
   101         m_desc.blueShift = b ? a : 0;
       
   102         m_desc.greenShift = g ? a + b : 0;
       
   103         m_desc.redShift = r ? a + b + g : 0;
       
   104 #else
       
   105         m_desc.luminanceShift = 0;
       
   106         m_desc.redShift = 0;
       
   107         m_desc.greenShift = g ? r : 0;
       
   108         m_desc.blueShift = b ? r + g : 0;
       
   109         m_desc.alphaShift = a ? r + g + b : 0;
       
   110 
       
   111 #endif
       
   112         m_desc.internalFormat = l ? (a ? Color::sLA : Color::lLA) : ((r || g || b ) ? Color::sRGBA : Color::lRGBA);
       
   113 
       
   114         m_desc.bitsPerPixel = bpp;
       
   115         m_desc.bytesPerPixel = bpp / 8;
       
   116 
       
   117         {
       
   118             // Determine shape
       
   119             if (m_desc.hasAlpha())
       
   120             {
       
   121                 if (m_desc.redBits > 0)
       
   122                     shape = Color::SHAPE_ARGB;
       
   123                 else if (m_desc.isLuminance())
       
   124                     shape = Color::SHAPE_AL;
       
   125                 else
       
   126                 {
       
   127                     RI_ASSERT(m_desc.isAlphaOnly());
       
   128                     shape = Color::SHAPE_A;
       
   129                 }
       
   130             } else
       
   131             {
       
   132                 if (m_desc.redBits > 0)
       
   133                 {
       
   134                     if (m_desc.bitsPerPixel == 32)
       
   135                         shape = Color::SHAPE_XRGB;
       
   136                     else
       
   137                     {
       
   138                         RI_ASSERT(m_desc.bitsPerPixel == 24 || m_desc.bitsPerPixel == 16);
       
   139                         shape = Color::SHAPE_RGB;
       
   140                     }
       
   141                 } else if (m_desc.isLuminance())
       
   142                 {
       
   143                     shape = Color::SHAPE_L;
       
   144                 } else
       
   145                 {
       
   146                     RI_ASSERT(false);
       
   147                 }
       
   148             }
       
   149         }
       
   150 
       
   151         m_desc.shape = shape;
       
   152         //m_desc.format = Color::descriptorToVGImageFormat(m_desc);
       
   153         m_desc.vgFormat = (VGImageFormat)-1;
       
   154         RI_ASSERT(Color::isValidDescriptor(m_desc));
       
   155         m_samples = samples;
       
   156         m_maskBits = maskBits;
       
   157         m_configID = ID;
       
   158         m_config = (EGLConfig)ID;
       
   159     }
       
   160 
       
   161     Color::Descriptor configToDescriptor(bool sRGB, bool premultiplied) const
       
   162     {
       
   163         Color::Descriptor desc = m_desc;
       
   164         unsigned int f = m_desc.luminanceBits ? Color::LUMINANCE : 0;
       
   165         f |= sRGB ? Color::NONLINEAR : 0;
       
   166         f |= premultiplied ? Color::PREMULTIPLIED : 0;
       
   167         desc.internalFormat = (Color::InternalFormat)f;
       
   168         return desc;
       
   169     }
       
   170 
       
   171     //EGL RED SIZE bits of Red in the color buffer
       
   172     //EGL GREEN SIZE bits of Green in the color buffer
       
   173     //EGL BLUE SIZE bits of Blue in the color buffer
       
   174     //EGL ALPHA SIZE bits of Alpha in the color buffer
       
   175     //EGL LUMINANCE SIZE bits of Luminance in the color buffer
       
   176     Color::Descriptor	m_desc;
       
   177     int					m_samples;
       
   178     int                 m_maskBits;
       
   179     EGLint				m_configID;			//EGL CONFIG ID unique EGLConfig identifier
       
   180     EGLConfig           m_config;
       
   181     //EGL BUFFER SIZE depth of the color buffer (sum of channel bits)
       
   182     //EGL ALPHA MASK SIZE number alpha mask bits (always 8)
       
   183     //EGL BIND TO TEXTURE RGB boolean True if bindable to RGB textures. (always EGL_FALSE)
       
   184     //EGL BIND TO TEXTURE RGBA boolean True if bindable to RGBA textures. (always EGL_FALSE)
       
   185     //EGL COLOR BUFFER TYPE enum color buffer type (EGL_RGB_BUFFER, EGL_LUMINANCE_BUFFER)
       
   186     //EGL CONFIG CAVEAT enum any caveats for the configuration (always EGL_NONE)
       
   187     //EGL DEPTH SIZE integer bits of Z in the depth buffer (always 0)
       
   188     //EGL LEVEL integer frame buffer level (always 0)
       
   189     //EGL MAX PBUFFER WIDTH integer maximum width of pbuffer (always INT_MAX)
       
   190     //EGL MAX PBUFFER HEIGHT integer maximum height of pbuffer (always INT_MAX)
       
   191     //EGL MAX PBUFFER PIXELS integer maximum size of pbuffer (always INT_MAX)
       
   192     //EGL MAX SWAP INTERVAL integer maximum swap interval (always 1)
       
   193     //EGL MIN SWAP INTERVAL integer minimum swap interval (always 1)
       
   194     //EGL NATIVE RENDERABLE boolean EGL TRUE if native rendering APIs can render to surface (always EGL_FALSE)
       
   195     //EGL NATIVE VISUAL ID integer handle of corresponding native visual (always 0)
       
   196     //EGL NATIVE VISUAL TYPE integer native visual type of the associated visual (always EGL_NONE)
       
   197     //EGL RENDERABLE TYPE bitmask which client rendering APIs are supported. (always EGL_OPENVG_BIT)
       
   198     //EGL SAMPLE BUFFERS integer number of multisample buffers (always 0)
       
   199     //EGL SAMPLES integer number of samples per pixel (always 0)
       
   200     //EGL STENCIL SIZE integer bits of Stencil in the stencil buffer (always 0)
       
   201     //EGL SURFACE TYPE bitmask which types of EGL surfaces are supported. (always EGL WINDOW BIT | EGL PIXMAP BIT | EGL PBUFFER BIT)
       
   202     //EGL TRANSPARENT TYPE enum type of transparency supported (always EGL_NONE)
       
   203     //EGL TRANSPARENT RED VALUE integer transparent red value (undefined)
       
   204     //EGL TRANSPARENT GREEN VALUE integer transparent green value (undefined)
       
   205     //EGL TRANSPARENT BLUE VALUE integer transparent blue value (undefined)
       
   206 };
       
   207 
       
   208 /*-------------------------------------------------------------------*//*!
       
   209 * \brief
       
   210 * \param
       
   211 * \return
       
   212 * \note
       
   213 *//*-------------------------------------------------------------------*/
       
   214 
       
   215 class RIEGLContext
       
   216 {
       
   217 public:
       
   218     RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config);
       
   219     ~RIEGLContext();
       
   220     void	addReference()				{ m_referenceCount++; }
       
   221     int		removeReference()			{ m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; }
       
   222 
       
   223     VGContext*      getVGContext() const      { return m_vgContext; }
       
   224     EGLConfig       getConfig() const         { return m_config; }
       
   225     DynamicBlitter& getBlitter()              { return m_blitter; }
       
   226 private:
       
   227     RIEGLContext(const RIEGLContext&);
       
   228     RIEGLContext& operator=(const RIEGLContext&);
       
   229     VGContext*		m_vgContext;
       
   230     const EGLConfig	m_config;
       
   231     int				m_referenceCount;
       
   232     DynamicBlitter  m_blitter;
       
   233 };
       
   234 
       
   235 RIEGLContext::RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config) :
       
   236     m_vgContext(vgctx),
       
   237     m_config(config),
       
   238     m_referenceCount(0)
       
   239 {
       
   240 }
       
   241 RIEGLContext::~RIEGLContext()
       
   242 {
       
   243     RI_ASSERT(m_referenceCount == 0);
       
   244     RI_DELETE(m_vgContext);
       
   245 }
       
   246 
       
   247 /*-------------------------------------------------------------------*//*!
       
   248 * \brief
       
   249 * \param
       
   250 * \return
       
   251 * \note
       
   252 *//*-------------------------------------------------------------------*/
       
   253 
       
   254 class RIEGLSurface
       
   255 {
       
   256 public:
       
   257     RIEGLSurface(void* OSWindowContext, const EGLConfig config, Drawable* drawable, bool largestPbuffer, int renderBuffer);
       
   258     ~RIEGLSurface();
       
   259     void	addReference()				{ m_referenceCount++; }
       
   260     int		removeReference()			{ m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; }
       
   261 
       
   262     void*           getOSWindowContext() const { return m_OSWindowContext; }
       
   263     EGLConfig       getConfig() const          { return m_config; }
       
   264     Drawable*       getDrawable() const        { return m_drawable; }
       
   265     bool            isLargestPbuffer() const   { return m_largestPbuffer; }
       
   266     int             getRenderBuffer() const    { return m_renderBuffer; }
       
   267 
       
   268 private:
       
   269     RIEGLSurface(const RIEGLSurface&);
       
   270     RIEGLSurface& operator=(const RIEGLSurface&);
       
   271     void*            m_OSWindowContext;
       
   272     const EGLConfig	 m_config;
       
   273     Drawable*        m_drawable;
       
   274     bool			 m_largestPbuffer;
       
   275     int				 m_renderBuffer;		//EGL_BACK_BUFFER or EGL_SINGLE_BUFFER
       
   276     int				 m_referenceCount;
       
   277 };
       
   278 
       
   279 RIEGLSurface::RIEGLSurface(void* OSWindowContext, const EGLConfig config, Drawable* drawable, bool largestPbuffer, int renderBuffer) :
       
   280     m_OSWindowContext(OSWindowContext),
       
   281     m_config(config),
       
   282     m_drawable(drawable),
       
   283     m_largestPbuffer(largestPbuffer),
       
   284     m_renderBuffer(renderBuffer),
       
   285     m_referenceCount(0)
       
   286 {
       
   287     RI_ASSERT(m_renderBuffer == EGL_BACK_BUFFER);   //only back buffer rendering is supported
       
   288     m_drawable->addReference();
       
   289 }
       
   290 
       
   291 RIEGLSurface::~RIEGLSurface()
       
   292 {
       
   293     RI_ASSERT(m_referenceCount == 0);
       
   294     OSDestroyWindowContext((OSWindowContext*)m_OSWindowContext);
       
   295     if(m_drawable)
       
   296     {
       
   297         if(!m_drawable->removeReference())
       
   298             RI_DELETE(m_drawable);
       
   299     }
       
   300 }
       
   301 
       
   302 /*-------------------------------------------------------------------*//*!
       
   303 * \brief
       
   304 * \param
       
   305 * \return
       
   306 * \note
       
   307 *//*-------------------------------------------------------------------*/
       
   308 
       
   309 #define EGL_NUMCONFIGS		5
       
   310 
       
   311 class RIEGLDisplay
       
   312 {
       
   313 public:
       
   314     RIEGLDisplay(EGLDisplay id);
       
   315     ~RIEGLDisplay();
       
   316 
       
   317     int                getNumConfigs() const              { return EGL_NUMCONFIGS; }
       
   318     const RIEGLConfig& getConfig(int i) const             { RI_ASSERT(i >= 0 && i < EGL_NUMCONFIGS); return m_configs[i]; }
       
   319     const RIEGLConfig& getConfig(const EGLConfig config) const        { for(int i=0;i<EGL_NUMCONFIGS;i++) { if(m_configs[i].m_config == config) return m_configs[i]; } RI_ASSERT(0); return m_configs[0]; }
       
   320 
       
   321     EGLDisplay         getID() const                       { return m_id; }
       
   322 
       
   323     void              addContext(RIEGLContext* ctx)       { RI_ASSERT(ctx); m_contexts.push_back(ctx); }  //throws bad_alloc
       
   324     void              removeContext(RIEGLContext* ctx)    { RI_ASSERT(ctx); bool res = m_contexts.remove(ctx); RI_ASSERT(res); RI_UNREF(res); }
       
   325 
       
   326     void              addSurface(RIEGLSurface* srf)       { RI_ASSERT(srf); m_surfaces.push_back(srf); }  //throws bad_alloc
       
   327     void              removeSurface(RIEGLSurface* srf)    { RI_ASSERT(srf); bool res = m_surfaces.remove(srf); RI_ASSERT(res); RI_UNREF(res); }
       
   328 
       
   329     EGLBoolean        contextExists(const EGLContext ctx) const;
       
   330     EGLBoolean        surfaceExists(const EGLSurface srf) const;
       
   331     EGLBoolean        configExists(const EGLConfig cfg) const;
       
   332 
       
   333 private:
       
   334     RIEGLDisplay(const RIEGLDisplay& t);
       
   335     RIEGLDisplay& operator=(const RIEGLDisplay&t);
       
   336 
       
   337     EGLDisplay              m_id;
       
   338 
       
   339     Array<RIEGLContext*>	m_contexts;
       
   340     Array<RIEGLSurface*>	m_surfaces;
       
   341 
       
   342     RIEGLConfig             m_configs[EGL_NUMCONFIGS];
       
   343 };
       
   344 
       
   345 RIEGLDisplay::RIEGLDisplay(EGLDisplay id) :
       
   346     m_id(id),
       
   347     m_contexts(),
       
   348     m_surfaces()
       
   349 {
       
   350 
       
   351     //sorted by RGB/LUMINANCE (exact), larger total number of color bits (at least), buffer size (at least), config ID (exact)
       
   352     //NOTE: 16 bit configs need to be sorted on the fly if the request ignores some channels
       
   353     //NOTE: config IDs start from 1
       
   354     //                 R  B  G  A  L  bpp samples maskBits ID
       
   355     int i = 0;
       
   356     m_configs[i].set(8, 8, 8, 8, 0, 32, 1, 8, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 32
       
   357     m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 8, i+1); i++;    // RGBX
       
   358     m_configs[i].set(5, 6, 5, 0, 0, 16, 1, 8, i+1); i++;	// 565
       
   359     m_configs[i].set(0, 0, 0, 0, 8, 8,  1, 8, i+1); i++;	// L8
       
   360     m_configs[i].set(0, 0, 0, 8, 0, 8,  1, 8, i+1); i++;	// A8
       
   361     // \note The reference implementation does not support LA16 config, so it is currently
       
   362     // not possible to test it. See if the format fits the specification.
       
   363     //m_configs[i].set(0, 0, 0, 8, 8, 16,  1, 8, i+1); i++;	// LA16
       
   364 #if 0
       
   365     m_configs[i].set(8, 8, 8, 8, 0, 32, 1, 8, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 32
       
   366     m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 8, i+1); i++;    // RGBX
       
   367     m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 8, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 24
       
   368     //m_configs[i].set(5, 5, 5, 1, 0, 16, 1, 4, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 16
       
   369     m_configs[i].set(5, 6, 5, 0, 0, 16, 1, 4, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 16
       
   370     //m_configs[i].set(4, 4, 4, 4, 0, 16, 1, 4, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 16
       
   371     m_configs[i].set(0, 0, 0, 8, 0, 8,  1, 8, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 8
       
   372     m_configs[i].set(0, 0, 0, 4, 0, 4,  1, 4, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 8
       
   373     m_configs[i].set(0, 0, 0, 1, 0, 1,  1, 1, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 8
       
   374     m_configs[i].set(0, 0, 0, 0, 8, 8,  1, 8, i+1); i++;	//EGL_LUMINANCE_BUFFER, buffer size = 8
       
   375     //m_configs[i].set(0, 0, 0, 0, 1, 1,  1, 1, i+1); i++;	//EGL_LUMINANCE_BUFFER, buffer size = 1
       
   376 
       
   377     //configs without mask
       
   378     m_configs[i].set(8, 8, 8, 8, 0, 32, 1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 32
       
   379     m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 24
       
   380     //m_configs[i].set(5, 5, 5, 1, 0, 16, 1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 16
       
   381     m_configs[i].set(5, 6, 5, 0, 0, 16, 1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 16
       
   382     //m_configs[i].set(4, 4, 4, 4, 0, 16, 1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 16
       
   383     m_configs[i].set(0, 0, 0, 8, 0, 8,  1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 8
       
   384     m_configs[i].set(0, 0, 0, 4, 0, 4,  1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 8
       
   385     m_configs[i].set(0, 0, 0, 1, 0, 1,  1, 0, i+1); i++;	//EGL_RGB_BUFFER, buffer size = 8
       
   386     m_configs[i].set(0, 0, 0, 0, 8, 8,  1, 0, i+1); i++;	//EGL_LUMINANCE_BUFFER, buffer size = 8
       
   387     //m_configs[i].set(0, 0, 0, 0, 1, 1,  1, 0, 20);	//EGL_LUMINANCE_BUFFER, buffer size = 1
       
   388 #endif
       
   389 
       
   390     RI_ASSERT(EGL_NUMCONFIGS == i);
       
   391 
       
   392 /*
       
   393 attrib                default        criteria order   priority
       
   394 --------------------------------------------------------------
       
   395 EGL_COLOR_BUFFER_TYPE EGL_RGB_BUFFER Exact    None    2
       
   396 EGL_RED_SIZE          0              AtLeast  Special 3
       
   397 EGL_GREEN_SIZE        0              AtLeast  Special 3
       
   398 EGL_BLUE_SIZE         0              AtLeast  Special 3
       
   399 EGL_LUMINANCE_SIZE    0              AtLeast  Special 3
       
   400 EGL_ALPHA_SIZE        0              AtLeast  Special 3
       
   401 EGL_BUFFER_SIZE       0              AtLeast  Smaller 4
       
   402 EGL_ALPHA_MASK_SIZE   0              AtLeast  Smaller 9
       
   403 EGL_CONFIG_ID         EGL_DONT_CARE  Exact    Smaller 11
       
   404 */
       
   405 }
       
   406 
       
   407 RIEGLDisplay::~RIEGLDisplay()
       
   408 {
       
   409     //mark everything for deletion, but don't delete the current context and surface
       
   410     for(int i=0;i<m_contexts.size();i++)
       
   411     {
       
   412         if(!m_contexts[i]->removeReference())
       
   413             RI_DELETE(m_contexts[i]);
       
   414     }
       
   415     m_contexts.clear();	//remove all contexts from the list (makes further references to the current contexts invalid)
       
   416 
       
   417     for(int i=0;i<m_surfaces.size();i++)
       
   418     {
       
   419         if(!m_surfaces[i]->removeReference())
       
   420             RI_DELETE(m_surfaces[i]);
       
   421     }
       
   422     m_surfaces.clear();	//remove all surfaces from the list (makes further references to the current surfaces invalid)
       
   423 }
       
   424 
       
   425 EGLBoolean RIEGLDisplay::contextExists(const EGLContext ctx) const
       
   426 {
       
   427     for(int i=0;i<m_contexts.size();i++)
       
   428     {
       
   429         if(m_contexts[i] == ctx)
       
   430             return EGL_TRUE;
       
   431     }
       
   432     return EGL_FALSE;
       
   433 }
       
   434 
       
   435 EGLBoolean RIEGLDisplay::surfaceExists(const EGLSurface surf) const
       
   436 {
       
   437     for(int i=0;i<m_surfaces.size();i++)
       
   438     {
       
   439         if(m_surfaces[i] == surf)
       
   440             return EGL_TRUE;
       
   441     }
       
   442     return EGL_FALSE;
       
   443 }
       
   444 
       
   445 EGLBoolean RIEGLDisplay::configExists(const EGLConfig config) const
       
   446 {
       
   447     for(int i=0;i<EGL_NUMCONFIGS;i++)
       
   448     {
       
   449         if(m_configs[i].m_config == config)
       
   450         return EGL_TRUE;
       
   451     }
       
   452     return EGL_FALSE;
       
   453 }
       
   454 
       
   455 /*-------------------------------------------------------------------*//*!
       
   456 * \brief
       
   457 * \param
       
   458 * \return
       
   459 * \note
       
   460 *//*-------------------------------------------------------------------*/
       
   461 
       
   462 class RIEGLThread
       
   463 {
       
   464 public:
       
   465     RIEGLThread(void* currentThreadID);
       
   466     ~RIEGLThread();
       
   467 
       
   468     void*           getThreadID() const       { return m_threadID; }
       
   469 
       
   470     void            makeCurrent(RIEGLContext* c, RIEGLSurface* s)       { m_context = c; m_surface = s; }
       
   471     RIEGLContext*	getCurrentContext() const   { return m_context; }
       
   472     RIEGLSurface*	getCurrentSurface() const   { return m_surface; }
       
   473 
       
   474     void            setError(EGLint error)      { m_error = error; }
       
   475     EGLint          getError() const            { return m_error; }
       
   476 
       
   477     void            bindAPI(EGLint api)         { m_boundAPI = api; }
       
   478     EGLint          getBoundAPI() const         { return m_boundAPI; }
       
   479 
       
   480 private:
       
   481     RIEGLThread(const RIEGLThread&);
       
   482     RIEGLThread operator=(const RIEGLThread&);
       
   483 
       
   484     RIEGLContext*		m_context;
       
   485     RIEGLSurface*		m_surface;
       
   486     EGLint              m_error;
       
   487     void*               m_threadID;
       
   488     EGLint              m_boundAPI;
       
   489 };
       
   490 
       
   491 RIEGLThread::RIEGLThread(void* currentThreadID) :
       
   492     m_context(NULL),
       
   493     m_surface(NULL),
       
   494     m_error(EGL_SUCCESS),
       
   495     m_threadID(currentThreadID),
       
   496     m_boundAPI(EGL_NONE)
       
   497 {
       
   498 }
       
   499 
       
   500 RIEGLThread::~RIEGLThread()
       
   501 {
       
   502 }
       
   503 
       
   504 /*-------------------------------------------------------------------*//*!
       
   505 * \brief
       
   506 * \param
       
   507 * \return
       
   508 * \note
       
   509 *//*-------------------------------------------------------------------*/
       
   510 
       
   511 class EGL
       
   512 {
       
   513 public:
       
   514     EGL();
       
   515     ~EGL();
       
   516 
       
   517     void	addReference()				{ m_referenceCount++; }
       
   518     int		removeReference()			{ m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; }
       
   519 
       
   520     void                addDisplay(RIEGLDisplay* display)           { RI_ASSERT(display); m_displays.push_back(display); }  //throws bad alloc
       
   521     void                removeDisplay(RIEGLDisplay* display)        { RI_ASSERT(display); bool res = m_displays.remove(display); RI_ASSERT(res); RI_UNREF(res); }
       
   522     RIEGLDisplay*       getDisplay(const EGLDisplay displayID) const;
       
   523     EGLDisplay          findDisplay(const EGLContext ctx) const;
       
   524 
       
   525     void                addCurrentThread(RIEGLThread* thread)       { RI_ASSERT(thread); m_currentThreads.push_back(thread); }  //throws bad alloc
       
   526     void                removeCurrentThread(RIEGLThread* thread)    { RI_ASSERT(thread); bool res = m_currentThreads.remove(thread); RI_ASSERT(res); RI_UNREF(res); }
       
   527     RIEGLThread*        getCurrentThread() const;
       
   528 
       
   529     RIEGLThread*        getThread();
       
   530     void                destroyThread();
       
   531 
       
   532     bool                isInUse(const void* image) const;
       
   533 
       
   534 private:
       
   535     EGL(const EGL&);						// Not allowed.
       
   536     const EGL& operator=(const EGL&);		// Not allowed.
       
   537 
       
   538     Array<RIEGLThread*>		m_threads;			//threads that have called EGL
       
   539     Array<RIEGLThread*>		m_currentThreads;	//threads that have a bound context
       
   540     Array<RIEGLDisplay*>	m_displays;
       
   541 
       
   542     int                     m_referenceCount;
       
   543 };
       
   544 
       
   545 EGL::EGL() :
       
   546     m_threads(),
       
   547     m_currentThreads(),
       
   548     m_displays(),
       
   549     m_referenceCount(0)
       
   550 {
       
   551 }
       
   552 EGL::~EGL()
       
   553 {
       
   554     for(int i=0;i<m_displays.size();i++)
       
   555     {
       
   556         RI_DELETE(m_displays[i]);
       
   557     }
       
   558     for(int i=0;i<m_threads.size();i++)
       
   559     {
       
   560         RI_DELETE(m_threads[i]);
       
   561     }
       
   562     //currentThreads contain just pointers to threads we just deleted
       
   563 }
       
   564 
       
   565 /*-------------------------------------------------------------------*//*!
       
   566 * \brief
       
   567 * \param
       
   568 * \return
       
   569 * \note
       
   570 *//*-------------------------------------------------------------------*/
       
   571 
       
   572 static EGL* g_egl = NULL;	//never use this directly
       
   573 static EGL* getEGL()
       
   574 {
       
   575     if(!g_egl)
       
   576     {
       
   577         try
       
   578         {
       
   579             g_egl = RI_NEW(EGL, ());				//throws bad_alloc
       
   580             g_egl->addReference();
       
   581         }
       
   582         catch(std::bad_alloc)
       
   583         {
       
   584             g_egl = NULL;
       
   585         }
       
   586     }
       
   587     return g_egl;
       
   588 }
       
   589 static void releaseEGL()
       
   590 {
       
   591     if(g_egl)
       
   592     {
       
   593         if(!g_egl->removeReference())
       
   594         {
       
   595             RI_DELETE(g_egl);
       
   596             g_egl = NULL;
       
   597         }
       
   598     }
       
   599 }
       
   600 
       
   601 /*-------------------------------------------------------------------*//*!
       
   602 * \brief	Given a display ID, return the corresponding object, or NULL
       
   603 *			if the ID hasn't been initialized.
       
   604 * \param
       
   605 * \return
       
   606 * \note		if egl has been initialized for this display, the display ID can
       
   607 *			be found from egl->m_displays
       
   608 *//*-------------------------------------------------------------------*/
       
   609 
       
   610 RIEGLDisplay* EGL::getDisplay(EGLDisplay displayID) const
       
   611 {
       
   612     for(int i=0;i<m_displays.size();i++)
       
   613     {
       
   614         if(displayID == m_displays[i]->getID())
       
   615             return m_displays[i];
       
   616     }
       
   617     return NULL;		//error: the display hasn't been eglInitialized
       
   618 }
       
   619 
       
   620 /*-------------------------------------------------------------------*//*!
       
   621 * \brief	return EGLDisplay for the current context
       
   622 * \param
       
   623 * \return
       
   624 * \note
       
   625 *//*-------------------------------------------------------------------*/
       
   626 
       
   627 EGLDisplay EGL::findDisplay(EGLContext ctx) const
       
   628 {
       
   629     for(int i=0;i<m_displays.size();i++)
       
   630     {
       
   631         if(m_displays[i]->contextExists(ctx))
       
   632             return m_displays[i]->getID();
       
   633     }
       
   634     return EGL_NO_DISPLAY;
       
   635 }
       
   636 
       
   637 /*-------------------------------------------------------------------*//*!
       
   638 * \brief	return an EGL thread struct for the thread made current, or
       
   639 *            NULL if there's no current context.
       
   640 * \param
       
   641 * \return
       
   642 * \note
       
   643 *//*-------------------------------------------------------------------*/
       
   644 
       
   645 RIEGLThread* EGL::getCurrentThread() const
       
   646 {
       
   647     void* currentThreadID = OSGetCurrentThreadID();
       
   648     for(int i=0;i<m_currentThreads.size();i++)
       
   649     {
       
   650         if(currentThreadID == m_currentThreads[i]->getThreadID())
       
   651             return m_currentThreads[i];
       
   652     }
       
   653     return NULL;		//thread is not current
       
   654 }
       
   655 
       
   656 /*-------------------------------------------------------------------*//*!
       
   657 * \brief	return an EGL thread struct corresponding to current OS thread.
       
   658 * \param
       
   659 * \return
       
   660 * \note
       
   661 *//*-------------------------------------------------------------------*/
       
   662 
       
   663 RIEGLThread* EGL::getThread()
       
   664 {
       
   665     void* currentThreadID = OSGetCurrentThreadID();
       
   666     for(int i=0;i<m_threads.size();i++)
       
   667     {
       
   668         if(currentThreadID == m_threads[i]->getThreadID())
       
   669             return m_threads[i];
       
   670     }
       
   671 
       
   672     //EGL doesn't have a struct for the thread yet, add it to EGL's list
       
   673     RIEGLThread* newThread = NULL;
       
   674     try
       
   675     {
       
   676         newThread = RI_NEW(RIEGLThread, (OSGetCurrentThreadID()));	//throws bad_alloc
       
   677         m_threads.push_back(newThread);	//throws bad_alloc
       
   678         return newThread;
       
   679     }
       
   680     catch(std::bad_alloc)
       
   681     {
       
   682         RI_DELETE(newThread);
       
   683         return NULL;
       
   684     }
       
   685 }
       
   686 
       
   687 /*-------------------------------------------------------------------*//*!
       
   688 * \brief	destroy an EGL thread struct
       
   689 * \param
       
   690 * \return
       
   691 * \note
       
   692 *//*-------------------------------------------------------------------*/
       
   693 
       
   694 void EGL::destroyThread()
       
   695 {
       
   696     void* currentThreadID = OSGetCurrentThreadID();
       
   697     for(int i=0;i<m_threads.size();i++)
       
   698     {
       
   699         if(currentThreadID == m_threads[i]->getThreadID())
       
   700         {
       
   701             RIEGLThread* thread = m_threads[i];
       
   702             bool res = m_threads.remove(thread);
       
   703             RI_ASSERT(res);
       
   704             RI_UNREF(res);
       
   705             RI_DELETE(thread);
       
   706             break;
       
   707         }
       
   708     }
       
   709 }
       
   710 
       
   711 /*-------------------------------------------------------------------*//*!
       
   712 * \brief
       
   713 * \param
       
   714 * \return
       
   715 * \note
       
   716 *//*-------------------------------------------------------------------*/
       
   717 
       
   718 bool EGL::isInUse(const void* image) const
       
   719 {
       
   720     for(int i=0;i<m_currentThreads.size();i++)
       
   721     {
       
   722         RIEGLSurface* s = m_currentThreads[i]->getCurrentSurface();
       
   723         if(s && s->getDrawable() && s->getDrawable()->isInUse((Image*)image))
       
   724             return true;
       
   725     }
       
   726     return false;
       
   727 }
       
   728 
       
   729 /*-------------------------------------------------------------------*//*!
       
   730 * \brief
       
   731 * \param
       
   732 * \return
       
   733 * \note
       
   734 *//*-------------------------------------------------------------------*/
       
   735 
       
   736 #define EGL_GET_DISPLAY(DISPLAY, RETVAL) \
       
   737     OSAcquireMutex(); \
       
   738     EGL* egl = getEGL(); \
       
   739     if(!egl) \
       
   740     { \
       
   741         OSReleaseMutex(); \
       
   742         return RETVAL; \
       
   743     } \
       
   744     RIEGLDisplay* display = egl->getDisplay(DISPLAY); \
       
   745 
       
   746 #define EGL_GET_EGL(RETVAL) \
       
   747     OSAcquireMutex(); \
       
   748     EGL* egl = getEGL(); \
       
   749     if(!egl) \
       
   750     { \
       
   751         OSReleaseMutex(); \
       
   752         return RETVAL; \
       
   753     } \
       
   754 
       
   755 #define EGL_IF_ERROR(COND, ERRORCODE, RETVAL) \
       
   756     if(COND) { eglSetError(egl, ERRORCODE); OSReleaseMutex(); return RETVAL; } \
       
   757 
       
   758 #define EGL_RETURN(ERRORCODE, RETVAL) \
       
   759     { \
       
   760         eglSetError(egl, ERRORCODE); \
       
   761         OSReleaseMutex(); \
       
   762         return RETVAL; \
       
   763     }
       
   764 
       
   765 // Note: egl error handling model differs from OpenVG. The latest error is stored instead of the oldest one.
       
   766 static void eglSetError(EGL* egl, EGLint error)
       
   767 {
       
   768     RIEGLThread* thread = egl->getThread();
       
   769     if(thread)
       
   770         thread->setError(error);
       
   771 }
       
   772 
       
   773 /*-------------------------------------------------------------------*//*!
       
   774 * \brief	Returns the OpenVG context current to the calling thread.
       
   775 * \param
       
   776 * \return
       
   777 * \note		This function is always called from a mutexed API function
       
   778 *//*-------------------------------------------------------------------*/
       
   779 
       
   780 void* eglvgGetCurrentVGContext(void)
       
   781 {
       
   782     EGL* egl = getEGL();
       
   783     if(egl)
       
   784     {
       
   785         RIEGLThread* thread = egl->getCurrentThread();
       
   786         if(thread)
       
   787         {
       
   788             RI_ASSERT(thread->getCurrentContext() && thread->getCurrentSurface());
       
   789             return thread->getCurrentContext()->getVGContext();
       
   790         }
       
   791     }
       
   792     return NULL;	//not initialized or made current
       
   793 }
       
   794 
       
   795 bool  eglvgLockSurface(bool read, bool write)
       
   796 {
       
   797     (void)read;
       
   798     (void)write;
       
   799     return true;
       
   800 }
       
   801 
       
   802 bool  eglvgUnlockSurface()
       
   803 {
       
   804     return true;
       
   805 }
       
   806 
       
   807 /*-------------------------------------------------------------------*//*!
       
   808 * \brief	Check if the image is current in any of the displays
       
   809 * \param
       
   810 * \return
       
   811 * \note		This function is always called from a mutexed API function
       
   812 *//*-------------------------------------------------------------------*/
       
   813 
       
   814 bool eglvgIsInUse(void* image)
       
   815 {
       
   816     EGL* egl = getEGL();
       
   817     if(egl)
       
   818     {
       
   819         return egl->isInUse(image);
       
   820     }
       
   821     return false;
       
   822 }
       
   823 
       
   824 //==============================================================================================
       
   825 
       
   826 }	//namespace OpenVGRI
       
   827 
       
   828 using namespace OpenVGRI;
       
   829 
       
   830 
       
   831 
       
   832 
       
   833 
       
   834 /*-------------------------------------------------------------------*//*!
       
   835 * \brief
       
   836 * \param
       
   837 * \return
       
   838 * \note
       
   839 *//*-------------------------------------------------------------------*/
       
   840 
       
   841 EGLint EGLAPIENTRY eglGetError()
       
   842 {
       
   843     OSAcquireMutex();
       
   844     EGLint ret = EGL_SUCCESS;
       
   845     EGL* egl = getEGL();
       
   846     if(egl)
       
   847     {
       
   848         RIEGLThread* thread = egl->getThread();
       
   849         if(thread)
       
   850             ret = thread->getError();	//initialized, return error code
       
   851     }
       
   852     else ret = EGL_NOT_INITIALIZED;
       
   853     OSReleaseMutex();
       
   854     return ret;
       
   855 }
       
   856 
       
   857 /*-------------------------------------------------------------------*//*!
       
   858 * \brief
       
   859 * \param
       
   860 * \return
       
   861 * \note
       
   862 *//*-------------------------------------------------------------------*/
       
   863 
       
   864 EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
       
   865 {
       
   866     return OSGetDisplay(display_id);
       
   867 }
       
   868 
       
   869 /*-------------------------------------------------------------------*//*!
       
   870 * \brief
       
   871 * \param
       
   872 * \return
       
   873 * \note
       
   874 *//*-------------------------------------------------------------------*/
       
   875 
       
   876 EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
       
   877 {
       
   878     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
   879     EGL_IF_ERROR(display, EGL_SUCCESS, EGL_TRUE);	//already initialized
       
   880 
       
   881     //create the current display
       
   882     //if a context and a surface are bound by the time of eglTerminate, they remain bound until eglMakeCurrent is called
       
   883     RIEGLDisplay* newDisplay = NULL;
       
   884     try
       
   885     {
       
   886         newDisplay = RI_NEW(RIEGLDisplay, (dpy));	//throws bad_alloc
       
   887         egl->addDisplay(newDisplay);	//throws bad_alloc
       
   888         display = newDisplay;
       
   889         RI_ASSERT(display);
       
   890     }
       
   891     catch(std::bad_alloc)
       
   892     {
       
   893         RI_DELETE(newDisplay);
       
   894         EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE);
       
   895     }
       
   896 
       
   897     if(major) *major = 1;
       
   898     if(minor) *minor = 2;
       
   899     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
   900 }
       
   901 
       
   902 /*-------------------------------------------------------------------*//*!
       
   903 * \brief
       
   904 * \param
       
   905 * \return
       
   906 * \note
       
   907 *//*-------------------------------------------------------------------*/
       
   908 
       
   909 EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
       
   910 {
       
   911     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
   912     EGL_IF_ERROR(!display, EGL_SUCCESS, EGL_TRUE);
       
   913     egl->removeDisplay(display);
       
   914     RI_DELETE(display);
       
   915     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
   916 }
       
   917 
       
   918 /*-------------------------------------------------------------------*//*!
       
   919 * \brief
       
   920 * \param
       
   921 * \return
       
   922 * \note
       
   923 *//*-------------------------------------------------------------------*/
       
   924 
       
   925 const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
       
   926 {
       
   927     EGL_GET_DISPLAY(dpy, NULL);
       
   928     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, NULL);
       
   929 
       
   930     static const char apis[] = "OpenVG";
       
   931     static const char extensions[] = "";
       
   932     static const char vendor[] = "Khronos Group";
       
   933     static const char version[] = "1.3";
       
   934 
       
   935     const char* ret = NULL;
       
   936     switch(name)
       
   937     {
       
   938     case EGL_CLIENT_APIS:
       
   939         ret = apis;
       
   940         break;
       
   941 
       
   942     case EGL_EXTENSIONS:
       
   943         ret = extensions;
       
   944         break;
       
   945 
       
   946     case EGL_VENDOR:
       
   947         ret = vendor;
       
   948         break;
       
   949 
       
   950     case EGL_VERSION:
       
   951         ret = version;
       
   952         break;
       
   953 
       
   954     default:
       
   955         EGL_RETURN(EGL_BAD_PARAMETER, NULL);
       
   956     }
       
   957     EGL_RETURN(EGL_SUCCESS, ret);
       
   958 }
       
   959 
       
   960 /*-------------------------------------------------------------------*//*!
       
   961 * \brief
       
   962 * \param
       
   963 * \return
       
   964 * \note
       
   965 *//*-------------------------------------------------------------------*/
       
   966 
       
   967 EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
       
   968 {
       
   969     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
   970     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
   971     EGL_IF_ERROR(!num_config, EGL_BAD_PARAMETER, EGL_FALSE);
       
   972     if(!configs)
       
   973     {
       
   974         *num_config = display->getNumConfigs();
       
   975         EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
   976     }
       
   977     *num_config = RI_INT_MIN(config_size, display->getNumConfigs());
       
   978     for(int i=0;i<*num_config;i++)
       
   979         configs[i] = display->getConfig(i).m_config;
       
   980 
       
   981     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
   982 }
       
   983 
       
   984 /*-------------------------------------------------------------------*//*!
       
   985 * \brief
       
   986 * \param
       
   987 * \return
       
   988 * \note
       
   989 *//*-------------------------------------------------------------------*/
       
   990 
       
   991 static bool smaller(EGLint c, EGLint filter)
       
   992 {
       
   993     return (filter != EGL_DONT_CARE) && (c < filter);
       
   994 }
       
   995 
       
   996 EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
       
   997 {
       
   998     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
   999     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1000     EGL_IF_ERROR(!num_config, EGL_BAD_PARAMETER, EGL_FALSE);
       
  1001 
       
  1002     if(!configs)
       
  1003     {
       
  1004         *num_config = display->getNumConfigs();
       
  1005         EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1006     }
       
  1007     *num_config = 0;
       
  1008     if(!config_size)
       
  1009         EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1010 
       
  1011     int bufferSize = 0;
       
  1012     int redSize = 0;
       
  1013     int greenSize = 0;
       
  1014     int blueSize = 0;
       
  1015     int luminanceSize = 0;
       
  1016     int alphaSize = 0;
       
  1017     int alphaMaskSize = 0;
       
  1018     int colorBufferType = EGL_RGB_BUFFER;
       
  1019     int configID = EGL_DONT_CARE;
       
  1020     int sampleBuffers = 0;
       
  1021     int samples = 0;
       
  1022     if(attrib_list)
       
  1023     {
       
  1024         for(int i=0;attrib_list[i] != EGL_NONE;i+=2)
       
  1025         {
       
  1026             switch(attrib_list[i])
       
  1027             {
       
  1028             case EGL_BUFFER_SIZE:				//depth of the color buffer
       
  1029                 bufferSize = attrib_list[i+1];
       
  1030                 break;
       
  1031             case EGL_RED_SIZE:					//bits of Red in the color buffer
       
  1032                 redSize = attrib_list[i+1];
       
  1033                 break;
       
  1034             case EGL_GREEN_SIZE:				//bits of Green in the color buffer
       
  1035                 greenSize = attrib_list[i+1];
       
  1036                 break;
       
  1037             case EGL_BLUE_SIZE:					//bits of Blue in the color buffer
       
  1038                 blueSize = attrib_list[i+1];
       
  1039                 break;
       
  1040             case EGL_LUMINANCE_SIZE:			//bits of Luminance in the color buffer
       
  1041                 luminanceSize = attrib_list[i+1];
       
  1042                 break;
       
  1043             case EGL_ALPHA_SIZE:				//bits of Alpha in the color buffer
       
  1044                 alphaSize = attrib_list[i+1];
       
  1045                 break;
       
  1046             case EGL_ALPHA_MASK_SIZE:			//bits of Alpha in the alpha mask buffer
       
  1047                 alphaMaskSize = attrib_list[i+1];
       
  1048                 if(attrib_list[i+1] > 8)
       
  1049                     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);	//not supported
       
  1050                 break;
       
  1051             case EGL_COLOR_BUFFER_TYPE:			//enum color buffer type (EGL_RGB_BUFFER, EGL_LUMINANCE_BUFFER)
       
  1052                 EGL_IF_ERROR(attrib_list[i+1] != EGL_RGB_BUFFER && attrib_list[i+1] != EGL_LUMINANCE_BUFFER && attrib_list[i+1] != EGL_DONT_CARE, EGL_BAD_ATTRIBUTE, EGL_FALSE);
       
  1053                 colorBufferType = attrib_list[i+1];
       
  1054                 break;
       
  1055             case EGL_CONFIG_ID:					//unique EGLConfig identifier
       
  1056                 configID = attrib_list[i+1];
       
  1057                 break;
       
  1058 
       
  1059             case EGL_SAMPLE_BUFFERS:			//integer number of multisample buffers
       
  1060                 sampleBuffers = attrib_list[i+1];
       
  1061                 break;
       
  1062             case EGL_SAMPLES:					//integer number of samples per pixel
       
  1063                 samples = attrib_list[i+1];
       
  1064                 break;
       
  1065 
       
  1066             case EGL_BIND_TO_TEXTURE_RGB:		//boolean True if bindable to RGB textures. (always EGL_FALSE)
       
  1067             case EGL_BIND_TO_TEXTURE_RGBA:		//boolean True if bindable to RGBA textures. (always EGL_FALSE)
       
  1068             case EGL_DEPTH_SIZE:				//integer bits of Z in the depth buffer (always 0)
       
  1069             case EGL_LEVEL:						//integer frame buffer level (always 0)
       
  1070             case EGL_NATIVE_RENDERABLE:			//boolean EGL TRUE if native rendering APIs can render to surface (always EGL_FALSE)
       
  1071             case EGL_STENCIL_SIZE:				//integer bits of Stencil in the stencil buffer (always 0)
       
  1072                 if(attrib_list[i+1])
       
  1073                     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);	//not supported
       
  1074                 break;
       
  1075 
       
  1076             case EGL_CONFIG_CAVEAT:				//enum any caveats for the configuration (always EGL_NONE)
       
  1077             case EGL_NATIVE_VISUAL_TYPE:		//integer native visual type of the associated visual (always EGL_NONE)
       
  1078                 if(attrib_list[i+1] != EGL_NONE)
       
  1079                     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);	//not supported
       
  1080                 break;
       
  1081 
       
  1082             case EGL_MAX_SWAP_INTERVAL:			//integer maximum swap interval (always 1)
       
  1083             case EGL_MIN_SWAP_INTERVAL:			//integer minimum swap interval (always 1)
       
  1084                 if(attrib_list[i+1] != 1)
       
  1085                     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);	//not supported
       
  1086                 break;
       
  1087 
       
  1088             case EGL_RENDERABLE_TYPE:			//bitmask which client rendering APIs are supported. (always EGL_OPENVG_BIT)
       
  1089                 if(!(attrib_list[i+1] & EGL_OPENVG_BIT))
       
  1090                     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);	//not supported
       
  1091                 break;
       
  1092 
       
  1093             case EGL_SURFACE_TYPE:				//bitmask which types of EGL surfaces are supported. (always EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT | EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT)
       
  1094                 break;	//all types are always supported
       
  1095 
       
  1096             case EGL_TRANSPARENT_TYPE:			//enum type of transparency supported (always EGL_NONE)
       
  1097             case EGL_NATIVE_VISUAL_ID:			//integer handle of corresponding native visual (always 0)
       
  1098             case EGL_MAX_PBUFFER_WIDTH:			//integer maximum width of pbuffer (always INT_MAX)
       
  1099             case EGL_MAX_PBUFFER_HEIGHT:		//integer maximum height of pbuffer (always INT_MAX)
       
  1100             case EGL_MAX_PBUFFER_PIXELS:		//integer maximum size of pbuffer (always INT_MAX)
       
  1101             case EGL_TRANSPARENT_RED_VALUE:		//integer transparent red value (undefined)
       
  1102             case EGL_TRANSPARENT_GREEN_VALUE:	//integer transparent green value (undefined)
       
  1103             case EGL_TRANSPARENT_BLUE_VALUE:	//integer transparent blue value (undefined)
       
  1104                 break;	//ignored
       
  1105 
       
  1106             default:
       
  1107                 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_FALSE);	//unknown attribute
       
  1108             }
       
  1109         }
       
  1110     }
       
  1111 
       
  1112     if(configID && configID != EGL_DONT_CARE)
       
  1113     {	//if CONFIG_ID is defined, ignore the rest of the attribs
       
  1114         for(int i=0;i<EGL_NUMCONFIGS;i++)
       
  1115         {
       
  1116             if(display->getConfig(i).m_configID == configID)
       
  1117             {
       
  1118                 *num_config = 1;
       
  1119                 *configs = display->getConfig(i).m_config;
       
  1120             }
       
  1121         }
       
  1122         EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1123     }
       
  1124 
       
  1125     //go through all configs, add passed configs to return list
       
  1126     //TODO take alpha mask size into account
       
  1127     EGLConfig found[EGL_NUMCONFIGS];
       
  1128     int keys[EGL_NUMCONFIGS];
       
  1129     int numFound = 0;
       
  1130     for(int i=0;i<display->getNumConfigs();i++)
       
  1131     {
       
  1132         const RIEGLConfig& c = display->getConfig(i);
       
  1133 
       
  1134         int configMaskBits = c.m_maskBits;
       
  1135         int colorBits = c.m_desc.redBits + c.m_desc.greenBits + c.m_desc.blueBits;
       
  1136         int luminanceBits = c.m_desc.luminanceBits;
       
  1137         int configBufferSize;
       
  1138         if(colorBits)
       
  1139         {
       
  1140             RI_ASSERT(!luminanceBits);
       
  1141             colorBits += c.m_desc.alphaBits;
       
  1142             configBufferSize = colorBits;
       
  1143         }
       
  1144         else if(luminanceBits)
       
  1145         {
       
  1146             luminanceBits += c.m_desc.alphaBits;
       
  1147             configBufferSize = luminanceBits;
       
  1148         }
       
  1149         else
       
  1150         {	//alpha only surface
       
  1151             colorBits = c.m_desc.alphaBits;
       
  1152             luminanceBits = c.m_desc.alphaBits;
       
  1153             configBufferSize = colorBits;
       
  1154         }
       
  1155 
       
  1156         if (smaller(configBufferSize, bufferSize))
       
  1157             continue;
       
  1158 
       
  1159         int configSampleBuffers = c.m_samples == 1 ? 0 : 1;
       
  1160         if (smaller(configSampleBuffers, sampleBuffers))
       
  1161             continue;
       
  1162         if (smaller(c.m_samples, samples))
       
  1163             continue;
       
  1164 
       
  1165         if (smaller(c.m_desc.redBits, redSize)
       
  1166             || smaller(c.m_desc.greenBits, greenSize)
       
  1167             || smaller(c.m_desc.blueBits, blueSize)
       
  1168             || smaller(c.m_desc.alphaBits, alphaSize) )
       
  1169             continue;
       
  1170 
       
  1171         if (smaller(c.m_desc.luminanceBits, luminanceSize))
       
  1172             continue;
       
  1173 
       
  1174         if (smaller(configMaskBits, alphaMaskSize))
       
  1175             continue;
       
  1176 
       
  1177         if ((colorBufferType == EGL_RGB_BUFFER && !colorBits) ||
       
  1178             (colorBufferType == EGL_LUMINANCE_BUFFER && !luminanceBits))
       
  1179             continue;
       
  1180 
       
  1181         // \todo Add the alphaMaskSize into the sort order also!
       
  1182         int sortKey = c.m_configID;	//sort from smaller to larger
       
  1183         int sortBits = 0;
       
  1184         if(redSize != 0 && redSize != EGL_DONT_CARE)
       
  1185             sortBits += c.m_desc.redBits;
       
  1186         if(greenSize != 0 && greenSize != EGL_DONT_CARE)
       
  1187             sortBits += c.m_desc.greenBits;
       
  1188         if(blueSize != 0 && blueSize != EGL_DONT_CARE)
       
  1189             sortBits += c.m_desc.blueBits;
       
  1190         if(alphaSize != 0 && alphaSize != EGL_DONT_CARE)
       
  1191             sortBits += c.m_desc.alphaBits;
       
  1192         if(luminanceSize != 0 && luminanceSize != EGL_DONT_CARE)
       
  1193             sortBits += c.m_desc.luminanceBits;
       
  1194         RI_ASSERT(c.m_configID <= EGL_NUMCONFIGS);	//if there are more configs, increase the shift value
       
  1195         RI_ASSERT(sortBits <= 32);
       
  1196         sortKey += (32-sortBits) << 4;	//sort from larger to smaller
       
  1197 
       
  1198         found[numFound] = c.m_config;
       
  1199         keys[numFound++] = sortKey;
       
  1200     }
       
  1201     if(!numFound)
       
  1202         EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1203 
       
  1204     //sort return list into increasing order
       
  1205     for(int e=0;e<numFound-1;e++)
       
  1206     {
       
  1207         for(int f=e+1;f<numFound;f++)
       
  1208         {
       
  1209             if(keys[e] > keys[f])
       
  1210             {
       
  1211                 EGLConfig tmp = found[e];
       
  1212                 found[e] = found[f];
       
  1213                 found[f] = tmp;
       
  1214                 RI_INT_SWAP(keys[e], keys[f]);
       
  1215             }
       
  1216         }
       
  1217     }
       
  1218 
       
  1219     //write configs into return array
       
  1220     numFound = RI_INT_MIN(numFound, config_size);
       
  1221     for(int i=0;i<numFound;i++)
       
  1222     {
       
  1223         configs[i] = found[i];
       
  1224     }
       
  1225     *num_config = numFound;
       
  1226 
       
  1227     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1228 }
       
  1229 
       
  1230 /*-------------------------------------------------------------------*//*!
       
  1231 * \brief
       
  1232 * \param
       
  1233 * \return
       
  1234 * \note
       
  1235 *//*-------------------------------------------------------------------*/
       
  1236 
       
  1237 EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
       
  1238 {
       
  1239     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1240     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1241     EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_FALSE);
       
  1242     const RIEGLConfig& c = display->getConfig(config);
       
  1243     switch(attribute)
       
  1244     {
       
  1245     case EGL_BUFFER_SIZE:
       
  1246         *value = RI_INT_MAX(c.m_desc.redBits + c.m_desc.greenBits + c.m_desc.blueBits + c.m_desc.alphaBits, c.m_desc.luminanceBits + c.m_desc.alphaBits);
       
  1247         break;
       
  1248 
       
  1249     case EGL_RED_SIZE:
       
  1250         *value = c.m_desc.redBits;
       
  1251         break;
       
  1252 
       
  1253     case EGL_GREEN_SIZE:
       
  1254         *value = c.m_desc.greenBits;
       
  1255         break;
       
  1256 
       
  1257     case EGL_BLUE_SIZE:
       
  1258         *value = c.m_desc.blueBits;
       
  1259         break;
       
  1260 
       
  1261     case EGL_LUMINANCE_SIZE:
       
  1262         *value = c.m_desc.luminanceBits;
       
  1263         break;
       
  1264 
       
  1265     case EGL_ALPHA_SIZE:
       
  1266         *value = c.m_desc.alphaBits;
       
  1267         break;
       
  1268 
       
  1269     case EGL_ALPHA_MASK_SIZE:
       
  1270         *value = c.m_maskBits;
       
  1271         break;
       
  1272 
       
  1273     case EGL_BIND_TO_TEXTURE_RGB:
       
  1274     case EGL_BIND_TO_TEXTURE_RGBA:
       
  1275         *value = EGL_FALSE;
       
  1276         break;
       
  1277 
       
  1278     case EGL_COLOR_BUFFER_TYPE:
       
  1279         if(c.m_desc.redBits)
       
  1280             *value = EGL_RGB_BUFFER;
       
  1281         else
       
  1282             *value = EGL_LUMINANCE_BUFFER;
       
  1283         break;
       
  1284 
       
  1285     case EGL_CONFIG_CAVEAT:
       
  1286         *value = EGL_NONE;
       
  1287         break;
       
  1288 
       
  1289     case EGL_CONFIG_ID:
       
  1290         *value = c.m_configID;
       
  1291         break;
       
  1292 
       
  1293     case EGL_DEPTH_SIZE:
       
  1294         *value = 0;
       
  1295         break;
       
  1296 
       
  1297     case EGL_LEVEL:
       
  1298         *value = 0;
       
  1299         break;
       
  1300 
       
  1301     case EGL_MAX_PBUFFER_WIDTH:
       
  1302     case EGL_MAX_PBUFFER_HEIGHT:
       
  1303         *value = 16384;			//NOTE arbitrary maximum
       
  1304         break;
       
  1305 
       
  1306     case EGL_MAX_PBUFFER_PIXELS:
       
  1307         *value = 16384*16384;	//NOTE arbitrary maximum
       
  1308         break;
       
  1309 
       
  1310     case EGL_MAX_SWAP_INTERVAL:
       
  1311     case EGL_MIN_SWAP_INTERVAL:
       
  1312         *value = 1;
       
  1313         break;
       
  1314 
       
  1315     case EGL_NATIVE_RENDERABLE:
       
  1316         *value = EGL_FALSE;
       
  1317         break;
       
  1318 
       
  1319     case EGL_NATIVE_VISUAL_ID:
       
  1320         *value = 0;
       
  1321         break;
       
  1322 
       
  1323     case EGL_NATIVE_VISUAL_TYPE:
       
  1324         *value = EGL_NONE;
       
  1325         break;
       
  1326 
       
  1327     case EGL_RENDERABLE_TYPE:
       
  1328         *value = EGL_OPENVG_BIT;
       
  1329         break;
       
  1330 
       
  1331     case EGL_SAMPLE_BUFFERS:
       
  1332         *value = c.m_samples > 1 ? 1 : 0;
       
  1333         break;
       
  1334 
       
  1335     case EGL_SAMPLES:
       
  1336         *value = c.m_samples > 1 ? c.m_samples : 0;
       
  1337         break;
       
  1338 
       
  1339     case EGL_STENCIL_SIZE:
       
  1340         *value = 0;
       
  1341         break;
       
  1342 
       
  1343     case EGL_SURFACE_TYPE:
       
  1344         *value = EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT | EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT;
       
  1345         break;
       
  1346 
       
  1347     case EGL_TRANSPARENT_TYPE:
       
  1348         *value = EGL_NONE;
       
  1349         break;
       
  1350 
       
  1351     case EGL_TRANSPARENT_RED_VALUE:
       
  1352     case EGL_TRANSPARENT_GREEN_VALUE:
       
  1353     case EGL_TRANSPARENT_BLUE_VALUE:
       
  1354         *value = 0;
       
  1355         break;
       
  1356 
       
  1357     case EGL_CONFORMANT:
       
  1358         *value = EGL_OPENVG_BIT;  //TODO return proper value
       
  1359         break;
       
  1360 
       
  1361     default:
       
  1362         EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_FALSE);
       
  1363     }
       
  1364     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1365 }
       
  1366 
       
  1367 /*-------------------------------------------------------------------*//*!
       
  1368 * \brief
       
  1369 * \param
       
  1370 * \return
       
  1371 * \note
       
  1372 *//*-------------------------------------------------------------------*/
       
  1373 
       
  1374 EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
       
  1375 {
       
  1376     EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE);
       
  1377     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
       
  1378     EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE);
       
  1379 
       
  1380     int renderBuffer = EGL_BACK_BUFFER;
       
  1381     int colorSpace = EGL_VG_COLORSPACE_sRGB;
       
  1382     int alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
       
  1383     if(attrib_list)
       
  1384     {
       
  1385         for(int i=0;attrib_list[i] != EGL_NONE;i+=2)
       
  1386         {
       
  1387             switch(attrib_list[i])
       
  1388             {
       
  1389             case EGL_RENDER_BUFFER:
       
  1390                 renderBuffer = attrib_list[i+1];
       
  1391                 break;
       
  1392 
       
  1393             case EGL_VG_COLORSPACE:
       
  1394                 colorSpace = attrib_list[i+1];
       
  1395                 break;
       
  1396 
       
  1397             case EGL_VG_ALPHA_FORMAT:
       
  1398                 alphaFormat = attrib_list[i+1];
       
  1399                 break;
       
  1400 
       
  1401             default:
       
  1402                 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
       
  1403             }
       
  1404         }
       
  1405     }
       
  1406     //we ignore the renderBuffer parameter since we can only render to double buffered surfaces
       
  1407 
       
  1408     //TODO If the attributes of win do not correspond to config, then an EGL BAD MATCH error is generated.
       
  1409     //TODO If there is already an EGLConfig associated with win (as a result of a previous eglCreateWindowSurface call), then an EGL BAD ALLOC error is generated
       
  1410 
       
  1411     void* wc = NULL;
       
  1412     OpenVGRI::Drawable* d = NULL;
       
  1413     RIEGLSurface* s = NULL;
       
  1414     try
       
  1415     {
       
  1416         wc = OSCreateWindowContext((EGLNativeWindowType)win);
       
  1417         RI_ASSERT(wc);
       
  1418         //TODO what should happen if window width or height is zero?
       
  1419         int windowWidth = 0, windowHeight = 0;
       
  1420         OSGetWindowSize((OSWindowContext*)wc, windowWidth, windowHeight);
       
  1421         bool isWindow = OSIsWindow((const OSWindowContext*)wc);
       
  1422         if(windowWidth <= 0 || windowHeight <= 0 || !isWindow)
       
  1423         {
       
  1424             OSDestroyWindowContext((OSWindowContext*)wc);
       
  1425             EGL_IF_ERROR(!isWindow, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
       
  1426             EGL_IF_ERROR(windowWidth <= 0 || windowHeight <= 0, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
       
  1427         }
       
  1428         Color::Descriptor colorDescriptor = display->getConfig(config).configToDescriptor((colorSpace == EGL_VG_COLORSPACE_LINEAR) ? false : true, (alphaFormat == EGL_VG_ALPHA_FORMAT_PRE) ? true : false);
       
  1429         d = RI_NEW(OpenVGRI::Drawable, (colorDescriptor, windowWidth, windowHeight, display->getConfig(config).m_samples, display->getConfig(config).m_maskBits));	//throws bad_alloc
       
  1430         RI_ASSERT(d);
       
  1431         s = RI_NEW(RIEGLSurface,(wc, config, d, false, renderBuffer));	//throws bad_alloc
       
  1432         RI_ASSERT(s);
       
  1433         s->addReference();
       
  1434         display->addSurface(s);	//throws bad_alloc
       
  1435     }
       
  1436     catch(std::bad_alloc)
       
  1437     {
       
  1438         OSDestroyWindowContext((OSWindowContext*)wc);
       
  1439         RI_DELETE(d);
       
  1440         RI_DELETE(s);
       
  1441         EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE);
       
  1442     }
       
  1443     EGL_RETURN(EGL_SUCCESS, (EGLSurface)s);
       
  1444 }
       
  1445 
       
  1446 /*-------------------------------------------------------------------*//*!
       
  1447 * \brief
       
  1448 * \param
       
  1449 * \return
       
  1450 * \note
       
  1451 *//*-------------------------------------------------------------------*/
       
  1452 
       
  1453 EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
       
  1454 {
       
  1455     EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE);
       
  1456     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
       
  1457     EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE);
       
  1458 
       
  1459     int width = 0, height = 0;
       
  1460     bool largestPbuffer = false;
       
  1461     int colorSpace = EGL_VG_COLORSPACE_sRGB;
       
  1462     int alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
       
  1463     if(attrib_list)
       
  1464     {
       
  1465         for(int i=0;attrib_list[i] != EGL_NONE;i+=2)
       
  1466         {
       
  1467             switch(attrib_list[i])
       
  1468             {
       
  1469             case EGL_WIDTH:
       
  1470                 width = attrib_list[i+1];
       
  1471                 break;
       
  1472 
       
  1473             case EGL_HEIGHT:
       
  1474                 height = attrib_list[i+1];
       
  1475                 break;
       
  1476 
       
  1477             case EGL_LARGEST_PBUFFER:
       
  1478                 largestPbuffer = attrib_list[i+1] ? true : false;
       
  1479                 break;
       
  1480 
       
  1481             case EGL_VG_COLORSPACE:
       
  1482                 colorSpace = attrib_list[i+1];
       
  1483                 break;
       
  1484 
       
  1485             case EGL_VG_ALPHA_FORMAT:
       
  1486                 alphaFormat = attrib_list[i+1];
       
  1487                 break;
       
  1488 
       
  1489             case EGL_TEXTURE_FORMAT:	//config doesn't support OpenGL ES
       
  1490             case EGL_TEXTURE_TARGET:	//config doesn't support OpenGL ES
       
  1491             case EGL_MIPMAP_TEXTURE:	//config doesn't support OpenGL ES
       
  1492             default:
       
  1493                 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
       
  1494             break;
       
  1495             }
       
  1496         }
       
  1497     }
       
  1498     EGL_IF_ERROR(width <= 0 || height <= 0, EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
       
  1499 
       
  1500     OpenVGRI::Drawable* d = NULL;
       
  1501     RIEGLSurface* s = NULL;
       
  1502     try
       
  1503     {
       
  1504         d = RI_NEW(OpenVGRI::Drawable, (display->getConfig(config).configToDescriptor((colorSpace == EGL_VG_COLORSPACE_LINEAR) ? false : true, (alphaFormat == EGL_VG_ALPHA_FORMAT_PRE) ? true : false), width, height, display->getConfig(config).m_samples, display->getConfig(config).m_maskBits));	//throws bad_alloc
       
  1505         RI_ASSERT(d);
       
  1506         s = RI_NEW(RIEGLSurface,(NULL, config, d, largestPbuffer, EGL_BACK_BUFFER));	//throws bad_alloc
       
  1507         RI_ASSERT(s);
       
  1508         s->addReference();
       
  1509         display->addSurface(s);	//throws bad_alloc
       
  1510     }
       
  1511     catch(std::bad_alloc)
       
  1512     {
       
  1513         RI_DELETE(d);
       
  1514         RI_DELETE(s);
       
  1515         EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE);
       
  1516     }
       
  1517     EGL_RETURN(EGL_SUCCESS, (EGLSurface)s);
       
  1518 }
       
  1519 
       
  1520 /*-------------------------------------------------------------------*//*!
       
  1521 * \brief
       
  1522 * \param
       
  1523 * \return
       
  1524 * \note
       
  1525 *//*-------------------------------------------------------------------*/
       
  1526 
       
  1527 EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
       
  1528 {
       
  1529     EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE);
       
  1530     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
       
  1531     EGL_IF_ERROR(buftype != EGL_OPENVG_IMAGE, EGL_BAD_PARAMETER, EGL_NO_SURFACE);
       
  1532     EGL_IF_ERROR(!buffer, EGL_BAD_PARAMETER, EGL_NO_SURFACE);	//TODO should also check if buffer really is a valid VGImage object (needs VG context for that)
       
  1533     Image* image = (Image*)buffer;
       
  1534     EGL_IF_ERROR(image->isInUse(), EGL_BAD_ACCESS, EGL_NO_SURFACE);	//buffer is in use by OpenVG
       
  1535     EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE);
       
  1536     EGL_IF_ERROR(attrib_list && attrib_list[0] != EGL_NONE, EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);	//there are no valid attribs for OpenVG
       
  1537     const Color::Descriptor& bc = ((Image*)buffer)->getDescriptor();
       
  1538     const Color::Descriptor& cc = display->getConfig(config).m_desc;
       
  1539     EGL_IF_ERROR(bc.redBits != cc.redBits || bc.greenBits != cc.greenBits || bc.blueBits != cc.blueBits ||
       
  1540                  bc.alphaBits != cc.alphaBits || bc.luminanceBits != cc.luminanceBits, EGL_BAD_MATCH, EGL_NO_SURFACE);
       
  1541 
       
  1542     //TODO If buffer is already bound to another pbuffer, an EGL BAD ACCESS error is generated.
       
  1543 
       
  1544     OpenVGRI::Drawable* d = NULL;
       
  1545     RIEGLSurface* s = NULL;
       
  1546     try
       
  1547     {
       
  1548         d = RI_NEW(OpenVGRI::Drawable, (image, display->getConfig(config).m_maskBits));
       
  1549         RI_ASSERT(d);
       
  1550         s = RI_NEW(RIEGLSurface,(NULL, config, d, false, EGL_BACK_BUFFER));	//throws bad_alloc
       
  1551         RI_ASSERT(s);
       
  1552         s->addReference();
       
  1553         display->addSurface(s);	//throws bad_alloc
       
  1554     }
       
  1555     catch(std::bad_alloc)
       
  1556     {
       
  1557         RI_DELETE(d);
       
  1558         RI_DELETE(s);
       
  1559         EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE);
       
  1560     }
       
  1561     EGL_RETURN(EGL_SUCCESS, (EGLSurface)s);
       
  1562 }
       
  1563 
       
  1564 /*-------------------------------------------------------------------*//*!
       
  1565 * \brief
       
  1566 * \param
       
  1567 * \return
       
  1568 * \note
       
  1569 *//*-------------------------------------------------------------------*/
       
  1570 
       
  1571 EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
       
  1572 {
       
  1573     // Seems that this function has not been implemented correctly in the RI:
       
  1574     // cannot assume that EGLNativePixmapType has format, data, etc.
       
  1575 #if 0
       
  1576     EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE);
       
  1577     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
       
  1578     EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE);
       
  1579     EGL_IF_ERROR(!pixmap || !isValidImageFormat(pixmap->format) || !pixmap->data || pixmap->width <= 0 || pixmap->height <= 0, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
       
  1580     RI_UNREF(attrib_list);
       
  1581     EGL_IF_ERROR(display->getConfig(config).m_samples != 1, EGL_BAD_MATCH, EGL_NO_SURFACE);
       
  1582 
       
  1583     //TODO If there is already an EGLSurface associated with pixmap (as a result of a previous eglCreatePixmapSurface call), then a EGL BAD ALLOC error is generated.
       
  1584 
       
  1585     Drawable* d = NULL;
       
  1586     RIEGLSurface* s = NULL;
       
  1587     try
       
  1588     {
       
  1589         d = RI_NEW(Drawable, (Color::formatToDescriptor((VGImageFormat)pixmap->format), pixmap->width, pixmap->height, pixmap->stride, (RIuint8*)pixmap->data, display->getConfig(config).m_maskBits));	//throws bad_alloc
       
  1590         RI_ASSERT(d);
       
  1591         s = RI_NEW(RIEGLSurface,(NULL, config, d, false, EGL_BACK_BUFFER));	//throws bad_alloc
       
  1592         RI_ASSERT(s);
       
  1593         s->addReference();
       
  1594         display->addSurface(s);	//throws bad_alloc
       
  1595     }
       
  1596     catch(std::bad_alloc)
       
  1597     {
       
  1598         RI_DELETE(d);
       
  1599         RI_DELETE(s);
       
  1600         EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE);
       
  1601     }
       
  1602     EGL_RETURN(EGL_SUCCESS, (EGLSurface)s);
       
  1603 #else
       
  1604     (void)dpy;
       
  1605     (void)config;
       
  1606     (void)pixmap;
       
  1607     (void)attrib_list;
       
  1608     return 0;
       
  1609 #endif
       
  1610 }
       
  1611 
       
  1612 /*-------------------------------------------------------------------*//*!
       
  1613 * \brief
       
  1614 * \param
       
  1615 * \return
       
  1616 * \note
       
  1617 *//*-------------------------------------------------------------------*/
       
  1618 
       
  1619 EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
       
  1620 {
       
  1621     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1622     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1623     EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE);
       
  1624 
       
  1625     display->removeSurface((RIEGLSurface*)surface);
       
  1626     if(!((RIEGLSurface*)surface)->removeReference())
       
  1627         RI_DELETE((RIEGLSurface*)surface);
       
  1628 
       
  1629     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1630 }
       
  1631 
       
  1632 /*-------------------------------------------------------------------*//*!
       
  1633 * \brief
       
  1634 * \param
       
  1635 * \return
       
  1636 * \note
       
  1637 *//*-------------------------------------------------------------------*/
       
  1638 
       
  1639 EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
       
  1640 {
       
  1641     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1642     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1643     EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE);
       
  1644     RI_UNREF(attribute);
       
  1645     RI_UNREF(value);
       
  1646     //do nothing
       
  1647     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1648 }
       
  1649 
       
  1650 /*-------------------------------------------------------------------*//*!
       
  1651 * \brief
       
  1652 * \param
       
  1653 * \return
       
  1654 * \note
       
  1655 *//*-------------------------------------------------------------------*/
       
  1656 
       
  1657 EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
       
  1658 {
       
  1659     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1660     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1661     EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE);
       
  1662     //TODO give an error if value is NULL?
       
  1663 
       
  1664     RIEGLSurface* s = (RIEGLSurface*)surface;
       
  1665     switch(attribute)
       
  1666     {
       
  1667     case EGL_VG_ALPHA_FORMAT:
       
  1668         *value = (s->getDrawable()->getDescriptor().isPremultiplied()) ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE;
       
  1669         break;
       
  1670 
       
  1671     case EGL_VG_COLORSPACE:
       
  1672         *value = (s->getDrawable()->getDescriptor().isNonlinear()) ? EGL_VG_COLORSPACE_sRGB : EGL_VG_COLORSPACE_LINEAR;
       
  1673         break;
       
  1674 
       
  1675     case EGL_CONFIG_ID:
       
  1676         *value = display->getConfig(s->getConfig()).m_configID;
       
  1677         break;
       
  1678 
       
  1679     case EGL_HEIGHT:
       
  1680         *value = s->getDrawable()->getHeight();
       
  1681         break;
       
  1682 
       
  1683     case EGL_HORIZONTAL_RESOLUTION:
       
  1684         *value = EGL_UNKNOWN;			//TODO Horizontal dot pitch
       
  1685         break;
       
  1686 
       
  1687     case EGL_LARGEST_PBUFFER:
       
  1688         if(!s->getOSWindowContext())
       
  1689             *value = s->isLargestPbuffer() ? EGL_TRUE : EGL_FALSE;
       
  1690         break;
       
  1691 
       
  1692     case EGL_MIPMAP_TEXTURE:
       
  1693         if(!s->getOSWindowContext())
       
  1694             *value = EGL_FALSE;
       
  1695         break;
       
  1696 
       
  1697     case EGL_MIPMAP_LEVEL:
       
  1698         if(!s->getOSWindowContext())
       
  1699             *value = 0;
       
  1700         break;
       
  1701 
       
  1702     case EGL_PIXEL_ASPECT_RATIO:
       
  1703         *value = EGL_UNKNOWN;			//TODO Display aspect ratio
       
  1704         break;
       
  1705 
       
  1706     case EGL_RENDER_BUFFER:
       
  1707         *value = s->getRenderBuffer();
       
  1708         break;
       
  1709 
       
  1710     case EGL_SWAP_BEHAVIOR:
       
  1711         *value = EGL_BUFFER_PRESERVED;
       
  1712         break;
       
  1713 
       
  1714     case EGL_TEXTURE_FORMAT:
       
  1715         if(!s->getOSWindowContext())
       
  1716             *value = EGL_NO_TEXTURE;
       
  1717         break;
       
  1718 
       
  1719     case EGL_TEXTURE_TARGET:
       
  1720         if(!s->getOSWindowContext())
       
  1721             *value = EGL_NO_TEXTURE;
       
  1722         break;
       
  1723 
       
  1724     case EGL_VERTICAL_RESOLUTION:
       
  1725         *value = EGL_UNKNOWN;			//TODO Vertical dot pitch
       
  1726         break;
       
  1727 
       
  1728     case EGL_WIDTH:
       
  1729         *value = s->getDrawable()->getWidth();
       
  1730         break;
       
  1731 
       
  1732     default:
       
  1733         EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_FALSE);
       
  1734     }
       
  1735     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1736 }
       
  1737 
       
  1738 /*-------------------------------------------------------------------*//*!
       
  1739 * \brief
       
  1740 * \param
       
  1741 * \return
       
  1742 * \note
       
  1743 *//*-------------------------------------------------------------------*/
       
  1744 
       
  1745 EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
       
  1746 {
       
  1747     EGL_GET_DISPLAY(dpy, EGL_NO_CONTEXT);
       
  1748     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_CONTEXT);
       
  1749     EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_CONTEXT);
       
  1750     RI_UNREF(attrib_list);
       
  1751 
       
  1752     RIEGLThread* thread = egl->getThread();
       
  1753     if(!thread)
       
  1754         EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
       
  1755 
       
  1756     //creation of OpenGL ES contexts is not allowed in this implementation
       
  1757     if(thread->getBoundAPI() != EGL_OPENVG_API)
       
  1758         EGL_RETURN(EGL_BAD_MATCH, EGL_NO_CONTEXT);
       
  1759 
       
  1760     OpenVGRI::VGContext* vgctx = NULL;
       
  1761     RIEGLContext* c = NULL;
       
  1762     try
       
  1763     {
       
  1764         vgctx = RI_NEW(OpenVGRI::VGContext, (share_context ? ((RIEGLContext*)share_context)->getVGContext() : NULL));	//throws bad_alloc
       
  1765         c = RI_NEW(RIEGLContext, (vgctx, config));	//throws bad_alloc
       
  1766         c->addReference();
       
  1767         display->addContext(c);	//throws bad_alloc
       
  1768     }
       
  1769     catch(std::bad_alloc)
       
  1770     {
       
  1771         RI_DELETE(vgctx);
       
  1772         RI_DELETE(c);
       
  1773         EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
       
  1774     }
       
  1775 
       
  1776     EGL_RETURN(EGL_SUCCESS, (EGLContext)c);
       
  1777 }
       
  1778 
       
  1779 /*-------------------------------------------------------------------*//*!
       
  1780 * \brief
       
  1781 * \param
       
  1782 * \return
       
  1783 * \note
       
  1784 *//*-------------------------------------------------------------------*/
       
  1785 
       
  1786 EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
       
  1787 {
       
  1788     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1789     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1790     EGL_IF_ERROR(!display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE);
       
  1791 
       
  1792     RIEGLContext* context = (RIEGLContext*)ctx;
       
  1793     display->removeContext(context);
       
  1794     if(!context->removeReference() )
       
  1795         RI_DELETE(context);
       
  1796 
       
  1797     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1798 }
       
  1799 
       
  1800 /*-------------------------------------------------------------------*//*!
       
  1801 * \brief
       
  1802 * \param
       
  1803 * \return
       
  1804 * \note
       
  1805 *//*-------------------------------------------------------------------*/
       
  1806 
       
  1807 EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
       
  1808 {
       
  1809     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1810     EGL_IF_ERROR(ctx != EGL_NO_CONTEXT && !display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE);
       
  1811     EGL_IF_ERROR(draw != EGL_NO_SURFACE && !display->surfaceExists(draw), EGL_BAD_SURFACE, EGL_FALSE);
       
  1812     EGL_IF_ERROR(read != EGL_NO_SURFACE && !display->surfaceExists(read), EGL_BAD_SURFACE, EGL_FALSE);
       
  1813     EGL_IF_ERROR(draw != read, EGL_BAD_MATCH, EGL_FALSE);	//TODO what's the proper error code?
       
  1814     EGL_IF_ERROR((draw != EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT) || (draw == EGL_NO_SURFACE && ctx != EGL_NO_CONTEXT), EGL_BAD_MATCH, EGL_FALSE);
       
  1815 
       
  1816     RIEGLSurface* s = NULL;
       
  1817     RIEGLContext* c = NULL;
       
  1818     if(draw != EGL_NO_SURFACE && ctx != EGL_NO_CONTEXT)
       
  1819     {
       
  1820         EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1821 
       
  1822         s = (RIEGLSurface*)draw;
       
  1823         c = (RIEGLContext*)ctx;
       
  1824 
       
  1825         //If either draw or read are pbuffers created with eglCreatePbufferFromClientBuffer, and the underlying bound client API buffers
       
  1826         //are in use by the client API that created them, an EGL BAD ACCESS error is generated.
       
  1827         EGL_IF_ERROR(s->getDrawable()->isInUse(), EGL_BAD_ACCESS, EGL_FALSE);
       
  1828 
       
  1829 
       
  1830         //TODO properly check compatibility of surface and context:
       
  1831         //-both have RGB or LUMINANCE configs
       
  1832         //-buffer bit depths match
       
  1833         //-configs support OpenVG
       
  1834         //-both have the same display
       
  1835         EGL_IF_ERROR(s->getConfig() != c->getConfig(), EGL_BAD_MATCH, EGL_FALSE);
       
  1836         //TODO check if context or surfaces are already bound to another thread
       
  1837 
       
  1838         //If a native window underlying either draw or read is no longer valid, an EGL BAD NATIVE WINDOW error is generated.
       
  1839         EGL_IF_ERROR(s->getOSWindowContext() && !OSIsWindow((const OSWindowContext*)s->getOSWindowContext()), EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
       
  1840 
       
  1841         //TODO If the previous context of the calling display has unflushed commands, and the previous surface is no longer valid, an EGL BAD CURRENT SURFACE error is generated. (can this happen?)
       
  1842         //TODO If the ancillary buffers for draw and read cannot be allocated, an EGL BAD ALLOC error is generated. (mask buffer?)
       
  1843     }
       
  1844 
       
  1845     //check if the thread is current
       
  1846     RIEGLThread* thread = egl->getCurrentThread();
       
  1847     if(thread)
       
  1848     {	//thread is current, release the old bindinds and remove the thread from the current thread list
       
  1849         RIEGLContext* pc = thread->getCurrentContext();
       
  1850         RIEGLSurface* ps = thread->getCurrentSurface();
       
  1851         if(pc)
       
  1852         {
       
  1853             vgFlush();
       
  1854             pc->getVGContext()->setDefaultDrawable(NULL);
       
  1855             if(!pc->removeReference())
       
  1856                 RI_DELETE(pc);
       
  1857         }
       
  1858         if(ps)
       
  1859         {
       
  1860             if(!ps->removeReference())
       
  1861                 RI_DELETE(ps);
       
  1862         }
       
  1863 
       
  1864         egl->removeCurrentThread(thread);
       
  1865     }
       
  1866 
       
  1867     if( c && s )
       
  1868     {
       
  1869         //bind context and surface to the current display
       
  1870         RIEGLThread* newThread = egl->getThread();
       
  1871         if(!newThread)
       
  1872             EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE);
       
  1873         newThread->makeCurrent(c, s);
       
  1874         c->getVGContext()->setDefaultDrawable(s->getDrawable());
       
  1875 
       
  1876         try
       
  1877         {
       
  1878             egl->addCurrentThread(newThread);	//throws bad_alloc
       
  1879         }
       
  1880         catch(std::bad_alloc)
       
  1881         {
       
  1882             EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE);
       
  1883         }
       
  1884 
       
  1885         c->addReference();
       
  1886         s->addReference();
       
  1887     }
       
  1888     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1889 }
       
  1890 
       
  1891 /*-------------------------------------------------------------------*//*!
       
  1892 * \brief
       
  1893 * \param
       
  1894 * \return
       
  1895 * \note
       
  1896 *//*-------------------------------------------------------------------*/
       
  1897 
       
  1898 EGLContext EGLAPIENTRY eglGetCurrentContext()
       
  1899 {
       
  1900     EGL_GET_EGL(EGL_NO_CONTEXT);
       
  1901     EGLContext ret = EGL_NO_CONTEXT;
       
  1902     RIEGLThread* thread = egl->getCurrentThread();
       
  1903     if(thread && thread->getBoundAPI() == EGL_OPENVG_API)
       
  1904     {
       
  1905         ret = thread->getCurrentContext();
       
  1906         RI_ASSERT(ret);
       
  1907     }
       
  1908     EGL_RETURN(EGL_SUCCESS, ret);
       
  1909 }
       
  1910 
       
  1911 /*-------------------------------------------------------------------*//*!
       
  1912 * \brief
       
  1913 * \param
       
  1914 * \return
       
  1915 * \note
       
  1916 *//*-------------------------------------------------------------------*/
       
  1917 
       
  1918 EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)
       
  1919 {
       
  1920     EGL_GET_EGL(EGL_NO_SURFACE);
       
  1921     EGL_IF_ERROR(readdraw != EGL_READ && readdraw != EGL_DRAW, EGL_BAD_PARAMETER, EGL_NO_SURFACE);
       
  1922     EGLContext ret = EGL_NO_SURFACE;
       
  1923     RIEGLThread* thread = egl->getCurrentThread();
       
  1924     if(thread && thread->getBoundAPI() == EGL_OPENVG_API)
       
  1925     {
       
  1926         ret = thread->getCurrentSurface();
       
  1927         RI_ASSERT(ret);
       
  1928     }
       
  1929     EGL_RETURN(EGL_SUCCESS, ret);
       
  1930 }
       
  1931 
       
  1932 /*-------------------------------------------------------------------*//*!
       
  1933 * \brief	Returns the current display
       
  1934 * \param
       
  1935 * \return
       
  1936 * \note
       
  1937 *//*-------------------------------------------------------------------*/
       
  1938 
       
  1939 EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)
       
  1940 {
       
  1941     EGL_GET_EGL(EGL_NO_DISPLAY);
       
  1942 
       
  1943     RIEGLThread* thread = egl->getCurrentThread();
       
  1944     if(!thread || thread->getBoundAPI() != EGL_OPENVG_API)
       
  1945         EGL_RETURN(EGL_SUCCESS, EGL_NO_DISPLAY);
       
  1946 
       
  1947     RIEGLContext* ctx = thread->getCurrentContext();
       
  1948     RI_ASSERT(ctx);
       
  1949     EGLDisplay ret = egl->findDisplay(ctx);
       
  1950     EGL_RETURN(EGL_SUCCESS, ret);
       
  1951 }
       
  1952 
       
  1953 /*-------------------------------------------------------------------*//*!
       
  1954 * \brief
       
  1955 * \param
       
  1956 * \return
       
  1957 * \note
       
  1958 *//*-------------------------------------------------------------------*/
       
  1959 
       
  1960 EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value)
       
  1961 {
       
  1962     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  1963     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  1964     EGL_IF_ERROR(!display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE);
       
  1965     EGL_IF_ERROR(attribute != EGL_CONFIG_ID && attribute != EGL_CONTEXT_CLIENT_TYPE, EGL_BAD_ATTRIBUTE, EGL_FALSE);
       
  1966     if(attribute == EGL_CONFIG_ID)
       
  1967         *value = display->getConfig(((RIEGLContext*)ctx)->getConfig()).m_configID;
       
  1968     if(attribute == EGL_CONTEXT_CLIENT_TYPE)
       
  1969         *value = EGL_OPENVG_API;
       
  1970     // \todo [kalle 05/Jul/05] Handling of EGL_RENDER_BUFFER attribute is missing.
       
  1971     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1972 }
       
  1973 
       
  1974 /*-------------------------------------------------------------------*//*!
       
  1975 * \brief
       
  1976 * \param
       
  1977 * \return
       
  1978 * \note
       
  1979 *//*-------------------------------------------------------------------*/
       
  1980 
       
  1981 EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
       
  1982 {
       
  1983     EGL_GET_EGL(EGL_FALSE);
       
  1984     EGL_IF_ERROR(api != EGL_OPENVG_API && api != EGL_OPENGL_ES_API, EGL_BAD_PARAMETER, EGL_FALSE);
       
  1985     RIEGLThread* thread = egl->getThread();
       
  1986     if(thread)
       
  1987         thread->bindAPI(api);
       
  1988     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  1989 }
       
  1990 
       
  1991 /*-------------------------------------------------------------------*//*!
       
  1992 * \brief
       
  1993 * \param
       
  1994 * \return
       
  1995 * \note
       
  1996 *//*-------------------------------------------------------------------*/
       
  1997 
       
  1998 EGLenum EGLAPIENTRY eglQueryAPI(void)
       
  1999 {
       
  2000     EGL_GET_EGL(EGL_NONE);
       
  2001     RIEGLThread* thread = egl->getThread();
       
  2002     if(thread)
       
  2003         EGL_RETURN(EGL_SUCCESS, thread->getBoundAPI());
       
  2004     EGL_RETURN(EGL_SUCCESS, EGL_NONE);
       
  2005 }
       
  2006 
       
  2007 /*-------------------------------------------------------------------*//*!
       
  2008 * \brief
       
  2009 * \param
       
  2010 * \return
       
  2011 * \note
       
  2012 *//*-------------------------------------------------------------------*/
       
  2013 
       
  2014 EGLBoolean EGLAPIENTRY eglWaitClient()
       
  2015 {
       
  2016     EGL_GET_EGL(EGL_FALSE);
       
  2017     RIEGLThread* thread = egl->getCurrentThread();
       
  2018     if(thread && thread->getBoundAPI() == EGL_OPENVG_API)
       
  2019         vgFinish();
       
  2020     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  2021 }
       
  2022 
       
  2023 /*-------------------------------------------------------------------*//*!
       
  2024 * \brief	Waits for OpenGL ES
       
  2025 * \param
       
  2026 * \return
       
  2027 * \note
       
  2028 *//*-------------------------------------------------------------------*/
       
  2029 
       
  2030 EGLBoolean EGLAPIENTRY eglWaitGL(void)
       
  2031 {
       
  2032     return EGL_TRUE;
       
  2033 }
       
  2034 
       
  2035 /*-------------------------------------------------------------------*//*!
       
  2036 * \brief
       
  2037 * \param
       
  2038 * \return
       
  2039 * \note		We don't support native rendering
       
  2040 *//*-------------------------------------------------------------------*/
       
  2041 
       
  2042 EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
       
  2043 {
       
  2044     RI_UNREF(engine);
       
  2045     return EGL_TRUE;
       
  2046 }
       
  2047 
       
  2048 /*-------------------------------------------------------------------*//*!
       
  2049 * \brief
       
  2050 * \param
       
  2051 * \return
       
  2052 * \note
       
  2053 *//*-------------------------------------------------------------------*/
       
  2054 
       
  2055 EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
       
  2056 {
       
  2057     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  2058     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  2059     EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE);
       
  2060 
       
  2061     RIEGLSurface* s = (RIEGLSurface*)surface;
       
  2062 
       
  2063     RIEGLThread* currentThread = egl->getCurrentThread();
       
  2064     EGL_IF_ERROR(!currentThread || currentThread->getCurrentSurface() != s, EGL_BAD_SURFACE, EGL_FALSE);
       
  2065     EGL_IF_ERROR(!OSIsWindow((const OSWindowContext*)s->getOSWindowContext()), EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
       
  2066 
       
  2067     vgFlush();
       
  2068 
       
  2069     if(!s->getOSWindowContext())
       
  2070     {	//do nothing for other than window surfaces (NOTE: single-buffered window surfaces should return immediately as well)
       
  2071         EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  2072     }
       
  2073 
       
  2074     int windowWidth = 0, windowHeight = 0;
       
  2075     OSGetWindowSize((OSWindowContext*)s->getOSWindowContext(), windowWidth, windowHeight);
       
  2076 
       
  2077     if(windowWidth != s->getDrawable()->getWidth() || windowHeight != s->getDrawable()->getHeight())
       
  2078     {	//resize the back buffer
       
  2079         RIEGLContext* c = currentThread->getCurrentContext();
       
  2080         RI_ASSERT(c);
       
  2081         try
       
  2082         {
       
  2083             s->getDrawable()->resize(c->getVGContext(), windowWidth, windowHeight);	//throws bad_alloc
       
  2084         }
       
  2085         catch(std::bad_alloc)
       
  2086         {
       
  2087             c->getVGContext()->setDefaultDrawable(NULL);
       
  2088             EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE);
       
  2089         }
       
  2090     }
       
  2091 
       
  2092     OSBlitToWindow((OSWindowContext*)s->getOSWindowContext(), s->getDrawable());
       
  2093 
       
  2094     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  2095 }
       
  2096 
       
  2097 /*-------------------------------------------------------------------*//*!
       
  2098 * \brief
       
  2099 * \param
       
  2100 * \return
       
  2101 * \note
       
  2102 *//*-------------------------------------------------------------------*/
       
  2103 
       
  2104 EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
       
  2105 {
       
  2106     // This RI implementation does not make sense.
       
  2107 #if 0
       
  2108     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  2109     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  2110     EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE);
       
  2111     EGL_IF_ERROR(!target || !isValidImageFormat(target->format) || !target->data || target->width <= 0 || target->height <= 0, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
       
  2112     RIEGLThread* currentThread = egl->getCurrentThread();
       
  2113     RIEGLContext* c = currentThread->getCurrentContext();
       
  2114     RI_ASSERT(c);
       
  2115     try
       
  2116     {
       
  2117         Image output(Color::formatToDescriptor((VGImageFormat)target->format), target->width, target->height, target->stride, (RIuint8*)target->data);
       
  2118         output.addReference();
       
  2119         output.blit(c->getVGContext(), ((RIEGLSurface*)surface)->getDrawable()->getColorBuffer()->getImage(), 0, 0, 0, 0, target->width, target->height);	//throws bad_alloc
       
  2120         output.removeReference();
       
  2121     }
       
  2122     catch(std::bad_alloc)
       
  2123     {
       
  2124     }
       
  2125     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  2126 #else
       
  2127     (void)dpy;
       
  2128     (void)surface;
       
  2129     (void)target;
       
  2130     return EGL_FALSE;
       
  2131 #endif
       
  2132 }
       
  2133 
       
  2134 /*-------------------------------------------------------------------*//*!
       
  2135 * \brief
       
  2136 * \param
       
  2137 * \return
       
  2138 * \note		We support only swap interval one
       
  2139 *//*-------------------------------------------------------------------*/
       
  2140 
       
  2141 EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
       
  2142 {
       
  2143     EGL_GET_DISPLAY(dpy, EGL_FALSE);
       
  2144     EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE);
       
  2145     RI_UNREF(interval);
       
  2146     EGL_RETURN(EGL_SUCCESS, EGL_TRUE);
       
  2147 }
       
  2148 
       
  2149 /*-------------------------------------------------------------------*//*!
       
  2150 * \brief
       
  2151 * \param
       
  2152 * \return
       
  2153 * \note
       
  2154 *//*-------------------------------------------------------------------*/
       
  2155 
       
  2156 typedef void RI_Proc();
       
  2157 
       
  2158 __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
       
  2159 {
       
  2160     if(!procname)
       
  2161         return NULL;
       
  2162     return NULL;
       
  2163 }
       
  2164 
       
  2165 /*-------------------------------------------------------------------*//*!
       
  2166 * \brief
       
  2167 * \param
       
  2168 * \return
       
  2169 * \note
       
  2170 *//*-------------------------------------------------------------------*/
       
  2171 
       
  2172 EGLBoolean EGLAPIENTRY eglReleaseThread(void)
       
  2173 {
       
  2174     EGL_GET_EGL(EGL_FALSE);
       
  2175 
       
  2176     //check if the thread is current
       
  2177     RIEGLThread* thread = egl->getCurrentThread();
       
  2178     if(thread)
       
  2179     {	//thread is current, release the old bindings and remove the thread from the current thread list
       
  2180         RIEGLContext* pc = thread->getCurrentContext();
       
  2181         RIEGLSurface* ps = thread->getCurrentSurface();
       
  2182         if(pc)
       
  2183         {
       
  2184             vgFlush();
       
  2185             pc->getVGContext()->setDefaultDrawable(NULL);
       
  2186             if(!pc->removeReference())
       
  2187                 RI_DELETE(pc);
       
  2188         }
       
  2189         if(ps)
       
  2190         {
       
  2191             if(!ps->removeReference())
       
  2192                 RI_DELETE(ps);
       
  2193         }
       
  2194 
       
  2195         egl->removeCurrentThread(thread);
       
  2196     }
       
  2197 
       
  2198     //destroy EGL's thread struct
       
  2199     egl->destroyThread();
       
  2200 
       
  2201     //destroy the EGL instance
       
  2202     releaseEGL();
       
  2203 
       
  2204     OSReleaseMutex();
       
  2205     OSDeinitMutex();
       
  2206 
       
  2207     return EGL_SUCCESS;
       
  2208 }
       
  2209 
       
  2210 #undef EGL_NUMCONFIGS