glxdriswrast.c revision 35c4bbdf
1/* 2 * Copyright © 2008 George Sapountzis <gsap7@yahoo.gr> 3 * Copyright © 2008 Red Hat, Inc 4 * 5 * Permission to use, copy, modify, distribute, and sell this software 6 * and its documentation for any purpose is hereby granted without 7 * fee, provided that the above copyright notice appear in all copies 8 * and that both that copyright notice and this permission notice 9 * appear in supporting documentation, and that the name of the 10 * copyright holders not be used in advertising or publicity 11 * pertaining to distribution of the software without specific, 12 * written prior permission. The copyright holders make no 13 * representations about the suitability of this software for any 14 * purpose. It is provided "as is" without express or implied 15 * warranty. 16 * 17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 24 * SOFTWARE. 25 */ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <stdint.h> 32#include <stdio.h> 33#include <string.h> 34#include <errno.h> 35#include <sys/time.h> 36#include <dlfcn.h> 37 38#include <GL/gl.h> 39#include <GL/internal/dri_interface.h> 40#include <GL/glxtokens.h> 41 42#include "scrnintstr.h" 43#include "pixmapstr.h" 44#include "gcstruct.h" 45#include "os.h" 46 47#include "glxserver.h" 48#include "glxutil.h" 49#include "glxdricommon.h" 50 51#include "extension_string.h" 52 53/* RTLD_LOCAL is not defined on Cygwin */ 54#ifdef __CYGWIN__ 55#ifndef RTLD_LOCAL 56#define RTLD_LOCAL 0 57#endif 58#endif 59 60typedef struct __GLXDRIscreen __GLXDRIscreen; 61typedef struct __GLXDRIcontext __GLXDRIcontext; 62typedef struct __GLXDRIdrawable __GLXDRIdrawable; 63 64struct __GLXDRIscreen { 65 __GLXscreen base; 66 __DRIscreen *driScreen; 67 void *driver; 68 69 const __DRIcoreExtension *core; 70 const __DRIswrastExtension *swrast; 71 const __DRIcopySubBufferExtension *copySubBuffer; 72 const __DRItexBufferExtension *texBuffer; 73 const __DRIconfig **driConfigs; 74 75 unsigned char glx_enable_bits[__GLX_EXT_BYTES]; 76}; 77 78struct __GLXDRIcontext { 79 __GLXcontext base; 80 __DRIcontext *driContext; 81}; 82 83struct __GLXDRIdrawable { 84 __GLXdrawable base; 85 __DRIdrawable *driDrawable; 86 __GLXDRIscreen *screen; 87 88 GCPtr gc; /* scratch GC for span drawing */ 89 GCPtr swapgc; /* GC for swapping the color buffers */ 90}; 91 92static void 93__glXDRIdrawableDestroy(__GLXdrawable * drawable) 94{ 95 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; 96 const __DRIcoreExtension *core = private->screen->core; 97 98 (*core->destroyDrawable) (private->driDrawable); 99 100 FreeGC(private->gc, (GContext) 0); 101 FreeGC(private->swapgc, (GContext) 0); 102 103 __glXDrawableRelease(drawable); 104 105 free(private); 106} 107 108static GLboolean 109__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable) 110{ 111 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; 112 const __DRIcoreExtension *core = private->screen->core; 113 114 (*core->swapBuffers) (private->driDrawable); 115 116 return TRUE; 117} 118 119static void 120__glXDRIdrawableCopySubBuffer(__GLXdrawable * basePrivate, 121 int x, int y, int w, int h) 122{ 123 __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; 124 const __DRIcopySubBufferExtension *copySubBuffer = 125 private->screen->copySubBuffer; 126 127 if (copySubBuffer) 128 (*copySubBuffer->copySubBuffer) (private->driDrawable, x, y, w, h); 129} 130 131static void 132__glXDRIcontextDestroy(__GLXcontext * baseContext) 133{ 134 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 135 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; 136 137 (*screen->core->destroyContext) (context->driContext); 138 __glXContextDestroy(&context->base); 139 free(context); 140} 141 142static int 143__glXDRIcontextMakeCurrent(__GLXcontext * baseContext) 144{ 145 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 146 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; 147 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; 148 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; 149 150 return (*screen->core->bindContext) (context->driContext, 151 draw->driDrawable, read->driDrawable); 152} 153 154static int 155__glXDRIcontextLoseCurrent(__GLXcontext * baseContext) 156{ 157 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 158 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; 159 160 return (*screen->core->unbindContext) (context->driContext); 161} 162 163static int 164__glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc, 165 unsigned long mask) 166{ 167 __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst; 168 __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc; 169 __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen; 170 171 return (*screen->core->copyContext) (dst->driContext, 172 src->driContext, mask); 173} 174 175static int 176__glXDRIbindTexImage(__GLXcontext * baseContext, 177 int buffer, __GLXdrawable * glxPixmap) 178{ 179 __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap; 180 const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer; 181 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 182 183 if (texBuffer == NULL) 184 return Success; 185 186#if __DRI_TEX_BUFFER_VERSION >= 2 187 if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) { 188 (*texBuffer->setTexBuffer2) (context->driContext, 189 glxPixmap->target, 190 glxPixmap->format, drawable->driDrawable); 191 } 192 else 193#endif 194 texBuffer->setTexBuffer(context->driContext, 195 glxPixmap->target, drawable->driDrawable); 196 197 return Success; 198} 199 200static int 201__glXDRIreleaseTexImage(__GLXcontext * baseContext, 202 int buffer, __GLXdrawable * pixmap) 203{ 204 /* FIXME: Just unbind the texture? */ 205 return Success; 206} 207 208static __GLXtextureFromPixmap __glXDRItextureFromPixmap = { 209 __glXDRIbindTexImage, 210 __glXDRIreleaseTexImage 211}; 212 213static void 214__glXDRIscreenDestroy(__GLXscreen * baseScreen) 215{ 216 int i; 217 218 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; 219 220 (*screen->core->destroyScreen) (screen->driScreen); 221 222 dlclose(screen->driver); 223 224 __glXScreenDestroy(baseScreen); 225 226 if (screen->driConfigs) { 227 for (i = 0; screen->driConfigs[i] != NULL; i++) 228 free((__DRIconfig **) screen->driConfigs[i]); 229 free(screen->driConfigs); 230 } 231 232 free(screen); 233} 234 235static __GLXcontext * 236__glXDRIscreenCreateContext(__GLXscreen * baseScreen, 237 __GLXconfig * glxConfig, 238 __GLXcontext * baseShareContext, 239 unsigned num_attribs, 240 const uint32_t *attribs, 241 int *error) 242{ 243 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; 244 __GLXDRIcontext *context, *shareContext; 245 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; 246 const __DRIcoreExtension *core = screen->core; 247 __DRIcontext *driShare; 248 249 /* DRISWRAST won't support createContextAttribs, so these parameters will 250 * never be used. 251 */ 252 (void) num_attribs; 253 (void) attribs; 254 (void) error; 255 256 shareContext = (__GLXDRIcontext *) baseShareContext; 257 if (shareContext) 258 driShare = shareContext->driContext; 259 else 260 driShare = NULL; 261 262 context = calloc(1, sizeof *context); 263 if (context == NULL) 264 return NULL; 265 266 context->base.destroy = __glXDRIcontextDestroy; 267 context->base.makeCurrent = __glXDRIcontextMakeCurrent; 268 context->base.loseCurrent = __glXDRIcontextLoseCurrent; 269 context->base.copy = __glXDRIcontextCopy; 270 context->base.textureFromPixmap = &__glXDRItextureFromPixmap; 271 272 context->driContext = 273 (*core->createNewContext) (screen->driScreen, 274 config->driConfig, driShare, context); 275 276 return &context->base; 277} 278 279static __GLXdrawable * 280__glXDRIscreenCreateDrawable(ClientPtr client, 281 __GLXscreen * screen, 282 DrawablePtr pDraw, 283 XID drawId, 284 int type, XID glxDrawId, __GLXconfig * glxConfig) 285{ 286 XID gcvals[2]; 287 int status; 288 __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; 289 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; 290 __GLXDRIdrawable *private; 291 292 private = calloc(1, sizeof *private); 293 if (private == NULL) 294 return NULL; 295 296 private->screen = driScreen; 297 if (!__glXDrawableInit(&private->base, screen, 298 pDraw, type, glxDrawId, glxConfig)) { 299 free(private); 300 return NULL; 301 } 302 303 private->base.destroy = __glXDRIdrawableDestroy; 304 private->base.swapBuffers = __glXDRIdrawableSwapBuffers; 305 private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; 306 307 gcvals[0] = GXcopy; 308 private->gc = 309 CreateGC(pDraw, GCFunction, gcvals, &status, (XID) 0, serverClient); 310 gcvals[1] = FALSE; 311 private->swapgc = 312 CreateGC(pDraw, GCFunction | GCGraphicsExposures, gcvals, &status, 313 (XID) 0, serverClient); 314 315 private->driDrawable = 316 (*driScreen->swrast->createNewDrawable) (driScreen->driScreen, 317 config->driConfig, private); 318 319 return &private->base; 320} 321 322static void 323swrastGetDrawableInfo(__DRIdrawable * draw, 324 int *x, int *y, int *w, int *h, void *loaderPrivate) 325{ 326 __GLXDRIdrawable *drawable = loaderPrivate; 327 DrawablePtr pDraw = drawable->base.pDraw; 328 329 *x = pDraw->x; 330 *y = pDraw->y; 331 *w = pDraw->width; 332 *h = pDraw->height; 333} 334 335static void 336swrastPutImage(__DRIdrawable * draw, int op, 337 int x, int y, int w, int h, char *data, void *loaderPrivate) 338{ 339 __GLXDRIdrawable *drawable = loaderPrivate; 340 DrawablePtr pDraw = drawable->base.pDraw; 341 GCPtr gc; 342 __GLXcontext *cx = lastGLContext; 343 344 switch (op) { 345 case __DRI_SWRAST_IMAGE_OP_DRAW: 346 gc = drawable->gc; 347 break; 348 case __DRI_SWRAST_IMAGE_OP_SWAP: 349 gc = drawable->swapgc; 350 break; 351 default: 352 return; 353 } 354 355 ValidateGC(pDraw, gc); 356 357 gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, data); 358 if (cx != lastGLContext) { 359 lastGLContext = cx; 360 cx->makeCurrent(cx); 361 } 362} 363 364static void 365swrastGetImage(__DRIdrawable * draw, 366 int x, int y, int w, int h, char *data, void *loaderPrivate) 367{ 368 __GLXDRIdrawable *drawable = loaderPrivate; 369 DrawablePtr pDraw = drawable->base.pDraw; 370 ScreenPtr pScreen = pDraw->pScreen; 371 __GLXcontext *cx = lastGLContext; 372 373 pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data); 374 if (cx != lastGLContext) { 375 lastGLContext = cx; 376 cx->makeCurrent(cx); 377 } 378} 379 380static const __DRIswrastLoaderExtension swrastLoaderExtension = { 381 {__DRI_SWRAST_LOADER, 1}, 382 swrastGetDrawableInfo, 383 swrastPutImage, 384 swrastGetImage 385}; 386 387static const __DRIextension *loader_extensions[] = { 388 &systemTimeExtension.base, 389 &swrastLoaderExtension.base, 390 NULL 391}; 392 393static void 394initializeExtensions(__GLXDRIscreen * screen) 395{ 396 const __DRIextension **extensions; 397 int i; 398 399 __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); 400 LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); 401 402 if (screen->swrast->base.version >= 3) { 403 __glXEnableExtension(screen->glx_enable_bits, 404 "GLX_ARB_create_context"); 405 __glXEnableExtension(screen->glx_enable_bits, 406 "GLX_ARB_create_context_profile"); 407 __glXEnableExtension(screen->glx_enable_bits, 408 "GLX_EXT_create_context_es_profile"); 409 __glXEnableExtension(screen->glx_enable_bits, 410 "GLX_EXT_create_context_es2_profile"); 411 } 412 413 /* these are harmless to enable unconditionally */ 414 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_framebuffer_sRGB"); 415 __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float"); 416 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_fbconfig_packed_float"); 417 __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_make_current_read"); 418 419 extensions = screen->core->getExtensions(screen->driScreen); 420 421 for (i = 0; extensions[i]; i++) { 422 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { 423 screen->copySubBuffer = 424 (const __DRIcopySubBufferExtension *) extensions[i]; 425 } 426 427 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { 428 screen->texBuffer = (const __DRItexBufferExtension *) extensions[i]; 429 /* GLX_EXT_texture_from_pixmap is always enabled. */ 430 } 431 432#ifdef __DRI2_FLUSH_CONTROL 433 if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) { 434 __glXEnableExtension(screen->glx_enable_bits, 435 "GLX_ARB_context_flush_control\n"); 436 } 437#endif 438 439 } 440} 441 442/* white lie */ 443extern glx_func_ptr glXGetProcAddressARB(const char *); 444 445static __GLXscreen * 446__glXDRIscreenProbe(ScreenPtr pScreen) 447{ 448 const char *driverName = "swrast"; 449 __GLXDRIscreen *screen; 450 size_t buffer_size; 451 452 screen = calloc(1, sizeof *screen); 453 if (screen == NULL) 454 return NULL; 455 456 screen->base.destroy = __glXDRIscreenDestroy; 457 screen->base.createContext = __glXDRIscreenCreateContext; 458 screen->base.createDrawable = __glXDRIscreenCreateDrawable; 459 screen->base.swapInterval = NULL; 460 screen->base.pScreen = pScreen; 461 462 __glXInitExtensionEnableBits(screen->glx_enable_bits); 463 464 screen->driver = glxProbeDriver(driverName, 465 (void **) &screen->core, 466 __DRI_CORE, 1, 467 (void **) &screen->swrast, 468 __DRI_SWRAST, 1); 469 if (screen->driver == NULL) { 470 goto handle_error; 471 } 472 473 screen->driScreen = 474 (*screen->swrast->createNewScreen) (pScreen->myNum, 475 loader_extensions, 476 &screen->driConfigs, screen); 477 478 if (screen->driScreen == NULL) { 479 LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n"); 480 goto handle_error; 481 } 482 483 initializeExtensions(screen); 484 485 screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs, 486 GLX_WINDOW_BIT | 487 GLX_PIXMAP_BIT | 488 GLX_PBUFFER_BIT); 489 490 __glXScreenInit(&screen->base, pScreen); 491 492 /* The first call simply determines the length of the extension string. 493 * This allows us to allocate some memory to hold the extension string, 494 * but it requires that we call __glXGetExtensionString a second time. 495 */ 496 buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); 497 if (buffer_size > 0) { 498 free(screen->base.GLXextensions); 499 500 screen->base.GLXextensions = xnfalloc(buffer_size); 501 (void) __glXGetExtensionString(screen->glx_enable_bits, 502 screen->base.GLXextensions); 503 } 504 505 screen->base.GLXmajor = 1; 506 screen->base.GLXminor = 4; 507 508 __glXsetGetProcAddress(glXGetProcAddressARB); 509 510 LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName); 511 512 return &screen->base; 513 514 handle_error: 515 if (screen->driver) 516 dlclose(screen->driver); 517 518 free(screen); 519 520 LogMessage(X_ERROR, "GLX: could not load software renderer\n"); 521 522 return NULL; 523} 524 525_X_EXPORT __GLXprovider __glXDRISWRastProvider = { 526 __glXDRIscreenProbe, 527 "DRISWRAST", 528 NULL 529}; 530