Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
      3  * All Rights Reserved.
      4  * Copyright 2010 George Sapountzis <gsapountzis (at) 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 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 *
    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 *
    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
    208 driDestroyContext(__DRIcontext *pcp)
    209 {
    210     if (pcp) {
    211 	driDriverAPI.DestroyContext(pcp);
    212 	FREE(pcp);
    213     }
    214 }
    215 
    216 static int
    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 
    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 
    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 
    279 static void dri_get_drawable(__DRIdrawable *pdp)
    280 {
    281     pdp->refcount++;
    282 }
    283 
    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 *
    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
    324 driDestroyDrawable(__DRIdrawable *pdp)
    325 {
    326     dri_put_drawable(pdp);
    327 }
    328 
    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