drisw_glx.c revision cfec000e7514342fd51859906e173ba2d474a55c
1579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata/* 2579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * Copyright 2008 George Sapountzis 3579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * 4579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * Permission is hereby granted, free of charge, to any person obtaining a 5579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * copy of this software and associated documentation files (the "Software"), 6579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * to deal in the Software without restriction, including without limitation 7579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b370df27c76fd875f3312be487868528121a4838Enrico Granata * and/or sell copies of the Software, and to permit persons to whom the 90d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * Software is furnished to do so, subject to the following conditions: 100d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * 11b370df27c76fd875f3312be487868528121a4838Enrico Granata * The above copyright notice and this permission notice (including the next 12b370df27c76fd875f3312be487868528121a4838Enrico Granata * paragraph) shall be included in all copies or substantial portions of the 130d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * Software. 14b370df27c76fd875f3312be487868528121a4838Enrico Granata * 150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b370df27c76fd875f3312be487868528121a4838Enrico Granata * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b370df27c76fd875f3312be487868528121a4838Enrico Granata * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b370df27c76fd875f3312be487868528121a4838Enrico Granata * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b370df27c76fd875f3312be487868528121a4838Enrico Granata * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20b370df27c76fd875f3312be487868528121a4838Enrico Granata * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21b370df27c76fd875f3312be487868528121a4838Enrico Granata * SOFTWARE. 22b370df27c76fd875f3312be487868528121a4838Enrico Granata */ 23f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata 24b370df27c76fd875f3312be487868528121a4838Enrico Granata#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 25f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata 260d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata#include <X11/Xlib.h> 27b370df27c76fd875f3312be487868528121a4838Enrico Granata#include "glxclient.h" 28f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata#include <dlfcn.h> 29f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata#include "dri_common.h" 30f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata 31b370df27c76fd875f3312be487868528121a4838Enrico Granatastruct drisw_display 32b370df27c76fd875f3312be487868528121a4838Enrico Granata{ 33b370df27c76fd875f3312be487868528121a4838Enrico Granata __GLXDRIdisplay base; 340d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata}; 35b370df27c76fd875f3312be487868528121a4838Enrico Granata 36b370df27c76fd875f3312be487868528121a4838Enrico Granatastruct drisw_context 37f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata{ 380d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata struct glx_context base; 39f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata __DRIcontext *driContext; 40f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata 410d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata}; 42f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata 43b370df27c76fd875f3312be487868528121a4838Enrico Granatastruct drisw_screen 44b370df27c76fd875f3312be487868528121a4838Enrico Granata{ 450d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata struct glx_screen base; 46b370df27c76fd875f3312be487868528121a4838Enrico Granata 47f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata __DRIscreen *driScreen; 48f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata __GLXDRIscreen vtable; 49b370df27c76fd875f3312be487868528121a4838Enrico Granata const __DRIcoreExtension *core; 50f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata const __DRIswrastExtension *swrast; 51f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata const __DRIconfig **driver_configs; 527b9aacf4a454465af905e505f74245173714b23bEnrico Granata 53b370df27c76fd875f3312be487868528121a4838Enrico Granata void *driver; 54b370df27c76fd875f3312be487868528121a4838Enrico Granata}; 55b370df27c76fd875f3312be487868528121a4838Enrico Granata 56f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granatastruct drisw_drawable 57b370df27c76fd875f3312be487868528121a4838Enrico Granata{ 58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata __GLXDRIdrawable base; 590d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata 60b370df27c76fd875f3312be487868528121a4838Enrico Granata GC gc; 61f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata GC swapgc; 62f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata 63b370df27c76fd875f3312be487868528121a4838Enrico Granata __DRIdrawable *driDrawable; 64b370df27c76fd875f3312be487868528121a4838Enrico Granata XVisualInfo *visinfo; 650d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata XImage *ximage; 66b370df27c76fd875f3312be487868528121a4838Enrico Granata}; 67b370df27c76fd875f3312be487868528121a4838Enrico Granata 68b370df27c76fd875f3312be487868528121a4838Enrico Granatastatic Bool 690d235d5864e996d95f485df1a0df406126e1ccdeEnrico GranataXCreateDrawable(struct drisw_drawable * pdp, 70b370df27c76fd875f3312be487868528121a4838Enrico Granata Display * dpy, XID drawable, int visualid) 71b370df27c76fd875f3312be487868528121a4838Enrico Granata{ 72b370df27c76fd875f3312be487868528121a4838Enrico Granata XGCValues gcvalues; 73b370df27c76fd875f3312be487868528121a4838Enrico Granata long visMask; 74579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata XVisualInfo visTemp; 75579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata int num_visuals; 76579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata 77b370df27c76fd875f3312be487868528121a4838Enrico Granata /* create GC's */ 78b370df27c76fd875f3312be487868528121a4838Enrico Granata pdp->gc = XCreateGC(dpy, drawable, 0, NULL); 79b370df27c76fd875f3312be487868528121a4838Enrico Granata pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL); 800d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata 81b370df27c76fd875f3312be487868528121a4838Enrico Granata gcvalues.function = GXcopy; 82a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata gcvalues.graphics_exposures = False; 83579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues); 84579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues); 85b370df27c76fd875f3312be487868528121a4838Enrico Granata XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues); 86b370df27c76fd875f3312be487868528121a4838Enrico Granata 878f18240a09893310c43673901d863892ae7b0611Enrico Granata /* visual */ 888f18240a09893310c43673901d863892ae7b0611Enrico Granata visTemp.screen = DefaultScreen(dpy); 89b370df27c76fd875f3312be487868528121a4838Enrico Granata visTemp.visualid = visualid; 90f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata visMask = (VisualScreenMask | VisualIDMask); 91b370df27c76fd875f3312be487868528121a4838Enrico Granata pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals); 92b370df27c76fd875f3312be487868528121a4838Enrico Granata 93f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata /* create XImage */ 94805f79b15edd61887c26a3f0ea80457790ba5807Enrico Granata pdp->ximage = XCreateImage(dpy, 95b370df27c76fd875f3312be487868528121a4838Enrico Granata pdp->visinfo->visual, 96b370df27c76fd875f3312be487868528121a4838Enrico Granata pdp->visinfo->depth, 97b370df27c76fd875f3312be487868528121a4838Enrico Granata ZPixmap, 0, /* format, offset */ 980d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata NULL, /* data */ 99b370df27c76fd875f3312be487868528121a4838Enrico Granata 0, 0, /* width, height */ 100b370df27c76fd875f3312be487868528121a4838Enrico Granata 32, /* bitmap_pad */ 101a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata 0); /* bytes_per_line */ 102579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata 103579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata /** 104579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * swrast does not handle 24-bit depth with 24 bpp, so let X do the 105579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * the conversion for us. 106579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata */ 1078f18240a09893310c43673901d863892ae7b0611Enrico Granata if (pdp->ximage->bits_per_pixel == 24) 108579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata pdp->ximage->bits_per_pixel = 32; 109579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata 110579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata return True; 111579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata} 112b370df27c76fd875f3312be487868528121a4838Enrico Granata 113b370df27c76fd875f3312be487868528121a4838Enrico Granatastatic void 114b370df27c76fd875f3312be487868528121a4838Enrico GranataXDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable) 115{ 116 XDestroyImage(pdp->ximage); 117 XFree(pdp->visinfo); 118 119 XFreeGC(dpy, pdp->gc); 120 XFreeGC(dpy, pdp->swapgc); 121} 122 123/** 124 * swrast loader functions 125 */ 126 127static void 128swrastGetDrawableInfo(__DRIdrawable * draw, 129 int *x, int *y, int *w, int *h, 130 void *loaderPrivate) 131{ 132 struct drisw_drawable *pdp = loaderPrivate; 133 __GLXDRIdrawable *pdraw = &(pdp->base); 134 Display *dpy = pdraw->psc->dpy; 135 Drawable drawable; 136 137 Window root; 138 unsigned uw, uh, bw, depth; 139 140 drawable = pdraw->xDrawable; 141 142 XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth); 143 *w = uw; 144 *h = uh; 145} 146 147/** 148 * Align renderbuffer pitch. 149 * 150 * This should be chosen by the driver and the loader (libGL, xserver/glx) 151 * should use the driver provided pitch. 152 * 153 * It seems that the xorg loader (that is the xserver loading swrast_dri for 154 * indirect rendering, not client-side libGL) requires that the pitch is 155 * exactly the image width padded to 32 bits. XXX 156 * 157 * The above restriction can probably be overcome by using ScratchPixmap and 158 * CopyArea in the xserver, similar to ShmPutImage, and setting the width of 159 * the scratch pixmap to 'pitch / cpp'. 160 */ 161static inline int 162bytes_per_line(unsigned pitch_bits, unsigned mul) 163{ 164 unsigned mask = mul - 1; 165 166 return ((pitch_bits + mask) & ~mask) / 8; 167} 168 169static void 170swrastPutImage(__DRIdrawable * draw, int op, 171 int x, int y, int w, int h, 172 char *data, void *loaderPrivate) 173{ 174 struct drisw_drawable *pdp = loaderPrivate; 175 __GLXDRIdrawable *pdraw = &(pdp->base); 176 Display *dpy = pdraw->psc->dpy; 177 Drawable drawable; 178 XImage *ximage; 179 GC gc; 180 181 switch (op) { 182 case __DRI_SWRAST_IMAGE_OP_DRAW: 183 gc = pdp->gc; 184 break; 185 case __DRI_SWRAST_IMAGE_OP_SWAP: 186 gc = pdp->swapgc; 187 break; 188 default: 189 return; 190 } 191 192 drawable = pdraw->xDrawable; 193 194 ximage = pdp->ximage; 195 ximage->data = data; 196 ximage->width = w; 197 ximage->height = h; 198 ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32); 199 200 XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h); 201 202 ximage->data = NULL; 203} 204 205static void 206swrastGetImage(__DRIdrawable * read, 207 int x, int y, int w, int h, 208 char *data, void *loaderPrivate) 209{ 210 struct drisw_drawable *prp = loaderPrivate; 211 __GLXDRIdrawable *pread = &(prp->base); 212 Display *dpy = pread->psc->dpy; 213 Drawable readable; 214 XImage *ximage; 215 216 readable = pread->xDrawable; 217 218 ximage = prp->ximage; 219 ximage->data = data; 220 ximage->width = w; 221 ximage->height = h; 222 ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32); 223 224 XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0); 225 226 ximage->data = NULL; 227} 228 229static const __DRIswrastLoaderExtension swrastLoaderExtension = { 230 {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION}, 231 swrastGetDrawableInfo, 232 swrastPutImage, 233 swrastGetImage 234}; 235 236static const __DRIextension *loader_extensions[] = { 237 &systemTimeExtension.base, 238 &swrastLoaderExtension.base, 239 NULL 240}; 241 242/** 243 * GLXDRI functions 244 */ 245 246static void 247drisw_destroy_context(struct glx_context *context) 248{ 249 struct drisw_context *pcp = (struct drisw_context *) context; 250 struct drisw_screen *psc = (struct drisw_screen *) context->psc; 251 252 driReleaseDrawables(&pcp->base); 253 254 if (context->xid) 255 glx_send_destroy_context(psc->base.dpy, context->xid); 256 257 if (context->extensions) 258 XFree((char *) context->extensions); 259 260 (*psc->core->destroyContext) (pcp->driContext); 261 262 Xfree(pcp); 263} 264 265static int 266drisw_bind_context(struct glx_context *context, struct glx_context *old, 267 GLXDrawable draw, GLXDrawable read) 268{ 269 struct drisw_context *pcp = (struct drisw_context *) context; 270 struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; 271 struct drisw_drawable *pdraw, *pread; 272 273 pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw); 274 pread = (struct drisw_drawable *) driFetchDrawable(context, read); 275 276 driReleaseDrawables(&pcp->base); 277 278 if (pdraw == NULL || pread == NULL) 279 return GLXBadDrawable; 280 281 if ((*psc->core->bindContext) (pcp->driContext, 282 pdraw->driDrawable, pread->driDrawable)) 283 return Success; 284 285 return GLXBadContext; 286} 287 288static void 289drisw_unbind_context(struct glx_context *context, struct glx_context *new) 290{ 291 struct drisw_context *pcp = (struct drisw_context *) context; 292 struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; 293 294 (*psc->core->unbindContext) (pcp->driContext); 295} 296 297static const struct glx_context_vtable drisw_context_vtable = { 298 drisw_destroy_context, 299 drisw_bind_context, 300 drisw_unbind_context, 301 NULL, 302 NULL, 303 DRI_glXUseXFont, 304 NULL, 305 NULL, 306 NULL, /* get_proc_address */ 307}; 308 309static struct glx_context * 310drisw_create_context(struct glx_screen *base, 311 struct glx_config *config_base, 312 struct glx_context *shareList, int renderType) 313{ 314 struct drisw_context *pcp, *pcp_shared; 315 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 316 struct drisw_screen *psc = (struct drisw_screen *) base; 317 __DRIcontext *shared = NULL; 318 319 if (!psc->base.driScreen) 320 return NULL; 321 322 if (shareList) { 323 pcp_shared = (struct drisw_context *) shareList; 324 shared = pcp_shared->driContext; 325 } 326 327 pcp = Xmalloc(sizeof *pcp); 328 if (pcp == NULL) 329 return NULL; 330 331 memset(pcp, 0, sizeof *pcp); 332 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 333 Xfree(pcp); 334 return NULL; 335 } 336 337 pcp->driContext = 338 (*psc->core->createNewContext) (psc->driScreen, 339 config->driConfig, shared, pcp); 340 if (pcp->driContext == NULL) { 341 Xfree(pcp); 342 return NULL; 343 } 344 345 pcp->base.vtable = &drisw_context_vtable; 346 347 return &pcp->base; 348} 349 350static void 351driswDestroyDrawable(__GLXDRIdrawable * pdraw) 352{ 353 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 354 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 355 356 (*psc->core->destroyDrawable) (pdp->driDrawable); 357 358 XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable); 359 Xfree(pdp); 360} 361 362static __GLXDRIdrawable * 363driswCreateDrawable(struct glx_screen *base, XID xDrawable, 364 GLXDrawable drawable, struct glx_config *modes) 365{ 366 struct drisw_drawable *pdp; 367 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 368 struct drisw_screen *psc = (struct drisw_screen *) base; 369 370 const __DRIswrastExtension *swrast = psc->swrast; 371 372 pdp = Xmalloc(sizeof(*pdp)); 373 if (!pdp) 374 return NULL; 375 376 memset(pdp, 0, sizeof *pdp); 377 pdp->base.xDrawable = xDrawable; 378 pdp->base.drawable = drawable; 379 pdp->base.psc = &psc->base; 380 381 XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID); 382 383 /* Create a new drawable */ 384 pdp->driDrawable = 385 (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp); 386 387 if (!pdp->driDrawable) { 388 XDestroyDrawable(pdp, psc->base.dpy, xDrawable); 389 Xfree(pdp); 390 return NULL; 391 } 392 393 pdp->base.destroyDrawable = driswDestroyDrawable; 394 395 return &pdp->base; 396} 397 398static int64_t 399driswSwapBuffers(__GLXDRIdrawable * pdraw, 400 int64_t target_msc, int64_t divisor, int64_t remainder) 401{ 402 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; 403 struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc; 404 405 (void) target_msc; 406 (void) divisor; 407 (void) remainder; 408 409 (*psc->core->swapBuffers) (pdp->driDrawable); 410 411 return 0; 412} 413 414static void 415driswDestroyScreen(struct glx_screen *base) 416{ 417 struct drisw_screen *psc = (struct drisw_screen *) base; 418 419 /* Free the direct rendering per screen data */ 420 (*psc->core->destroyScreen) (psc->driScreen); 421 driDestroyConfigs(psc->driver_configs); 422 psc->driScreen = NULL; 423 if (psc->driver) 424 dlclose(psc->driver); 425} 426 427static void * 428driOpenSwrast(void) 429{ 430 void *driver = NULL; 431 432 if (driver == NULL) 433 driver = driOpenDriver("swrast"); 434 435 return driver; 436} 437 438static const struct glx_screen_vtable drisw_screen_vtable = { 439 drisw_create_context 440}; 441 442static struct glx_screen * 443driswCreateScreen(int screen, struct glx_display *priv) 444{ 445 __GLXDRIscreen *psp; 446 const __DRIconfig **driver_configs; 447 const __DRIextension **extensions; 448 struct drisw_screen *psc; 449 int i; 450 451 psc = Xcalloc(1, sizeof *psc); 452 if (psc == NULL) 453 return NULL; 454 455 memset(psc, 0, sizeof *psc); 456 if (!glx_screen_init(&psc->base, screen, priv)) { 457 Xfree(psc); 458 return NULL; 459 } 460 461 psc->driver = driOpenSwrast(); 462 if (psc->driver == NULL) 463 goto handle_error; 464 465 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 466 if (extensions == NULL) { 467 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 468 goto handle_error; 469 } 470 471 for (i = 0; extensions[i]; i++) { 472 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 473 psc->core = (__DRIcoreExtension *) extensions[i]; 474 if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0) 475 psc->swrast = (__DRIswrastExtension *) extensions[i]; 476 } 477 478 if (psc->core == NULL || psc->swrast == NULL) { 479 ErrorMessageF("core dri extension not found\n"); 480 goto handle_error; 481 } 482 483 psc->driScreen = 484 psc->swrast->createNewScreen(screen, loader_extensions, 485 &driver_configs, psc); 486 if (psc->driScreen == NULL) { 487 ErrorMessageF("failed to create dri screen\n"); 488 goto handle_error; 489 } 490 491 psc->base.configs = 492 driConvertConfigs(psc->core, psc->base.configs, driver_configs); 493 psc->base.visuals = 494 driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 495 496 psc->driver_configs = driver_configs; 497 498 psc->base.vtable = &drisw_screen_vtable; 499 psp = &psc->vtable; 500 psc->base.driScreen = psp; 501 psp->destroyScreen = driswDestroyScreen; 502 psp->createDrawable = driswCreateDrawable; 503 psp->swapBuffers = driswSwapBuffers; 504 505 return &psc->base; 506 507 handle_error: 508 if (psc->driver) 509 dlclose(psc->driver); 510 glx_screen_cleanup(&psc->base); 511 Xfree(psc); 512 513 ErrorMessageF("reverting to indirect rendering\n"); 514 515 return NULL; 516} 517 518/* Called from __glXFreeDisplayPrivate. 519 */ 520static void 521driswDestroyDisplay(__GLXDRIdisplay * dpy) 522{ 523 Xfree(dpy); 524} 525 526/* 527 * Allocate, initialize and return a __DRIdisplayPrivate object. 528 * This is called from __glXInitialize() when we are given a new 529 * display pointer. 530 */ 531_X_HIDDEN __GLXDRIdisplay * 532driswCreateDisplay(Display * dpy) 533{ 534 struct drisw_display *pdpyp; 535 536 pdpyp = Xmalloc(sizeof *pdpyp); 537 if (pdpyp == NULL) 538 return NULL; 539 540 pdpyp->base.destroyDisplay = driswDestroyDisplay; 541 pdpyp->base.createScreen = driswCreateScreen; 542 543 return &pdpyp->base; 544} 545 546#endif /* GLX_DIRECT_RENDERING */ 547