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