• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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