modesetting: add output slave support.
This allows the driver to operate as an output slave. It adds scan out pixmap, and the capability checks to make sure they available. Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
fa171c5a81
commit
02811f1a9c
|
@ -401,21 +401,20 @@ GetRec(ScrnInfoPtr pScrn)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void dispatch_dirty(ScreenPtr pScreen)
|
||||
static int dispatch_dirty_region(ScrnInfoPtr scrn,
|
||||
PixmapPtr pixmap,
|
||||
DamagePtr damage,
|
||||
int fb_id)
|
||||
{
|
||||
ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
|
||||
modesettingPtr ms = modesettingPTR(scrn);
|
||||
RegionPtr dirty = DamageRegion(ms->damage);
|
||||
RegionPtr dirty = DamageRegion(damage);
|
||||
unsigned num_cliprects = REGION_NUM_RECTS(dirty);
|
||||
|
||||
if (num_cliprects) {
|
||||
drmModeClip *clip = malloc(num_cliprects * sizeof(drmModeClip));
|
||||
drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
|
||||
BoxPtr rect = REGION_RECTS(dirty);
|
||||
int i, ret;
|
||||
|
||||
if (!clip)
|
||||
return;
|
||||
|
||||
|
||||
/* XXX no need for copy? */
|
||||
for (i = 0; i < num_cliprects; i++, rect++) {
|
||||
clip[i].x1 = rect->x1;
|
||||
|
@ -425,25 +424,71 @@ static void dispatch_dirty(ScreenPtr pScreen)
|
|||
}
|
||||
|
||||
/* TODO query connector property to see if this is needed */
|
||||
ret = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, clip, num_cliprects);
|
||||
free(clip);
|
||||
ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
|
||||
DamageEmpty(damage);
|
||||
if (ret) {
|
||||
if (ret == -EINVAL || ret == -ENOSYS) {
|
||||
ms->dirty_enabled = FALSE;
|
||||
DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
|
||||
DamageDestroy(ms->damage);
|
||||
ms->damage = NULL;
|
||||
xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n");
|
||||
return;
|
||||
} else
|
||||
ErrorF("%s: failed to send dirty (%i, %s)\n",
|
||||
__func__, ret, strerror(-ret));
|
||||
if (ret == -EINVAL)
|
||||
return ret;
|
||||
}
|
||||
|
||||
DamageEmpty(ms->damage);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dispatch_dirty(ScreenPtr pScreen)
|
||||
{
|
||||
ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
|
||||
modesettingPtr ms = modesettingPTR(scrn);
|
||||
PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
|
||||
int fb_id = ms->drmmode.fb_id;
|
||||
int ret;
|
||||
|
||||
ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id);
|
||||
if (ret == -EINVAL || ret == -ENOSYS) {
|
||||
ms->dirty_enabled = FALSE;
|
||||
DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
|
||||
DamageDestroy(ms->damage);
|
||||
ms->damage = NULL;
|
||||
xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
static void dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
|
||||
{
|
||||
modesettingPtr ms = modesettingPTR(scrn);
|
||||
PixmapPtr pixmap = crtc->randr_crtc->scanout_pixmap;
|
||||
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap);
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
DamagePtr damage = drmmode_crtc->slave_damage;
|
||||
int fb_id = ppriv->fb_id;
|
||||
int ret;
|
||||
|
||||
ret = dispatch_dirty_region(scrn, pixmap, damage, fb_id);
|
||||
if (ret) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void dispatch_slave_dirty(ScreenPtr pScreen)
|
||||
{
|
||||
ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
|
||||
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
||||
int c;
|
||||
|
||||
for (c = 0; c < xf86_config->num_crtc; c++) {
|
||||
xf86CrtcPtr crtc = xf86_config->crtc[c];
|
||||
|
||||
if (!crtc->randr_crtc)
|
||||
continue;
|
||||
if (!crtc->randr_crtc->scanout_pixmap)
|
||||
continue;
|
||||
|
||||
dispatch_dirty_crtc(scrn, crtc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void msBlockHandler(BLOCKHANDLER_ARGS_DECL)
|
||||
{
|
||||
SCREEN_PTR(arg);
|
||||
|
@ -452,8 +497,13 @@ static void msBlockHandler(BLOCKHANDLER_ARGS_DECL)
|
|||
pScreen->BlockHandler = ms->BlockHandler;
|
||||
pScreen->BlockHandler(BLOCKHANDLER_ARGS);
|
||||
pScreen->BlockHandler = msBlockHandler;
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
if (pScreen->isGPU)
|
||||
dispatch_slave_dirty(pScreen);
|
||||
else
|
||||
#endif
|
||||
if (ms->dirty_enabled)
|
||||
dispatch_dirty(pScreen);
|
||||
dispatch_dirty(pScreen);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -555,6 +605,16 @@ PreInit(ScrnInfoPtr pScrn, int flags)
|
|||
|
||||
ms->drmmode.fd = ms->fd;
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
pScrn->capabilities = 0;
|
||||
#ifdef DRM_CAP_PRIME
|
||||
ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value);
|
||||
if (ret == 0) {
|
||||
if (value & DRM_PRIME_CAP_IMPORT)
|
||||
pScrn->capabilities |= RR_Capability_SinkOutput;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp);
|
||||
if (defaultdepth == 24 && defaultbpp == 24)
|
||||
bppflags = Support24bppFb;
|
||||
|
@ -719,6 +779,25 @@ msShadowInit(ScreenPtr pScreen)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
static Bool
|
||||
msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
|
||||
{
|
||||
ScreenPtr screen = ppix->drawable.pScreen;
|
||||
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 (ret == FALSE)
|
||||
return ret;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static Bool
|
||||
ScreenInit(SCREEN_INIT_ARGS_DECL)
|
||||
{
|
||||
|
@ -757,6 +836,13 @@ ScreenInit(SCREEN_INIT_ARGS_DECL)
|
|||
if (!miSetPixmapDepths())
|
||||
return FALSE;
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
if (!dixRegisterScreenSpecificPrivateKey(pScreen, &ms->drmmode.pixmapPrivateKeyRec,
|
||||
PRIVATE_PIXMAP, sizeof(msPixmapPrivRec))) {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
pScrn->memPhysBase = 0;
|
||||
pScrn->fbOffset = 0;
|
||||
|
||||
|
@ -816,6 +902,10 @@ ScreenInit(SCREEN_INIT_ARGS_DECL)
|
|||
ms->BlockHandler = pScreen->BlockHandler;
|
||||
pScreen->BlockHandler = msBlockHandler;
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking;
|
||||
#endif
|
||||
|
||||
if (!xf86CrtcScreenInit(pScreen))
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -138,6 +138,43 @@ static int dumb_bo_destroy(int fd, struct dumb_bo *bo)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
static struct dumb_bo *dumb_get_bo_from_handle(int fd, int handle, int pitch, int size)
|
||||
{
|
||||
struct dumb_bo *bo;
|
||||
int ret;
|
||||
|
||||
bo = calloc(1, sizeof(*bo));
|
||||
if (!bo)
|
||||
return NULL;
|
||||
|
||||
ret = drmPrimeFDToHandle(fd, handle, &bo->handle);
|
||||
if (ret) {
|
||||
free(bo);
|
||||
return NULL;
|
||||
}
|
||||
bo->pitch = pitch;
|
||||
bo->size = size;
|
||||
return bo;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
Bool drmmode_SetSlaveBO(PixmapPtr ppix,
|
||||
drmmode_ptr drmmode,
|
||||
int fd_handle, int pitch, int size)
|
||||
{
|
||||
msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
|
||||
|
||||
ppriv->backing_bo = dumb_get_bo_from_handle(drmmode->fd, fd_handle, pitch, size);
|
||||
if (!ppriv->backing_bo)
|
||||
return FALSE;
|
||||
|
||||
close(fd_handle);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
|
||||
drmModeModeInfo *kmode,
|
||||
|
@ -274,7 +311,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
|||
int output_count = 0;
|
||||
Bool ret = TRUE;
|
||||
int i;
|
||||
int fb_id;
|
||||
uint32_t fb_id;
|
||||
drmModeModeInfo kmode;
|
||||
int height;
|
||||
|
||||
|
@ -338,6 +375,13 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
|||
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
|
||||
|
||||
fb_id = drmmode->fb_id;
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
if (crtc->randr_crtc->scanout_pixmap) {
|
||||
msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
|
||||
fb_id = ppriv->fb_id;
|
||||
x = y = 0;
|
||||
} else
|
||||
#endif
|
||||
if (drmmode_crtc->rotate_fb_id) {
|
||||
fb_id = drmmode_crtc->rotate_fb_id;
|
||||
x = y = 0;
|
||||
|
@ -455,6 +499,54 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
|
|||
size, red, green, blue);
|
||||
}
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
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;
|
||||
msPixmapPrivPtr ppriv;
|
||||
void *ptr;
|
||||
|
||||
if (!ppix) {
|
||||
if (crtc->randr_crtc->scanout_pixmap) {
|
||||
ppriv = msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
|
||||
drmModeRmFB(drmmode->fd, ppriv->fb_id);
|
||||
}
|
||||
if (drmmode_crtc->slave_damage) {
|
||||
DamageUnregister(&crtc->randr_crtc->scanout_pixmap->drawable,
|
||||
drmmode_crtc->slave_damage);
|
||||
drmmode_crtc->slave_damage = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ppriv = msGetPixmapPriv(drmmode, ppix);
|
||||
if (!drmmode_crtc->slave_damage) {
|
||||
drmmode_crtc->slave_damage = DamageCreate(NULL, NULL,
|
||||
DamageReportNone,
|
||||
TRUE,
|
||||
crtc->randr_crtc->pScreen,
|
||||
NULL);
|
||||
}
|
||||
ptr = drmmode_map_slave_bo(drmmode, ppriv);
|
||||
ppix->devPrivate.ptr = ptr;
|
||||
DamageRegister(&ppix->drawable, drmmode_crtc->slave_damage);
|
||||
|
||||
if (ppriv->fb_id == 0) {
|
||||
int r;
|
||||
r = drmModeAddFB(drmmode->fd, ppix->drawable.width,
|
||||
ppix->drawable.height,
|
||||
ppix->drawable.depth,
|
||||
ppix->drawable.bitsPerPixel,
|
||||
ppix->devKind,
|
||||
ppriv->backing_bo->handle,
|
||||
&ppriv->fb_id);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
|
||||
.dpms = drmmode_crtc_dpms,
|
||||
.set_mode_major = drmmode_set_mode_major,
|
||||
|
@ -466,6 +558,9 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
|
|||
|
||||
.gamma_set = drmmode_crtc_gamma_set,
|
||||
.destroy = NULL, /* XXX */
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
.set_scanout_pixmap = drmmode_set_scanout_pixmap,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -1065,6 +1160,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
|
|||
/* workout clones */
|
||||
drmmode_clones_init(pScrn, drmmode);
|
||||
|
||||
#if XF86_CRTC_VERSION >= 5
|
||||
xf86ProviderSetup(pScrn, NULL, "modesetting");
|
||||
#endif
|
||||
|
||||
xf86InitialConfiguration(pScrn, TRUE);
|
||||
|
||||
return TRUE;
|
||||
|
@ -1324,6 +1423,22 @@ void *drmmode_map_front_bo(drmmode_ptr drmmode)
|
|||
|
||||
}
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ppriv->backing_bo->ptr)
|
||||
return ppriv->backing_bo->ptr;
|
||||
|
||||
ret = dumb_bo_map(drmmode->fd, ppriv->backing_bo);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
return ppriv->backing_bo->ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
|
||||
{
|
||||
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
||||
|
|
|
@ -32,6 +32,11 @@
|
|||
#include "libudev.h"
|
||||
#endif
|
||||
|
||||
/* the perfect storm */
|
||||
#if XF86_CRTC_VERSION >= 5 && defined(HAVE_DRMPRIMEFDTOHANDLE) && HAVE_SCREEN_SPECIFIC_PRIVATE_KEYS
|
||||
#define MODESETTING_OUTPUT_SLAVE_SUPPORT 1
|
||||
#endif
|
||||
|
||||
struct dumb_bo {
|
||||
uint32_t handle;
|
||||
uint32_t size;
|
||||
|
@ -58,6 +63,9 @@ typedef struct {
|
|||
Bool shadow_enable;
|
||||
void *shadow_fb;
|
||||
|
||||
#ifdef HAVE_SCREEN_SPECIFIC_PRIVATE_KEYS
|
||||
DevPrivateKeyRec pixmapPrivateKeyRec;
|
||||
#endif
|
||||
} drmmode_rec, *drmmode_ptr;
|
||||
|
||||
typedef struct {
|
||||
|
@ -67,6 +75,7 @@ typedef struct {
|
|||
struct dumb_bo *cursor_bo;
|
||||
unsigned rotate_fb_id;
|
||||
uint16_t lut_r[256], lut_g[256], lut_b[256];
|
||||
DamagePtr slave_damage;
|
||||
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
|
||||
|
||||
typedef struct {
|
||||
|
@ -90,6 +99,23 @@ typedef struct {
|
|||
int enc_clone_mask;
|
||||
} drmmode_output_private_rec, *drmmode_output_private_ptr;
|
||||
|
||||
#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT
|
||||
typedef struct _msPixmapPriv {
|
||||
uint32_t fb_id;
|
||||
struct dumb_bo *backing_bo; /* if this pixmap is backed by a dumb bo */
|
||||
} msPixmapPrivRec, *msPixmapPrivPtr;
|
||||
|
||||
|
||||
extern DevPrivateKeyRec msPixmapPrivateKeyRec;
|
||||
#define msPixmapPrivateKey (&msPixmapPrivateKeyRec)
|
||||
|
||||
#define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec))
|
||||
|
||||
void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv);
|
||||
Bool drmmode_SetSlaveBO(PixmapPtr ppix,
|
||||
drmmode_ptr drmmode,
|
||||
int fd_handle, int pitch, int size);
|
||||
#endif
|
||||
|
||||
extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
|
||||
void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags);
|
||||
|
@ -105,6 +131,7 @@ Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
|
|||
void drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
|
||||
void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode, int *depth, int *bpp);
|
||||
|
||||
|
||||
#ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
|
||||
#define DRM_CAP_DUMB_PREFERRED_DEPTH 3
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue