1 /*
2 * Copyright (c) 2016, NVIDIA CORPORATION.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and/or associated documentation files (the
6 * "Materials"), to deal in the Materials without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Materials, and to
9 * permit persons to whom the Materials are furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * unaltered in all copies or substantial portions of the Materials.
14 * Any additions, deletions, or changes to the original source files
15 * must be clearly indicated in accompanying documentation.
16 *
17 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
24 */
25
26 #include "winsys_dispatch.h"
27
28 #include "glvnd_pthread.h"
29 #include "lkdhash.h"
30 #include <assert.h>
31
32 // The initial size to use when we allocate the function list. This is large
33 // enough to hold all of the functions defined in libGLX.
34 #define INITIAL_LIST_SIZE 64
35
36 typedef struct __GLVNDwinsysDispatchIndexEntryRec {
37 char *name;
38 void *dispatchFunc;
39 } __GLVNDwinsysDispatchIndexEntry;
40
41 static __GLVNDwinsysDispatchIndexEntry *dispatchIndexList = NULL;
42 static int dispatchIndexCount = 0;
43 static int dispatchIndexAllocCount = 0;
44
__glvndWinsysDispatchInit(void)45 void __glvndWinsysDispatchInit(void)
46 {
47 // Nothing to do.
48 }
49
__glvndWinsysDispatchCleanup(void)50 void __glvndWinsysDispatchCleanup(void)
51 {
52 int i;
53
54 for (i=0; i<dispatchIndexCount; i++) {
55 free(dispatchIndexList[i].name);
56 }
57 free(dispatchIndexList);
58 dispatchIndexList = NULL;
59 dispatchIndexCount = dispatchIndexAllocCount = 0;
60 }
61
62
__glvndWinsysDispatchFindIndex(const char * name)63 int __glvndWinsysDispatchFindIndex(const char *name)
64 {
65 int i;
66
67 for (i=0; i<dispatchIndexCount; i++) {
68 if (strcmp(dispatchIndexList[i].name, name) == 0) {
69 return i;
70 }
71 }
72
73 return -1;
74 }
75
__glvndWinsysDispatchAllocIndex(const char * name,void * dispatch)76 int __glvndWinsysDispatchAllocIndex(const char *name, void *dispatch)
77 {
78 assert(__glvndWinsysDispatchFindIndex(name) < 0);
79
80 if (dispatchIndexCount == dispatchIndexAllocCount) {
81 __GLVNDwinsysDispatchIndexEntry *newList;
82 int newSize = dispatchIndexAllocCount * 2;
83 if (newSize <= 0) {
84 newSize = INITIAL_LIST_SIZE;
85 }
86
87 newList = realloc(dispatchIndexList, newSize * sizeof(__GLVNDwinsysDispatchIndexEntry));
88 if (newList == NULL) {
89 return -1;
90 }
91
92 dispatchIndexList = newList;
93 dispatchIndexAllocCount = newSize;
94 }
95
96 dispatchIndexList[dispatchIndexCount].name = strdup(name);
97 if (dispatchIndexList[dispatchIndexCount].name == NULL) {
98 return -1;
99 }
100
101 dispatchIndexList[dispatchIndexCount].dispatchFunc = dispatch;
102 return dispatchIndexCount++;
103 }
104
__glvndWinsysDispatchGetName(int index)105 const char *__glvndWinsysDispatchGetName(int index)
106 {
107 if (index >= 0 && index < dispatchIndexCount) {
108 return dispatchIndexList[index].name;
109 } else {
110 return NULL;
111 }
112 }
113
__glvndWinsysDispatchGetDispatch(int index)114 void *__glvndWinsysDispatchGetDispatch(int index)
115 {
116 if (index >= 0 && index < dispatchIndexCount) {
117 return dispatchIndexList[index].dispatchFunc;
118 } else {
119 return NULL;
120 }
121 }
122
__glvndWinsysDispatchGetCount(void)123 int __glvndWinsysDispatchGetCount(void)
124 {
125 return dispatchIndexCount;
126 }
127
128
129 typedef struct __GLVNDwinsysDispatchFuncHashRec {
130 int index;
131 void *implFunc;
132 UT_hash_handle hh;
133 } __GLVNDwinsysDispatchFuncHash;
134
135 struct __GLVNDwinsysVendorDispatchRec {
136 DEFINE_LKDHASH(__GLVNDwinsysDispatchFuncHash, table);
137 };
138
__glvndWinsysVendorDispatchCreate(void)139 __GLVNDwinsysVendorDispatch *__glvndWinsysVendorDispatchCreate(void)
140 {
141 __GLVNDwinsysVendorDispatch *table = (__GLVNDwinsysVendorDispatch *)
142 malloc(sizeof(__GLVNDwinsysVendorDispatch));
143 if (table == NULL) {
144 return NULL;
145 }
146
147 LKDHASH_INIT(table->table);
148 return table;
149 }
150
__glvndWinsysVendorDispatchDestroy(__GLVNDwinsysVendorDispatch * table)151 void __glvndWinsysVendorDispatchDestroy(__GLVNDwinsysVendorDispatch *table)
152 {
153 if (table != NULL) {
154 LKDHASH_TEARDOWN(__GLVNDwinsysDispatchFuncHash,
155 table->table, NULL, NULL, 0);
156 free(table);
157 }
158 }
159
__glvndWinsysVendorDispatchAddFunc(__GLVNDwinsysVendorDispatch * table,int index,void * func)160 int __glvndWinsysVendorDispatchAddFunc(__GLVNDwinsysVendorDispatch *table, int index, void *func)
161 {
162 __GLVNDwinsysDispatchFuncHash *entry;
163
164 LKDHASH_WRLOCK(table->table);
165 HASH_FIND_INT(_LH(table->table), &index, entry);
166 if (entry == NULL) {
167 entry = (__GLVNDwinsysDispatchFuncHash *) malloc(sizeof(__GLVNDwinsysDispatchFuncHash));
168 if (entry == NULL) {
169 LKDHASH_UNLOCK(table->table);
170 return -1;
171 }
172
173 entry->index = index;
174 HASH_ADD_INT(_LH(table->table), index, entry);
175 }
176 entry->implFunc = func;
177 LKDHASH_UNLOCK(table->table);
178 return 0;
179 }
180
__glvndWinsysVendorDispatchLookupFunc(__GLVNDwinsysVendorDispatch * table,int index)181 void *__glvndWinsysVendorDispatchLookupFunc(__GLVNDwinsysVendorDispatch *table, int index)
182 {
183 __GLVNDwinsysDispatchFuncHash *entry;
184 void *func;
185
186 LKDHASH_RDLOCK(table->table);
187 HASH_FIND_INT(_LH(table->table), &index, entry);
188 if (entry != NULL) {
189 func = entry->implFunc;
190 } else {
191 func = NULL;
192 }
193 LKDHASH_UNLOCK(table->table);
194
195 return func;
196 }
197
198