/* Get GEM handle for the pixmap */ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) { struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap); #ifdef USE_GLAMOR ScreenPtr screen = pixmap->drawable.pScreen; RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen)); #endif if (bo) { *handle = bo->handle; return TRUE; } #ifdef USE_GLAMOR if (info->use_glamor) { struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); CARD16 stride; CARD32 size; int fd, r; if (!priv) { priv = calloc(1, sizeof(*priv)); radeon_set_pixmap_private(pixmap, priv); } if (priv->handle_valid) { *handle = priv->handle; return TRUE; } fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size); if (fd < 0) return FALSE; r = drmPrimeFDToHandle(info->dri2.drm_fd, fd, &priv->handle); close(fd); if (r == 0) { struct drm_radeon_gem_set_tiling args = { .handle = priv->handle }; priv->handle_valid = TRUE; *handle = priv->handle; if (drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_GEM_GET_TILING, &args, sizeof(args)) == 0) priv->tiling_flags = args.tiling_flags; return TRUE; } } #endif return FALSE; } uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix) { #ifdef USE_GLAMOR RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); if (info->use_glamor) { struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix); if (!priv || (!priv->bo && !priv->handle_valid)) { uint32_t handle; radeon_get_pixmap_handle(pPix, &handle); priv = radeon_get_pixmap_private(pPix); } return priv ? priv->tiling_flags : 0; } else #endif { struct radeon_exa_pixmap_priv *driver_priv; driver_priv = exaGetPixmapDriverPrivate(pPix); return driver_priv ? driver_priv->tiling_flags : 0; } }
static PixmapPtr radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned usage) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONInfoPtr info = RADEONPTR(scrn); struct radeon_pixmap *priv; PixmapPtr pixmap, new_pixmap = NULL; if (!RADEON_CREATE_PIXMAP_SHARED(usage)) { if (info->shadow_primary) { if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) return fbCreatePixmap(screen, w, h, depth, usage); } else { pixmap = glamor_create_pixmap(screen, w, h, depth, usage); if (pixmap) return pixmap; } } if (w > 32767 || h > 32767) return NullPixmap; if (depth == 1) return fbCreatePixmap(screen, w, h, depth, usage); if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) return fbCreatePixmap(screen, w, h, depth, usage); pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); if (pixmap == NullPixmap) return pixmap; if (w && h) { int stride; priv = calloc(1, sizeof (struct radeon_pixmap)); if (priv == NULL) goto fallback_pixmap; priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage, pixmap->drawable.bitsPerPixel, &stride, &priv->surface, &priv->tiling_flags); if (!priv->bo) goto fallback_priv; radeon_set_pixmap_private(pixmap, priv); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) goto fallback_glamor; pixmap->devPrivate.ptr = NULL; } return pixmap; fallback_glamor: if (RADEON_CREATE_PIXMAP_SHARED(usage)) { /* XXX need further work to handle the DRI2 failure case. * Glamor don't know how to handle a BO only pixmap. Put * a warning indicator here. */ xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Failed to create textured DRI2/PRIME pixmap."); return pixmap; } /* Create textured pixmap failed means glamor failed to * create a texture from current BO for some reasons. We turn * to create a new glamor pixmap and clean up current one. * One thing need to be noted, this new pixmap doesn't * has a priv and bo attached to it. It's glamor's responsbility * to take care of it. Glamor will mark this new pixmap as a * texture only pixmap and will never fallback to DDX layer * afterwards. */ new_pixmap = glamor_create_pixmap(screen, w, h, depth, usage); radeon_bo_unref(priv->bo); fallback_priv: free(priv); fallback_pixmap: fbDestroyPixmap(pixmap); if (new_pixmap) return new_pixmap; else return fbCreatePixmap(screen, w, h, depth, usage); }