Home | History | Annotate | Download | only in mapi
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.9
      4  *
      5  * Copyright (C) 2010 LunarG Inc.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  *
     25  * Authors:
     26  *    Chia-I Wu <olv (at) lunarg.com>
     27  */
     28 
     29 #include <stdlib.h>
     30 #include <string.h>
     31 
     32 #include "u_current.h"
     33 #include "u_thread.h"
     34 #include "mapi.h"
     35 #include "stub.h"
     36 #include "table.h"
     37 
     38 /* dynamic stubs will run out before this array */
     39 static const struct mapi_stub *mapi_stub_map[MAPI_TABLE_NUM_SLOTS];
     40 static int mapi_num_stubs;
     41 
     42 static const struct mapi_stub *
     43 get_stub(const char *name, const struct mapi_stub *alias)
     44 {
     45    const struct mapi_stub *stub;
     46 
     47    stub = stub_find_public(name);
     48    if (!stub) {
     49       struct mapi_stub *dyn = stub_find_dynamic(name, 1);
     50       if (dyn) {
     51          stub_fix_dynamic(dyn, alias);
     52          stub = dyn;
     53       }
     54    }
     55 
     56    return stub;
     57 }
     58 
     59 /**
     60  * Initialize mapi.  spec consists of NULL-separated strings.  The first string
     61  * denotes the version.  It is followed by variable numbers of entries.  Each
     62  * entry can have multiple names.  An empty name terminates an entry.  An empty
     63  * entry terminates the spec.  A spec of two entries, Foo and Bar, is as
     64  * follows
     65  *
     66  *   "1\0"
     67  *   "Foo\0"
     68  *   "FooEXT\0"
     69  *   "\0"
     70  *   "Bar\0"
     71  *   "\0"
     72  */
     73 void
     74 mapi_init(const char *spec)
     75 {
     76    u_mutex_declare_static(mutex);
     77    const char *p;
     78    int ver, count;
     79 
     80    u_mutex_lock(mutex);
     81 
     82    /* already initialized */
     83    if (mapi_num_stubs) {
     84       u_mutex_unlock(mutex);
     85       return;
     86    }
     87 
     88    count = 0;
     89    p = spec;
     90 
     91    /* parse version string */
     92    ver = atoi(p);
     93    if (ver != 1) {
     94       u_mutex_unlock(mutex);
     95       return;
     96    }
     97    p += strlen(p) + 1;
     98 
     99    while (*p) {
    100       const struct mapi_stub *stub;
    101 
    102       stub = get_stub(p, NULL);
    103       /* out of dynamic entries */
    104       if (!stub)
    105          break;
    106       p += strlen(p) + 1;
    107 
    108       while (*p) {
    109          get_stub(p, stub);
    110          p += strlen(p) + 1;
    111       }
    112 
    113       mapi_stub_map[count++] = stub;
    114       p++;
    115    }
    116 
    117    mapi_num_stubs = count;
    118 
    119    u_mutex_unlock(mutex);
    120 }
    121 
    122 /**
    123  * Return the address of an entry.  Optionally generate the entry if it does
    124  * not exist.
    125  */
    126 mapi_proc
    127 mapi_get_proc_address(const char *name)
    128 {
    129    const struct mapi_stub *stub;
    130 
    131    stub = stub_find_public(name);
    132    if (!stub)
    133       stub = stub_find_dynamic(name, 0);
    134 
    135    return (stub) ? (mapi_proc) stub_get_addr(stub) : NULL;
    136 }
    137 
    138 /**
    139  * Create a dispatch table.
    140  */
    141 struct mapi_table *
    142 mapi_table_create(void)
    143 {
    144    const struct mapi_table *noop = table_get_noop();
    145    struct mapi_table *tbl;
    146 
    147    tbl = malloc(MAPI_TABLE_SIZE);
    148    if (tbl)
    149       memcpy(tbl, noop, MAPI_TABLE_SIZE);
    150 
    151    return tbl;
    152 }
    153 
    154 /**
    155  * Destroy a dispatch table.
    156  */
    157 void
    158 mapi_table_destroy(struct mapi_table *tbl)
    159 {
    160    free(tbl);
    161 }
    162 
    163 /**
    164  * Fill a dispatch table.  The order of the procs is determined when mapi_init
    165  * is called.
    166  */
    167 void
    168 mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs)
    169 {
    170    const struct mapi_table *noop = table_get_noop();
    171    int i;
    172 
    173    for (i = 0; i < mapi_num_stubs; i++) {
    174       const struct mapi_stub *stub = mapi_stub_map[i];
    175       int slot = stub_get_slot(stub);
    176       mapi_func func = (mapi_func) procs[i];
    177 
    178       if (!func)
    179          func = table_get_func(noop, slot);
    180       table_set_func(tbl, slot, func);
    181    }
    182 }
    183 
    184 /**
    185  * Make a dispatch table current.
    186  */
    187 void
    188 mapi_table_make_current(const struct mapi_table *tbl)
    189 {
    190    u_current_set(tbl);
    191 }
    192