dri: drop stray includes and typedef
[mesa.git] / src / mesa / drivers / dri / common / dri_util.c
1 /**
2 * \file dri_util.c
3 * DRI utility functions.
4 *
5 * This module acts as glue between GLX and the actual hardware driver. A DRI
6 * driver doesn't really \e have to use any of this - it's optional. But, some
7 * useful stuff is done here that otherwise would have to be duplicated in most
8 * drivers.
9 *
10 * Basically, these utility functions take care of some of the dirty details of
11 * screen initialization, context creation, context binding, DRM setup, etc.
12 *
13 * These functions are compiled into each DRI driver so libGL.so knows nothing
14 * about them.
15 */
16
17
18 #include <xf86drm.h>
19 #include "dri_util.h"
20 #include "utils.h"
21 #include "xmlpool.h"
22 #include "../glsl/glsl_parser_extras.h"
23
24 PUBLIC const char __dri2ConfigOptions[] =
25 DRI_CONF_BEGIN
26 DRI_CONF_SECTION_PERFORMANCE
27 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
28 DRI_CONF_SECTION_END
29 DRI_CONF_END;
30
31 static const uint __dri2NConfigOptions = 1;
32
33 static void dri_get_drawable(__DRIdrawable *pdp);
34 static void dri_put_drawable(__DRIdrawable *pdp);
35
36 /*****************************************************************/
37 /** \name Context (un)binding functions */
38 /*****************************************************************/
39 /*@{*/
40
41 /**
42 * Unbind context.
43 *
44 * \param scrn the screen.
45 * \param gc context.
46 *
47 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
48 *
49 * \internal
50 * This function calls __DriverAPIRec::UnbindContext, and then decrements
51 * __DRIdrawableRec::refcount which must be non-zero for a successful
52 * return.
53 *
54 * While casting the opaque private pointers associated with the parameters
55 * into their respective real types it also assures they are not \c NULL.
56 */
57 static int driUnbindContext(__DRIcontext *pcp)
58 {
59 __DRIdrawable *pdp;
60 __DRIdrawable *prp;
61
62 /*
63 ** Assume error checking is done properly in glXMakeCurrent before
64 ** calling driUnbindContext.
65 */
66
67 if (pcp == NULL)
68 return GL_FALSE;
69
70 pdp = pcp->driDrawablePriv;
71 prp = pcp->driReadablePriv;
72
73 /* already unbound */
74 if (!pdp && !prp)
75 return GL_TRUE;
76 /* Let driver unbind drawable from context */
77 driDriverAPI.UnbindContext(pcp);
78
79 assert(pdp);
80 if (pdp->refcount == 0) {
81 /* ERROR!!! */
82 return GL_FALSE;
83 }
84
85 dri_put_drawable(pdp);
86
87 if (prp != pdp) {
88 if (prp->refcount == 0) {
89 /* ERROR!!! */
90 return GL_FALSE;
91 }
92
93 dri_put_drawable(prp);
94 }
95
96
97 /* XXX this is disabled so that if we call SwapBuffers on an unbound
98 * window we can determine the last context bound to the window and
99 * use that context's lock. (BrianP, 2-Dec-2000)
100 */
101 pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
102
103 return GL_TRUE;
104 }
105
106 /**
107 * This function takes both a read buffer and a draw buffer. This is needed
108 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
109 * function.
110 */
111 static int driBindContext(__DRIcontext *pcp,
112 __DRIdrawable *pdp,
113 __DRIdrawable *prp)
114 {
115 /*
116 ** Assume error checking is done properly in glXMakeCurrent before
117 ** calling driUnbindContext.
118 */
119
120 if (!pcp)
121 return GL_FALSE;
122
123 /* Bind the drawable to the context */
124 pcp->driDrawablePriv = pdp;
125 pcp->driReadablePriv = prp;
126 if (pdp) {
127 pdp->driContextPriv = pcp;
128 dri_get_drawable(pdp);
129 }
130 if (prp && pdp != prp) {
131 dri_get_drawable(prp);
132 }
133
134 /* Call device-specific MakeCurrent */
135 return driDriverAPI.MakeCurrent(pcp, pdp, prp);
136 }
137
138 static __DRIdrawable *
139 dri2CreateNewDrawable(__DRIscreen *screen,
140 const __DRIconfig *config,
141 void *loaderPrivate)
142 {
143 __DRIdrawable *pdraw;
144
145 pdraw = malloc(sizeof *pdraw);
146 if (!pdraw)
147 return NULL;
148
149 pdraw->driContextPriv = NULL;
150 pdraw->loaderPrivate = loaderPrivate;
151 pdraw->refcount = 1;
152 pdraw->lastStamp = 0;
153 pdraw->w = 0;
154 pdraw->h = 0;
155 pdraw->driScreenPriv = screen;
156
157 if (!driDriverAPI.CreateBuffer(screen, pdraw, &config->modes, 0)) {
158 free(pdraw);
159 return NULL;
160 }
161
162 pdraw->dri2.stamp = pdraw->lastStamp + 1;
163
164 return pdraw;
165 }
166
167 static __DRIbuffer *
168 dri2AllocateBuffer(__DRIscreen *screen,
169 unsigned int attachment, unsigned int format,
170 int width, int height)
171 {
172 return driDriverAPI.AllocateBuffer(screen, attachment, format,
173 width, height);
174 }
175
176 static void
177 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
178 {
179 driDriverAPI.ReleaseBuffer(screen, buffer);
180 }
181
182
183 static int
184 dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
185 {
186 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
187 return -1;
188
189 *val = driQueryOptionb(&screen->optionCache, var);
190
191 return 0;
192 }
193
194 static int
195 dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
196 {
197 if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
198 !driCheckOption(&screen->optionCache, var, DRI_ENUM))
199 return -1;
200
201 *val = driQueryOptioni(&screen->optionCache, var);
202
203 return 0;
204 }
205
206 static int
207 dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
208 {
209 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
210 return -1;
211
212 *val = driQueryOptionf(&screen->optionCache, var);
213
214 return 0;
215 }
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 __DRIscreen *psp;
226
227 if (pdp) {
228 pdp->refcount--;
229 if (pdp->refcount)
230 return;
231
232 psp = pdp->driScreenPriv;
233 driDriverAPI.DestroyBuffer(pdp);
234 free(pdp);
235 }
236 }
237
238 static void
239 driDestroyDrawable(__DRIdrawable *pdp)
240 {
241 dri_put_drawable(pdp);
242 }
243
244 /*@}*/
245
246
247 /*****************************************************************/
248 /** \name Context handling functions */
249 /*****************************************************************/
250 /*@{*/
251
252 /**
253 * Destroy the per-context private information.
254 *
255 * \internal
256 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
257 * drmDestroyContext(), and finally frees \p contextPrivate.
258 */
259 static void
260 driDestroyContext(__DRIcontext *pcp)
261 {
262 if (pcp) {
263 driDriverAPI.DestroyContext(pcp);
264 free(pcp);
265 }
266 }
267
268 static unsigned int
269 dri2GetAPIMask(__DRIscreen *screen)
270 {
271 return screen->api_mask;
272 }
273
274 static __DRIcontext *
275 dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
276 const __DRIconfig *config,
277 __DRIcontext *shared, void *data)
278 {
279 __DRIcontext *context;
280 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
281 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
282 gl_api mesa_api;
283
284 if (!(screen->api_mask & (1 << api)))
285 return NULL;
286
287 switch (api) {
288 case __DRI_API_OPENGL:
289 mesa_api = API_OPENGL;
290 break;
291 case __DRI_API_GLES:
292 mesa_api = API_OPENGLES;
293 break;
294 case __DRI_API_GLES2:
295 mesa_api = API_OPENGLES2;
296 break;
297 default:
298 return NULL;
299 }
300
301 context = malloc(sizeof *context);
302 if (!context)
303 return NULL;
304
305 context->driScreenPriv = screen;
306 context->driDrawablePriv = NULL;
307 context->loaderPrivate = data;
308
309 if (!driDriverAPI.CreateContext(mesa_api, modes,
310 context, shareCtx) ) {
311 free(context);
312 return NULL;
313 }
314
315 return context;
316 }
317
318
319 static __DRIcontext *
320 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
321 __DRIcontext *shared, void *data)
322 {
323 return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
324 config, shared, data);
325 }
326
327 static int
328 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
329 {
330 (void) dest;
331 (void) src;
332 (void) mask;
333 return GL_FALSE;
334 }
335
336 /*@}*/
337
338
339 /*****************************************************************/
340 /** \name Screen handling functions */
341 /*****************************************************************/
342 /*@{*/
343
344 /**
345 * Destroy the per-screen private information.
346 *
347 * \internal
348 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
349 * drmClose(), and finally frees \p screenPrivate.
350 */
351 static void driDestroyScreen(__DRIscreen *psp)
352 {
353 if (psp) {
354 /* No interaction with the X-server is possible at this point. This
355 * routine is called after XCloseDisplay, so there is no protocol
356 * stream open to the X-server anymore.
357 */
358
359 _mesa_destroy_shader_compiler();
360
361 if (driDriverAPI.DestroyScreen)
362 driDriverAPI.DestroyScreen(psp);
363
364 driDestroyOptionCache(&psp->optionCache);
365 driDestroyOptionInfo(&psp->optionInfo);
366
367 free(psp);
368 }
369 }
370
371 static void
372 setupLoaderExtensions(__DRIscreen *psp,
373 const __DRIextension **extensions)
374 {
375 int i;
376
377 for (i = 0; extensions[i]; i++) {
378 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
379 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
380 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
381 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
382 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
383 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
384 }
385 }
386
387 /**
388 * DRI2
389 */
390 static __DRIscreen *
391 dri2CreateNewScreen(int scrn, int fd,
392 const __DRIextension **extensions,
393 const __DRIconfig ***driver_configs, void *data)
394 {
395 static const __DRIextension *emptyExtensionList[] = { NULL };
396 __DRIscreen *psp;
397 drmVersionPtr version;
398
399 psp = calloc(1, sizeof(*psp));
400 if (!psp)
401 return NULL;
402
403 setupLoaderExtensions(psp, extensions);
404
405 version = drmGetVersion(fd);
406 if (version) {
407 psp->drm_version.major = version->version_major;
408 psp->drm_version.minor = version->version_minor;
409 psp->drm_version.patch = version->version_patchlevel;
410 drmFreeVersion(version);
411 }
412
413 psp->extensions = emptyExtensionList;
414 psp->fd = fd;
415 psp->myNum = scrn;
416
417 psp->api_mask = (1 << __DRI_API_OPENGL);
418 *driver_configs = driDriverAPI.InitScreen(psp);
419 if (*driver_configs == NULL) {
420 free(psp);
421 return NULL;
422 }
423
424 psp->loaderPrivate = data;
425
426 driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
427 __dri2NConfigOptions);
428 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
429 "dri2");
430
431 return psp;
432 }
433
434 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
435 {
436 return psp->extensions;
437 }
438
439 /** Core interface */
440 const __DRIcoreExtension driCoreExtension = {
441 { __DRI_CORE, __DRI_CORE_VERSION },
442 NULL,
443 driDestroyScreen,
444 driGetExtensions,
445 driGetConfigAttrib,
446 driIndexConfigAttrib,
447 NULL,
448 driDestroyDrawable,
449 NULL,
450 NULL,
451 driCopyContext,
452 driDestroyContext,
453 driBindContext,
454 driUnbindContext
455 };
456
457 /** DRI2 interface */
458 const __DRIdri2Extension driDRI2Extension = {
459 { __DRI_DRI2, __DRI_DRI2_VERSION },
460 dri2CreateNewScreen,
461 dri2CreateNewDrawable,
462 dri2CreateNewContext,
463 dri2GetAPIMask,
464 dri2CreateNewContextForAPI,
465 dri2AllocateBuffer,
466 dri2ReleaseBuffer
467 };
468
469 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
470 { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
471 dri2ConfigQueryb,
472 dri2ConfigQueryi,
473 dri2ConfigQueryf,
474 };
475
476 void
477 dri2InvalidateDrawable(__DRIdrawable *drawable)
478 {
479 drawable->dri2.stamp++;
480 }
481
482 /**
483 * Check that the gl_framebuffer associated with dPriv is the right size.
484 * Resize the gl_framebuffer if needed.
485 * It's expected that the dPriv->driverPrivate member points to a
486 * gl_framebuffer object.
487 */
488 void
489 driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
490 {
491 struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
492 if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
493 ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
494 /* if the driver needs the hw lock for ResizeBuffers, the drawable
495 might have changed again by now */
496 assert(fb->Width == dPriv->w);
497 assert(fb->Height == dPriv->h);
498 }
499 }