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
setupLoaderExtensions(__DRIscreen * psp,const __DRIextension ** extensions)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 *
driCreateNewScreen(int scrn,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)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
driDestroyScreen(__DRIscreen * psp)78 static void driDestroyScreen(__DRIscreen *psp)
79 {
80 if (psp) {
81 driDriverAPI.DestroyScreen(psp);
82 FREE(psp);
83 }
84 }
85
driGetExtensions(__DRIscreen * psp)86 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
87 {
88 return psp->extensions;
89 }
90
91
92 /**
93 * Context functions
94 */
95
96 static __DRIcontext *
driCreateContextAttribs(__DRIscreen * screen,int api,const __DRIconfig * config,__DRIcontext * shared,unsigned num_attribs,const uint32_t * attribs,unsigned * error,void * data)97 driCreateContextAttribs(__DRIscreen *screen, int api,
98 const __DRIconfig *config,
99 __DRIcontext *shared,
100 unsigned num_attribs,
101 const uint32_t *attribs,
102 unsigned *error,
103 void *data)
104 {
105 __DRIcontext *pcp;
106 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
107 void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
108 gl_api mesa_api;
109 unsigned major_version = 1;
110 unsigned minor_version = 0;
111 uint32_t flags = 0;
112
113 /* Either num_attribs is zero and attribs is NULL, or num_attribs is not
114 * zero and attribs is not NULL.
115 */
116 assert((num_attribs == 0) == (attribs == NULL));
117
118 switch (api) {
119 case __DRI_API_OPENGL:
120 mesa_api = API_OPENGL;
121 break;
122 case __DRI_API_GLES:
123 mesa_api = API_OPENGLES;
124 break;
125 case __DRI_API_GLES2:
126 mesa_api = API_OPENGLES2;
127 break;
128 case __DRI_API_OPENGL_CORE:
129 default:
130 return NULL;
131 }
132
133 for (unsigned i = 0; i < num_attribs; i++) {
134 switch (attribs[i * 2]) {
135 case __DRI_CTX_ATTRIB_MAJOR_VERSION:
136 major_version = attribs[i * 2 + 1];
137 break;
138 case __DRI_CTX_ATTRIB_MINOR_VERSION:
139 minor_version = attribs[i * 2 + 1];
140 break;
141 case __DRI_CTX_ATTRIB_FLAGS:
142 flags = attribs[i * 2 + 1];
143 break;
144 default:
145 /* We can't create a context that satisfies the requirements of an
146 * attribute that we don't understand. Return failure.
147 */
148 return NULL;
149 }
150 }
151
152 /* There are no forward-compatible contexts before OpenGL 3.0. The
153 * GLX_ARB_create_context spec says:
154 *
155 * "Forward-compatible contexts are defined only for OpenGL versions
156 * 3.0 and later."
157 *
158 * Moreover, Mesa can't fulfill the requirements of a forward-looking
159 * context. Return failure if a forward-looking context is requested.
160 *
161 * In Mesa, a debug context is the same as a regular context.
162 */
163 if (major_version >= 3) {
164 if ((flags & ~__DRI_CTX_FLAG_DEBUG) != 0)
165 return NULL;
166 }
167
168 pcp = CALLOC_STRUCT(__DRIcontextRec);
169 if (!pcp)
170 return NULL;
171
172 pcp->loaderPrivate = data;
173
174 pcp->driScreenPriv = screen;
175 pcp->driDrawablePriv = NULL;
176 pcp->driReadablePriv = NULL;
177
178 if (!driDriverAPI.CreateContext(mesa_api, modes, pcp,
179 major_version, minor_version,
180 flags, error, shareCtx)) {
181 FREE(pcp);
182 return NULL;
183 }
184
185 return pcp;
186 }
187
188 static __DRIcontext *
driCreateNewContextForAPI(__DRIscreen * psp,int api,const __DRIconfig * config,__DRIcontext * shared,void * data)189 driCreateNewContextForAPI(__DRIscreen *psp, int api,
190 const __DRIconfig *config,
191 __DRIcontext *shared, void *data)
192 {
193 unsigned error;
194
195 return driCreateContextAttribs(psp, api, config, shared, 0, NULL,
196 &error, data);
197 }
198
199 static __DRIcontext *
driCreateNewContext(__DRIscreen * psp,const __DRIconfig * config,__DRIcontext * shared,void * data)200 driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
201 __DRIcontext *shared, void *data)
202 {
203 return driCreateNewContextForAPI(psp, __DRI_API_OPENGL,
204 config, shared, data);
205 }
206
207 static void
driDestroyContext(__DRIcontext * pcp)208 driDestroyContext(__DRIcontext *pcp)
209 {
210 if (pcp) {
211 driDriverAPI.DestroyContext(pcp);
212 FREE(pcp);
213 }
214 }
215
216 static int
driCopyContext(__DRIcontext * dst,__DRIcontext * src,unsigned long mask)217 driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask)
218 {
219 return GL_FALSE;
220 }
221
222 static void dri_get_drawable(__DRIdrawable *pdp);
223 static void dri_put_drawable(__DRIdrawable *pdp);
224
driBindContext(__DRIcontext * pcp,__DRIdrawable * pdp,__DRIdrawable * prp)225 static int driBindContext(__DRIcontext *pcp,
226 __DRIdrawable *pdp,
227 __DRIdrawable *prp)
228 {
229 /* Bind the drawable to the context */
230 if (pcp) {
231 pcp->driDrawablePriv = pdp;
232 pcp->driReadablePriv = prp;
233 if (pdp) {
234 pdp->driContextPriv = pcp;
235 dri_get_drawable(pdp);
236 }
237 if (prp && pdp != prp) {
238 dri_get_drawable(prp);
239 }
240 }
241
242 return driDriverAPI.MakeCurrent(pcp, pdp, prp);
243 }
244
driUnbindContext(__DRIcontext * pcp)245 static int driUnbindContext(__DRIcontext *pcp)
246 {
247 __DRIdrawable *pdp;
248 __DRIdrawable *prp;
249
250 if (pcp == NULL)
251 return GL_FALSE;
252
253 pdp = pcp->driDrawablePriv;
254 prp = pcp->driReadablePriv;
255
256 /* already unbound */
257 if (!pdp && !prp)
258 return GL_TRUE;
259
260 driDriverAPI.UnbindContext(pcp);
261
262 dri_put_drawable(pdp);
263
264 if (prp != pdp) {
265 dri_put_drawable(prp);
266 }
267
268 pcp->driDrawablePriv = NULL;
269 pcp->driReadablePriv = NULL;
270
271 return GL_TRUE;
272 }
273
274
275 /**
276 * Drawable functions
277 */
278
dri_get_drawable(__DRIdrawable * pdp)279 static void dri_get_drawable(__DRIdrawable *pdp)
280 {
281 pdp->refcount++;
282 }
283
dri_put_drawable(__DRIdrawable * pdp)284 static void dri_put_drawable(__DRIdrawable *pdp)
285 {
286 if (pdp) {
287 pdp->refcount--;
288 if (pdp->refcount)
289 return;
290
291 driDriverAPI.DestroyBuffer(pdp);
292 FREE(pdp);
293 }
294 }
295
296 static __DRIdrawable *
driCreateNewDrawable(__DRIscreen * psp,const __DRIconfig * config,void * data)297 driCreateNewDrawable(__DRIscreen *psp,
298 const __DRIconfig *config, void *data)
299 {
300 __DRIdrawable *pdp;
301
302 pdp = CALLOC_STRUCT(__DRIdrawableRec);
303 if (!pdp)
304 return NULL;
305
306 pdp->loaderPrivate = data;
307
308 pdp->driScreenPriv = psp;
309 pdp->driContextPriv = NULL;
310
311 dri_get_drawable(pdp);
312
313 if (!driDriverAPI.CreateBuffer(psp, pdp, &config->modes, GL_FALSE)) {
314 FREE(pdp);
315 return NULL;
316 }
317
318 pdp->lastStamp = 1; /* const */
319
320 return pdp;
321 }
322
323 static void
driDestroyDrawable(__DRIdrawable * pdp)324 driDestroyDrawable(__DRIdrawable *pdp)
325 {
326 dri_put_drawable(pdp);
327 }
328
driSwapBuffers(__DRIdrawable * pdp)329 static void driSwapBuffers(__DRIdrawable *pdp)
330 {
331 driDriverAPI.SwapBuffers(pdp);
332 }
333
334 const __DRIcoreExtension driCoreExtension = {
335 { __DRI_CORE, __DRI_CORE_VERSION },
336 NULL, /* driCreateNewScreen */
337 driDestroyScreen,
338 driGetExtensions,
339 driGetConfigAttrib,
340 driIndexConfigAttrib,
341 NULL, /* driCreateNewDrawable */
342 driDestroyDrawable,
343 driSwapBuffers,
344 driCreateNewContext,
345 driCopyContext,
346 driDestroyContext,
347 driBindContext,
348 driUnbindContext
349 };
350
351 const __DRIswrastExtension driSWRastExtension = {
352 { __DRI_SWRAST, __DRI_SWRAST_VERSION },
353 driCreateNewScreen,
354 driCreateNewDrawable,
355 driCreateNewContextForAPI,
356 driCreateContextAttribs
357 };
358