Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2010 Linaro Limited
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * Contributor(s):
  29.  *      Alexandros Frantzis <alexandros.frantzis@linaro.org>
  30.  */
  31.  
  32. #include "cairoint.h"
  33. #include "cairo-gl-private.h"
  34. #include "cairo-gl-dispatch-private.h"
  35. #if CAIRO_HAS_DLSYM
  36. #include <dlfcn.h>
  37. #endif
  38.  
  39. #if CAIRO_HAS_DLSYM
  40. static void *
  41. _cairo_gl_dispatch_open_lib (void)
  42. {
  43.     return dlopen (NULL, RTLD_LAZY);
  44. }
  45.  
  46. static void
  47. _cairo_gl_dispatch_close_lib (void *handle)
  48. {
  49.     dlclose (handle);
  50. }
  51.  
  52. static cairo_gl_generic_func_t
  53. _cairo_gl_dispatch_get_proc_addr (void *handle, const char *name)
  54. {
  55.     return (cairo_gl_generic_func_t) dlsym (handle, name);
  56. }
  57. #else
  58. static void *
  59. _cairo_gl_dispatch_open_lib (void)
  60. {
  61.     return NULL;
  62. }
  63.  
  64. static void
  65. _cairo_gl_dispatch_close_lib (void *handle)
  66. {
  67.     return;
  68. }
  69.  
  70. static cairo_gl_generic_func_t
  71. _cairo_gl_dispatch_get_proc_addr (void *handle, const char *name)
  72. {
  73.     return NULL;
  74. }
  75. #endif /* CAIRO_HAS_DLSYM */
  76.  
  77.  
  78. static void
  79. _cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch,
  80.                                  cairo_gl_get_proc_addr_func_t get_proc_addr,
  81.                                  cairo_gl_dispatch_entry_t *entries,
  82.                                  cairo_gl_dispatch_name_t dispatch_name)
  83. {
  84.     cairo_gl_dispatch_entry_t *entry = entries;
  85.     void *handle = _cairo_gl_dispatch_open_lib ();
  86.  
  87.     while (entry->name[CAIRO_GL_DISPATCH_NAME_CORE] != NULL) {
  88.         void *dispatch_ptr = &((char *) dispatch)[entry->offset];
  89.         const char *name = entry->name[dispatch_name];
  90.  
  91.         /*
  92.          * In strictly conforming EGL implementations, eglGetProcAddress() can
  93.          * be used only to get extension functions, but some of the functions
  94.          * we want belong to core GL(ES). If the *GetProcAddress function
  95.          * provided by the context fails, try to get the address of the wanted
  96.          * GL function using standard system facilities (eg dlsym() in *nix
  97.          * systems).
  98.          */
  99.         cairo_gl_generic_func_t func = get_proc_addr (name);
  100.         if (func == NULL)
  101.             func = _cairo_gl_dispatch_get_proc_addr (handle, name);
  102.  
  103.         *((cairo_gl_generic_func_t *) dispatch_ptr) = func;
  104.  
  105.         ++entry;
  106.     }
  107.  
  108.     _cairo_gl_dispatch_close_lib (handle);
  109. }
  110.  
  111. static cairo_status_t
  112. _cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch,
  113.                                  cairo_gl_get_proc_addr_func_t get_proc_addr,
  114.                                  int gl_version, cairo_gl_flavor_t gl_flavor)
  115. {
  116.     cairo_gl_dispatch_name_t dispatch_name;
  117.  
  118.     if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
  119.     {
  120.         if (gl_version >= CAIRO_GL_VERSION_ENCODE (1, 5))
  121.             dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
  122.         else if (_cairo_gl_has_extension ("GL_ARB_vertex_buffer_object"))
  123.             dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
  124.         else
  125.             return CAIRO_STATUS_DEVICE_ERROR;
  126.     }
  127.     else if (gl_flavor == CAIRO_GL_FLAVOR_ES &&
  128.              gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
  129.     {
  130.         dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
  131.     }
  132.     else
  133.     {
  134.         return CAIRO_STATUS_DEVICE_ERROR;
  135.     }
  136.  
  137.     _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
  138.                                      dispatch_buffers_entries, dispatch_name);
  139.  
  140.     return CAIRO_STATUS_SUCCESS;
  141. }
  142.  
  143. static cairo_status_t
  144. _cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t *dispatch,
  145.                                  cairo_gl_get_proc_addr_func_t get_proc_addr,
  146.                                  int gl_version, cairo_gl_flavor_t gl_flavor)
  147. {
  148.     cairo_gl_dispatch_name_t dispatch_name;
  149.  
  150.     if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
  151.     {
  152.         if (gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
  153.             dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
  154.         else if (_cairo_gl_has_extension ("GL_ARB_shader_objects"))
  155.             dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
  156.         else
  157.             return CAIRO_STATUS_DEVICE_ERROR;
  158.     }
  159.     else if (gl_flavor == CAIRO_GL_FLAVOR_ES &&
  160.              gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
  161.     {
  162.         dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
  163.     }
  164.     else
  165.     {
  166.         return CAIRO_STATUS_DEVICE_ERROR;
  167.     }
  168.  
  169.     _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
  170.                                      dispatch_shaders_entries, dispatch_name);
  171.  
  172.     return CAIRO_STATUS_SUCCESS;
  173. }
  174.  
  175. static cairo_status_t
  176. _cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t *dispatch,
  177.                              cairo_gl_get_proc_addr_func_t get_proc_addr,
  178.                              int gl_version, cairo_gl_flavor_t gl_flavor)
  179. {
  180.     cairo_gl_dispatch_name_t dispatch_name;
  181.  
  182.     if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
  183.     {
  184.         if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
  185.             _cairo_gl_has_extension ("GL_ARB_framebuffer_object"))
  186.             dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
  187.         else if (_cairo_gl_has_extension ("GL_EXT_framebuffer_object"))
  188.             dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
  189.         else
  190.             return CAIRO_STATUS_DEVICE_ERROR;
  191.     }
  192.     else if (gl_flavor == CAIRO_GL_FLAVOR_ES &&
  193.              gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
  194.     {
  195.         dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
  196.     }
  197.     else
  198.     {
  199.         return CAIRO_STATUS_DEVICE_ERROR;
  200.     }
  201.  
  202.     _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
  203.                                      dispatch_fbo_entries, dispatch_name);
  204.  
  205.     return CAIRO_STATUS_SUCCESS;
  206. }
  207.  
  208. static cairo_status_t
  209. _cairo_gl_dispatch_init_multisampling (cairo_gl_dispatch_t *dispatch,
  210.                                        cairo_gl_get_proc_addr_func_t get_proc_addr,
  211.                                        int gl_version,
  212.                                        cairo_gl_flavor_t gl_flavor)
  213. {
  214.     /* For the multisampling table, there are two GLES versions of the
  215.      * extension, so we put one in the EXT slot and one in the real ES slot.*/
  216.     cairo_gl_dispatch_name_t dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
  217.     if (gl_flavor == CAIRO_GL_FLAVOR_ES) {
  218.         if (_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture"))
  219.             dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
  220.         else if (_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture"))
  221.             dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
  222.     }
  223.     _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
  224.                                      dispatch_multisampling_entries,
  225.                                      dispatch_name);
  226.     return CAIRO_STATUS_SUCCESS;
  227. }
  228.  
  229. cairo_status_t
  230. _cairo_gl_dispatch_init (cairo_gl_dispatch_t *dispatch,
  231.                          cairo_gl_get_proc_addr_func_t get_proc_addr)
  232. {
  233.     cairo_status_t status;
  234.     int gl_version;
  235.     cairo_gl_flavor_t gl_flavor;
  236.  
  237.     gl_version = _cairo_gl_get_version ();
  238.     gl_flavor = _cairo_gl_get_flavor ();
  239.  
  240.     status = _cairo_gl_dispatch_init_buffers (dispatch, get_proc_addr,
  241.                                               gl_version, gl_flavor);
  242.     if (status != CAIRO_STATUS_SUCCESS)
  243.         return status;
  244.  
  245.     status = _cairo_gl_dispatch_init_shaders (dispatch, get_proc_addr,
  246.                                               gl_version, gl_flavor);
  247.     if (status != CAIRO_STATUS_SUCCESS)
  248.         return status;
  249.  
  250.     status = _cairo_gl_dispatch_init_fbo (dispatch, get_proc_addr,
  251.                                           gl_version, gl_flavor);
  252.     if (status != CAIRO_STATUS_SUCCESS)
  253.         return status;
  254.  
  255.     status = _cairo_gl_dispatch_init_multisampling (dispatch, get_proc_addr,
  256.                                                     gl_version, gl_flavor);
  257.     if (status != CAIRO_STATUS_SUCCESS)
  258.         return status;
  259.  
  260.     return CAIRO_STATUS_SUCCESS;
  261. }
  262.