aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/drivers')
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/Makefile.am3
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/dri2.c2
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/driver.c104
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/driver.h15
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c337
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h33
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c134
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h45
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/present.c228
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/vblank.c28
10 files changed, 691 insertions, 238 deletions
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am b/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am
index 5b08600c1..82c4f2f32 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am
+++ b/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am
@@ -48,6 +48,9 @@ modesetting_drv_la_SOURCES = \
driver.h \
drmmode_display.c \
drmmode_display.h \
+ dumb_bo.c \
+ dumb_bo.h \
+ present.c \
vblank.c \
$(NULL)
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/dri2.c b/xorg-server/hw/xfree86/drivers/modesetting/dri2.c
index 6c88060b0..63cb0659d 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/dri2.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/dri2.c
@@ -43,8 +43,6 @@
#include "dri2.h"
#ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
enum ms_dri2_frame_event_type {
MS_DRI2_QUEUE_SWAP,
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/driver.c b/xorg-server/hw/xfree86/drivers/modesetting/driver.c
index 592f2469b..1ebf807e5 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/driver.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/driver.c
@@ -61,11 +61,6 @@
#include "driver.h"
-#ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
-#endif
-
static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y);
static Bool CloseScreen(ScreenPtr pScreen);
static Bool EnterVT(ScrnInfoPtr pScrn);
@@ -453,11 +448,12 @@ dispatch_dirty_region(ScrnInfoPtr scrn,
modesettingPtr ms = modesettingPTR(scrn);
RegionPtr dirty = DamageRegion(damage);
unsigned num_cliprects = REGION_NUM_RECTS(dirty);
+ int ret = 0;
if (num_cliprects) {
drmModeClip *clip = malloc(num_cliprects * sizeof(drmModeClip));
BoxPtr rect = REGION_RECTS(dirty);
- int i, ret;
+ int i;
if (!clip)
return -ENOMEM;
@@ -474,12 +470,8 @@ dispatch_dirty_region(ScrnInfoPtr scrn,
ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
free(clip);
DamageEmpty(damage);
- if (ret) {
- if (ret == -EINVAL)
- return ret;
- }
}
- return 0;
+ return ret;
}
static void
@@ -593,7 +585,7 @@ try_enable_glamor(ScrnInfoPtr pScrn)
Bool do_glamor = (!accel_method_str ||
strcmp(accel_method_str, "glamor") == 0);
- ms->glamor = FALSE;
+ ms->drmmode.glamor = FALSE;
#ifdef GLAMOR
if (!do_glamor) {
@@ -604,7 +596,7 @@ try_enable_glamor(ScrnInfoPtr pScrn)
if (xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME)) {
if (glamor_egl_init(pScrn, ms->fd)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n");
- ms->glamor = TRUE;
+ ms->drmmode.glamor = TRUE;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"glamor initialization failed\n");
@@ -788,7 +780,7 @@ PreInit(ScrnInfoPtr pScrn, int flags)
try_enable_glamor(pScrn);
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
xf86LoadSubModule(pScrn, "dri2");
} else {
Bool prefer_shadow = TRUE;
@@ -861,7 +853,7 @@ msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
*size = stride;
- return ((uint8_t *) ms->drmmode.front_bo->ptr + row * stride + offset);
+ return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset);
}
static void
@@ -877,7 +869,8 @@ CreateScreenResources(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap;
Bool ret;
- void *pixels;
+ void *pixels = NULL;
+ int err;
pScreen->CreateScreenResources = ms->createScreenResources;
ret = pScreen->CreateScreenResources(pScreen);
@@ -886,27 +879,19 @@ CreateScreenResources(ScreenPtr pScreen)
if (!drmmode_set_desired_modes(pScrn, &ms->drmmode))
return FALSE;
-#ifdef GLAMOR
- if (ms->glamor) {
- if (!glamor_egl_create_textured_screen_ext(pScreen,
- ms->drmmode.front_bo->handle,
- pScrn->displayWidth *
- pScrn->bitsPerPixel / 8,
- NULL)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "glamor_egl_create_textured_screen_ext() failed\n");
- return FALSE;
- }
- }
-#endif
+ if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode))
+ return FALSE;
drmmode_uevent_init(pScrn, &ms->drmmode);
if (!ms->drmmode.sw_cursor)
drmmode_map_cursor_bos(pScrn, &ms->drmmode);
- pixels = drmmode_map_front_bo(&ms->drmmode);
- if (!pixels)
- return FALSE;
+
+ if (!ms->drmmode.gbm) {
+ pixels = drmmode_map_front_bo(&ms->drmmode);
+ if (!pixels)
+ return FALSE;
+ }
rootPixmap = pScreen->GetScreenPixmap(pScreen);
@@ -922,18 +907,22 @@ CreateScreenResources(ScreenPtr pScreen)
return FALSE;
}
- ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
- pScreen, rootPixmap);
+ err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0);
- if (ms->damage) {
- DamageRegister(&rootPixmap->drawable, ms->damage);
- ms->dirty_enabled = TRUE;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
- }
- else {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to create screen damage record\n");
- return FALSE;
+ if (err != -EINVAL && err != -ENOSYS) {
+ ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+ pScreen, rootPixmap);
+
+ if (ms->damage) {
+ DamageRegister(&rootPixmap->drawable, ms->damage);
+ ms->dirty_enabled = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to create screen damage record\n");
+ return FALSE;
+ }
}
return ret;
}
@@ -996,6 +985,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!SetMaster(pScrn))
return FALSE;
+#ifdef GLAMOR_HAS_GBM
+ if (ms->drmmode.glamor)
+ ms->drmmode.gbm = glamor_egl_get_gbm_device(pScreen);
+#endif
+
/* HW dependent - FIXME */
pScrn->displayWidth = pScrn->virtualX;
if (!drmmode_create_initial_bos(pScrn, &ms->drmmode))
@@ -1053,7 +1047,7 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
fbPictureInit(pScreen, NULL, 0);
#ifdef GLAMOR
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
if (!glamor_init(pScreen,
GLAMOR_USE_EGL_SCREEN |
GLAMOR_USE_SCREEN |
@@ -1106,6 +1100,19 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+#ifdef GLAMOR
+ if (ms->drmmode.glamor) {
+ XF86VideoAdaptorPtr glamor_adaptor;
+
+ glamor_adaptor = glamor_xv_init(pScreen, 16);
+ if (glamor_adaptor != NULL)
+ xf86XVScreenInit(pScreen, &glamor_adaptor, 1);
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to initialize XV support.\n");
+ }
+#endif
+
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@@ -1116,11 +1123,16 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
}
#ifdef GLAMOR
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
if (!ms_dri2_screen_init(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to initialize the DRI2 extension.\n");
}
+
+ if (!ms_present_screen_init(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to initialize the Present extension.\n");
+ }
}
#endif
@@ -1190,7 +1202,7 @@ CloseScreen(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
#ifdef GLAMOR
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
ms_dri2_close_screen(pScreen);
}
#endif
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/driver.h b/xorg-server/hw/xfree86/drivers/modesetting/driver.h
index 9eda1c4da..3decc3eea 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/driver.h
+++ b/xorg-server/hw/xfree86/drivers/modesetting/driver.h
@@ -33,6 +33,14 @@
#include <xf86Crtc.h>
#include <damage.h>
+#ifdef GLAMOR
+#define GLAMOR_FOR_XORG 1
+#include "glamor.h"
+#ifdef GLAMOR_HAS_GBM
+#include <gbm.h>
+#endif
+#endif
+
#include "drmmode_display.h"
#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
@@ -97,7 +105,6 @@ typedef struct _modesettingRec {
Bool dirty_enabled;
uint32_t cursor_width, cursor_height;
- Bool glamor;
} modesettingRec, *modesettingPtr;
#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
@@ -107,6 +114,10 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
ms_drm_handler_proc handler,
ms_drm_abort_proc abort);
+void ms_drm_abort(ScrnInfoPtr scrn,
+ Bool (*match)(void *data, void *match_data),
+ void *match_data);
+
xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
xf86CrtcPtr desired, BoxPtr crtc_box_ret);
@@ -122,3 +133,5 @@ void ms_dri2_close_screen(ScreenPtr screen);
Bool ms_vblank_screen_init(ScreenPtr screen);
void ms_vblank_close_screen(ScreenPtr screen);
+
+Bool ms_present_screen_init(ScreenPtr screen);
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c
index ef9009e98..824500bae 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -33,6 +33,7 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
+#include "dumb_bo.h"
#include "xf86str.h"
#include "X11/Xatom.h"
#include "micmap.h"
@@ -49,112 +50,64 @@
#include "driver.h"
-static struct dumb_bo *
-dumb_bo_create(int fd,
- const unsigned width, const unsigned height, const unsigned bpp)
-{
- struct drm_mode_create_dumb arg;
- struct dumb_bo *bo;
- int ret;
-
- bo = calloc(1, sizeof(*bo));
- if (!bo)
- return NULL;
-
- memset(&arg, 0, sizeof(arg));
- arg.width = width;
- arg.height = height;
- arg.bpp = bpp;
-
- ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
- if (ret)
- goto err_free;
-
- bo->handle = arg.handle;
- bo->size = arg.size;
- bo->pitch = arg.pitch;
-
- return bo;
- err_free:
- free(bo);
- return NULL;
-}
-
static int
-dumb_bo_map(int fd, struct dumb_bo *bo)
+drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
{
- struct drm_mode_map_dumb arg;
int ret;
- void *map;
- if (bo->ptr) {
- bo->map_count++;
- return 0;
+#ifdef GLAMOR_HAS_GBM
+ if (bo->gbm) {
+ gbm_bo_destroy(bo->gbm);
+ bo->gbm = NULL;
}
+#endif
- memset(&arg, 0, sizeof(arg));
- arg.handle = bo->handle;
-
- ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
- if (ret)
- return ret;
-
- map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, arg.offset);
- if (map == MAP_FAILED)
- return -errno;
+ if (bo->dumb) {
+ ret = dumb_bo_destroy(drmmode->fd, bo->dumb);
+ if (ret == 0)
+ bo->dumb = NULL;
+ }
- bo->ptr = map;
return 0;
}
-#if 0
-static int
-dumb_bo_unmap(int fd, struct dumb_bo *bo)
+static uint32_t
+drmmode_bo_get_pitch(drmmode_bo *bo)
{
- bo->map_count--;
- return 0;
-}
+#ifdef GLAMOR_HAS_GBM
+ if (bo->gbm)
+ return gbm_bo_get_stride(bo->gbm);
#endif
-int
-dumb_bo_destroy(int fd, struct dumb_bo *bo)
-{
- struct drm_mode_destroy_dumb arg;
- int ret;
-
- if (bo->ptr) {
- munmap(bo->ptr, bo->size);
- bo->ptr = NULL;
- }
-
- memset(&arg, 0, sizeof(arg));
- arg.handle = bo->handle;
- ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
- if (ret)
- return -errno;
-
- free(bo);
- return 0;
+ return bo->dumb->pitch;
}
-struct dumb_bo *
-dumb_get_bo_from_fd(int fd, int handle, int pitch, int size)
+uint32_t
+drmmode_bo_get_handle(drmmode_bo *bo)
{
- struct dumb_bo *bo;
- int ret;
+#ifdef GLAMOR_HAS_GBM
+ if (bo->gbm)
+ return gbm_bo_get_handle(bo->gbm).u32;
+#endif
- bo = calloc(1, sizeof(*bo));
- if (!bo)
- return NULL;
+ return bo->dumb->handle;
+}
- ret = drmPrimeFDToHandle(fd, handle, &bo->handle);
- if (ret) {
- free(bo);
- return NULL;
+static Bool
+drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
+ unsigned width, unsigned height, unsigned bpp)
+{
+#ifdef GLAMOR_HAS_GBM
+ if (drmmode->glamor) {
+ bo->gbm = gbm_bo_create(drmmode->gbm, width, height,
+ GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
+ return bo->gbm != NULL;
}
- bo->pitch = pitch;
- bo->size = size;
- return bo;
+#endif
+
+ bo->dumb = dumb_bo_create(drmmode->fd, width, height, bpp);
+ return bo->dumb != NULL;
}
Bool
@@ -232,18 +185,8 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
static void
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
-#if 0
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
-
-// drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-// drmmode_ptr drmmode = drmmode_crtc->drmmode;
-
- /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
- if (mode == DPMSModeOff) {
-// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
-// 0, 0, 0, NULL, 0, NULL);
- }
-#endif
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_crtc->dpms_mode = mode;
}
#if 0
@@ -315,8 +258,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
ret = drmModeAddFB(drmmode->fd,
pScrn->virtualX, height,
pScrn->depth, pScrn->bitsPerPixel,
- drmmode->front_bo->pitch,
- drmmode->front_bo->handle, &drmmode->fb_id);
+ drmmode_bo_get_pitch(&drmmode->front_bo),
+ drmmode_bo_get_handle(&drmmode->front_bo),
+ &drmmode->fb_id);
if (ret < 0) {
ErrorF("failed to add fb %d\n", ret);
return FALSE;
@@ -385,6 +329,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (crtc->scrn->pScreen)
xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+
+ crtc->funcs->dpms(crtc, DPMSModeOn);
+
/* go through all the outputs and force DPMS them back on? */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -432,25 +379,32 @@ drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
}
static void
-drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
+drmmode_set_cursor(xf86CrtcPtr crtc)
{
- modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- int i;
- uint32_t *ptr;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
uint32_t handle = drmmode_crtc->cursor_bo->handle;
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ static Bool use_set_cursor2 = TRUE;
int ret;
- /* cursor should be mapped already */
- ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
+ if (use_set_cursor2) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ CursorPtr cursor = xf86_config->cursor;
- for (i = 0; i < ms->cursor_width * ms->cursor_height; i++)
- ptr[i] = image[i]; // cpu_to_le32(image[i]);
+ ret =
+ drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ handle, ms->cursor_width, ms->cursor_height,
+ cursor->bits->xhot, cursor->bits->yhot);
+ if (ret == -EINVAL)
+ use_set_cursor2 = FALSE;
+ else
+ return;
+ }
+
+ ret = drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
+ ms->cursor_width, ms->cursor_height);
- ret =
- drmModeSetCursor(drmmode_crtc->drmmode->fd,
- drmmode_crtc->mode_crtc->crtc_id, handle,
- ms->cursor_width, ms->cursor_height);
if (ret) {
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
@@ -462,46 +416,44 @@ drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
}
static void
-drmmode_hide_cursor(xf86CrtcPtr crtc)
+drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int i;
+ uint32_t *ptr;
- drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
- ms->cursor_width, ms->cursor_height);
+ /* cursor should be mapped already */
+ ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
+
+ for (i = 0; i < ms->cursor_width * ms->cursor_height; i++)
+ ptr[i] = image[i]; // cpu_to_le32(image[i]);
+ if (drmmode_crtc->cursor_up)
+ drmmode_set_cursor(crtc);
}
static void
-drmmode_show_cursor(xf86CrtcPtr crtc)
+drmmode_hide_cursor(xf86CrtcPtr crtc)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- uint32_t handle = drmmode_crtc->cursor_bo->handle;
- static Bool use_set_cursor2 = TRUE;
-
- if (use_set_cursor2) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
- CursorPtr cursor = xf86_config->cursor;
- int ret;
-
- ret =
- drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- handle, ms->cursor_width, ms->cursor_height,
- cursor->bits->xhot, cursor->bits->yhot);
- if (ret == -EINVAL)
- use_set_cursor2 = FALSE;
- else
- return;
- }
- drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
+ drmmode_crtc->cursor_up = FALSE;
+ drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
ms->cursor_width, ms->cursor_height);
}
static void
+drmmode_show_cursor(xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_crtc->cursor_up = TRUE;
+ drmmode_set_cursor(crtc);
+}
+
+static void
drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
uint16_t * blue, int size)
{
@@ -1019,8 +971,7 @@ static const char *const output_names[] = {
};
static void
-drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num,
- int *num_dvi, int *num_hdmi)
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
{
xf86OutputPtr output;
drmModeConnectorPtr koutput;
@@ -1172,6 +1123,42 @@ drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
}
}
+Bool
+drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode)
+{
+#ifdef GLAMOR
+ ScrnInfoPtr scrn = drmmode->scrn;
+ ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn);
+ PixmapPtr screen_pixmap;
+ void *gbm_bo;
+
+ if (!drmmode->glamor)
+ return TRUE;
+
+#ifdef GLAMOR_HAS_GBM
+ gbm_bo = drmmode->front_bo.gbm;
+ screen_pixmap = screen->GetScreenPixmap(screen);
+
+ if (!glamor_egl_create_textured_pixmap_from_gbm_bo(screen_pixmap, gbm_bo)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed");
+ return FALSE;
+ }
+ glamor_set_screen_pixmap(screen_pixmap, NULL);
+#else
+ if (!glamor_egl_create_textured_screen(screen,
+ drmmode_bo_get_handle(&drmmode->front_bo),
+ scrn->displayWidth *
+ scrn->bitsPerPixel / 8)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "glamor_egl_create_textured_screen() failed\n");
+ return FALSE;
+ }
+#endif
+#endif
+
+ return TRUE;
+}
+
static Bool
drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
{
@@ -1180,14 +1167,14 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
drmmode_crtc_private_ptr
drmmode_crtc = xf86_config->crtc[0]->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- struct dumb_bo *old_front = NULL;
+ drmmode_bo old_front;
Bool ret;
ScreenPtr screen = xf86ScrnToScreen(scrn);
uint32_t old_fb_id;
int i, pitch, old_width, old_height, old_pitch;
int cpp = (scrn->bitsPerPixel + 7) / 8;
PixmapPtr ppix = screen->GetScreenPixmap(screen);
- void *new_pixels;
+ void *new_pixels = NULL;
if (scrn->virtualX == width && scrn->virtualY == height)
return TRUE;
@@ -1202,16 +1189,15 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
old_width = scrn->virtualX;
old_height = scrn->virtualY;
- old_pitch = drmmode->front_bo->pitch;
+ old_pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
old_fb_id = drmmode->fb_id;
old_front = drmmode->front_bo;
- drmmode->front_bo =
- dumb_bo_create(drmmode->fd, width, height, scrn->bitsPerPixel);
- if (!drmmode->front_bo)
+ if (!drmmode_create_bo(drmmode, &drmmode->front_bo,
+ width, height, scrn->bitsPerPixel))
goto fail;
- pitch = drmmode->front_bo->pitch;
+ pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
scrn->virtualX = width;
scrn->virtualY = height;
@@ -1219,30 +1205,32 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
scrn->bitsPerPixel, pitch,
- drmmode->front_bo->handle, &drmmode->fb_id);
+ drmmode_bo_get_handle(&drmmode->front_bo),
+ &drmmode->fb_id);
if (ret)
goto fail;
- new_pixels = drmmode_map_front_bo(drmmode);
- if (!new_pixels)
- goto fail;
+ if (!drmmode->gbm) {
+ new_pixels = drmmode_map_front_bo(drmmode);
+ if (!new_pixels)
+ goto fail;
+ }
- if (!drmmode->shadow_enable)
- screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
- pitch, new_pixels);
- else {
- void *new_shadow;
+ if (drmmode->shadow_enable) {
uint32_t size = scrn->displayWidth * scrn->virtualY *
((scrn->bitsPerPixel + 7) >> 3);
- new_shadow = calloc(1, size);
- if (new_shadow == NULL)
+ new_pixels = calloc(1, size);
+ if (new_pixels == NULL)
goto fail;
free(drmmode->shadow_fb);
- drmmode->shadow_fb = new_shadow;
- screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
- pitch, drmmode->shadow_fb);
+ drmmode->shadow_fb = new_pixels;
}
+ screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, new_pixels);
+
+ if (!drmmode_glamor_handle_new_screen_pixmap(drmmode))
+ goto fail;
+
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -1255,14 +1243,13 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
if (old_fb_id) {
drmModeRmFB(drmmode->fd, old_fb_id);
- dumb_bo_destroy(drmmode->fd, old_front);
+ drmmode_bo_destroy(drmmode, &old_front);
}
return TRUE;
fail:
- if (drmmode->front_bo)
- dumb_bo_destroy(drmmode->fd, drmmode->front_bo);
+ drmmode_bo_destroy(drmmode, &drmmode->front_bo);
drmmode->front_bo = old_front;
scrn->virtualX = old_width;
scrn->virtualY = old_height;
@@ -1279,7 +1266,7 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
Bool
drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
{
- int i, num_dvi = 0, num_hdmi = 0;
+ int i;
int ret;
uint64_t value = 0;
@@ -1307,7 +1294,7 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
drmmode_crtc_init(pScrn, drmmode, i);
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
- drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
+ drmmode_output_init(pScrn, drmmode, i);
/* workout clones */
drmmode_clones_init(pScrn, drmmode);
@@ -1468,7 +1455,7 @@ drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
return TRUE;
}
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
static void
drmmode_handle_uevents(int fd, void *closure)
{
@@ -1488,7 +1475,7 @@ drmmode_handle_uevents(int fd, void *closure)
void
drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
{
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
struct udev *u;
struct udev_monitor *mon;
@@ -1521,7 +1508,7 @@ drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
void
drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
{
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
if (drmmode->uevent_handler) {
struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
@@ -1548,10 +1535,9 @@ drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
width = pScrn->virtualX;
height = pScrn->virtualY;
- drmmode->front_bo = dumb_bo_create(drmmode->fd, width, height, bpp);
- if (!drmmode->front_bo)
+ if (!drmmode_create_bo(drmmode, &drmmode->front_bo, width, height, bpp))
return FALSE;
- pScrn->displayWidth = drmmode->front_bo->pitch / cpp;
+ pScrn->displayWidth = drmmode_bo_get_pitch(&drmmode->front_bo) / cpp;
width = ms->cursor_width;
height = ms->cursor_height;
@@ -1571,14 +1557,14 @@ drmmode_map_front_bo(drmmode_ptr drmmode)
{
int ret;
- if (drmmode->front_bo->ptr)
- return drmmode->front_bo->ptr;
+ if (drmmode->front_bo.dumb->ptr)
+ return drmmode->front_bo.dumb->ptr;
- ret = dumb_bo_map(drmmode->fd, drmmode->front_bo);
+ ret = dumb_bo_map(drmmode->fd, drmmode->front_bo.dumb);
if (ret)
return NULL;
- return drmmode->front_bo->ptr;
+ return drmmode->front_bo.dumb->ptr;
}
@@ -1625,8 +1611,7 @@ drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
drmmode->fb_id = 0;
}
- dumb_bo_destroy(drmmode->fd, drmmode->front_bo);
- drmmode->front_bo = NULL;
+ drmmode_bo_destroy(drmmode, &drmmode->front_bo);
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h
index 987608c55..66d0ca260 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -28,17 +28,20 @@
#define DRMMODE_DISPLAY_H
#include "xf86drmMode.h"
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
#include "libudev.h"
#endif
-struct dumb_bo {
- uint32_t handle;
- uint32_t size;
- void *ptr;
- int map_count;
- uint32_t pitch;
-};
+#include "dumb_bo.h"
+
+struct gbm_device;
+
+typedef struct {
+ struct dumb_bo *dumb;
+#ifdef GLAMOR_HAS_GBM
+ struct gbm_bo *gbm;
+#endif
+} drmmode_bo;
typedef struct {
int fd;
@@ -48,14 +51,18 @@ typedef struct {
drmModeFBPtr mode_fb;
int cpp;
ScrnInfoPtr scrn;
-#ifdef HAVE_UDEV
+
+ struct gbm_device *gbm;
+
+#ifdef CONFIG_UDEV_KMS
struct udev_monitor *uevent_monitor;
InputHandlerProc uevent_handler;
#endif
drmEventContext event_context;
- struct dumb_bo *front_bo;
+ drmmode_bo front_bo;
Bool sw_cursor;
+ Bool glamor;
Bool shadow_enable;
void *shadow_fb;
@@ -79,7 +86,9 @@ typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
uint32_t vblank_pipe;
+ int dpms_mode;
struct dumb_bo *cursor_bo;
+ Bool cursor_up;
unsigned rotate_fb_id;
uint16_t lut_r[256], lut_g[256], lut_b[256];
DamagePtr slave_damage;
@@ -128,6 +137,8 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec;
#define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec))
+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);
Bool drmmode_SetSlaveBO(PixmapPtr ppix,
drmmode_ptr drmmode,
@@ -147,8 +158,6 @@ 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);
-struct dumb_bo *dumb_get_bo_from_fd(int drm_fd, int fd, int pitch, int size);
-int dumb_bo_destroy(int fd, struct dumb_bo *bo);
#ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c
new file mode 100644
index 000000000..58d420e07
--- /dev/null
+++ b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#include "dumb_bo.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <xf86drm.h>
+
+struct dumb_bo *
+dumb_bo_create(int fd,
+ const unsigned width, const unsigned height, const unsigned bpp)
+{
+ struct drm_mode_create_dumb arg;
+ struct dumb_bo *bo;
+ int ret;
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo)
+ return NULL;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.width = width;
+ arg.height = height;
+ arg.bpp = bpp;
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
+ if (ret)
+ goto err_free;
+
+ bo->handle = arg.handle;
+ bo->size = arg.size;
+ bo->pitch = arg.pitch;
+
+ return bo;
+ err_free:
+ free(bo);
+ return NULL;
+}
+
+int
+dumb_bo_map(int fd, struct dumb_bo *bo)
+{
+ struct drm_mode_map_dumb arg;
+ int ret;
+ void *map;
+
+ if (bo->ptr) {
+ return 0;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->handle;
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
+ if (ret)
+ return ret;
+
+ map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, arg.offset);
+ if (map == MAP_FAILED)
+ return -errno;
+
+ bo->ptr = map;
+ return 0;
+}
+
+int
+dumb_bo_destroy(int fd, struct dumb_bo *bo)
+{
+ struct drm_mode_destroy_dumb arg;
+ int ret;
+
+ if (bo->ptr) {
+ munmap(bo->ptr, bo->size);
+ bo->ptr = NULL;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->handle;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
+ if (ret)
+ return -errno;
+
+ free(bo);
+ return 0;
+}
+
+struct dumb_bo *
+dumb_get_bo_from_fd(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;
+}
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h
new file mode 100644
index 000000000..9235e61e2
--- /dev/null
+++ b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+#ifndef DUMB_BO_H
+#define DUMB_BO_H
+
+#include <stdint.h>
+
+struct dumb_bo {
+ uint32_t handle;
+ uint32_t size;
+ void *ptr;
+ uint32_t pitch;
+};
+
+struct dumb_bo *dumb_bo_create(int fd, const unsigned width,
+ const unsigned height, const unsigned bpp);
+int dumb_bo_map(int fd, struct dumb_bo *bo);
+int dumb_bo_destroy(int fd, struct dumb_bo *bo);
+struct dumb_bo *dumb_get_bo_from_fd(int fd, int handle, int pitch, int size);
+
+#endif
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/present.c b/xorg-server/hw/xfree86/drivers/modesetting/present.c
new file mode 100644
index 000000000..359e11316
--- /dev/null
+++ b/xorg-server/hw/xfree86/drivers/modesetting/present.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <xf86.h>
+#include <xf86Crtc.h>
+#include <xf86drm.h>
+#include <xf86str.h>
+#include <present.h>
+
+#include "driver.h"
+
+#if 0
+#define DebugPresent(x) ErrorF x
+#else
+#define DebugPresent(x)
+#endif
+
+struct ms_present_vblank_event {
+ uint64_t event_id;
+};
+
+static RRCrtcPtr
+ms_present_get_crtc(WindowPtr window)
+{
+ xf86CrtcPtr xf86_crtc = ms_dri2_crtc_covering_drawable(&window->drawable);
+ return xf86_crtc ? xf86_crtc->randr_crtc : NULL;
+}
+
+static int
+ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+
+ return ms_get_crtc_ust_msc(xf86_crtc, ust, msc);
+}
+
+/*
+ * Flush the DRM event queue when full; makes space for new events.
+ */
+static Bool
+ms_flush_drm_events(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+
+ struct pollfd p = { .fd = ms->fd, .events = POLLIN };
+ int r;
+
+ do {
+ r = poll(&p, 1, 0);
+ } while (r == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (r <= 0)
+ return TRUE;
+
+ return drmHandleEvent(ms->fd, &ms->event_context) >= 0;
+}
+
+/*
+ * Called when the queued vblank event has occurred
+ */
+static void
+ms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data)
+{
+ struct ms_present_vblank_event *event = data;
+
+ DebugPresent(("\t\tmh %lld msc %llu\n",
+ (long long) event->event_id, (long long) msc));
+
+ present_event_notify(event->event_id, usec, msc);
+ free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+ms_present_vblank_abort(void *data)
+{
+ struct ms_present_vblank_event *event = data;
+
+ DebugPresent(("\t\tma %lld\n", (long long) event->event_id));
+
+ free(event);
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+ms_present_queue_vblank(RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ struct ms_present_vblank_event *event;
+ drmVBlank vbl;
+ int ret;
+ uint32_t seq;
+
+ event = calloc(sizeof(struct ms_present_vblank_event), 1);
+ if (!event)
+ return BadAlloc;
+ event->event_id = event_id;
+ seq = ms_drm_queue_alloc(xf86_crtc, event,
+ ms_present_vblank_handler,
+ ms_present_vblank_abort);
+ if (!seq) {
+ free(event);
+ return BadAlloc;
+ }
+
+ vbl.request.type =
+ DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
+ vbl.request.sequence = ms_crtc_msc_to_kernel_msc(xf86_crtc, msc);
+ vbl.request.signal = seq;
+ for (;;) {
+ ret = drmWaitVBlank(ms->fd, &vbl);
+ if (!ret)
+ break;
+ if (errno != EBUSY || !ms_flush_drm_events(screen))
+ return BadAlloc;
+ }
+ DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n",
+ (long long) event_id, seq, (long long) msc,
+ vbl.request.sequence));
+ return Success;
+}
+
+static Bool
+ms_present_event_match(void *data, void *match_data)
+{
+ struct ms_present_vblank_event *event = data;
+ uint64_t *match = match_data;
+
+ return *match == event->event_id;
+}
+
+/*
+ * Remove a pending vblank event from the DRM queue so that it is not reported
+ * to the extension
+ */
+static void
+ms_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ ms_drm_abort(scrn, ms_present_event_match, &event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+ms_present_flush(WindowPtr window)
+{
+#ifdef GLAMOR
+ ScreenPtr screen = window->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+
+ if (ms->drmmode.glamor)
+ glamor_block_handler(screen);
+#endif
+}
+
+static present_screen_info_rec ms_present_screen_info = {
+ .version = PRESENT_SCREEN_INFO_VERSION,
+
+ .get_crtc = ms_present_get_crtc,
+ .get_ust_msc = ms_present_get_ust_msc,
+ .queue_vblank = ms_present_queue_vblank,
+ .abort_vblank = ms_present_abort_vblank,
+ .flush = ms_present_flush,
+
+ .capabilities = PresentCapabilityNone,
+ .check_flip = 0,
+ .flip = 0,
+ .unflip = 0,
+};
+
+Bool
+ms_present_screen_init(ScreenPtr screen)
+{
+ return present_screen_init(screen, &ms_present_screen_info);
+}
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/vblank.c b/xorg-server/hw/xfree86/drivers/modesetting/vblank.c
index 5031ef8ff..711f6edb3 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/vblank.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/vblank.c
@@ -88,6 +88,14 @@ static int ms_box_area(BoxPtr box)
return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
}
+static Bool
+ms_crtc_on(xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
+}
+
/*
* Return the crtc covering 'box'. If two crtcs cover a portion of
* 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
@@ -114,7 +122,7 @@ ms_covering_crtc(ScrnInfoPtr scrn,
crtc = xf86_config->crtc[c];
/* If the CRTC is off, treat it as not covering */
- if (!crtc->enabled)
+ if (!ms_crtc_on(crtc))
continue;
ms_crtc_box(crtc, &crtc_box);
@@ -323,6 +331,24 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn)
}
/*
+ * Externally usable abort function that uses a callback to match a single
+ * queued entry to abort
+ */
+void
+ms_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data),
+ void *match_data)
+{
+ struct ms_drm_queue *q;
+
+ xorg_list_for_each_entry(q, &ms_drm_queue, list) {
+ if (match(q->data, match_data)) {
+ ms_drm_abort_one(q);
+ break;
+ }
+ }
+}
+
+/*
* General DRM kernel handler. Looks for the matching sequence number in the
* drm event queue and calls the handler for it.
*/