/* ** Free the per screen configs data as well as the array of ** __glXScreenConfigs. */ static void FreeScreenConfigs(struct glx_display * priv) { struct glx_screen *psc; GLint i, screens; /* Free screen configuration information */ screens = ScreenCount(priv->dpy); for (i = 0; i < screens; i++) { psc = priv->screens[i]; if (psc->configs) { glx_config_destroy_list(psc->configs); if (psc->effectiveGLXexts) Xfree(psc->effectiveGLXexts); psc->configs = NULL; /* NOTE: just for paranoia */ } if (psc->visuals) { glx_config_destroy_list(psc->visuals); psc->visuals = NULL; /* NOTE: just for paranoia */ } Xfree((char *) psc->serverGLXexts); #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) if (psc->driScreen) { psc->driScreen->destroyScreen(psc); } else { Xfree(psc); } #else Xfree(psc); #endif } XFree((char *) priv->screens); priv->screens = NULL; }
_X_HIDDEN void glx_screen_cleanup(struct glx_screen *psc) { if (psc->configs) { glx_config_destroy_list(psc->configs); free(psc->effectiveGLXexts); psc->configs = NULL; /* NOTE: just for paranoia */ } if (psc->visuals) { glx_config_destroy_list(psc->visuals); psc->visuals = NULL; /* NOTE: just for paranoia */ } free((char *) psc->serverGLXexts); }
/** * Allocate a linked list of \c struct glx_config structures. The fields of * each structure will be initialized to "reasonable" default values. In * most cases this is the default value defined by table 3.4 of the GLX * 1.3 specification. This means that most values are either initialized to * zero or \c GLX_DONT_CARE (which is -1). As support for additional * extensions is added, the new values will be initialized to appropriate * values from the extension specification. * * \param count Number of structures to allocate. * \param minimum_size Minimum size of a structure to allocate. This allows * for differences in the version of the * \c struct glx_config stucture used in libGL and in a * DRI-based driver. * \returns A pointer to the first element in a linked list of \c count * stuctures on success, or \c NULL on failure. */ _X_HIDDEN struct glx_config * glx_config_create_list(unsigned count) { const size_t size = sizeof(struct glx_config); struct glx_config *base = NULL; struct glx_config **next; unsigned i; next = &base; for (i = 0; i < count; i++) { *next = (struct glx_config *) malloc(size); if (*next == NULL) { glx_config_destroy_list(base); base = NULL; break; } (void) memset(*next, 0, size); (*next)->visualID = GLX_DONT_CARE; (*next)->visualType = GLX_DONT_CARE; (*next)->visualRating = GLX_NONE; (*next)->transparentPixel = GLX_NONE; (*next)->transparentRed = GLX_DONT_CARE; (*next)->transparentGreen = GLX_DONT_CARE; (*next)->transparentBlue = GLX_DONT_CARE; (*next)->transparentAlpha = GLX_DONT_CARE; (*next)->transparentIndex = GLX_DONT_CARE; (*next)->xRenderable = GLX_DONT_CARE; (*next)->fbconfigID = GLX_DONT_CARE; (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; (*next)->bindToTextureRgb = GLX_DONT_CARE; (*next)->bindToTextureRgba = GLX_DONT_CARE; (*next)->bindToMipmapTexture = GLX_DONT_CARE; (*next)->bindToTextureTargets = GLX_DONT_CARE; (*next)->yInverted = GLX_DONT_CARE; next = &((*next)->next); } return base; }
_X_HIDDEN struct glx_config * driConvertConfigs(const __DRIcoreExtension * core, struct glx_config *configs, const __DRIconfig **driConfigs) { struct glx_config head, *tail, *m; tail = &head; head.next = NULL; for (m = configs; m; m = m->next) { tail->next = createDriMode(core, m, driConfigs); if (tail->next == NULL) { /* no matching dri config for m */ continue; } tail = tail->next; } glx_config_destroy_list(configs); return head.next; }
/** * Perform the required libGL-side initialization and call the client-side * driver's \c __driCreateNewScreen function. * * \param dpy Display pointer. * \param scrn Screen number on the display. * \param psc DRI screen information. * \param driDpy DRI display information. * \param createNewScreen Pointer to the client-side driver's * \c __driCreateNewScreen function. * \returns A pointer to the \c __DRIscreen structure returned by * the client-side driver on success, or \c NULL on failure. */ static void * CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, struct dri_display * driDpy) { void *psp = NULL; drm_handle_t hSAREA; drmAddress pSAREA = MAP_FAILED; char *BusID; __DRIversion ddx_version; __DRIversion dri_version; __DRIversion drm_version; __DRIframebuffer framebuffer; int fd = -1; int status; drm_magic_t magic; drmVersionPtr version; int newlyopened; char *driverName; drm_handle_t hFB; int junk; const __DRIconfig **driver_configs; struct glx_config *visual, *configs = NULL, *visuals = NULL; /* DRI protocol version. */ dri_version.major = driDpy->driMajor; dri_version.minor = driDpy->driMinor; dri_version.patch = driDpy->driPatch; framebuffer.base = MAP_FAILED; framebuffer.dev_priv = NULL; framebuffer.size = 0; if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { ErrorMessageF("XF86DRIOpenConnection failed\n"); goto handle_error; } fd = drmOpenOnce(NULL, BusID, &newlyopened); free(BusID); /* No longer needed */ if (fd < 0) { ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); goto handle_error; } if (drmGetMagic(fd, &magic)) { ErrorMessageF("drmGetMagic failed\n"); goto handle_error; } version = drmGetVersion(fd); if (version) { drm_version.major = version->version_major; drm_version.minor = version->version_minor; drm_version.patch = version->version_patchlevel; drmFreeVersion(version); } else { drm_version.major = -1; drm_version.minor = -1; drm_version.patch = -1; } if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { ErrorMessageF("XF86DRIAuthConnection failed\n"); goto handle_error; } /* Get device name (like "radeon") and the ddx version numbers. * We'll check the version in each DRI driver's "createNewScreen" * function. */ if (!XF86DRIGetClientDriverName(dpy, scrn, &ddx_version.major, &ddx_version.minor, &ddx_version.patch, &driverName)) { ErrorMessageF("XF86DRIGetClientDriverName failed\n"); goto handle_error; } free(driverName); /* No longer needed. */ /* * Get device-specific info. pDevPriv will point to a struct * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that * has information about the screen size, depth, pitch, ancilliary * buffers, DRM mmap handles, etc. */ if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, &framebuffer.size, &framebuffer.stride, &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { ErrorMessageF("XF86DRIGetDeviceInfo failed\n"); goto handle_error; } framebuffer.width = DisplayWidth(dpy, scrn); framebuffer.height = DisplayHeight(dpy, scrn); /* Map the framebuffer region. */ status = drmMap(fd, hFB, framebuffer.size, (drmAddressPtr) & framebuffer.base); if (status != 0) { ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status)); goto handle_error; } /* Map the SAREA region. Further mmap regions may be setup in * each DRI driver's "createNewScreen" function. */ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); if (status != 0) { ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status)); goto handle_error; } psp = (*psc->legacy->createNewScreen) (scrn, &ddx_version, &dri_version, &drm_version, &framebuffer, pSAREA, fd, loader_extensions, &driver_configs, psc); if (psp == NULL) { ErrorMessageF("Calling driver entry point failed\n"); goto handle_error; } configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); if (!configs || !visuals) goto handle_error; glx_config_destroy_list(psc->base.configs); psc->base.configs = configs; glx_config_destroy_list(psc->base.visuals); psc->base.visuals = visuals; psc->driver_configs = driver_configs; /* Visuals with depth != screen depth are subject to automatic compositing * in the X server, so DRI1 can't render to them properly. Mark them as * non-conformant to prevent apps from picking them up accidentally. */ for (visual = psc->base.visuals; visual; visual = visual->next) { XVisualInfo template;