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->SourceValidate(pDraw, x, y, w, h, IncludeInferiors); 328 pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data); 329 if (cx != lastGLContext) { 330 lastGLContext = cx; 331 cx->makeCurrent(cx); 332 } 333} 334 335static const __DRIswrastLoaderExtension swrastLoaderExtension = { 336 {__DRI_SWRAST_LOADER, 1}, 337 swrastGetDrawableInfo, 338 swrastPutImage, 339 swrastGetImage 340}; 341 342static const __DRIextension *loader_extensions[] = { 343 &swrastLoaderExtension.base, 344 NULL 345}; 346 347static void 348initializeExtensions(__GLXscreen * screen) 349{ 350 const __DRIextension **extensions; 351 __GLXDRIscreen *dri = (__GLXDRIscreen *)screen; 352 int i; 353 354 __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); 355 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_no_config_context"); 356 357 if (dri->swrast->base.version >= 3) { 358 __glXEnableExtension(screen->glx_enable_bits, 359 "GLX_ARB_create_context"); 360 __glXEnableExtension(screen->glx_enable_bits, 361 "GLX_ARB_create_context_no_error"); 362 __glXEnableExtension(screen->glx_enable_bits, 363 "GLX_ARB_create_context_profile"); 364 __glXEnableExtension(screen->glx_enable_bits, 365 "GLX_EXT_create_context_es_profile"); 366 __glXEnableExtension(screen->glx_enable_bits, 367 "GLX_EXT_create_context_es2_profile"); 368 } 369 370 /* these are harmless to enable unconditionally */ 371 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_framebuffer_sRGB"); 372 __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float"); 373 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_fbconfig_packed_float"); 374 __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); 375 376 extensions = dri->core->getExtensions(dri->driScreen); 377 378 for (i = 0; extensions[i]; i++) { 379 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { 380 dri->copySubBuffer = 381 (const __DRIcopySubBufferExtension *) extensions[i]; 382 } 383 384 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { 385 dri->texBuffer = (const __DRItexBufferExtension *) extensions[i]; 386 } 387 388#ifdef __DRI2_FLUSH_CONTROL 389 if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) { 390 __glXEnableExtension(screen->glx_enable_bits, 391 "GLX_ARB_context_flush_control"); 392 } 393#endif 394 395 } 396} 397 398static void 399__glXDRIscreenDestroy(__GLXscreen * baseScreen) 400{ 401 int i; 402 403 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; 404 405 (*screen->core->destroyScreen) (screen->driScreen); 406 407 dlclose(screen->driver); 408 409 __glXScreenDestroy(baseScreen); 410 411 if (screen->driConfigs) { 412 for (i = 0; screen->driConfigs[i] != NULL; i++) 413 free((__DRIconfig **) screen->driConfigs[i]); 414 free(screen->driConfigs); 415 } 416 417 free(screen); 418} 419 420static __GLXscreen * 421__glXDRIscreenProbe(ScreenPtr pScreen) 422{ 423 const char *driverName = "swrast"; 424 __GLXDRIscreen *screen; 425 426 screen = calloc(1, sizeof *screen); 427 if (screen == NULL) 428 return NULL; 429 430 screen->base.destroy = __glXDRIscreenDestroy; 431 screen->base.createContext = __glXDRIscreenCreateContext; 432 screen->base.createDrawable = __glXDRIscreenCreateDrawable; 433 screen->base.swapInterval = NULL; 434 screen->base.pScreen = pScreen; 435 436 __glXInitExtensionEnableBits(screen->base.glx_enable_bits); 437 438 screen->driver = glxProbeDriver(driverName, 439 (void **) &screen->core, 440 __DRI_CORE, 1, 441 (void **) &screen->swrast, 442 __DRI_SWRAST, 1); 443 if (screen->driver == NULL) { 444 goto handle_error; 445 } 446 447 screen->driScreen = 448 (*screen->swrast->createNewScreen) (pScreen->myNum, 449 loader_extensions, 450 &screen->driConfigs, screen); 451 452 if (screen->driScreen == NULL) { 453 LogMessage(X_ERROR, "IGLX error: Calling driver entry point failed\n"); 454 goto handle_error; 455 } 456 457 initializeExtensions(&screen->base); 458 459 screen->base.fbconfigs = glxConvertConfigs(screen->core, 460 screen->driConfigs); 461 462#if !defined(XQUARTZ) && !defined(WIN32) 463 screen->base.glvnd = strdup("mesa"); 464#endif 465 __glXScreenInit(&screen->base, pScreen); 466 467 __glXsetGetProcAddress(glXGetProcAddressARB); 468 469 LogMessage(X_INFO, "IGLX: Loaded and initialized %s\n", driverName); 470 471 return &screen->base; 472 473 handle_error: 474 if (screen->driver) 475 dlclose(screen->driver); 476 477 free(screen); 478 479 LogMessage(X_ERROR, "GLX: could not load software renderer\n"); 480 481 return NULL; 482} 483 484__GLXprovider __glXDRISWRastProvider = { 485 __glXDRIscreenProbe, 486 "DRISWRAST", 487 NULL 488}; 489