b720750eac9a419c672020793c2acf7c050f23d6
[mesa.git] / src / mesa / drivers / dri / common / drisw_util.c
1 /*
2 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file drisw_util.c
26 *
27 * DRISW utility functions, i.e. dri_util.c stripped from drm-specific bits.
28 */
29
30 #include "dri_util.h"
31 #include "utils.h"
32
33
34 /**
35 * Screen functions
36 */
37
38 static void
39 setupLoaderExtensions(__DRIscreen *psp,
40 const __DRIextension **extensions)
41 {
42 int i;
43
44 for (i = 0; extensions[i]; i++) {
45 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0)
46 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
47 }
48 }
49
50 static __DRIscreen *
51 driCreateNewScreen(int scrn, const __DRIextension **extensions,
52 const __DRIconfig ***driver_configs, void *data)
53 {
54 static const __DRIextension *emptyExtensionList[] = { NULL };
55 __DRIscreen *psp;
56
57 (void) data;
58
59 psp = CALLOC_STRUCT(__DRIscreenRec);
60 if (!psp)
61 return NULL;
62
63 setupLoaderExtensions(psp, extensions);
64
65 psp->extensions = emptyExtensionList;
66 psp->fd = -1;
67 psp->myNum = scrn;
68
69 *driver_configs = driDriverAPI.InitScreen(psp);
70
71 if (*driver_configs == NULL) {
72 FREE(psp);
73 return NULL;
74 }
75
76 return psp;
77 }
78
79 static void driDestroyScreen(__DRIscreen *psp)
80 {
81 if (psp) {
82 driDriverAPI.DestroyScreen(psp);
83
84 FREE(psp);
85 }
86 }
87
88 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
89 {
90 return psp->extensions;
91 }
92
93
94 /**
95 * Context functions
96 */
97
98 static __DRIcontext *
99 driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
100 __DRIcontext *shared, void *data)
101 {
102 __DRIcontext *pcp;
103 void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
104
105 pcp = CALLOC_STRUCT(__DRIcontextRec);
106 if (!pcp)
107 return NULL;
108
109 pcp->loaderPrivate = data;
110
111 pcp->driScreenPriv = psp;
112 pcp->driDrawablePriv = NULL;
113 pcp->driReadablePriv = NULL;
114
115 if (!driDriverAPI.CreateContext(API_OPENGL,
116 &config->modes, pcp, shareCtx)) {
117 FREE(pcp);
118 return NULL;
119 }
120
121 return pcp;
122 }
123
124 static __DRIcontext *
125 driCreateNewContextForAPI(__DRIscreen *psp, int api,
126 const __DRIconfig *config,
127 __DRIcontext *shared, void *data)
128 {
129 __DRIcontext *pcp;
130 void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
131 gl_api mesa_api;
132
133 switch (api) {
134 case __DRI_API_OPENGL:
135 mesa_api = API_OPENGL;
136 break;
137 case __DRI_API_GLES:
138 mesa_api = API_OPENGLES;
139 break;
140 case __DRI_API_GLES2:
141 mesa_api = API_OPENGLES2;
142 break;
143 default:
144 return NULL;
145 }
146
147 pcp = CALLOC_STRUCT(__DRIcontextRec);
148 if (!pcp)
149 return NULL;
150
151 pcp->loaderPrivate = data;
152
153 pcp->driScreenPriv = psp;
154 pcp->driDrawablePriv = NULL;
155 pcp->driReadablePriv = NULL;
156
157 if (!driDriverAPI.CreateContext(mesa_api,
158 &config->modes, pcp, shareCtx)) {
159 FREE(pcp);
160 return NULL;
161 }
162
163 return pcp;
164 }
165
166 static void
167 driDestroyContext(__DRIcontext *pcp)
168 {
169 if (pcp) {
170 driDriverAPI.DestroyContext(pcp);
171 FREE(pcp);
172 }
173 }
174
175 static int
176 driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask)
177 {
178 return GL_FALSE;
179 }
180
181 static void dri_get_drawable(__DRIdrawable *pdp);
182 static void dri_put_drawable(__DRIdrawable *pdp);
183
184 static int driBindContext(__DRIcontext *pcp,
185 __DRIdrawable *pdp,
186 __DRIdrawable *prp)
187 {
188 /* Bind the drawable to the context */
189 if (pcp) {
190 pcp->driDrawablePriv = pdp;
191 pcp->driReadablePriv = prp;
192 if (pdp) {
193 pdp->driContextPriv = pcp;
194 dri_get_drawable(pdp);
195 }
196 if ( prp && pdp != prp ) {
197 dri_get_drawable(prp);
198 }
199 }
200
201 return driDriverAPI.MakeCurrent(pcp, pdp, prp);
202 }
203
204 static int driUnbindContext(__DRIcontext *pcp)
205 {
206 __DRIdrawable *pdp;
207 __DRIdrawable *prp;
208
209 if (pcp == NULL)
210 return GL_FALSE;
211
212 pdp = pcp->driDrawablePriv;
213 prp = pcp->driReadablePriv;
214
215 /* already unbound */
216 if (!pdp && !prp)
217 return GL_TRUE;
218
219 driDriverAPI.UnbindContext(pcp);
220
221 dri_put_drawable(pdp);
222
223 if (prp != pdp) {
224 dri_put_drawable(prp);
225 }
226
227 pcp->driDrawablePriv = NULL;
228 pcp->driReadablePriv = NULL;
229
230 return GL_TRUE;
231 }
232
233
234 /**
235 * Drawable functions
236 */
237
238 static void dri_get_drawable(__DRIdrawable *pdp)
239 {
240 pdp->refcount++;
241 }
242
243 static void dri_put_drawable(__DRIdrawable *pdp)
244 {
245 if (pdp) {
246 pdp->refcount--;
247 if (pdp->refcount)
248 return;
249
250 driDriverAPI.DestroyBuffer(pdp);
251
252 FREE(pdp);
253 }
254 }
255
256 static __DRIdrawable *
257 driCreateNewDrawable(__DRIscreen *psp,
258 const __DRIconfig *config, void *data)
259 {
260 __DRIdrawable *pdp;
261
262 pdp = CALLOC_STRUCT(__DRIdrawableRec);
263 if (!pdp)
264 return NULL;
265
266 pdp->loaderPrivate = data;
267
268 pdp->driScreenPriv = psp;
269 pdp->driContextPriv = NULL;
270
271 dri_get_drawable(pdp);
272
273 if (!driDriverAPI.CreateBuffer(psp, pdp, &config->modes, GL_FALSE)) {
274 FREE(pdp);
275 return NULL;
276 }
277
278 pdp->lastStamp = 1; /* const */
279
280 return pdp;
281 }
282
283 static void
284 driDestroyDrawable(__DRIdrawable *pdp)
285 {
286 dri_put_drawable(pdp);
287 }
288
289 static void driSwapBuffers(__DRIdrawable *pdp)
290 {
291 driDriverAPI.SwapBuffers(pdp);
292 }
293
294 const __DRIcoreExtension driCoreExtension = {
295 { __DRI_CORE, __DRI_CORE_VERSION },
296 NULL, /* driCreateNewScreen */
297 driDestroyScreen,
298 driGetExtensions,
299 driGetConfigAttrib,
300 driIndexConfigAttrib,
301 NULL, /* driCreateNewDrawable */
302 driDestroyDrawable,
303 driSwapBuffers,
304 driCreateNewContext,
305 driCopyContext,
306 driDestroyContext,
307 driBindContext,
308 driUnbindContext
309 };
310
311 const __DRIswrastExtension driSWRastExtension = {
312 { __DRI_SWRAST, __DRI_SWRAST_VERSION },
313 driCreateNewScreen,
314 driCreateNewDrawable,
315 driCreateNewContextForAPI
316 };