diff --git a/configure.ac b/configure.ac index f187a1357..328563e6f 100644 --- a/configure.ac +++ b/configure.ac @@ -2105,6 +2105,10 @@ if test "x$GLAMOR" = xyes; then if test "x$GBM" = xyes; then AC_DEFINE(GLAMOR_HAS_GBM, 1, [Build glamor with GBM-based EGL support]) + AC_CHECK_DECL(GBM_BO_USE_LINEAR, + [AC_DEFINE(GLAMOR_HAS_GBM_LINEAR, 1, [Have GBM_BO_USE_LINEAR])], [], + [#include + #include ]) fi fi diff --git a/dix/cursor.c b/dix/cursor.c index 1525857e3..e45945619 100644 --- a/dix/cursor.c +++ b/dix/cursor.c @@ -80,9 +80,7 @@ FreeCursorBits(CursorBitsPtr bits) return; free(bits->source); free(bits->mask); -#ifdef ARGB_CURSOR free(bits->argb); -#endif dixFiniPrivates(bits, PRIVATE_CURSOR_BITS); if (bits->refcnt == 0) { GlyphSharePtr *prev, this; @@ -165,7 +163,6 @@ CheckForEmptyMask(CursorBitsPtr bits) while (n--) if (*(msk++) != 0) return; -#ifdef ARGB_CURSOR if (bits->argb) { CARD32 *argb = bits->argb; @@ -174,7 +171,6 @@ CheckForEmptyMask(CursorBitsPtr bits) if (*argb++ & 0xff000000) return; } -#endif bits->emptyMask = TRUE; } @@ -259,9 +255,7 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS) bits->source = psrcbits; bits->mask = pmaskbits; -#ifdef ARGB_CURSOR bits->argb = argb; -#endif bits->width = cm->width; bits->height = cm->height; bits->xhot = cm->xhot; @@ -400,9 +394,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS); bits->source = srcbits; bits->mask = mskbits; -#ifdef ARGB_CURSOR bits->argb = 0; -#endif bits->width = cm.width; bits->height = cm.height; bits->xhot = cm.xhot; diff --git a/glamor/glamor.h b/glamor/glamor.h index 0d57fff88..0931bbccd 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -142,7 +142,8 @@ extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen); extern _X_EXPORT unsigned int glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, - int h); + int h, + Bool linear); extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr, unsigned int, Bool, CARD16 *, CARD32 *); @@ -197,6 +198,21 @@ extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen, extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size); +/* @glamor_gbm_bo_from_pixmap: Get a GBM bo from a pixmap. + * + * @screen: Current screen pointer. + * @pixmap: The pixmap from which we want the fd. + * @stride, @size: Pointers to fill the stride and size of the + * buffer associated to the fd. + * + * the pixmap and the buffer represented by the gbm_bo will share the same + * content. + * + * Returns the gbm_bo on success, NULL on error. + * */ +extern _X_EXPORT void *glamor_gbm_bo_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap); + /* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd. * * @screen: Current screen pointer. @@ -217,6 +233,25 @@ extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen, CARD8 depth, CARD8 bpp); +/* @glamor_back_pixmap_from_fd: Backs an existing pixmap with a dma-buf fd. + * + * @pixmap: Pixmap to change backing for + * @fd: The dma-buf fd to import. + * @width: The width of the buffer. + * @height: The height of the buffer. + * @stride: The stride of the buffer. + * @depth: The depth of the buffer. + * @bpp: The number of bpp of the buffer. + * + * Returns TRUE if successful, FALSE on failure. + * */ +extern _X_EXPORT Bool glamor_back_pixmap_from_fd(PixmapPtr pixmap, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp); #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index dc5456118..e01f723fc 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -187,7 +187,7 @@ glamor_egl_get_gbm_device(ScreenPtr screen) } unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) +glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; @@ -200,6 +200,9 @@ glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) glamor_egl = glamor_egl_get_screen_private(scrn); bo = gbm_bo_create(glamor_egl->gbm, w, h, GBM_FORMAT_ARGB8888, +#ifdef GLAMOR_HAS_GBM_LINEAR + (linear ? GBM_BO_USE_LINEAR : 0) | +#endif GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); if (!bo) return 0; @@ -392,13 +395,10 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name) } #endif -int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) -{ #ifdef GLAMOR_HAS_GBM +static void * +_get_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, unsigned int tex) +{ ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -407,7 +407,6 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; struct gbm_bo *bo; - int fd = -1; EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, @@ -427,13 +426,64 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, (EGLClientBuffer) (uintptr_t) tex, attribs); if (image == EGL_NO_IMAGE_KHR) - goto failure; + return NULL; glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_egl_set_pixmap_image(pixmap, image); } bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); + if (!bo) + return NULL; + + pixmap->devKind = gbm_bo_get_stride(bo); + + return bo; +} +#endif + +void * +glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) +{ +#ifdef GLAMOR_HAS_GBM + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL || !glamor_priv->dri3_enabled) + return NULL; + switch (pixmap_priv->type) { + case GLAMOR_TEXTURE_DRM: + case GLAMOR_TEXTURE_ONLY: + if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) + return NULL; + return _get_gbm_bo_from_pixmap(screen, pixmap, + pixmap_priv->fbo->tex); + default: + break; + } + return NULL; +#else + return NULL; +#endif +} + +int +glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, + PixmapPtr pixmap, + unsigned int tex, + Bool want_name, CARD16 *stride, CARD32 *size) +{ +#ifdef GLAMOR_HAS_GBM + struct glamor_egl_screen_private *glamor_egl; + struct gbm_bo *bo; + int fd = -1; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + bo = _get_gbm_bo_from_pixmap(screen, pixmap, tex); if (!bo) goto failure; @@ -458,19 +508,19 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, #endif } -_X_EXPORT PixmapPtr -glamor_pixmap_from_fd(ScreenPtr screen, - int fd, - CARD16 width, - CARD16 height, - CARD16 stride, CARD8 depth, CARD8 bpp) +_X_EXPORT Bool +glamor_back_pixmap_from_fd(PixmapPtr pixmap, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, CARD8 depth, CARD8 bpp) { #ifdef GLAMOR_HAS_GBM + ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; EGLImageKHR image; - PixmapPtr pixmap; Bool ret = FALSE; EGLint attribs[] = { @@ -486,10 +536,10 @@ glamor_pixmap_from_fd(ScreenPtr screen, glamor_egl = glamor_egl_get_screen_private(scrn); if (!glamor_egl->dri3_capable) - return NULL; + return FALSE; if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0) - return NULL; + return FALSE; attribs[1] = width; attribs[3] = height; @@ -501,29 +551,48 @@ glamor_pixmap_from_fd(ScreenPtr screen, NULL, attribs); if (image == EGL_NO_IMAGE_KHR) - return NULL; + return FALSE; /* EGL_EXT_image_dma_buf_import can impose restrictions on the * usage of the image. Use gbm_bo to bypass the limitations. */ - bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); eglDestroyImageKHR(glamor_egl->display, image); if (!bo) - return NULL; + return FALSE; - pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); gbm_bo_destroy(bo); if (ret) - return pixmap; - else { + return TRUE; + return FALSE; +#else + return FALSE; +#endif +} + +_X_EXPORT PixmapPtr +glamor_pixmap_from_fd(ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, CARD8 depth, CARD8 bpp) +{ +#ifdef GLAMOR_HAS_GBM + PixmapPtr pixmap; + Bool ret; + + pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height, + stride, depth, bpp); + if (ret == FALSE) { screen->DestroyPixmap(pixmap); return NULL; } + return pixmap; #else return NULL; #endif diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c index a93f62dcb..c11e6d51b 100644 --- a/glamor/glamor_egl_stubs.c +++ b/glamor/glamor_egl_stubs.c @@ -50,7 +50,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, } unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) +glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) { return 0; } diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index ea0e80102..6017f5e32 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -228,6 +228,9 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, fbo->external = FALSE; fbo->format = format; + if (flag == CREATE_PIXMAP_USAGE_SHARED) + fbo->external = TRUE; + if (flag != GLAMOR_CREATE_FBO_NO_FBO) { if (glamor_pixmap_ensure_fb(glamor_priv, fbo) != 0) { glamor_purge_fbo(glamor_priv, fbo); @@ -313,7 +316,7 @@ glamor_destroy_fbo(glamor_screen_private *glamor_priv, static int _glamor_create_tex(glamor_screen_private *glamor_priv, - int w, int h, GLenum format) + int w, int h, GLenum format, Bool linear) { unsigned int tex = 0; @@ -323,7 +326,7 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, * an ARGB8888 based texture for us. */ if (glamor_priv->dri3_enabled && format == GL_RGBA) { tex = glamor_egl_create_argb8888_based_texture(glamor_priv->screen, - w, h); + w, h, linear); } if (!tex) { glamor_make_current(glamor_priv); @@ -344,14 +347,14 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo; GLint tex = 0; - if (flag == GLAMOR_CREATE_FBO_NO_FBO) + if (flag == GLAMOR_CREATE_FBO_NO_FBO || flag == CREATE_PIXMAP_USAGE_SHARED) goto new_fbo; fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, format); if (fbo) return fbo; new_fbo: - tex = _glamor_create_tex(glamor_priv, w, h, format); + tex = _glamor_create_tex(glamor_priv, w, h, format, flag == CREATE_PIXMAP_USAGE_SHARED); fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag); return fbo; @@ -531,7 +534,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) if (!pixmap_priv->fbo->tex) pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, format); + pixmap->drawable.height, format, FALSE); if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0) if (glamor_pixmap_ensure_fb(glamor_priv, pixmap_priv->fbo) != 0) diff --git a/hw/kdrive/ephyr/ephyrcursor.c b/hw/kdrive/ephyr/ephyrcursor.c index 852be33e0..808b3c72c 100644 --- a/hw/kdrive/ephyr/ephyrcursor.c +++ b/hw/kdrive/ephyr/ephyrcursor.c @@ -100,7 +100,6 @@ ephyrRealizeCoreCursor(EphyrScrPriv *scr, CursorPtr cursor) xcb_free_pixmap(conn, mask); } -#ifdef ARGB_CURSOR static xcb_render_pictformat_t get_argb_format(void) { @@ -170,7 +169,6 @@ can_argb_cursor(void) return v->major_version == 0 && v->minor_version >= 5; } -#endif static Bool ephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor) @@ -179,11 +177,9 @@ ephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor) KdScreenInfo *kscr = pScreenPriv->screen; EphyrScrPriv *scr = kscr->driver; -#ifdef ARGB_CURSOR if (cursor->bits->argb && can_argb_cursor()) ephyrRealizeARGBCursor(scr, cursor); else -#endif { ephyrRealizeCoreCursor(scr, cursor); } diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index b8ec8a0ef..2b4df0cf7 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -123,7 +123,7 @@ static ModuleDefault ModuleDefaults[] = { /* Forward declarations */ static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, - int scrnum, MessageType from); + int scrnum, MessageType from, Bool auto_gpu_device); static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor); static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active, Bool gpu); @@ -1524,7 +1524,7 @@ configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, else scrnum = adjp->adj_scrnum; if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum, - X_CONFIG)) { + X_CONFIG, (scrnum == 0 && !adjp->list.next))) { do { free(slp[count].screen); } while (count--); @@ -1574,7 +1574,7 @@ configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen); slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); if (!configScreen(slp[0].screen, screen, - 0, X_CONFIG)) { + 0, X_CONFIG, TRUE)) { free(slp[0].screen); free(slp); return FALSE; @@ -1703,7 +1703,7 @@ configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen, slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec)); slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); slp[1].screen = NULL; - if (!configScreen(slp[0].screen, conf_screen, 0, from)) { + if (!configScreen(slp[0].screen, conf_screen, 0, from, TRUE)) { free(slp); return FALSE; } @@ -1768,7 +1768,7 @@ configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor) static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, - MessageType from) + MessageType from, Bool auto_gpu_device) { int count = 0; XF86ConfDisplayPtr dispptr; @@ -1825,7 +1825,8 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, screenp->device = NULL; } - if (conf_screen->num_gpu_devices == 0 && xf86configptr->conf_device_lst) { + if (auto_gpu_device && conf_screen->num_gpu_devices == 0 && + xf86configptr->conf_device_lst) { XF86ConfDevicePtr sdevice = xf86configptr->conf_device_lst->list.next; for (i = 0; i < MAX_GPUDEVICES; i++) { diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index e90e4b842..860333863 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -123,6 +123,7 @@ typedef enum { OPTION_DEVICE_PATH, OPTION_SHADOW_FB, OPTION_ACCEL_METHOD, + OPTION_PAGEFLIP, } modesettingOpts; static const OptionInfoRec Options[] = { @@ -130,6 +131,7 @@ static const OptionInfoRec Options[] = { {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE}, {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, + {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -531,6 +533,38 @@ dispatch_slave_dirty(ScreenPtr pScreen) } } +static void +redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) +{ + + RegionRec pixregion; + + PixmapRegionInit(&pixregion, dirty->slave_dst); + DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); + PixmapSyncDirtyHelper(dirty, &pixregion); + + DamageRegionProcessPending(&dirty->slave_dst->drawable); + RegionUninit(&pixregion); +} + +static void +ms_dirty_update(ScreenPtr screen) +{ + RegionPtr region; + PixmapDirtyUpdatePtr ent; + + if (xorg_list_is_empty(&screen->pixmap_dirty_list)) + return; + + xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { + region = DamageRegion(ent->damage); + if (RegionNotEmpty(region)) { + redisplay_dirty(screen, ent); + DamageEmpty(ent->damage); + } + } +} + static void msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask) { @@ -540,10 +574,12 @@ msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask) pScreen->BlockHandler(pScreen, pTimeout, pReadmask); ms->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = msBlockHandler; - if (pScreen->isGPU) + if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode) dispatch_slave_dirty(pScreen); else if (ms->dirty_enabled) dispatch_dirty(pScreen); + + ms_dirty_update(pScreen); } static void @@ -727,6 +763,10 @@ PreInit(ScrnInfoPtr pScrn, int flags) if (ret == 0) { if (value & DRM_PRIME_CAP_IMPORT) pScrn->capabilities |= RR_Capability_SinkOutput; +#if GLAMOR_HAS_GBM_LINEAR + if (value & DRM_PRIME_CAP_EXPORT) + pScrn->capabilities |= RR_Capability_SourceOutput; +#endif } #endif drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp); @@ -782,7 +822,8 @@ PreInit(ScrnInfoPtr pScrn, int flags) try_enable_glamor(pScrn); if (ms->drmmode.glamor) { - xf86LoadSubModule(pScrn, "dri2"); + ms->drmmode.pageflip = + xf86ReturnOptValBool(ms->Options, OPTION_PAGEFLIP, TRUE); } else { Bool prefer_shadow = TRUE; @@ -799,6 +840,8 @@ PreInit(ScrnInfoPtr pScrn, int flags) "ShadowFB: preferred %s, enabled %s\n", prefer_shadow ? "YES" : "NO", ms->drmmode.shadow_enable ? "YES" : "NO"); + + ms->drmmode.pageflip = FALSE; } if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) { @@ -937,6 +980,23 @@ msShadowInit(ScreenPtr pScreen) return TRUE; } +static Bool +msSharePixmapBacking(PixmapPtr ppix, ScreenPtr screen, void **handle) +{ +#ifdef GLAMOR_HAS_GBM + int ret; + CARD16 stride; + CARD32 size; + ret = glamor_fd_from_pixmap(ppix->drawable.pScreen, ppix, &stride, &size); + if (ret == -1) + return FALSE; + + *handle = (void *)(long)(ret); + return TRUE; +#endif + return FALSE; +} + static Bool msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) { @@ -944,10 +1004,18 @@ msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) ScrnInfoPtr scrn = xf86ScreenToScrn(screen); modesettingPtr ms = modesettingPTR(scrn); Bool ret; - int size = ppix->devKind * ppix->drawable.height; int ihandle = (int) (long) fd_handle; - ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size); + if (ms->drmmode.reverse_prime_offload_mode) { + ret = glamor_back_pixmap_from_fd(ppix, ihandle, + ppix->drawable.width, + ppix->drawable.height, + ppix->devKind, ppix->drawable.depth, + ppix->drawable.bitsPerPixel); + } else { + int size = ppix->devKind * ppix->drawable.height; + ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size); + } if (ret == FALSE) return ret; @@ -1089,7 +1157,10 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv) ms->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = msBlockHandler; + pScreen->SharePixmapBacking = msSharePixmapBacking; pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking; + pScreen->StartPixmapTracking = PixmapStartDirtyTracking; + pScreen->StopPixmapTracking = PixmapStopDirtyTracking; if (!xf86CrtcScreenInit(pScreen)) return FALSE; @@ -1132,6 +1203,9 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize the Present extension.\n"); } + /* enable reverse prime if we are a GPU screen, and accelerated */ + if (pScreen->isGPU) + ms->drmmode.reverse_prime_offload_mode = TRUE; } #endif diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 3decc3eea..9ae4966fd 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -101,6 +101,12 @@ typedef struct _modesettingRec { drmEventContext event_context; + /** + * Page flipping stuff. + * @{ + */ + /** @} */ + DamagePtr damage; Bool dirty_enabled; @@ -117,6 +123,9 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc, void ms_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data); +void ms_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq); + +Bool ms_crtc_on(xf86CrtcPtr crtc); xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw); xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box, diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index f3c9909ef..8dbac07f2 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -50,7 +50,9 @@ #include "driver.h" -static int +static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height); + +int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo) { int ret; @@ -71,7 +73,7 @@ drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo) return 0; } -static uint32_t +uint32_t drmmode_bo_get_pitch(drmmode_bo *bo) { #ifdef GLAMOR_HAS_GBM @@ -141,6 +143,35 @@ drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo, return bo->dumb != NULL; } +Bool +drmmode_bo_for_pixmap(drmmode_ptr drmmode, drmmode_bo *bo, PixmapPtr pixmap) +{ + ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn); + uint16_t pitch; + uint32_t size; + int fd; + +#ifdef GLAMOR_HAS_GBM + if (drmmode->glamor) { + bo->gbm = glamor_gbm_bo_from_pixmap(screen, pixmap); + bo->dumb = NULL; + return bo->gbm != NULL; + } +#endif + + fd = glamor_fd_from_pixmap(screen, pixmap, &pitch, &size); + if (fd < 0) { + xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR, + "Failed to get fd for flip to new front.\n"); + return FALSE; + } + + bo->dumb = dumb_get_bo_from_fd(drmmode->fd, fd, pitch, size); + close(fd); + + return bo->dumb != NULL; +} + Bool drmmode_SetSlaveBO(PixmapPtr ppix, drmmode_ptr drmmode, int fd_handle, int pitch, int size) @@ -343,10 +374,14 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, fb_id = drmmode->fb_id; if (crtc->randr_crtc->scanout_pixmap) { - msPixmapPrivPtr ppriv = - msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap); - fb_id = ppriv->fb_id; - x = y = 0; + if (!drmmode->reverse_prime_offload_mode) { + msPixmapPrivPtr ppriv = + msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap); + fb_id = ppriv->fb_id; + x = 0; + } else + x = drmmode_crtc->prime_pixmap_x; + y = 0; } else if (drmmode_crtc->rotate_fb_id) { fb_id = drmmode_crtc->rotate_fb_id; @@ -363,6 +398,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (crtc->scrn->pScreen) xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen); + drmmode_crtc->need_modeset = FALSE; crtc->funcs->dpms(crtc, DPMSModeOn); /* go through all the outputs and force DPMS them back on? */ @@ -502,7 +538,54 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green, } static Bool -drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) +drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix) +{ + ScreenPtr screen = xf86ScrnToScreen(crtc->scrn); + PixmapPtr screenpix = screen->GetScreenPixmap(screen); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + int c, total_width = 0, max_height = 0, this_x = 0; + + if (!ppix) { + if (crtc->randr_crtc->scanout_pixmap) + PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix); + drmmode_crtc->prime_pixmap_x = 0; + return TRUE; + } + /* iterate over all the attached crtcs to work out the bounding box */ + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr iter = xf86_config->crtc[c]; + if (!iter->enabled && iter != crtc) + continue; + if (iter == crtc) { + this_x = total_width; + total_width += ppix->drawable.width; + if (max_height < ppix->drawable.height) + max_height = ppix->drawable.height; + } else { + total_width += iter->mode.HDisplay; + if (max_height < iter->mode.VDisplay) + max_height = iter->mode.VDisplay; + } + } + + if (total_width != screenpix->drawable.width || + max_height != screenpix->drawable.height) { + + if (!drmmode_xf86crtc_resize(crtc->scrn, total_width, max_height)) + return FALSE; + + screenpix = screen->GetScreenPixmap(screen); + screen->width = screenpix->drawable.width = total_width; + screen->height = screenpix->drawable.height = max_height; + } + drmmode_crtc->prime_pixmap_x = this_x; + PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0); + return TRUE; +} + +static Bool +drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; @@ -543,6 +626,18 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) return TRUE; } +static Bool +drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + if (drmmode->reverse_prime_offload_mode) + return drmmode_set_scanout_pixmap_gpu(crtc, ppix); + else + return drmmode_set_scanout_pixmap_cpu(crtc, ppix); +} + static void * drmmode_shadow_allocate(xf86CrtcPtr crtc, int width, int height) { @@ -939,6 +1034,7 @@ static void drmmode_output_dpms(xf86OutputPtr output, int mode) { drmmode_output_private_ptr drmmode_output = output->driver_private; + xf86CrtcPtr crtc = output->crtc; drmModeConnectorPtr koutput = drmmode_output->mode_output; drmmode_ptr drmmode = drmmode_output->drmmode; @@ -947,6 +1043,13 @@ drmmode_output_dpms(xf86OutputPtr output, int mode) drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, drmmode_output->dpms_enum_id, mode); + + if (mode == DPMSModeOn && crtc) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + if (drmmode_crtc->need_modeset) + drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, + crtc->x, crtc->y); + } return; } diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index b0e45b6e0..fe363c577 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -46,7 +46,6 @@ typedef struct { typedef struct { int fd; unsigned fb_id; - unsigned old_fb_id; drmModeFBPtr mode_fb; int cpp; ScrnInfoPtr scrn; @@ -63,6 +62,8 @@ typedef struct { Bool glamor; Bool shadow_enable; + /** Is Option "PageFlip" enabled? */ + Bool pageflip; void *shadow_fb; /** @@ -79,6 +80,8 @@ typedef struct { uint32_t triple_buffer_name; DevPrivateKeyRec pixmapPrivateKeyRec; + + Bool reverse_prime_offload_mode; } drmmode_rec, *drmmode_ptr; typedef struct { @@ -93,7 +96,7 @@ typedef struct { drmmode_bo rotate_bo; unsigned rotate_fb_id; - + unsigned prime_pixmap_x; /** * @{ MSC (vblank count) handling for the PRESENT extension. * @@ -105,6 +108,8 @@ typedef struct { uint32_t msc_prev; uint64_t msc_high; /** @} */ + + Bool need_modeset; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -139,6 +144,9 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec; #define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec)) +Bool drmmode_bo_for_pixmap(drmmode_ptr drmmode, drmmode_bo *bo, PixmapPtr pixmap); +int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo); +uint32_t drmmode_bo_get_pitch(drmmode_bo *bo); uint32_t drmmode_bo_get_handle(drmmode_bo *bo); Bool drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode); void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv); diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c index 359e11316..090539861 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -44,6 +44,7 @@ #include #include "driver.h" +#include "drmmode_display.h" #if 0 #define DebugPresent(x) ErrorF x @@ -72,8 +73,11 @@ ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) /* * Flush the DRM event queue when full; makes space for new events. + * + * Returns a negative value on error, 0 if there was nothing to process, + * or 1 if we handled any events. */ -static Bool +static int ms_flush_drm_events(ScreenPtr screen) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); @@ -86,10 +90,19 @@ ms_flush_drm_events(ScreenPtr screen) r = poll(&p, 1, 0); } while (r == -1 && (errno == EINTR || errno == EAGAIN)); + /* If there was an error, r will be < 0. Return that. If there was + * nothing to process, r == 0. Return that. + */ if (r <= 0) - return TRUE; + return r; - return drmHandleEvent(ms->fd, &ms->event_context) >= 0; + /* Try to handle the event. If there was an error, return it. */ + r = drmHandleEvent(ms->fd, &ms->event_context); + if (r < 0) + return r; + + /* Otherwise return 1 to indicate that we handled an event. */ + return 1; } /* @@ -159,8 +172,13 @@ ms_present_queue_vblank(RRCrtcPtr crtc, ret = drmWaitVBlank(ms->fd, &vbl); if (!ret) break; - if (errno != EBUSY || !ms_flush_drm_events(screen)) + /* If we hit EBUSY, then try to flush events. If we can't, then + * this is an error. + */ + if (errno != EBUSY || ms_flush_drm_events(screen) < 0) { + ms_drm_abort_seq(scrn, seq); return BadAlloc; + } } DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n", (long long) event_id, seq, (long long) msc, @@ -206,6 +224,413 @@ ms_present_flush(WindowPtr window) #endif } +#ifdef GLAMOR + +/* + * Event data for an in progress flip. + * This contains a pointer to the vblank event, + * and information about the flip in progress. + * a reference to this is stored in the per-crtc + * flips. + */ +struct ms_flipdata { + ScreenPtr screen; + struct ms_present_vblank_event *event; + /* number of CRTC events referencing this */ + int flip_count; + uint64_t fe_msc; + uint64_t fe_usec; + uint32_t old_fb_id; +}; + +/* + * Per crtc pageflipping infomation, + * These are submitted to the queuing code + * one of them per crtc per flip. + */ +struct ms_crtc_pageflip { + Bool on_reference_crtc; + /* reference to the ms_flipdata */ + struct ms_flipdata *flipdata; +}; + +/** + * Free an ms_crtc_pageflip. + * + * Drops the reference count on the flipdata. + */ +static void +ms_present_flip_free(struct ms_crtc_pageflip *flip) +{ + struct ms_flipdata *flipdata = flip->flipdata; + + free(flip); + if (--flipdata->flip_count > 0) + return; + free(flipdata); +} + +/** + * Callback for the DRM event queue when a single flip has completed + * + * Once the flip has been completed on all pipes, notify the + * extension code telling it when that happened + */ +static void +ms_flip_handler(uint64_t msc, uint64_t ust, void *data) +{ + struct ms_crtc_pageflip *flip = data; + ScreenPtr screen = flip->flipdata->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + struct ms_flipdata *flipdata = flip->flipdata; + + DebugPresent(("\t\tms:fh %lld c %d msc %llu ust %llu\n", + (long long) flipdata->event->event_id, + flipdata->flip_count, + (long long) msc, (long long) ust)); + + if (flip->on_reference_crtc) { + flipdata->fe_msc = msc; + flipdata->fe_usec = ust; + } + + if (flipdata->flip_count == 1) { + DebugPresent(("\t\tms:fc %lld c %d msc %llu ust %llu\n", + (long long) flipdata->event->event_id, + flipdata->flip_count, + (long long) flipdata->fe_msc, (long long) flipdata->fe_usec)); + + + ms_present_vblank_handler(flipdata->fe_msc, + flipdata->fe_usec, + flipdata->event); + + drmModeRmFB(ms->fd, flipdata->old_fb_id); + } + ms_present_flip_free(flip); +} + +/* + * Callback for the DRM queue abort code. A flip has been aborted. + */ +static void +ms_present_flip_abort(void *data) +{ + struct ms_crtc_pageflip *flip = data; + struct ms_flipdata *flipdata = flip->flipdata; + + DebugPresent(("\t\tms:fa %lld c %d\n", (long long) flipdata->event->event_id, flipdata->flip_count)); + + if (flipdata->flip_count == 1) + free(flipdata->event); + + ms_present_flip_free(flip); +} + +static Bool +queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc, + struct ms_flipdata *flipdata, + int ref_crtc_vblank_pipe, uint32_t flags) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct ms_crtc_pageflip *flip; + uint32_t seq; + int err; + + flip = calloc(1, sizeof(struct ms_crtc_pageflip)); + if (flip == NULL) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue: carrier alloc failed.\n"); + return FALSE; + } + + /* Only the reference crtc will finally deliver its page flip + * completion event. All other crtc's events will be discarded. + */ + flip->on_reference_crtc = (drmmode_crtc->vblank_pipe == ref_crtc_vblank_pipe); + flip->flipdata = flipdata; + + seq = ms_drm_queue_alloc(crtc, flip, ms_flip_handler, ms_present_flip_abort); + if (!seq) { + free(flip); + return FALSE; + } + + DebugPresent(("\t\tms:fq %lld c %d -> %d seq %llu\n", + (long long) flipdata->event->event_id, + flipdata->flip_count, flipdata->flip_count + 1, + (long long) seq)); + + /* take a reference on flipdata for use in flip */ + flipdata->flip_count++; + + while (drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id, + ms->drmmode.fb_id, flags, (void *) (uintptr_t) seq)) { + err = errno; + /* We may have failed because the event queue was full. Flush it + * and retry. If there was nothing to flush, then we failed for + * some other reason and should just return an error. + */ + if (ms_flush_drm_events(screen) <= 0) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed: %s\n", strerror(err)); + /* Aborting will also decrement flip_count and free(flip). */ + ms_drm_abort_seq(scrn, seq); + return FALSE; + } + + /* We flushed some events, so try again. */ + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n"); + } + + /* The page flip succeded. */ + return TRUE; +} + + +static Bool +ms_do_pageflip(ScreenPtr screen, + PixmapPtr new_front, + struct ms_present_vblank_event *event, + int ref_crtc_vblank_pipe, + Bool async) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_bo new_front_bo; + uint32_t flags; + int i; + struct ms_flipdata *flipdata; + glamor_block_handler(screen); + + new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front); + new_front_bo.dumb = NULL; + if (!new_front_bo.gbm) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to get GBM bo for flip to new front.\n"); + return FALSE; + } + + flipdata = calloc(1, sizeof(struct ms_flipdata)); + if (!flipdata) { + drmmode_bo_destroy(&ms->drmmode, &new_front_bo); + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to allocate flipdata.\n"); + return FALSE; + } + + flipdata->event = event; + flipdata->screen = screen; + + /* + * Take a local reference on flipdata. + * if the first flip fails, the sequence abort + * code will free the crtc flip data, and drop + * it's reference which would cause this to be + * freed when we still required it. + */ + flipdata->flip_count++; + + /* Create a new handle for the back buffer */ + flipdata->old_fb_id = ms->drmmode.fb_id; + if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, + drmmode_bo_get_pitch(&new_front_bo), + drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) { + goto error_out; + } + + drmmode_bo_destroy(&ms->drmmode, &new_front_bo); + + flags = DRM_MODE_PAGE_FLIP_EVENT; + if (async) + flags |= DRM_MODE_PAGE_FLIP_ASYNC; + + /* Queue flips on all enabled CRTCs. + * + * Note that if/when we get per-CRTC buffers, we'll have to update this. + * Right now it assumes a single shared fb across all CRTCs, with the + * kernel fixing up the offset of each CRTC as necessary. + * + * Also, flips queued on disabled or incorrectly configured displays + * may never complete; this is a configuration error. + */ + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + + if (!ms_crtc_on(crtc)) + continue; + + if (!queue_flip_on_crtc(screen, crtc, flipdata, + ref_crtc_vblank_pipe, + flags)) { + goto error_undo; + } + } + + /* + * Do we have more than our local reference, + * if so and no errors, then drop our local + * reference and return now. + */ + if (flipdata->flip_count > 1) { + flipdata->flip_count--; + return TRUE; + } + +error_undo: + + /* + * Have we just got the local reference? + * free the framebuffer if so since nobody successfully + * submitted anything + */ + if (flipdata->flip_count == 1) { + drmModeRmFB(ms->fd, ms->drmmode.fb_id); + ms->drmmode.fb_id = flipdata->old_fb_id; + } + +error_out: + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", + strerror(errno)); + /* if only the local reference - free the structure, + * else drop the local reference and return */ + if (flipdata->flip_count == 1) + free(flipdata); + else + flipdata->flip_count--; + + return FALSE; +} + +/* + * Test to see if page flipping is possible on the target crtc + */ +static Bool +ms_present_check_flip(RRCrtcPtr crtc, + WindowPtr window, + PixmapPtr pixmap, + Bool sync_flip) +{ + ScreenPtr screen = window->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int num_crtcs_on = 0; + int i; + + if (!ms->drmmode.pageflip) + return FALSE; + + if (!scrn->vtSema) + return FALSE; + + for (i = 0; i < config->num_crtc; i++) { + drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private; + + /* Don't do pageflipping if CRTCs are rotated. */ + if (drmmode_crtc->rotate_bo.gbm) + return FALSE; + + if (ms_crtc_on(config->crtc[i])) + num_crtcs_on++; + } + + /* We can't do pageflipping if all the CRTCs are off. */ + if (num_crtcs_on == 0) + return FALSE; + + /* Check stride, can't change that on flip */ + if (pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo)) + return FALSE; + + /* Make sure there's a bo we can get to */ + /* XXX: actually do this. also...is it sufficient? + * if (!glamor_get_pixmap_private(pixmap)) + * return FALSE; + */ + + return TRUE; +} + +/* + * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, + * then wait for vblank. Otherwise, flip immediately + */ +static Bool +ms_present_flip(RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip) +{ + ScreenPtr screen = crtc->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + xf86CrtcPtr xf86_crtc = crtc->devPrivate; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + Bool ret; + struct ms_present_vblank_event *event; + + if (!ms_present_check_flip(crtc, screen->root, pixmap, sync_flip)) + return FALSE; + + event = calloc(1, sizeof(struct ms_present_vblank_event)); + if (!event) + return FALSE; + + event->event_id = event_id; + ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip); + if (!ret) + xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); + + return ret; +} + +/* + * Queue a flip back to the normal frame buffer + */ +static void +ms_present_unflip(ScreenPtr screen, uint64_t event_id) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + PixmapPtr pixmap = screen->GetScreenPixmap(screen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + struct ms_present_vblank_event *event; + + event = calloc(1, sizeof(struct ms_present_vblank_event)); + if (!event) + return; + + event->event_id = event_id; + + if (ms_present_check_flip(NULL, screen->root, pixmap, TRUE) && + ms_do_pageflip(screen, pixmap, event, -1, FALSE)) { + return; + } + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + if (!crtc->enabled) + continue; + + if (drmmode_crtc->dpms_mode == DPMSModeOn) + crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, + crtc->x, crtc->y); + else + drmmode_crtc->need_modeset = TRUE; + } + + present_event_notify(event_id, 0, 0); +} +#endif + static present_screen_info_rec ms_present_screen_info = { .version = PRESENT_SCREEN_INFO_VERSION, @@ -216,13 +641,24 @@ static present_screen_info_rec ms_present_screen_info = { .flush = ms_present_flush, .capabilities = PresentCapabilityNone, - .check_flip = 0, - .flip = 0, - .unflip = 0, + .check_flip = ms_present_check_flip, +#ifdef GLAMOR + .flip = ms_present_flip, + .unflip = ms_present_unflip, +#endif }; Bool ms_present_screen_init(ScreenPtr screen) { + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + uint64_t value; + int ret; + + ret = drmGetCap(ms->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); + if (ret == 0 && value == 1) + ms_present_screen_info.capabilities |= PresentCapabilityAsync; + return present_screen_init(screen, &ms_present_screen_info); } diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c index a342662a7..0b7bf9d73 100644 --- a/hw/xfree86/drivers/modesetting/vblank.c +++ b/hw/xfree86/drivers/modesetting/vblank.c @@ -50,11 +50,6 @@ static struct xorg_list ms_drm_queue; static uint32_t ms_drm_seq; -struct ms_pageflip { - ScreenPtr screen; - Bool crtc_for_msc_ust; -}; - static void ms_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) { dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; @@ -88,7 +83,7 @@ static int ms_box_area(BoxPtr box) return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1); } -static Bool +Bool ms_crtc_on(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; @@ -323,6 +318,22 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn) } } +/** + * Abort by drm queue sequence number. + */ +void +ms_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq) +{ + struct ms_drm_queue *q, *tmp; + + xorg_list_for_each_entry_safe(q, tmp, &ms_drm_queue, list) { + if (q->seq == seq) { + ms_drm_abort_one(q); + break; + } + } +} + /* * Externally usable abort function that uses a callback to match a single * queued entry to abort diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c index 379a27a76..321cde775 100644 --- a/hw/xfree86/modes/xf86Cursors.c +++ b/hw/xfree86/modes/xf86Cursors.c @@ -258,9 +258,7 @@ xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src) CARD32 bits; const Rotation rotation = xf86_crtc_cursor_rotation(crtc); -#ifdef ARGB_CURSOR crtc->cursor_argb = FALSE; -#endif for (y = 0; y < cursor_info->MaxHeight; y++) for (x = 0; x < cursor_info->MaxWidth; x++) { @@ -458,9 +456,7 @@ xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src) CARD8 *cursor_image; const Rotation rotation = xf86_crtc_cursor_rotation(crtc); -#ifdef ARGB_CURSOR crtc->cursor_argb = FALSE; -#endif if (rotation == RR_Rotate_0) cursor_image = src; @@ -632,12 +628,10 @@ xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags) cursor_info->HideCursor = xf86_hide_cursors; cursor_info->ShowCursor = xf86_show_cursors; cursor_info->UseHWCursor = xf86_use_hw_cursor; -#ifdef ARGB_CURSOR if (flags & HARDWARE_CURSOR_ARGB) { cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb; cursor_info->LoadCursorARGBCheck = xf86_load_cursor_argb; } -#endif xf86_config->cursor = NULL; xf86_hide_cursors(scrn); @@ -691,11 +685,9 @@ xf86_reload_cursors(ScreenPtr screen) void *src = dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, screen); -#ifdef ARGB_CURSOR if (cursor->bits->argb && xf86DriverHasLoadCursorARGB(cursor_info)) xf86DriverLoadCursorARGB(cursor_info, cursor); else if (src) -#endif xf86DriverLoadCursorImage(cursor_info, src); x += scrn->frameX0 + cursor_screen_priv->HotX; diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c index 9c00a443f..bc1ea2166 100644 --- a/hw/xfree86/modes/xf86Rotate.c +++ b/hw/xfree86/modes/xf86Rotate.c @@ -43,12 +43,6 @@ #include "X11/extensions/dpmsconst.h" #include "X11/Xatom.h" -/* borrowed from composite extension, move to Render and publish? */ - -#define F(x) IntToxFixed(x) - -#define toF(x) ((float) (x) / 65536.0f) - static void xf86RotateCrtcRedisplay(xf86CrtcPtr crtc, RegionPtr region) { diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c index 04496d531..2a54571cb 100644 --- a/hw/xfree86/ramdac/xf86Cursor.c +++ b/hw/xfree86/ramdac/xf86Cursor.c @@ -340,12 +340,10 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) && (ScreenPriv->ForceHWCursorCount || (( -#ifdef ARGB_CURSOR cursor->bits->argb && infoPtr->UseHWCursorARGB && (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) || (cursor->bits->argb == 0 && -#endif (cursor->bits->height <= infoPtr->MaxHeight) && (cursor->bits->width <= infoPtr->MaxWidth) && (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))))) { diff --git a/hw/xfree86/ramdac/xf86Cursor.h b/hw/xfree86/ramdac/xf86Cursor.h index a389a9988..8c98bb151 100644 --- a/hw/xfree86/ramdac/xf86Cursor.h +++ b/hw/xfree86/ramdac/xf86Cursor.h @@ -19,11 +19,9 @@ typedef struct _xf86CursorInfoRec { unsigned char *(*RealizeCursor) (struct _xf86CursorInfoRec *, CursorPtr); Bool (*UseHWCursor) (ScreenPtr, CursorPtr); -#ifdef ARGB_CURSOR Bool (*UseHWCursorARGB) (ScreenPtr, CursorPtr); void (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr); Bool (*LoadCursorARGBCheck) (ScrnInfoPtr, CursorPtr); -#endif } xf86CursorInfoRec, *xf86CursorInfoPtr; @@ -77,8 +75,6 @@ extern _X_EXPORT void xf86ForceHWCursor(ScreenPtr pScreen, Bool on); #define HARDWARE_CURSOR_NIBBLE_SWAPPED 0x00000800 #define HARDWARE_CURSOR_SHOW_TRANSPARENT 0x00001000 #define HARDWARE_CURSOR_UPDATE_UNHIDDEN 0x00002000 -#ifdef ARGB_CURSOR #define HARDWARE_CURSOR_ARGB 0x00004000 -#endif #endif /* _XF86CURSOR_H */ diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c index be7154e0f..84febe0df 100644 --- a/hw/xfree86/ramdac/xf86HWCurs.c +++ b/hw/xfree86/ramdac/xf86HWCurs.c @@ -139,9 +139,7 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; -#ifdef ARGB_CURSOR if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr)) -#endif if (!bits) { bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs); dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, @@ -151,12 +149,10 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) (*infoPtr->HideCursor) (infoPtr->pScrn); -#ifdef ARGB_CURSOR if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) { if (!xf86DriverLoadCursorARGB (infoPtr, pCurs)) return FALSE; } else -#endif if (bits) if (!xf86DriverLoadCursorImage (infoPtr, bits)) return FALSE; @@ -213,12 +209,10 @@ xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed) xf86CursorScreenKey); xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; -#ifdef ARGB_CURSOR /* recoloring isn't applicable to ARGB cursors and drivers shouldn't have to ignore SetCursorColors requests */ if (pCurs->bits->argb) return; -#endif if (ScreenPriv->PalettedCursor) { xColorItem sourceColor, maskColor; diff --git a/hw/xquartz/xpr/xprCursor.c b/hw/xquartz/xpr/xprCursor.c index 4168f7c53..5e89348c0 100644 --- a/hw/xquartz/xpr/xprCursor.c +++ b/hw/xquartz/xpr/xprCursor.c @@ -85,7 +85,6 @@ load_cursor(CursorPtr src, int screen) hot_x = src->bits->xhot; hot_y = src->bits->yhot; -#ifdef ARGB_CURSOR if (src->bits->argb != NULL) { #if BITMAP_BIT_ORDER == MSBFirst rowbytes = src->bits->width * sizeof(CARD32); @@ -104,7 +103,6 @@ load_cursor(CursorPtr src, int screen) #endif } else -#endif { fg_color = 0xFF00 | (src->foreRed >> 8); fg_color <<= 16; diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index 6b6e59756..ece7dbe38 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -415,7 +415,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, } unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) +glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) { return 0; } diff --git a/include/cursorstr.h b/include/cursorstr.h index 221cd7034..3f306a496 100644 --- a/include/cursorstr.h +++ b/include/cursorstr.h @@ -64,9 +64,7 @@ typedef struct _CursorBits { unsigned short width, height, xhot, yhot; /* metrics */ int refcnt; /* can be shared */ PrivateRec *devPrivates; /* set by pScr->RealizeCursor */ -#ifdef ARGB_CURSOR CARD32 *argb; /* full-color alpha blended */ -#endif } CursorBits, *CursorBitsPtr; #define CURSOR_BITS_SIZE (sizeof(CursorBits) + dixPrivatesSize(PRIVATE_CURSOR_BITS)) diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 76f45f535..c2ba4347f 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -503,6 +503,9 @@ /* Build glamor's GBM-based EGL support */ #undef GLAMOR_HAS_GBM +/* Build glamor/gbm has linear support */ +#undef GLAMOR_HAS_GBM_LINEAR + /* byte order */ #undef X_BYTE_ORDER diff --git a/mi/midispcur.c b/mi/midispcur.c index 50f0dd212..d1da0fd58 100644 --- a/mi/midispcur.c +++ b/mi/midispcur.c @@ -46,9 +46,7 @@ in this Software without prior written authorization from The Open Group. #include "misprite.h" #include "gcstruct.h" -#ifdef ARGB_CURSOR #include "picturestr.h" -#endif #include "inputstr.h" @@ -68,9 +66,7 @@ typedef struct { GCPtr pSourceGC, pMaskGC; GCPtr pSaveGC, pRestoreGC; PixmapPtr pSave; -#ifdef ARGB_CURSOR PicturePtr pRootPicture; -#endif } miDCBufferRec, *miDCBufferPtr; #define miGetDCDevice(dev, screen) \ @@ -86,9 +82,7 @@ typedef struct { CloseScreenProcPtr CloseScreen; PixmapPtr sourceBits; /* source bits */ PixmapPtr maskBits; /* mask bits */ -#ifdef ARGB_CURSOR PicturePtr pPicture; -#endif CursorPtr pCursor; } miDCScreenRec, *miDCScreenPtr; @@ -133,11 +127,9 @@ miDCSwitchScreenCursor(ScreenPtr pScreen, CursorPtr pCursor, PixmapPtr sourceBit (*pScreen->DestroyPixmap)(pScreenPriv->maskBits); pScreenPriv->maskBits = maskBits; -#ifdef ARGB_CURSOR if (pScreenPriv->pPicture) FreePicture(pScreenPriv->pPicture, 0); pScreenPriv->pPicture = pPicture; -#endif pScreenPriv->pCursor = pCursor; } @@ -162,7 +154,6 @@ miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) return TRUE; } -#ifdef ARGB_CURSOR #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win)) static PicturePtr @@ -182,7 +173,6 @@ miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin) *ppPicture = pPicture; return pPicture; } -#endif static Bool miDCRealize(ScreenPtr pScreen, CursorPtr pCursor) @@ -195,8 +185,6 @@ miDCRealize(ScreenPtr pScreen, CursorPtr pCursor) if (pScreenPriv->pCursor == pCursor) return TRUE; -#ifdef ARGB_CURSOR - if (pCursor->bits->argb) { PixmapPtr pPixmap; PictFormatPtr pFormat; @@ -233,7 +221,7 @@ miDCRealize(ScreenPtr pScreen, CursorPtr pCursor) miDCSwitchScreenCursor(pScreen, pCursor, NULL, NULL, pPicture); return TRUE; } -#endif + sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); if (!sourceBits) @@ -373,7 +361,6 @@ miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, pWin = pScreen->root; pBuffer = miGetDCDevice(pDev, pScreen); -#ifdef ARGB_CURSOR if (pScreenPriv->pPicture) { if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) return FALSE; @@ -385,7 +372,6 @@ miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, x, y, pCursor->bits->width, pCursor->bits->height); } else -#endif { miDCPutBits((DrawablePtr) pWin, pBuffer->pSourceGC, pBuffer->pMaskGC, @@ -486,9 +472,7 @@ miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) if (!pBuffer->pRestoreGC) goto failure; -#ifdef ARGB_CURSOR pBuffer->pRootPicture = NULL; -#endif /* (re)allocated lazily depending on the cursor size */ pBuffer->pSave = NULL; @@ -525,11 +509,9 @@ miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0); -#ifdef ARGB_CURSOR /* If a pRootPicture was allocated for a root window, it * is freed when that root window is destroyed, so don't * free it again here. */ -#endif if (pBuffer->pSave) (*pScreen->DestroyPixmap) (pBuffer->pSave); diff --git a/xfixes/cursor.c b/xfixes/cursor.c index 94d24a8e2..5619aad2e 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -306,11 +306,9 @@ CopyCursorToImage(CursorPtr pCursor, CARD32 *image) int height = pCursor->bits->height; int npixels = width * height; -#ifdef ARGB_CURSOR if (pCursor->bits->argb) memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32)); else -#endif { unsigned char *srcLine = pCursor->bits->source; unsigned char *mskLine = pCursor->bits->mask;