diff options
Diffstat (limited to 'xorg-server/hw')
35 files changed, 1060 insertions, 491 deletions
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c index 93a48a9cd..907bbebae 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr.c @@ -1292,7 +1292,7 @@ ephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) if (p > max) max = p; - hostx_set_cmap_entry(p, + hostx_set_cmap_entry(pScreen, p, pdefs->red >> 8, pdefs->green >> 8, pdefs->blue >> 8); pdefs++; diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.h b/xorg-server/hw/kdrive/ephyr/ephyr.h index 2395a7f7e..18bfe11ff 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr.h +++ b/xorg-server/hw/kdrive/ephyr/ephyr.h @@ -83,6 +83,7 @@ typedef struct _ephyrScrPriv { KdScreenInfo *screen; int mynum; /* Screen number */ + unsigned long cmap[256]; /** * Per-screen Xlib-using state for glamor (private to diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c index 8d6d5e83b..f64861b50 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.c +++ b/xorg-server/hw/kdrive/ephyr/hostx.c @@ -82,8 +82,6 @@ struct EphyrHostXVars { KdScreenInfo **screens; long damage_debug_msec; - - unsigned long cmap[256]; }; /* memset ( missing> ) instead of below */ @@ -751,9 +749,12 @@ hostx_calculate_color_shift(unsigned long mask) } void -hostx_set_cmap_entry(unsigned char idx, +hostx_set_cmap_entry(ScreenPtr pScreen, unsigned char idx, unsigned char r, unsigned char g, unsigned char b) { + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; /* need to calculate the shifts for RGB because server could be BGR. */ /* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/ static int rshift, bshift, gshift = 0; @@ -765,7 +766,7 @@ hostx_set_cmap_entry(unsigned char idx, gshift = hostx_calculate_color_shift(HostX.visual->green_mask); bshift = hostx_calculate_color_shift(HostX.visual->blue_mask); } - HostX.cmap[idx] = ((r << rshift) & HostX.visual->red_mask) | + scrpriv->cmap[idx] = ((r << rshift) & HostX.visual->red_mask) | ((g << gshift) & HostX.visual->green_mask) | ((b << bshift) & HostX.visual->blue_mask); } @@ -1017,7 +1018,7 @@ hostx_paint_rect(KdScreenInfo *screen, unsigned char pixel = *(unsigned char *) (scrpriv->fb_data + idx); xcb_image_put_pixel(scrpriv->ximg, x, y, - HostX.cmap[pixel]); + scrpriv->cmap[pixel]); break; } default: diff --git a/xorg-server/hw/kdrive/ephyr/hostx.h b/xorg-server/hw/kdrive/ephyr/hostx.h index 87acd5a50..93aaa509c 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.h +++ b/xorg-server/hw/kdrive/ephyr/hostx.h @@ -141,7 +141,7 @@ hostx_get_visual_masks(KdScreenInfo *screen, CARD32 *rmsk, CARD32 *gmsk, CARD32 *bmsk); void -hostx_set_cmap_entry(unsigned char idx, +hostx_set_cmap_entry(ScreenPtr pScreen, unsigned char idx, unsigned char r, unsigned char g, unsigned char b); void *hostx_screen_init(KdScreenInfo *screen, diff --git a/xorg-server/hw/xfree86/common/xf86AutoConfig.c b/xorg-server/hw/xfree86/common/xf86AutoConfig.c index 03dad150a..1450afbfc 100644 --- a/xorg-server/hw/xfree86/common/xf86AutoConfig.c +++ b/xorg-server/hw/xfree86/common/xf86AutoConfig.c @@ -208,7 +208,6 @@ listPossibleVideoDrivers(char *matches[], int nmatches) if (xf86Info.consoleFd >= 0 && (i < (nmatches - 1))) { struct vis_identifier visid; const char *cp; - extern char xf86SolarisFbDev[PATH_MAX]; int iret; SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid)); diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index ffd66fad6..221ec530b 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -270,6 +270,9 @@ ProcDRI2GetBuffers(ClientPtr client) unsigned int *attachments; REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4); + if (stuff->count > (INT_MAX / 4)) + return BadLength; + if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, &pDrawable, &status)) return status; 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. */ diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c index 16fc1b739..cc50f36c4 100644 --- a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c +++ b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c @@ -46,15 +46,12 @@ #define SOL_CONSOLE_DEV "/dev/console" static Bool KeepTty = FALSE; -static Bool Protect0 = FALSE; static Bool UseConsole = FALSE; #ifdef HAS_USL_VTS static int VTnum = -1; static int xf86StartVT = -1; static int vtEnabled = 0; -extern void xf86VTAcquire(int); -extern void xf86VTRelease(int); #endif /* Device to open as xf86Info.consoleFd */ @@ -97,27 +94,6 @@ xf86OpenConsole(void) if (geteuid() != 0) FatalError("xf86OpenConsole: Server must be suid root\n"); - /* Protect page 0 to help find NULL dereferencing */ - /* mprotect() doesn't seem to work */ - if (Protect0) { - int fd = -1; - - if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0) { - xf86Msg(X_WARNING, - "xf86OpenConsole: cannot open /dev/zero (%s)\n", - strerror(errno)); - } - else { - if (mmap(0, 0x1000, PROT_NONE, - MAP_FIXED | MAP_SHARED, fd, 0) == MAP_FAILED) - xf86Msg(X_WARNING, - "xf86OpenConsole: failed to protect page 0 (%s)\n", - strerror(errno)); - - close(fd); - } - } - #ifdef HAS_USL_VTS /* @@ -371,15 +347,6 @@ xf86ProcessArgument(int argc, char **argv, int i) } /* - * Undocumented flag to protect page 0 from read/write to help catch NULL - * pointer dereferences. This is purely a debugging flag. - */ - if (!strcmp(argv[i], "-protect0")) { - Protect0 = TRUE; - return 1; - } - - /* * Use /dev/console as the console device. */ if (!strcmp(argv[i], "-C")) { diff --git a/xorg-server/hw/xfree86/os-support/xf86_OSlib.h b/xorg-server/hw/xfree86/os-support/xf86_OSlib.h index 3a83f348f..6190fe6a0 100644 --- a/xorg-server/hw/xfree86/os-support/xf86_OSlib.h +++ b/xorg-server/hw/xfree86/os-support/xf86_OSlib.h @@ -134,10 +134,15 @@ #endif #include <sys/kd.h> #include <sys/vt.h> + +extern _X_HIDDEN void xf86VTAcquire(int); +extern _X_HIDDEN void xf86VTRelease(int); #endif #if defined(sun) #include <sys/fbio.h> +extern _X_HIDDEN char xf86SolarisFbDev[PATH_MAX]; + #include <sys/kbd.h> #include <sys/kbio.h> diff --git a/xorg-server/hw/xwayland/xwayland-glamor.c b/xorg-server/hw/xwayland/xwayland-glamor.c index 4be883fa3..09b454f8a 100644 --- a/xorg-server/hw/xwayland/xwayland-glamor.c +++ b/xorg-server/hw/xwayland/xwayland-glamor.c @@ -398,9 +398,8 @@ xwl_screen_init_glamor(struct xwl_screen *xwl_screen, } void -glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) +glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) { - glamor_destroy_textured_pixmap(pixmap); } int diff --git a/xorg-server/hw/xwayland/xwayland-input.c b/xorg-server/hw/xwayland/xwayland-input.c index b8c543ce4..5e204189f 100644 --- a/xorg-server/hw/xwayland/xwayland-input.c +++ b/xorg-server/hw/xwayland/xwayland-input.c @@ -233,6 +233,9 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, xwl_seat->xwl_screen->serial = serial; switch (button) { + case BTN_LEFT: + index = 1; + break; case BTN_MIDDLE: index = 2; break; @@ -240,7 +243,9 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, index = 3; break; default: - index = button - BTN_LEFT + 1; + /* Skip indexes 4-7: they are used for vertical and horizontal scroll. + The rest of the buttons go in order: BTN_SIDE becomes 8, etc. */ + index = 8 + button - BTN_SIDE; break; } diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index fef46a94f..654c58c14 100644 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -793,6 +793,10 @@ winUseMsg(void) #ifdef XWIN_CLIPBOARD ErrorF("-nounicodeclipboard\n" "\tDo not use Unicode clipboard even if on a NT-based platform.\n"); + + ErrorF("-[no]primary\n" + "\tWhen clipboard integration is enabled, map the X11 PRIMARY selection\n" + "\tto the Windows clipboard. Default is enabled.\n"); #endif ErrorF("-refresh rate_in_Hz\n" diff --git a/xorg-server/hw/xwin/XWin.rc b/xorg-server/hw/xwin/XWin.rc index a142f3070..a54e0fdbb 100644 --- a/xorg-server/hw/xwin/XWin.rc +++ b/xorg-server/hw/xwin/XWin.rc @@ -93,6 +93,7 @@ BEGIN POPUP "TRAYICON_MENU" BEGIN MENUITEM "&Hide Root Window", ID_APP_HIDE_ROOT + MENUITEM "Clipboard may use &PRIMARY selection", ID_APP_MONITOR_PRIMARY MENUITEM "&About...", ID_APP_ABOUT MENUITEM SEPARATOR MENUITEM "E&xit...", ID_APP_EXIT diff --git a/xorg-server/hw/xwin/man/XWin.man b/xorg-server/hw/xwin/man/XWin.man index a043ac281..15a57db02 100644 --- a/xorg-server/hw/xwin/man/XWin.man +++ b/xorg-server/hw/xwin/man/XWin.man @@ -174,7 +174,7 @@ on remote hosts, when that information is available and it's useful to do so. .SH OPTIONS CONTROLLING WINDOWS INTEGRATION .TP 8 .B \-[no]clipboard -Enables [disables] the integration between the Cygwin/X clipboard and +Enables [disables] the integration between the X11 clipboard and \fIWindows\fP clipboard. The default is enabled. .TP 8 .B "\-emulate3buttons [\fItimeout\fP]" @@ -200,6 +200,10 @@ prevents the \fIWindows\fP mouse cursor from being drawn on top of the X cursor. This parameter has no effect unless \fB-swcursor\fP is also specified. .TP 8 +.B \-[no]primary +Clipboard integration may [will not] use the PRIMARY selection. +The default is enabled. +.TP 8 .B \-swcursor Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead. .TP 8 diff --git a/xorg-server/hw/xwin/winclipboard/internal.h b/xorg-server/hw/xwin/winclipboard/internal.h index 94956f80d..c6bde84af 100644 --- a/xorg-server/hw/xwin/winclipboard/internal.h +++ b/xorg-server/hw/xwin/winclipboard/internal.h @@ -39,10 +39,12 @@ #include <X11/Xwindows.h> #define WIN_XEVENTS_SUCCESS 0 -#define WIN_XEVENTS_CONVERT 2 -#define WIN_XEVENTS_NOTIFY 3 +#define WIN_XEVENTS_FAILED 1 +#define WIN_XEVENTS_NOTIFY_DATA 3 +#define WIN_XEVENTS_NOTIFY_TARGETS 4 #define WM_WM_REINIT (WM_USER + 1) +#define WM_WM_QUIT (WM_USER + 2) /* * References to external symbols @@ -95,9 +97,15 @@ typedef struct * winclipboardxevents.c */ +typedef struct +{ + Bool fUseUnicode; + Atom *targetList; +} ClipboardConversionData; + int winClipboardFlushXEvents(HWND hwnd, - Window iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom); + Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atom); Atom diff --git a/xorg-server/hw/xwin/winclipboard/thread.c b/xorg-server/hw/xwin/winclipboard/thread.c index c179e3f83..50e1e8cb5 100644 --- a/xorg-server/hw/xwin/winclipboard/thread.c +++ b/xorg-server/hw/xwin/winclipboard/thread.c @@ -123,6 +123,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) int iSelectError; Bool fShutdown = FALSE; static Bool fErrorHandlerSet = FALSE; + ClipboardConversionData data; winDebug("winClipboardProc - Hello\n"); @@ -254,21 +255,25 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) } } - /* Pre-flush X events */ - /* - * NOTE: Apparently you'll freeze if you don't do this, - * because there may be events in local data structures - * already. - */ - winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms); - - /* Pre-flush Windows messages */ - if (!winClipboardFlushWindowsMessageQueue(hwnd)) { - ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n"); - } + data.fUseUnicode = fUseUnicode; - /* Loop for X events */ + /* Loop for events */ while (1) { + + /* Process X events */ + winClipboardFlushXEvents(hwnd, + iWindow, pDisplay, &data, &atoms); + + /* Process Windows messages */ + if (!winClipboardFlushWindowsMessageQueue(hwnd)) { + ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue trapped " + "WM_QUIT message, exiting main loop.\n"); + break; + } + + /* We need to ensure that all pending requests are sent */ + XFlush(pDisplay); + /* Setup the file descriptor set */ /* * NOTE: You have to do this before every call to select @@ -315,10 +320,9 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) break; } - /* Branch on which descriptor became active */ if (FD_ISSET(iConnectionNumber, &fdsRead)) { - /* Process X events */ - winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms); + winDebug + ("winClipboardProc - X connection ready, pumping X event queue\n"); } #ifdef HAS_DEVWINDOWS @@ -328,14 +332,16 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) if (1) #endif { - /* Process Windows messages */ - if (!winClipboardFlushWindowsMessageQueue(hwnd)) { - ErrorF("winClipboardProc - " - "winClipboardFlushWindowsMessageQueue trapped " - "WM_QUIT message, exiting main loop.\n"); - break; - } + winDebug + ("winClipboardProc - /dev/windows ready, pumping Windows message queue\n"); } + +#ifdef HAS_DEVWINDOWS + if (!(FD_ISSET(iConnectionNumber, &fdsRead)) && + !(FD_ISSET(fdMessageQueue, &fdsRead))) { + winDebug("winClipboardProc - Spurious wake, select() returned %d\n", iReturn); + } +#endif } winClipboardProc_Exit: @@ -345,7 +351,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) winClipboardProc_Done: /* Close our Windows window */ if (g_hwndClipboard) { - winClipboardWindowDestroy(); + DestroyWindow(g_hwndClipboard); } /* Close our X window */ @@ -485,7 +491,7 @@ void winClipboardWindowDestroy(void) { if (g_hwndClipboard) { - SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0); + SendMessage(g_hwndClipboard, WM_WM_QUIT, 0, 0); } } diff --git a/xorg-server/hw/xwin/winclipboard/winclipboard.h b/xorg-server/hw/xwin/winclipboard/winclipboard.h index 52481301b..9c5c568a7 100644 --- a/xorg-server/hw/xwin/winclipboard/winclipboard.h +++ b/xorg-server/hw/xwin/winclipboard/winclipboard.h @@ -33,4 +33,6 @@ void winFixClipboardChain(void); void winClipboardWindowDestroy(void); +extern Bool fPrimarySelection; + #endif diff --git a/xorg-server/hw/xwin/winclipboard/wndproc.c b/xorg-server/hw/xwin/winclipboard/wndproc.c index 165ff558a..1ea5bc6b7 100644 --- a/xorg-server/hw/xwin/winclipboard/wndproc.c +++ b/xorg-server/hw/xwin/winclipboard/wndproc.c @@ -45,6 +45,7 @@ #include <sys/types.h> #include <sys/time.h> +#include <limits.h> #include <X11/Xatom.h> @@ -64,7 +65,7 @@ static int winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, - Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec) + ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec) { int iConnNumber; struct timeval tv; @@ -82,8 +83,18 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, fd_set fdsRead; long remainingTime; - /* We need to ensure that all pending events are processed */ - XSync(pDisplay, FALSE); + /* Process X events */ + iReturn = winClipboardFlushXEvents(hwnd, iWindow, pDisplay, data, atoms); + + winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn); + + if ((WIN_XEVENTS_NOTIFY_DATA == iReturn) || (WIN_XEVENTS_NOTIFY_TARGETS == iReturn) || (WIN_XEVENTS_FAILED == iReturn)) { + /* Bail out */ + return iReturn; + } + + /* We need to ensure that all pending requests are sent */ + XFlush(pDisplay); /* Setup the file descriptor set */ FD_ZERO(&fdsRead); @@ -112,24 +123,8 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, break; } - /* Branch on which descriptor became active */ - if (FD_ISSET(iConnNumber, &fdsRead)) { - /* Process X events */ - /* Exit when we see that server is shutting down */ - iReturn = winClipboardFlushXEvents(hwnd, - iWindow, pDisplay, fUseUnicode, atoms); - - winDebug - ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", - iReturn); - - if (WIN_XEVENTS_NOTIFY == iReturn) { - /* Bail out if notify processed */ - return iReturn; - } - } - else { - winDebug("winProcessXEventsTimeout - Spurious wake\n"); + if (!FD_ISSET(iConnNumber, &fdsRead)) { + winDebug("winProcessXEventsTimeout - Spurious wake, select() returned %d\n", iReturn); } } @@ -148,6 +143,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) static Display *pDisplay; static Window iWindow; static ClipboardAtoms *atoms; + static Bool fRunning; /* Branch on message type */ switch (message) { @@ -159,7 +155,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ChangeClipboardChain(hwnd, s_hwndNextViewer); s_hwndNextViewer = NULL; + } + return 0; + case WM_WM_QUIT: + { + winDebug("winClipboardWindowProc - WM_WM_QUIT\n"); + fRunning = FALSE; PostQuitMessage(0); } return 0; @@ -175,6 +177,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) pDisplay = cwcp->pClipboardDisplay; iWindow = cwcp->iClipboardWindow; atoms = cwcp->atoms; + fRunning = TRUE; first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ if (first == hwnd) @@ -307,6 +310,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; } + /* Bail when shutting down */ + if (!fRunning) + return 0; + /* * Do not take ownership of the X11 selections when something * other than CF_TEXT or CF_UNICODETEXT has been copied @@ -410,93 +417,151 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n"); return 0; - case WM_RENDERFORMAT: case WM_RENDERALLFORMATS: + winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n"); + + /* + WM_RENDERALLFORMATS is sent as we are shutting down, to render the + clipboard so it's contents remains available to other applications. + + Unfortunately, this can't work without major changes. The server is + already waiting for us to stop, so we can't ask for the rendering of + clipboard text now. + */ + + return 0; + + case WM_RENDERFORMAT: { int iReturn; Bool fConvertToUnicode; + Bool pasted = FALSE; + Atom selection; + ClipboardConversionData data; + int best_target = 0; - winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n"); + winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n", + wParam); /* Flag whether to convert to Unicode or not */ - if (message == WM_RENDERALLFORMATS) - fConvertToUnicode = FALSE; - else - fConvertToUnicode = (CF_UNICODETEXT == wParam); + fConvertToUnicode = (CF_UNICODETEXT == wParam); - /* Request the selection contents */ - iReturn = XConvertSelection(pDisplay, - winClipboardGetLastOwnedSelectionAtom(atoms), - atoms->atomCompoundText, - atoms->atomLocalProperty, - iWindow, CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow) { - ErrorF("winClipboardWindowProc - WM_RENDER*FORMAT - " - "XConvertSelection () failed\n"); - break; + selection = winClipboardGetLastOwnedSelectionAtom(atoms); + if (selection == None) { + ErrorF("winClipboardWindowProc - no monitored selection is owned\n"); + goto fake_paste; } - /* Special handling for WM_RENDERALLFORMATS */ - if (message == WM_RENDERALLFORMATS) { - /* We must open and empty the clipboard */ + winDebug("winClipboardWindowProc - requesting targets for selection from owner\n"); - /* Close clipboard if we have it open already */ - if (GetOpenClipboardWindow() == hwnd) { - CloseClipboard(); - } + /* Request the selection's supported conversion targets */ + XConvertSelection(pDisplay, + selection, + atoms->atomTargets, + atoms->atomLocalProperty, + iWindow, CurrentTime); - if (!OpenClipboard(hwnd)) { - ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - " - "OpenClipboard () failed: %08x\n", - GetLastError()); - break; - } + /* Process X events */ + data.fUseUnicode = fConvertToUnicode; + iReturn = winProcessXEventsTimeout(hwnd, + iWindow, + pDisplay, + &data, + atoms, + WIN_POLL_TIMEOUT); - if (!EmptyClipboard()) { - ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - " - "EmptyClipboard () failed: %08x\n", - GetLastError()); - break; - } + if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) { + ErrorF + ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n"); + goto fake_paste; } - /* Process the SelectionNotify event */ + /* Choose the most preferred target */ + { + struct target_priority + { + Atom target; + unsigned int priority; + }; + + struct target_priority target_priority_table[] = + { + { atoms->atomCompoundText, 0 }, +#ifdef X_HAVE_UTF8_STRING + { atoms->atomUTF8String, 1 }, +#endif + { XA_STRING, 2 }, + }; + + int best_priority = INT_MAX; + + int i,j; + for (i = 0 ; data.targetList[i] != 0; i++) + { + for (j = 0; j < sizeof(target_priority_table)/sizeof(struct target_priority); j ++) + { + if ((data.targetList[i] == target_priority_table[j].target) && + (target_priority_table[j].priority < best_priority)) + { + best_target = target_priority_table[j].target; + best_priority = target_priority_table[j].priority; + } + } + } + } + + free(data.targetList); + data.targetList = 0; + + winDebug("winClipboardWindowProc - best target is %d\n", best_target); + + /* No useful targets found */ + if (best_target == 0) + goto fake_paste; + + winDebug("winClipboardWindowProc - requesting selection from owner\n"); + + /* Request the selection contents */ + XConvertSelection(pDisplay, + selection, + best_target, + atoms->atomLocalProperty, + iWindow, CurrentTime); + + /* Process X events */ iReturn = winProcessXEventsTimeout(hwnd, iWindow, pDisplay, - fConvertToUnicode, + &data, atoms, WIN_POLL_TIMEOUT); /* - * The last call to winProcessXEventsTimeout - * from above had better have seen a notify event, or else we - * are dealing with a buggy or old X11 app. In these cases we - * have to paste some fake data to the Win32 clipboard to - * satisfy the requirement that we write something to it. + * winProcessXEventsTimeout had better have seen a notify event, + * or else we are dealing with a buggy or old X11 app. */ - if (WIN_XEVENTS_NOTIFY != iReturn) { - /* Paste no data, to satisfy required call to SetClipboardData */ - SetClipboardData(CF_UNICODETEXT, NULL); - SetClipboardData(CF_TEXT, NULL); - + if (WIN_XEVENTS_NOTIFY_DATA != iReturn) { ErrorF - ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n"); + ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n"); } - - /* Special handling for WM_RENDERALLFORMATS */ - if (message == WM_RENDERALLFORMATS) { - /* We must close the clipboard */ - - if (!CloseClipboard()) { - ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - " - "CloseClipboard () failed: %08x\n", - GetLastError()); - break; - } + else { + pasted = TRUE; } - winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n"); + /* + * If we couldn't get the data from the X clipboard, we + * have to paste some fake data to the Win32 clipboard to + * satisfy the requirement that we write something to it. + */ + fake_paste: + if (!pasted) + { + /* Paste no data, to satisfy required call to SetClipboardData */ + SetClipboardData(CF_UNICODETEXT, NULL); + SetClipboardData(CF_TEXT, NULL); + } + + winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n"); return 0; } } diff --git a/xorg-server/hw/xwin/winclipboard/xevents.c b/xorg-server/hw/xwin/winclipboard/xevents.c index 33d52aafd..835195b52 100644 --- a/xorg-server/hw/xwin/winclipboard/xevents.c +++ b/xorg-server/hw/xwin/winclipboard/xevents.c @@ -43,11 +43,15 @@ #undef _XSERVER64 #endif -#include "internal.h" +#include <limits.h> +#include <wchar.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/extensions/Xfixes.h> +#include "winclipboard.h" +#include "internal.h" + /* * Constants */ @@ -62,6 +66,7 @@ */ extern int xfixes_event_base; +Bool fPrimarySelection = TRUE; /* * Local variables @@ -133,13 +138,59 @@ winClipboardInitMonitoredSelections(void) lastOwnedSelectionIndex = CLIP_OWN_NONE; } +static int +winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) +{ + Atom type; + int format; + unsigned long nitems; + unsigned long after; + Atom *prop; + + /* Retrieve the selection data and delete the property */ + int iReturn = XGetWindowProperty(pDisplay, + iWindow, + atoms->atomLocalProperty, + 0, + INT_MAX, + True, + AnyPropertyType, + &type, + &format, + &nitems, + &after, + (unsigned char **)&prop); + if (iReturn != Success) { + ErrorF("winClipboardFlushXEvents - SelectionNotify - " + "XGetWindowProperty () failed, aborting: %d\n", iReturn); + } else { + int i; + data->targetList = malloc((nitems+1)*sizeof(Atom)); + + for (i = 0; i < nitems; i++) + { + Atom atom = prop[i]; + char *pszAtomName = XGetAtomName(pDisplay, atom); + data->targetList[i] = atom; + winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %d = %s\n", i, atom, pszAtomName); + XFree(pszAtomName); + } + + data->targetList[nitems] = 0; + + XFree(prop); + } + + return WIN_XEVENTS_NOTIFY_TARGETS; +} + /* * Process any pending X events */ int winClipboardFlushXEvents(HWND hwnd, - Window iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms) + Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) { Atom atomClipboard = atoms->atomClipboard; Atom atomLocalProperty = atoms->atomLocalProperty; @@ -158,14 +209,11 @@ winClipboardFlushXEvents(HWND hwnd, int iReturn; HGLOBAL hGlobal = NULL; XICCEncodingStyle xiccesStyle; - int iConvertDataLen = 0; char *pszConvertData = NULL; char *pszTextList[2] = { NULL }; int iCount; char **ppszTextList = NULL; wchar_t *pwszUnicodeStr = NULL; - int iUnicodeLen = 0; - int iReturnDataLen = 0; Bool fAbort = FALSE; Bool fCloseClipboard = FALSE; Bool fSetClipboardData = TRUE; @@ -272,7 +320,7 @@ winClipboardFlushXEvents(HWND hwnd, fCloseClipboard = TRUE; /* Check that clipboard format is available */ - if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) { + if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) { static int count; /* Hack to stop acroread spamming the log */ static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */ @@ -289,7 +337,7 @@ winClipboardFlushXEvents(HWND hwnd, fAbort = TRUE; goto winClipboardFlushXEvents_SelectionRequest_Done; } - else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) { + else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) { ErrorF("winClipboardFlushXEvents - CF_TEXT is not " "available from Win32 clipboard. Aborting.\n"); @@ -311,7 +359,7 @@ winClipboardFlushXEvents(HWND hwnd, xiccesStyle = XStringStyle; /* Get a pointer to the clipboard text, in desired format */ - if (fUseUnicode) { + if (data->fUseUnicode) { /* Retrieve clipboard data */ hGlobal = GetClipboardData(CF_UNICODETEXT); } @@ -330,8 +378,8 @@ winClipboardFlushXEvents(HWND hwnd, pszGlobalData = (char *) GlobalLock(hGlobal); /* Convert the Unicode string to UTF8 (MBCS) */ - if (fUseUnicode) { - iConvertDataLen = WideCharToMultiByte(CP_UTF8, + if (data->fUseUnicode) { + int iConvertDataLen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) pszGlobalData, -1, NULL, 0, NULL, NULL); @@ -346,7 +394,6 @@ winClipboardFlushXEvents(HWND hwnd, } else { pszConvertData = strdup(pszGlobalData); - iConvertDataLen = strlen(pszConvertData) + 1; } /* Convert DOS string to UNIX string */ @@ -361,7 +408,7 @@ winClipboardFlushXEvents(HWND hwnd, xtpText.nitems = 0; /* Create the text property from the text list */ - if (fUseUnicode) { + if (data->fUseUnicode) { #ifdef X_HAVE_UTF8_STRING iReturn = Xutf8TextListToTextProperty(pDisplay, pszTextList, @@ -491,7 +538,6 @@ winClipboardFlushXEvents(HWND hwnd, */ case SelectionNotify: - winDebug("winClipboardFlushXEvents - SelectionNotify\n"); { char *pszAtomName; @@ -506,75 +552,31 @@ winClipboardFlushXEvents(HWND hwnd, } /* - * Request conversion of UTF8 and CompoundText targets. - */ - if (event.xselection.property == None) { - if (event.xselection.target == XA_STRING) { - winDebug("winClipboardFlushXEvents - SelectionNotify - " - "XA_STRING\n"); + SelectionNotify with property of None indicates either: - return WIN_XEVENTS_CONVERT; - } - else if (event.xselection.target == atomUTF8String) { - winDebug("winClipboardFlushXEvents - SelectionNotify - " - "Requesting conversion of UTF8 target.\n"); - - XConvertSelection(pDisplay, - event.xselection.selection, - XA_STRING, - atomLocalProperty, iWindow, CurrentTime); - - /* Process the ConvertSelection event */ - XFlush(pDisplay); - return WIN_XEVENTS_CONVERT; - } -#ifdef X_HAVE_UTF8_STRING - else if (event.xselection.target == atomCompoundText) { - winDebug("winClipboardFlushXEvents - SelectionNotify - " - "Requesting conversion of CompoundText target.\n"); - - XConvertSelection(pDisplay, - event.xselection.selection, - atomUTF8String, - atomLocalProperty, iWindow, CurrentTime); - - /* Process the ConvertSelection event */ - XFlush(pDisplay); - return WIN_XEVENTS_CONVERT; - } -#endif - else { + (i) Generated by the X server if no owner for the specified selection exists + (perhaps it's disappeared on us mid-transaction), or + (ii) Sent by the selection owner when the requested selection conversion could + not be performed or server errors prevented the conversion data being returned + */ + if (event.xselection.property == None) { ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "Unknown format. Cannot request conversion, " - "aborting.\n"); - break; + "Conversion to format %d refused.\n", + event.xselection.target); + return WIN_XEVENTS_FAILED; } - } - /* Retrieve the size of the stored data */ - iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0, /* Don't get data, just size */ - False, - AnyPropertyType, - &xtpText.encoding, - &xtpText.format, - &xtpText.nitems, - &ulReturnBytesLeft, &xtpText.value); - if (iReturn != Success) { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "XGetWindowProperty () failed, aborting: %d\n", iReturn); - break; + if (event.xselection.target == atomTargets) { + return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms); } - winDebug("SelectionNotify - returned data %d left %d\n", - xtpText.nitems, ulReturnBytesLeft); - - /* Request the selection data */ + /* Retrieve the selection data and delete the property */ iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, - ulReturnBytesLeft, - False, + INT_MAX, + True, AnyPropertyType, &xtpText.encoding, &xtpText.format, @@ -583,7 +585,7 @@ winClipboardFlushXEvents(HWND hwnd, if (iReturn != Success) { ErrorF("winClipboardFlushXEvents - SelectionNotify - " "XGetWindowProperty () failed, aborting: %d\n", iReturn); - break; + goto winClipboardFlushXEvents_SelectionNotify_Done; } { @@ -597,7 +599,7 @@ winClipboardFlushXEvents(HWND hwnd, pszAtomName = NULL; } - if (fUseUnicode) { + if (data->fUseUnicode) { #ifdef X_HAVE_UTF8_STRING /* Convert the text property to a text list */ iReturn = Xutf8TextPropertyToTextList(pDisplay, @@ -614,8 +616,7 @@ winClipboardFlushXEvents(HWND hwnd, /* Conversion succeeded or some unconvertible characters */ if (ppszTextList != NULL) { int i; - - iReturnDataLen = 0; + int iReturnDataLen = 0; for (i = 0; i < iCount; i++) { iReturnDataLen += strlen(ppszTextList[i]); } @@ -664,14 +665,14 @@ winClipboardFlushXEvents(HWND hwnd, /* Convert the X clipboard string to DOS format */ winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData)); - if (fUseUnicode) { + if (data->fUseUnicode) { /* Find out how much space needed to convert MBCS to Unicode */ - iUnicodeLen = MultiByteToWideChar(CP_UTF8, + int iUnicodeLen = MultiByteToWideChar(CP_UTF8, 0, pszReturnData, -1, NULL, 0); - /* Allocate memory for the Unicode string */ - pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1)); + /* NOTE: iUnicodeLen includes space for null terminator */ + pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen); if (!pwszUnicodeStr) { ErrorF("winClipboardFlushXEvents - SelectionNotify " "malloc failed for pwszUnicodeStr, aborting.\n"); @@ -689,9 +690,10 @@ winClipboardFlushXEvents(HWND hwnd, /* Allocate global memory for the X clipboard data */ hGlobal = GlobalAlloc(GMEM_MOVEABLE, - sizeof(wchar_t) * (iUnicodeLen + 1)); + sizeof(wchar_t) * iUnicodeLen); } else { + int iConvertDataLen = 0; pszConvertData = strdup(pszReturnData); iConvertDataLen = strlen(pszConvertData) + 1; @@ -723,9 +725,8 @@ winClipboardFlushXEvents(HWND hwnd, } /* Copy the returned string into the global memory */ - if (fUseUnicode) { - memcpy(pszGlobalData, - pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1)); + if (data->fUseUnicode) { + wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr); free(pwszUnicodeStr); pwszUnicodeStr = NULL; } @@ -740,7 +741,7 @@ winClipboardFlushXEvents(HWND hwnd, pszGlobalData = NULL; /* Push the selection data to the Windows clipboard */ - if (fUseUnicode) + if (data->fUseUnicode) SetClipboardData(CF_UNICODETEXT, hGlobal); else SetClipboardData(CF_TEXT, hGlobal); @@ -770,7 +771,7 @@ winClipboardFlushXEvents(HWND hwnd, SetClipboardData(CF_UNICODETEXT, NULL); SetClipboardData(CF_TEXT, NULL); } - return WIN_XEVENTS_NOTIFY; + return WIN_XEVENTS_NOTIFY_DATA; case SelectionClear: winDebug("SelectionClear - doing nothing\n"); @@ -790,7 +791,7 @@ winClipboardFlushXEvents(HWND hwnd, winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n"); /* Save selection owners for monitored selections, ignore other selections */ - if (e->selection == XA_PRIMARY) { + if ((e->selection == XA_PRIMARY) && fPrimarySelection) { MonitorSelection(e, CLIP_OWN_PRIMARY); } else if (e->selection == atomClipboard) { diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.c b/xorg-server/hw/xwin/winclipboard/xwinclip.c index 3677974c4..856c4dd54 100644 --- a/xorg-server/hw/xwin/winclipboard/xwinclip.c +++ b/xorg-server/hw/xwin/winclipboard/xwinclip.c @@ -92,6 +92,13 @@ main (int argc, char *argv[]) continue; } + /* Look for -noprimary */ + if (!strcmp (argv[i], "-noprimary")) + { + fPrimarySelection = False; + continue; + } + /* Yack when we find a parameter that we don't know about */ printf ("Unknown parameter: %s\nExiting.\n", argv[i]); exit (1); diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.man b/xorg-server/hw/xwin/winclipboard/xwinclip.man index 822db91d4..a53dc3029 100644 --- a/xorg-server/hw/xwin/winclipboard/xwinclip.man +++ b/xorg-server/hw/xwin/winclipboard/xwinclip.man @@ -29,6 +29,9 @@ Specifies the X server display to connect to. .TP 8 .B \-nounicodeclipboard Do not use unicode text on the clipboard. +.TP 8 +.B \-noprimary +Do not monitor the PRIMARY selection. .SH "SEE ALSO" XWin(1) diff --git a/xorg-server/hw/xwin/winclipboardwrappers.c b/xorg-server/hw/xwin/winclipboardwrappers.c index 2679f4f98..2e6b63287 100644 --- a/xorg-server/hw/xwin/winclipboardwrappers.c +++ b/xorg-server/hw/xwin/winclipboardwrappers.c @@ -44,12 +44,6 @@ DISPATCH_PROC(winProcEstablishConnection); /* - * References to external symbols - */ - -extern Bool g_fClipboard; - -/* * Wrapper for internal EstablishConnection function. * Initializes internal clients that must not be started until * an external client has connected. diff --git a/xorg-server/hw/xwin/winprocarg.c b/xorg-server/hw/xwin/winprocarg.c index f2bf05bad..e8cccb4c2 100644 --- a/xorg-server/hw/xwin/winprocarg.c +++ b/xorg-server/hw/xwin/winprocarg.c @@ -37,13 +37,8 @@ from The Open Group. #include "winmsg.h" #include "winmonitors.h" -/* - * References to external symbols - */ - #ifdef XWIN_CLIPBOARD -extern Bool g_fUnicodeClipboard; -extern Bool g_fClipboard; +#include "winclipboard/winclipboard.h" #endif /* @@ -716,6 +711,26 @@ ddxProcessArgument(int argc, char *argv[], int i) /* Indicate that we have processed this argument */ return 1; } + + /* + * Look for the '-primary' argument + */ + if (IS_OPTION("-primary")) { + fPrimarySelection = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-noprimary' argument + */ + if (IS_OPTION("-noprimary")) { + fPrimarySelection = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } #endif /* diff --git a/xorg-server/hw/xwin/winresource.h b/xorg-server/hw/xwin/winresource.h index afbf9f28d..37e92ce61 100644 --- a/xorg-server/hw/xwin/winresource.h +++ b/xorg-server/hw/xwin/winresource.h @@ -43,6 +43,7 @@ #define ID_APP_HIDE_ROOT 201 #define ID_APP_ALWAYS_ON_TOP 202 #define ID_APP_ABOUT 203 +#define ID_APP_MONITOR_PRIMARY 204 #define ID_ABOUT_WEBSITE 303 diff --git a/xorg-server/hw/xwin/wintrayicon.c b/xorg-server/hw/xwin/wintrayicon.c index e0aa7e5ab..6acc0d712 100644 --- a/xorg-server/hw/xwin/wintrayicon.c +++ b/xorg-server/hw/xwin/wintrayicon.c @@ -32,9 +32,13 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" #include <shellapi.h> #include "winprefs.h" +#ifdef XWIN_CLIPBOARD +#include "winclipboard/winclipboard.h" +#endif /* * Initialize the tray icon @@ -170,6 +174,21 @@ winHandleIconMessage(HWND hwnd, UINT message, RemoveMenu(hmenuTray, ID_APP_HIDE_ROOT, MF_BYCOMMAND); } +#ifdef XWIN_CLIPBOARD + if (g_fClipboard) { + /* Set menu state to indicate if 'Monitor Primary' is enabled or not */ + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + mii.fState = fPrimarySelection ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(hmenuTray, ID_APP_MONITOR_PRIMARY, FALSE, &mii); + } + else { + /* Remove 'Monitor Primary' menu item */ + RemoveMenu(hmenuTray, ID_APP_MONITOR_PRIMARY, MF_BYCOMMAND); + } +#endif + SetupRootMenu(hmenuTray); /* diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c index 0c434c927..1bf3f5cde 100644 --- a/xorg-server/hw/xwin/winwndproc.c +++ b/xorg-server/hw/xwin/winwndproc.c @@ -1218,6 +1218,12 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; #endif +#ifdef XWIN_CLIPBOARD + case ID_APP_MONITOR_PRIMARY: + fPrimarySelection = !fPrimarySelection; + return 0; +#endif + case ID_APP_ABOUT: /* Display the About box */ winDisplayAboutDialog(s_pScreenPriv); |