glxdriswrast.c revision 1b5d61b8
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 76struct __GLXDRIcontext { 77 __GLXcontext base; 78 __DRIcontext *driContext; 79}; 80 81struct __GLXDRIdrawable { 82 __GLXdrawable base; 83 __DRIdrawable *driDrawable; 84 __GLXDRIscreen *screen; 85}; 86 87/* white lie */ 88extern glx_func_ptr glXGetProcAddressARB(const char *); 89 90static void 91__glXDRIdrawableDestroy(__GLXdrawable * drawable) 92{ 93 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; 94 const __DRIcoreExtension *core = private->screen->core; 95 96 (*core->destroyDrawable) (private->driDrawable); 97 98 __glXDrawableRelease(drawable); 99 100 free(private); 101} 102 103static GLboolean 104__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable) 105{ 106 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; 107 const __DRIcoreExtension *core = private->screen->core; 108 109 (*core->swapBuffers) (private->driDrawable); 110 111 return TRUE; 112} 113 114static void 115__glXDRIdrawableCopySubBuffer(__GLXdrawable * basePrivate, 116 int x, int y, int w, int h) 117{ 118 __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; 119 const __DRIcopySubBufferExtension *copySubBuffer = 120 private->screen->copySubBuffer; 121 122 if (copySubBuffer) 123 (*copySubBuffer->copySubBuffer) (private->driDrawable, x, y, w, h); 124} 125 126static void 127__glXDRIcontextDestroy(__GLXcontext * baseContext) 128{ 129 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 130 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; 131 132 (*screen->core->destroyContext) (context->driContext); 133 __glXContextDestroy(&context->base); 134 free(context); 135} 136 137static int 138__glXDRIcontextMakeCurrent(__GLXcontext * baseContext) 139{ 140 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 141 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; 142 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; 143 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; 144 145 return (*screen->core->bindContext) (context->driContext, 146 draw->driDrawable, read->driDrawable); 147} 148 149static int 150__glXDRIcontextLoseCurrent(__GLXcontext * baseContext) 151{ 152 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 153 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; 154 155 return (*screen->core->unbindContext) (context->driContext); 156} 157 158static int 159__glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc, 160 unsigned long mask) 161{ 162 __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst; 163 __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc; 164 __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen; 165 166 return (*screen->core->copyContext) (dst->driContext, 167 src->driContext, mask); 168} 169 170static int 171__glXDRIbindTexImage(__GLXcontext * baseContext, 172 int buffer, __GLXdrawable * glxPixmap) 173{ 174 __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap; 175 const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer; 176 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; 177 178 if (texBuffer == NULL) 179 return Success; 180 181#if __DRI_TEX_BUFFER_VERSION >= 2 182 if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) { 183 (*texBuffer->setTexBuffer2) (context->driContext, 184 glxPixmap->target, 185 glxPixmap->format, drawable->driDrawable); 186 } 187 else 188#endif 189 texBuffer->setTexBuffer(context->driContext, 190 glxPixmap->target, drawable->driDrawable); 191 192 return Success; 193} 194 195static int 196__glXDRIreleaseTexImage(__GLXcontext * baseContext, 197 int buffer, __GLXdrawable * pixmap) 198{ 199 /* FIXME: Just unbind the texture? */ 200 return Success; 201} 202 203static __GLXcontext * 204__glXDRIscreenCreateContext(__GLXscreen * baseScreen, 205 __GLXconfig * glxConfig, 206 __GLXcontext * baseShareContext, 207 unsigned num_attribs, 208 const uint32_t *attribs, 209 int *error) 210{ 211 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; 212 __GLXDRIcontext *context, *shareContext; 213 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; 214 const __DRIconfig *driConfig = config ? config->driConfig : NULL; 215 const __DRIcoreExtension *core = screen->core; 216 __DRIcontext *driShare; 217 218 /* DRISWRAST won't support createContextAttribs, so these parameters will 219 * never be used. 220 */ 221 (void) num_attribs; 222 (void) attribs; 223 (void) error; 224 225 shareContext = (__GLXDRIcontext *) baseShareContext; 226 if (shareContext) 227 driShare = shareContext->driContext; 228 else 229 driShare = NULL; 230 231 context = calloc(1, sizeof *context); 232 if (context == NULL) 233 return NULL; 234 235 context->base.config = glxConfig; 236 context->base.destroy = __glXDRIcontextDestroy; 237 context->base.makeCurrent = __glXDRIcontextMakeCurrent; 238 context->base.loseCurrent = __glXDRIcontextLoseCurrent; 239 context->base.copy = __glXDRIcontextCopy; 240 context->base.bindTexImage = __glXDRIbindTexImage; 241 context->base.releaseTexImage = __glXDRIreleaseTexImage; 242 243 context->driContext = 244 (*core->createNewContext) (screen->driScreen, driConfig, driShare, 245 context); 246 247 return &context->base; 248} 249 250static __GLXdrawable * 251__glXDRIscreenCreateDrawable(ClientPtr client, 252 __GLXscreen * screen, 253 DrawablePtr pDraw, 254 XID drawId, 255 int type, XID glxDrawId, __GLXconfig * glxConfig) 256{ 257 __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; 258 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; 259 __GLXDRIdrawable *private; 260 261 private = calloc(1, sizeof *private); 262 if (private == NULL) 263 return NULL; 264 265 private->screen = driScreen; 266 if (!__glXDrawableInit(&private->base, screen, 267 pDraw, type, glxDrawId, glxConfig)) { 268 free(private); 269 return NULL; 270 } 271 272 private->base.destroy = __glXDRIdrawableDestroy; 273 private->base.swapBuffers = __glXDRIdrawableSwapBuffers; 274 private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; 275 276 private->driDrawable = 277 (*driScreen->swrast->createNewDrawable) (driScreen->driScreen, 278 config->driConfig, private); 279 280 return &private->base; 281} 282 283static void 284swrastGetDrawableInfo(__DRIdrawable * draw, 285 int *x, int *y, int *w, int *h, void *loaderPrivate) 286{ 287 __GLXDRIdrawable *drawable = loaderPrivate; 288 DrawablePtr pDraw = drawable->base.pDraw; 289 290 *x = pDraw->x; 291 *y = pDraw->y; 292 *w = pDraw->width; 293 *h = pDraw->height; 294} 295 296static void 297swrastPutImage(__DRIdrawable * draw, int op, 298 int x, int y, int w, int h, char *data, void *loaderPrivate) 299{ 300 __GLXDRIdrawable *drawable = loaderPrivate; 301 DrawablePtr pDraw = drawable->base.pDraw; 302 GCPtr gc; 303 __GLXcontext *cx = lastGLContext; 304 305 if ((gc = GetScratchGC(pDraw->depth, pDraw->pScreen))) { 306 ValidateGC(pDraw, gc); 307 gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, 308 data); 309 FreeScratchGC(gc); 310 } 311 312 if (cx != lastGLContext) { 313 lastGLContext = cx; 314 cx->makeCurrent(cx); 315 } 316} 317 318static void 319swrastGetImage(__DRIdrawable * draw, 320 int x, int y, int w, int h, char *data, void *loaderPrivate) 321{ 322 __GLXDRIdrawable *drawable = loaderPrivate; 323 DrawablePtr pDraw = drawable->base.pDraw; 324 ScreenPtr pScreen = pDraw->pScreen; 325 __GLXcontext *cx = lastGLContext; 326 327 pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data); 328 if (cx != lastGLContext) { 329 lastGLContext = cx; 330 cx->makeCurrent(cx); 331 } 332} 333 334static const __DRIswrastLoaderExtension swrastLoaderExtension = { 335 {__DRI_SWRAST_LOADER, 1}, 336 swrastGetDrawableInfo, 337 swrastPutImage, 338 swrastGetImage 339}; 340 341static const __DRIextension *loader_extensions[] = { 342 &swrastLoaderExtension.base, 343 NULL 344}; 345 346static void 347initializeExtensions(__GLXscreen * screen) 348{ 349 const __DRIextension **extensions; 350 __GLXDRIscreen *dri = (__GLXDRIscreen *)screen; 351 int i; 352 353 __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); 354 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_no_config_context"); 355 356 if (dri->swrast->base.version >= 3) { 357 __glXEnableExtension(screen->glx_enable_bits, 358 "GLX_ARB_create_context"); 359 __glXEnableExtension(screen->glx_enable_bits, 360 "GLX_ARB_create_context_no_error"); 361 __glXEnableExtension(screen->glx_enable_bits, 362 "GLX_ARB_create_context_profile"); 363 __glXEnableExtension(screen->glx_enable_bits, 364 "GLX_EXT_create_context_es_profile"); 365 __glXEnableExtension(screen->glx_enable_bits, 366 "GLX_EXT_create_context_es2_profile"); 367 } 368 369 /* these are harmless to enable unconditionally */ 370 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_framebuffer_sRGB"); 371 __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float"); 372 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_fbconfig_packed_float"); 373 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); 374 375 extensions = dri->core->getExtensions(dri->driScreen); 376 377 for (i = 0; extensions[i]; i++) { 378 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { 379 dri->copySubBuffer = 380 (const __DRIcopySubBufferExtension *) extensions[i]; 381 } 382 383 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { 384 dri->texBuffer = (const __DRItexBufferExtension *) extensions[i]; 385 } 386 387#ifdef __DRI2_FLUSH_CONTROL 388 if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) { 389 __glXEnableExtension(screen->glx_enable_bits, 390 "GLX_ARB_context_flush_control"); 391 } 392#endif 393 394 } 395} 396 397static void 398__glXDRIscreenDestroy(__GLXscreen * baseScreen) 399{ 400 int i; 401 402 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; 403 404 (*screen->core->destroyScreen) (screen->driScreen); 405 406 dlclose(screen->driver); 407 408 __glXScreenDestroy(baseScreen); 409 410 if (screen->driConfigs) { 411 for (i = 0; screen->driConfigs[i] != NULL; i++) 412 free((__DRIconfig **) screen->driConfigs[i]); 413 free(screen->driConfigs); 414 } 415 416 free(screen); 417} 418 419static __GLXscreen * 420__glXDRIscreenProbe(ScreenPtr pScreen) 421{ 422 const char *driverName = "swrast"; 423 __GLXDRIscreen *screen; 424 425 screen = calloc(1, sizeof *screen); 426 if (screen == NULL) 427 return NULL; 428 429 screen->base.destroy = __glXDRIscreenDestroy; 430 screen->base.createContext = __glXDRIscreenCreateContext; 431 screen->base.createDrawable = __glXDRIscreenCreateDrawable; 432 screen->base.swapInterval = NULL; 433 screen->base.pScreen = pScreen; 434 435 __glXInitExtensionEnableBits(screen->base.glx_enable_bits); 436 437 screen->driver = glxProbeDriver(driverName, 438 (void **) &screen->core, 439 __DRI_CORE, 1, 440 (void **) &screen->swrast, 441 __DRI_SWRAST, 1); 442 if (screen->driver == NULL) { 443 goto handle_error; 444 } 445 446 screen->driScreen = 447 (*screen->swrast->createNewScreen) (pScreen->myNum, 448 loader_extensions, 449 &screen->driConfigs, screen); 450 451 if (screen->driScreen == NULL) { 452 LogMessage(X_ERROR, "IGLX error: Calling driver entry point failed\n"); 453 goto handle_error; 454 } 455 456 initializeExtensions(&screen->base); 457 458 screen->base.fbconfigs = glxConvertConfigs(screen->core, 459 screen->driConfigs); 460 461#if !defined(XQUARTZ) && !defined(WIN32) 462 screen->base.glvnd = strdup("mesa"); 463#endif 464 __glXScreenInit(&screen->base, pScreen); 465 466 __glXsetGetProcAddress(glXGetProcAddressARB); 467 468 LogMessage(X_INFO, "IGLX: Loaded and initialized %s\n", driverName); 469 470 return &screen->base; 471 472 handle_error: 473 if (screen->driver) 474 dlclose(screen->driver); 475 476 free(screen); 477 478 LogMessage(X_ERROR, "GLX: could not load software renderer\n"); 479 480 return NULL; 481} 482 483__GLXprovider __glXDRISWRastProvider = { 484 __glXDRIscreenProbe, 485 "DRISWRAST", 486 NULL 487}; 488