dri2: Add createContextAttribs entry point for DRISW version 3
[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 psp = CALLOC_STRUCT(__DRIscreenRec);
58 if (!psp)
59 return NULL;
60
61 setupLoaderExtensions(psp, extensions);
62
63 psp->loaderPrivate = data;
64
65 psp->extensions = emptyExtensionList;
66 psp->fd = -1;
67 psp->myNum = scrn;
68
69 *driver_configs = driDriverAPI.InitScreen(psp);
70 if (*driver_configs == NULL) {
71 FREE(psp);
72 return NULL;
73 }
74
75 return psp;
76 }
77
78 static void driDestroyScreen(__DRIscreen *psp)
79 {
80 if (psp) {
81 driDriverAPI.DestroyScreen(psp);
82 FREE(psp);
83 }
84 }
85
86 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
87 {
88 return psp->extensions;
89 }
90
91
92 /**
93 * Context functions
94 */
95
96 static __DRIcontext *
97 driCreateNewContextForAPI(__DRIscreen *psp, int api,
98 const __DRIconfig *config,
99 __DRIcontext *shared, void *data)
100 {
101 __DRIcontext *pcp;
102 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
103 void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
104 gl_api mesa_api;
105
106 switch (api) {
107 case __DRI_API_OPENGL:
108 mesa_api = API_OPENGL;
109 break;
110 case __DRI_API_GLES:
111 mesa_api = API_OPENGLES;
112 break;
113 case __DRI_API_GLES2:
114 mesa_api = API_OPENGLES2;
115 break;
116 default:
117 return NULL;
118 }
119
120 pcp = CALLOC_STRUCT(__DRIcontextRec);
121 if (!pcp)
122 return NULL;
123
124 pcp->loaderPrivate = data;
125
126 pcp->driScreenPriv = psp;
127 pcp->driDrawablePriv = NULL;
128 pcp->driReadablePriv = NULL;
129
130 if (!driDriverAPI.CreateContext(mesa_api, modes, pcp, shareCtx)) {
131 FREE(pcp);
132 return NULL;
133 }
134
135 return pcp;
136 }
137
138 static __DRIcontext *
139 driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
140 __DRIcontext *shared, void *data)
141 {
142 return driCreateNewContextForAPI(psp, __DRI_API_OPENGL,
143 config, shared, data);
144 }
145
146 static void
147 driDestroyContext(__DRIcontext *pcp)
148 {
149 if (pcp) {
150 driDriverAPI.DestroyContext(pcp);
151 FREE(pcp);
152 }
153 }
154
155 static int
156 driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask)
157 {
158 return GL_FALSE;
159 }
160
161 static void dri_get_drawable(__DRIdrawable *pdp);
162 static void dri_put_drawable(__DRIdrawable *pdp);
163
164 static int driBindContext(__DRIcontext *pcp,
165 __DRIdrawable *pdp,
166 __DRIdrawable *prp)
167 {
168 /* Bind the drawable to the context */
169 if (pcp) {
170 pcp->driDrawablePriv = pdp;
171 pcp->driReadablePriv = prp;
172 if (pdp) {
173 pdp->driContextPriv = pcp;
174 dri_get_drawable(pdp);
175 }
176 if (prp && pdp != prp) {
177 dri_get_drawable(prp);
178 }
179 }
180
181 return driDriverAPI.MakeCurrent(pcp, pdp, prp);
182 }
183
184 static int driUnbindContext(__DRIcontext *pcp)
185 {
186 __DRIdrawable *pdp;
187 __DRIdrawable *prp;
188
189 if (pcp == NULL)
190 return GL_FALSE;
191
192 pdp = pcp->driDrawablePriv;
193 prp = pcp->driReadablePriv;
194
195 /* already unbound */
196 if (!pdp && !prp)
197 return GL_TRUE;
198
199 driDriverAPI.UnbindContext(pcp);
200
201 dri_put_drawable(pdp);
202
203 if (prp != pdp) {
204 dri_put_drawable(prp);
205 }
206
207 pcp->driDrawablePriv = NULL;
208 pcp->driReadablePriv = NULL;
209
210 return GL_TRUE;
211 }
212
213
214 /**
215 * Drawable functions
216 */
217
218 static void dri_get_drawable(__DRIdrawable *pdp)
219 {
220 pdp->refcount++;
221 }
222
223 static void dri_put_drawable(__DRIdrawable *pdp)
224 {
225 if (pdp) {
226 pdp->refcount--;
227 if (pdp->refcount)
228 return;
229
230 driDriverAPI.DestroyBuffer(pdp);
231 FREE(pdp);
232 }
233 }
234
235 static __DRIdrawable *
236 driCreateNewDrawable(__DRIscreen *psp,
237 const __DRIconfig *config, void *data)
238 {
239 __DRIdrawable *pdp;
240
241 pdp = CALLOC_STRUCT(__DRIdrawableRec);
242 if (!pdp)
243 return NULL;
244
245 pdp->loaderPrivate = data;
246
247 pdp->driScreenPriv = psp;
248 pdp->driContextPriv = NULL;
249
250 dri_get_drawable(pdp);
251
252 if (!driDriverAPI.CreateBuffer(psp, pdp, &config->modes, GL_FALSE)) {
253 FREE(pdp);
254 return NULL;
255 }
256
257 pdp->lastStamp = 1; /* const */
258
259 return pdp;
260 }
261
262 static void
263 driDestroyDrawable(__DRIdrawable *pdp)
264 {
265 dri_put_drawable(pdp);
266 }
267
268 static void driSwapBuffers(__DRIdrawable *pdp)
269 {
270 driDriverAPI.SwapBuffers(pdp);
271 }
272
273 const __DRIcoreExtension driCoreExtension = {
274 { __DRI_CORE, __DRI_CORE_VERSION },
275 NULL, /* driCreateNewScreen */
276 driDestroyScreen,
277 driGetExtensions,
278 driGetConfigAttrib,
279 driIndexConfigAttrib,
280 NULL, /* driCreateNewDrawable */
281 driDestroyDrawable,
282 driSwapBuffers,
283 driCreateNewContext,
284 driCopyContext,
285 driDestroyContext,
286 driBindContext,
287 driUnbindContext
288 };
289
290 const __DRIswrastExtension driSWRastExtension = {
291 /* Force the version to 2 because the underlying driver don't (can't!)
292 * support the extra requirements of CreateContextAttribs.
293 */
294 { __DRI_SWRAST, 2 },
295 driCreateNewScreen,
296 driCreateNewDrawable,
297 driCreateNewContextForAPI,
298 NULL
299 };