static Bool
nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync,
			  uint64_t target_msc, PixmapPtr pixmap, Bool vsync)
{
	ScreenPtr screen = scrn->pScreen;
	struct nouveau_pixmap *priv = NULL;
	NVPtr pNv = NVPTR(scrn);
	uint32_t next_fb;
	CARD16 stride;
	CARD32 size;
	void *token;
	int ret;

#ifdef HAVE_GLAMOR
	if (pNv->AccelMethod == GLAMOR &&
	    !(priv = nouveau_glamor_pixmap_get(pixmap))) {
		int fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
		if (fd < 0)
			return FALSE;

		priv = calloc(1, sizeof(*priv));
		if (!priv)
			return FALSE;

		ret = nouveau_bo_prime_handle_ref(pNv->dev, fd, &priv->bo);
		if (ret) {
			free(priv);
			return FALSE;
		}

		nouveau_glamor_pixmap_set(pixmap, priv);
	} else
#endif
	if (!priv)
		priv = nouveau_pixmap(pixmap);

	ret = drmModeAddFB(pNv->dev->fd, pixmap->drawable.width,
			   pixmap->drawable.height, pixmap->drawable.depth,
			   pixmap->drawable.bitsPerPixel, pixmap->devKind,
			   priv->bo->handle, &next_fb);
	if (ret == 0) {
		struct nouveau_present_flip *flip =
			drmmode_event_queue(scrn, event_id, sizeof(*flip),
					    nouveau_present_flip, &token);
		if (flip) {
			xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
			int last = 0, i;

			drmmode_swap(scrn, next_fb, &flip->old);
			flip->fd = pNv->dev->fd;
			flip->msc = target_msc;

			for (i = 0; i < config->num_crtc; i++) {
				if (config->crtc[i]->enabled)
					last = i;
			}

			for (i = 0; i < config->num_crtc; i++) {
				int type = vsync ? 0 : DRM_MODE_PAGE_FLIP_ASYNC;
				int crtc = drmmode_crtc(config->crtc[i]);
				void *user = NULL;

				if (!config->crtc[i]->enabled)
					continue;

				if (token && ((crtc == sync) || (i == last))) {
					type |= DRM_MODE_PAGE_FLIP_EVENT;
					user  = token;
				}

				ret = drmModePageFlip(pNv->dev->fd, crtc,
						      next_fb, type, user);
				if (ret == 0 && user) {
					token = NULL;
				}
			}

			if (token == NULL) {
				return TRUE;
			}

			drmmode_swap(scrn, flip->old, &next_fb);
			drmmode_event_abort(scrn, event_id, false);
		}

		drmModeRmFB(pNv->dev->fd, next_fb);
	}

	return FALSE;
}
Beispiel #2
0
static void
xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
{
    ScrnInfoPtr		scrn = crtc->scrn;
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
    DisplayModePtr	mode = &crtc->mode;
    int			x_temp;
    int			y_temp;
    Bool		in_range;

    /* 
     * Move to crtc coordinate space
     */
    x -= crtc->x;
    y -= crtc->y;
    
    /*
     * Rotate
     */
    switch ((crtc->rotation) & 0xf) {
    case RR_Rotate_0:
	break;
    case RR_Rotate_90:
	x_temp = y;
	y_temp = mode->VDisplay - cursor_info->MaxWidth - x;
	x = x_temp;
	y = y_temp;
	break;
    case RR_Rotate_180:
	x_temp = mode->HDisplay - cursor_info->MaxWidth - x;
	y_temp = mode->VDisplay - cursor_info->MaxHeight - y;
	x = x_temp;
	y = y_temp;
	break;
    case RR_Rotate_270:
	x_temp = mode->HDisplay - cursor_info->MaxHeight -  y;
	y_temp = x;
	x = x_temp;
	y = y_temp;
	break;
    }
    
    /*
     * Reflect
     */
    if (crtc->rotation & RR_Reflect_X)
	x = mode->HDisplay - cursor_info->MaxWidth - x;
    if (crtc->rotation & RR_Reflect_Y)
	y = mode->VDisplay - cursor_info->MaxHeight - y;

    /*
     * Disable the cursor when it is outside the viewport
     */
    in_range = TRUE;
    if (x >= mode->HDisplay || y >= mode->VDisplay ||
	x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) 
    {
	in_range = FALSE;
	x = 0;
	y = 0;
    }

    crtc->cursor_in_range = in_range;
    
    if (in_range)
    {
	crtc->funcs->set_cursor_position (crtc, x, y);
	xf86_crtc_show_cursor (crtc);
    }
    else
	xf86_crtc_hide_cursor (crtc);
}
Beispiel #3
0
static Bool
xf86_dga_get_modes (ScreenPtr pScreen)
{
    ScrnInfoPtr		scrn = xf86Screens[pScreen->myNum];
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    DGAModePtr		modes, mode;
    DisplayModePtr	display_mode;
    int			bpp = scrn->bitsPerPixel >> 3;
    int			num;

    num = 0;
    display_mode = scrn->modes;
    while (display_mode)
    {
        num++;
        display_mode = display_mode->next;
        if (display_mode == scrn->modes)
            break;
    }

    if (!num)
        return FALSE;

    modes = xalloc(num * sizeof(DGAModeRec));
    if (!modes)
        return FALSE;

    num = 0;
    display_mode = scrn->modes;
    while (display_mode)
    {
        mode = modes + num++;

        mode->mode = display_mode;
        mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
        mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
        if (display_mode->Flags & V_DBLSCAN)
            mode->flags |= DGA_DOUBLESCAN;
        if (display_mode->Flags & V_INTERLACE)
            mode->flags |= DGA_INTERLACED;
        mode->byteOrder = scrn->imageByteOrder;
        mode->depth = scrn->depth;
        mode->bitsPerPixel = scrn->bitsPerPixel;
        mode->red_mask = scrn->mask.red;
        mode->green_mask = scrn->mask.green;
        mode->blue_mask = scrn->mask.blue;
        mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
        mode->viewportWidth = display_mode->HDisplay;
        mode->viewportHeight = display_mode->VDisplay;
        mode->xViewportStep = (bpp == 3) ? 2 : 1;
        mode->yViewportStep = 1;
        mode->viewportFlags = DGA_FLIP_RETRACE;
        mode->offset = 0;
        mode->address = (unsigned char *) xf86_config->dga_address;
        mode->bytesPerScanline = xf86_config->dga_stride;
        mode->imageWidth = xf86_config->dga_width;
        mode->imageHeight = xf86_config->dga_height;
        mode->pixmapWidth = mode->imageWidth;
        mode->pixmapHeight = mode->imageHeight;
        mode->maxViewportX = mode->imageWidth -	mode->viewportWidth;
        mode->maxViewportY = mode->imageHeight - mode->viewportHeight;

        display_mode = display_mode->next;
        if (display_mode == scrn->modes)
            break;
    }
    if (xf86_config->dga_modes)
        xfree (xf86_config->dga_modes);
    xf86_config->dga_nmode = num;
    xf86_config->dga_modes = modes;
    return TRUE;
}
Beispiel #4
0
static Bool
xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
			CARD16		width,
			CARD16		height,
			CARD32		mmWidth,
			CARD32		mmHeight)
{
    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
    ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    WindowPtr		pRoot = WindowTable[pScreen->myNum];
    PixmapPtr		pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
    Bool		ret = FALSE;
    int                 c;

#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
    if (xf86RandR12Key) {
#endif
        if (randrp->virtualX == -1 || randrp->virtualY == -1)
        {
	    randrp->virtualX = pScrn->virtualX;
	    randrp->virtualY = pScrn->virtualY;
        }
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
    }
#endif
    if (pRoot && pScrn->vtSema)
	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);

    /* Let the driver update virtualX and virtualY */
    if (!(*config->funcs->resize)(pScrn, width, height))
	goto finish;

    ret = TRUE;
    /* Update panning information */
    for (c = 0; c < config->num_crtc; c++) {
	xf86CrtcPtr crtc = config->crtc[c];
	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 ||
	    crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
	    if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1)
		crtc->panningTotalArea.x2 += width  - pScreen->width;
	    if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1)
		crtc->panningTotalArea.y2 += height - pScreen->height;
	    if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1)
		crtc->panningTrackingArea.x2 += width  - pScreen->width;
	    if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1)
		crtc->panningTrackingArea.y2 += height - pScreen->height;
	    xf86RandR13VerifyPanningArea (crtc, width, height);
	    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
	}
    }

    pScreen->width = pScrnPix->drawable.width = width;
    pScreen->height = pScrnPix->drawable.height = height;
    randrp->mmWidth = pScreen->mmWidth = mmWidth;
    randrp->mmHeight = pScreen->mmHeight = mmHeight;

    xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
    xf86SetViewport (pScreen, 0, 0);

finish:
    if (pRoot && pScrn->vtSema)
	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
#if RANDR_12_INTERFACE
    if (xf86RandR12Key && WindowTable[pScreen->myNum] && ret)
	RRScreenSizeNotify (pScreen);
#endif
    return ret;
}
Beispiel #5
0
Bool
xf86RandR12CreateScreenResources (ScreenPtr pScreen)
{
    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
    xf86CrtcConfigPtr   config;
    XF86RandRInfoPtr	randrp;
    int			c;
    int			width, height;
    int			mmWidth, mmHeight;
#ifdef PANORAMIX
    /* XXX disable RandR when using Xinerama */
    if (!noPanoramiXExtension)
	return TRUE;
#endif

    config = XF86_CRTC_CONFIG_PTR(pScrn);
    randrp = XF86RANDRINFO(pScreen);
    /*
     * Compute size of screen
     */
    width = 0; height = 0;
    for (c = 0; c < config->num_crtc; c++)
    {
	xf86CrtcPtr crtc = config->crtc[c];
	int	    crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
	int	    crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
	
	if (crtc->enabled) {
	    if (crtc_width > width)
		width = crtc_width;
	    if (crtc_height > height)
		height = crtc_height;
	    if (crtc->panningTotalArea.x2 > width)
		width = crtc->panningTotalArea.x2;
	    if (crtc->panningTotalArea.y2 > height)
		height = crtc->panningTotalArea.y2;
	}
    }
    
    if (width && height)
    {
	/*
	 * Compute physical size of screen
	 */
	if (monitorResolution) 
	{
	    mmWidth = width * 25.4 / monitorResolution;
	    mmHeight = height * 25.4 / monitorResolution;
	}
	else
	{
	    xf86OutputPtr   output = config->output[config->compat_output];

	    if (output->conf_monitor &&
		(output->conf_monitor->mon_width  > 0 &&
		 output->conf_monitor->mon_height > 0))
	    {
		/*
		 * Prefer user configured DisplaySize
		 */
		mmWidth = output->conf_monitor->mon_width;
		mmHeight = output->conf_monitor->mon_height;
	    }
	    else
	    {
		/*
		 * Otherwise, just set the screen to DEFAULT_DPI
		 */
		mmWidth = width * 25.4 / DEFAULT_DPI;
		mmHeight = height * 25.4 / DEFAULT_DPI;
	    }
	}
	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
		   "Setting screen physical size to %d x %d\n",
		   mmWidth, mmHeight);
	/*
	 * This is the initial setting of the screen size.
	 * We have to pre-set it here, otherwise panning would be adapted
	 * to the new screen size.
	 */
	pScreen->width  = width;
	pScreen->height = height;
	xf86RandR12ScreenSetSize (pScreen,
				  width,
				  height,
				  mmWidth,
				  mmHeight);
    }

#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
    if (xf86RandR12Key == NULL)
	return TRUE;
#endif

    if (randrp->virtualX == -1 || randrp->virtualY == -1)
    {
	randrp->virtualX = pScrn->virtualX;
	randrp->virtualY = pScrn->virtualY;
    }
    xf86CrtcSetScreenSubpixelOrder (pScreen);
#if RANDR_12_INTERFACE
    if (xf86RandR12CreateScreenResources12 (pScreen))
	return TRUE;
#endif
    return TRUE;
}
static Bool
dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv,
			   xf86CrtcPtr ref_crtc)
{
	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
	NVPtr pNv = NVPTR(scrn);
	uint32_t next_fb;
	int emitted = 0;
	int ret, i;
	dri2_flipdata_ptr flipdata;
	dri2_flipevtcarrier_ptr flipcarrier;

	ret = drmModeAddFB(pNv->dev->fd, scrn->virtualX, scrn->virtualY,
			   scrn->depth, scrn->bitsPerPixel,
			   scrn->displayWidth * scrn->bitsPerPixel / 8,
			   nouveau_pixmap(back)->bo->handle, &next_fb);
	if (ret) {
		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
			   "add fb failed: %s\n", strerror(errno));
		return FALSE;
	}

	flipdata = calloc(1, sizeof(dri2_flipdata_rec));
	if (!flipdata) {
		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
		"flip queue: data alloc failed.\n");
		goto error_undo;
	}

	flipdata->event_data = priv;
	flipdata->fd = pNv->dev->fd;

	for (i = 0; i < config->num_crtc; i++) {
		int head = drmmode_crtc(config->crtc[i]);
		void *token;

		if (!drmmode_crtc_on(config->crtc[i]))
			continue;

		flipdata->flip_count++;

		flipcarrier = drmmode_event_queue(scrn, ++dri2_sequence,
						  sizeof(*flipcarrier),
						  nouveau_dri2_flip_handler,
						  &token);
		if (!flipcarrier) {
			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
				   "flip queue: carrier alloc failed.\n");
			if (emitted == 0)
				free(flipdata);
			goto error_undo;
		}

		/* Only the reference crtc will finally deliver its page flip
		 * completion event. All other crtc's events will be discarded.
		 */
		flipcarrier->dispatch_me = (config->crtc[i] == ref_crtc);
		flipcarrier->flipdata = flipdata;

		ret = drmModePageFlip(pNv->dev->fd, head, next_fb,
				      DRM_MODE_PAGE_FLIP_EVENT, token);
		if (ret) {
			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
				   "flip queue failed: %s\n", strerror(errno));
			drmmode_event_abort(scrn, dri2_sequence--, false);
			if (emitted == 0)
				free(flipdata);
			goto error_undo;
		}

		emitted++;
	}

	/* Will release old fb after all crtc's completed flip. */
	drmmode_swap(scrn, next_fb, &flipdata->old_fb_id);
	return TRUE;

error_undo:
	drmModeRmFB(pNv->dev->fd, next_fb);
	return FALSE;
}
Beispiel #7
0
/*
 * Mirror the current mode configuration to RandR
 */
static Bool
xf86RandR12SetInfo12 (ScreenPtr pScreen)
{
    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
    RROutputPtr		*clones;
    RRCrtcPtr		*crtcs;
    int			ncrtc;
    int			o, c, l;
    RRCrtcPtr		randr_crtc;
    int			nclone;
    
    clones = xalloc(config->num_output * sizeof (RROutputPtr));
    crtcs = xalloc (config->num_crtc * sizeof (RRCrtcPtr));
    for (o = 0; o < config->num_output; o++)
    {
	xf86OutputPtr	output = config->output[o];
	
	ncrtc = 0;
	for (c = 0; c < config->num_crtc; c++)
	    if (output->possible_crtcs & (1 << c))
		crtcs[ncrtc++] = config->crtc[c]->randr_crtc;

	if (output->crtc)
	    randr_crtc = output->crtc->randr_crtc;
	else
	    randr_crtc = NULL;

	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
	{
	    xfree (crtcs);
	    xfree (clones);
	    return FALSE;
	}

	RROutputSetPhysicalSize(output->randr_output, 
				output->mm_width,
				output->mm_height);
	xf86RROutputSetModes (output->randr_output, output->probed_modes);

	switch (output->status) {
	case XF86OutputStatusConnected:
	    RROutputSetConnection (output->randr_output, RR_Connected);
	    break;
	case XF86OutputStatusDisconnected:
	    RROutputSetConnection (output->randr_output, RR_Disconnected);
	    break;
	case XF86OutputStatusUnknown:
	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
	    break;
	}

	RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);

	/*
	 * Valid clones
	 */
	nclone = 0;
	for (l = 0; l < config->num_output; l++)
	{
	    xf86OutputPtr	    clone = config->output[l];
	    
	    if (l != o && (output->possible_clones & (1 << l)))
		clones[nclone++] = clone->randr_output;
	}
	if (!RROutputSetClones (output->randr_output, clones, nclone))
	{
	    xfree (crtcs);
	    xfree (clones);
	    return FALSE;
	}
    }
    xfree (crtcs);
    xfree (clones);
    return TRUE;
}
Beispiel #8
0
static int
sna_video_overlay_set_attribute(ClientPtr client,
				XvPortPtr port,
				Atom attribute,
				INT32 value)
{
	struct sna_video *video = port->devPriv.ptr;
	struct sna *sna = video->sna;

	DBG(("%s: set(%lx) to %d\n", __FUNCTION__, (long)attribute, (int)value));
	if (attribute == xvBrightness) {
		if ((value < -128) || (value > 127))
			return BadValue;
		DBG(("%s: BRIGHTNESS %d -> %d\n", __FUNCTION__,
		     video->contrast, (int)value));
		video->brightness = value;
	} else if (attribute == xvContrast) {
		if ((value < 0) || (value > 255))
			return BadValue;
		DBG(("%s: CONTRAST %d -> %d\n", __FUNCTION__,
		     video->contrast, (int)value));
		video->contrast = value;
	} else if (attribute == xvSaturation) {
		if ((value < 0) || (value > 1023))
			return BadValue;
		DBG(("%s: SATURATION %d -> %d\n", __FUNCTION__,
		     video->saturation, (int)value));
		video->saturation = value;
	} else if (attribute == xvPipe) {
		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn);
		if ((value < -1) || (value >= xf86_config->num_crtc))
			return BadValue;
		if (value < 0)
			video->desired_crtc = NULL;
		else
			video->desired_crtc = xf86_config->crtc[value];
	} else if (attribute == xvAlwaysOnTop) {
		DBG(("%s: ALWAYS_ON_TOP: %d -> %d\n", __FUNCTION__,
		     video->AlwaysOnTop, !!value));
		video->AlwaysOnTop = !!value;
	} else if (attribute == xvGamma0 && HAS_GAMMA(sna)) {
		video->gamma0 = value;
	} else if (attribute == xvGamma1 && HAS_GAMMA(sna)) {
		video->gamma1 = value;
	} else if (attribute == xvGamma2 && HAS_GAMMA(sna)) {
		video->gamma2 = value;
	} else if (attribute == xvGamma3 && HAS_GAMMA(sna)) {
		video->gamma3 = value;
	} else if (attribute == xvGamma4 && HAS_GAMMA(sna)) {
		video->gamma4 = value;
	} else if (attribute == xvGamma5 && HAS_GAMMA(sna)) {
		video->gamma5 = value;
	} else if (attribute == xvColorKey) {
		video->color_key = value;
		DBG(("COLORKEY\n"));
	} else
		return BadMatch;

	if ((attribute == xvGamma0 ||
	     attribute == xvGamma1 ||
	     attribute == xvGamma2 ||
	     attribute == xvGamma3 ||
	     attribute == xvGamma4 ||
	     attribute == xvGamma5) && HAS_GAMMA(sna)) {
		DBG(("%s: GAMMA\n", __FUNCTION__));
	}

	if (!sna_video_overlay_update_attrs(video))
		return BadValue;

	if (attribute == xvColorKey)
		RegionEmpty(&video->clip);

	return Success;
}
static Bool
crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
		    Rotation rotation, int x, int y)
{
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    ScreenPtr pScreen = crtc->scrn->pScreen;
    xf86OutputPtr output = NULL;
    struct crtc_private *crtcp = crtc->driver_private;
    drmModeCrtcPtr drm_crtc = crtcp->drm_crtc;
    drmModeModeInfo drm_mode;
    int i, ret;
    unsigned int connector_id;
    PixmapPtr pixmap;

    for (i = 0; i < config->num_output; output = NULL, i++) {
	output = config->output[i];

	if (output->crtc == crtc)
	    break;
    }

    if (!output) {
	LogMessage(X_ERROR, "No output for this crtc.\n");
	return FALSE;
    }

    connector_id = xorg_output_get_id(output);

    drm_mode.clock = mode->Clock;
    drm_mode.hdisplay = mode->HDisplay;
    drm_mode.hsync_start = mode->HSyncStart;
    drm_mode.hsync_end = mode->HSyncEnd;
    drm_mode.htotal = mode->HTotal;
    drm_mode.vdisplay = mode->VDisplay;
    drm_mode.vsync_start = mode->VSyncStart;
    drm_mode.vsync_end = mode->VSyncEnd;
    drm_mode.vtotal = mode->VTotal;
    drm_mode.flags = mode->Flags;
    drm_mode.hskew = mode->HSkew;
    drm_mode.vscan = mode->VScan;
    drm_mode.vrefresh = mode->VRefresh;
    if (!mode->name)
	xf86SetModeDefaultName(mode);
    strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1);
    drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0';

    /*
     * Check if we need to scanout from something else than the root
     * pixmap. In that case, xf86CrtcRotate will take care of allocating
     * new opaque scanout buffer data "crtc->rotatedData".
     * However, it will not wrap
     * that data into pixmaps until the first rotated damage composite.
     * In out case, the buffer data is actually already a pixmap.
     */

    if (!xf86CrtcRotate(crtc))
	return FALSE;

    if (crtc->transform_in_use && crtc->rotatedData) {
	x = 0;
	y = 0;
	pixmap = (PixmapPtr) crtc->rotatedData;
    } else
	pixmap = pScreen->GetScreenPixmap(pScreen);

    if (crtcp->entry.pixmap != pixmap) {
	if (crtcp->entry.pixmap)
	    vmwgfx_scanout_unref(&crtcp->entry);

	crtcp->entry.pixmap = pixmap;
	crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->entry);
	if (crtcp->scanout_id == -1) {
	    LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n");
	    return FALSE;
	}
    }
    ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, crtcp->scanout_id, x, y,
			 &connector_id, 1, &drm_mode);
    if (ret)
	return FALSE;

    vmwgfx_scanout_refresh(pixmap);

    /* Only set gamma when needed, to avoid unneeded delays. */
#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
    if (!crtc->active && crtc->version >= 3)
	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
			       crtc->gamma_blue, crtc->gamma_size);
    crtc->active = TRUE;
#endif

    return TRUE;
}
Beispiel #10
0
Bool
xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
{
    ScrnInfoPtr		pScrn = crtc->scrn;
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    ScreenPtr		pScreen = pScrn->pScreen;
    
    if (rotation == RR_Rotate_0)
    {
	/* Free memory from rotation */
	if (crtc->rotatedPixmap || crtc->rotatedData)
	{
	    crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData);
	    crtc->rotatedPixmap = NULL;
	    crtc->rotatedData = NULL;
	}

	if (xf86_config->rotation_damage)
	{
	    /* Free damage structure */
	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
			      xf86_config->rotation_damage);
	    xf86_config->rotation_damage_registered = FALSE;
	    DamageDestroy (xf86_config->rotation_damage);
	    xf86_config->rotation_damage = NULL;
	    /* Free block/wakeup handler */
	    RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
					  xf86RotateWakeupHandler,
					  (pointer) pScreen);
	}
    }
    else
    {
	/* 
	 * these are the size of the shadow pixmap, which
	 * matches the mode, not the pre-rotated copy in the
	 * frame buffer
	 */
	int	    width = mode->HDisplay;
	int	    height = mode->VDisplay;
	void	    *shadowData = crtc->rotatedData;
	PixmapPtr   shadow = crtc->rotatedPixmap;
	int	    old_width = shadow ? shadow->drawable.width : 0;
	int	    old_height = shadow ? shadow->drawable.height : 0;
	
	/* Allocate memory for rotation */
	if (old_width != width || old_height != height)
	{
	    if (shadow || shadowData)
	    {
		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
		crtc->rotatedPixmap = NULL;
		crtc->rotatedData = NULL;
	    }
	    shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
	    if (!shadowData)
		goto bail1;
	    crtc->rotatedData = shadowData;
	    /* shadow will be damaged in xf86RotatePrepare */
	}
	else
	{
	    /* mark shadowed area as damaged so it will be repainted */
	    xf86CrtcDamageShadow (crtc);
	}
	
	if (!xf86_config->rotation_damage)
	{
	    /* Create damage structure */
	    xf86_config->rotation_damage = DamageCreate (NULL, NULL,
						DamageReportNone,
						TRUE, pScreen, pScreen);
	    if (!xf86_config->rotation_damage)
		goto bail2;
	    
	    /* Assign block/wakeup handler */
	    if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler,
						 xf86RotateWakeupHandler,
						 (pointer) pScreen))
	    {
		goto bail3;
	    }
	}
	if (0)
	{
bail3:
	    DamageDestroy (xf86_config->rotation_damage);
	    xf86_config->rotation_damage = NULL;
	    
bail2:
	    if (shadow || shadowData)
	    {
		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
		crtc->rotatedPixmap = NULL;
		crtc->rotatedData = NULL;
	    }
bail1:
	    if (old_width && old_height)
		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
								  NULL,
								  old_width,
								  old_height);
	    return FALSE;
	}
    }
    
    /* All done */
    return TRUE;
}
static Bool
SMI_CrtcConfigResize(ScrnInfoPtr       pScrn,
		     int               width,
		     int               height)
{
    SMIPtr pSmi = SMIPTR(pScrn);
    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
    int i;
    xf86CrtcPtr crtc;

    ENTER();

    /* Allocate another offscreen area and use it as screen, if it really has to be resized */
    if(!pSmi->NoAccel && pSmi->useEXA &&
       ( !pSmi->fbArea || width != pScrn->virtualX || height != pScrn->virtualY )){
	int aligned_pitch = (width*pSmi->Bpp + 15) & ~15;

	ExaOffscreenArea* fbArea = exaOffscreenAlloc(pScrn->pScreen, aligned_pitch*height, 16, TRUE, NULL, NULL);
	if(!fbArea){
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		   "SMI_CrtcConfigResize: Not enough memory to resize the framebuffer\n");
	    LEAVE(FALSE);
	}

	if(pSmi->fbArea)
	    exaOffscreenFree(pScrn->pScreen, pSmi->fbArea);

	pSmi->fbArea = fbArea;
	pSmi->FBOffset = fbArea->offset;
	pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;

	pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
					   -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);

#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0))
	if(pScrn->pixmapPrivate.ptr)
	    /* The pixmap devPrivate just set may be overwritten by
	       xf86EnableDisableFBAccess */
	    pScrn->pixmapPrivate.ptr = pSmi->FBBase + pSmi->FBOffset;
#endif

	/* Modify the screen pitch */
	pScrn->displayWidth = aligned_pitch / pSmi->Bpp;
	pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
					   -1, -1, -1, -1, aligned_pitch, NULL);

	/* Modify the screen dimensions */
	pScrn->virtualX = width;
	pScrn->virtualY = height;
	pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
					   width, height, -1, -1, 0, NULL);
    }

    /* Setup each crtc video processor */
    for(i=0;i<crtcConf->num_crtc;i++){
	crtc = crtcConf->crtc[i];
	SMICRTC(crtc)->video_init(crtc);
	SMICRTC(crtc)->adjust_frame(crtc,crtc->x,crtc->y);
    }

    LEAVE(TRUE);
}
static void
xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
{
    ScrnInfoPtr		scrn = crtc->scrn;
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
    DisplayModePtr	mode = &crtc->mode;
    Bool		in_range;
    int			dx, dy;

    /*
     * Transform position of cursor on screen
     */
    if (crtc->transform_in_use)
    {
	ScreenPtr	screen = scrn->pScreen;
	xf86CursorScreenPtr ScreenPriv =
	    (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
						  xf86CursorScreenKey);
	struct pict_f_vector   v;

	v.v[0] = (x + ScreenPriv->HotX) + 0.5;
	v.v[1] = (y + ScreenPriv->HotY) + 0.5;
	v.v[2] = 1;
	pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
	/* cursor will have 0.5 added to it already so floor is sufficent */
	x = floor (v.v[0]);
	y = floor (v.v[1]);
	/*
	 * Transform position of cursor upper left corner
	 */
	xf86_crtc_rotate_coord_back (crtc->rotation,
				     cursor_info->MaxWidth,
				     cursor_info->MaxHeight,
				     ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
	x -= dx;
	y -= dy;
   }
    else
    {
	x -= crtc->x;
	y -= crtc->y;
    }

    /*
     * Disable the cursor when it is outside the viewport
     */
    in_range = TRUE;
    if (x >= mode->HDisplay || y >= mode->VDisplay ||
	x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) 
    {
	in_range = FALSE;
	x = 0;
	y = 0;
    }

    crtc->cursor_in_range = in_range;
    
    if (in_range)
    {
	crtc->funcs->set_cursor_position (crtc, x, y);
	xf86_crtc_show_cursor (crtc);
    }
    else
	xf86_crtc_hide_cursor (crtc);
}
static Bool
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
		       Rotation rotation, int x, int y)
{
	ScrnInfoPtr scrn = crtc->scrn;
	intel_screen_private *intel = intel_get_screen_private(scrn);
	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
	drmmode_ptr drmmode = drmmode_crtc->drmmode;
	int saved_x, saved_y;
	Rotation saved_rotation;
	DisplayModeRec saved_mode;
	uint32_t *output_ids;
	int output_count = 0;
	int ret = TRUE;
	int i;
	int fb_id;
	drmModeModeInfo kmode;
	unsigned int pitch = scrn->displayWidth * intel->cpp;

	if (drmmode->fb_id == 0) {
		ret = drmModeAddFB(drmmode->fd,
				   scrn->virtualX, scrn->virtualY,
				   scrn->depth, scrn->bitsPerPixel,
				   pitch, intel->front_buffer->handle,
				   &drmmode->fb_id);
		if (ret < 0) {
			ErrorF("failed to add fb\n");
			return FALSE;
		}
	}

	saved_mode = crtc->mode;
	saved_x = crtc->x;
	saved_y = crtc->y;
	saved_rotation = crtc->rotation;

	crtc->mode = *mode;
	crtc->x = x;
	crtc->y = y;
	crtc->rotation = rotation;

	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
	if (!output_ids) {
		ret = FALSE;
		goto done;
	}

	for (i = 0; i < xf86_config->num_output; i++) {
		xf86OutputPtr output = xf86_config->output[i];
		drmmode_output_private_ptr drmmode_output;

		if (output->crtc != crtc)
			continue;

		drmmode_output = output->driver_private;
		output_ids[output_count] =
			drmmode_output->mode_output->connector_id;
		output_count++;
	}

#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
	if (!xf86CrtcRotate(crtc, mode, rotation))
		goto done;
#else
	if (!xf86CrtcRotate(crtc))
		goto done;
#endif

#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
			       crtc->gamma_blue, crtc->gamma_size);
#endif

	drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);


	fb_id = drmmode->fb_id;
	if (drmmode_crtc->rotate_fb_id) {
		fb_id = drmmode_crtc->rotate_fb_id;
		x = 0;
		y = 0;
	}
	ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
			     fb_id, x, y, output_ids, output_count, &kmode);
	if (ret)
		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
			   "failed to set mode: %s", strerror(-ret));
	else
		ret = TRUE;

	/* Turn on any outputs on this crtc that may have been disabled */
	for (i = 0; i < xf86_config->num_output; i++) {
		xf86OutputPtr output = xf86_config->output[i];

		if (output->crtc != crtc)
			continue;

		drmmode_output_dpms(output, DPMSModeOn);
	}

	intel_set_gem_max_sizes(scrn);

	if (scrn->pScreen)
		xf86_reload_cursors(scrn->pScreen);
done:
	if (!ret) {
		crtc->x = saved_x;
		crtc->y = saved_y;
		crtc->rotation = saved_rotation;
		crtc->mode = saved_mode;
	}
	return ret;
}
static Bool
drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
{
	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
	drmmode_crtc_private_ptr
		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
	drmmode_ptr drmmode = drmmode_crtc->drmmode;
	intel_screen_private *intel = intel_get_screen_private(scrn);
	drm_intel_bo *old_front = NULL;
	Bool	    ret;
	uint32_t    old_fb_id;
	int	    i, old_width, old_height, old_pitch;
	unsigned long pitch;
	uint32_t tiling;

	if (scrn->virtualX == width && scrn->virtualY == height)
		return TRUE;

	old_width = scrn->virtualX;
	old_height = scrn->virtualY;
	old_pitch = scrn->displayWidth;
	old_fb_id = drmmode->fb_id;
	old_front = intel->front_buffer;

	intel->front_buffer = intel_allocate_framebuffer(scrn,
							 width, height,
							 intel->cpp,
							 &pitch,
							 &tiling);
	if (!intel->front_buffer)
		goto fail;

	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
			   scrn->bitsPerPixel, pitch,
			   intel->front_buffer->handle,
			   &drmmode->fb_id);
	if (ret)
		goto fail;

	intel->front_pitch = pitch;
	intel->front_tiling = tiling;

	scrn->virtualX = width;
	scrn->virtualY = height;

	for (i = 0; i < xf86_config->num_crtc; i++) {
		xf86CrtcPtr crtc = xf86_config->crtc[i];

		if (!crtc->enabled)
			continue;

		drmmode_set_mode_major(crtc, &crtc->mode,
				       crtc->rotation, crtc->x, crtc->y);
	}

	intel_uxa_create_screen_resources(scrn->pScreen);

	if (old_fb_id)
		drmModeRmFB(drmmode->fd, old_fb_id);
	if (old_front)
		drm_intel_bo_unreference(old_front);

	return TRUE;

 fail:
	if (intel->front_buffer)
		drm_intel_bo_unreference(intel->front_buffer);
	intel->front_buffer = old_front;
	scrn->virtualX = old_width;
	scrn->virtualY = old_height;
	scrn->displayWidth = old_pitch;
	drmmode->fb_id = old_fb_id;

	return FALSE;
}
_X_EXPORT Bool
xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
{
    ScrnInfoPtr		pScrn = crtc->scrn;
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    ScreenPtr		pScreen = pScrn->pScreen;
    PictTransform	crtc_to_fb, fb_to_crtc;
    
    PictureTransformIdentity (&crtc_to_fb);
    PictureTransformIdentity (&fb_to_crtc);
    PictureTransformIsInverse ("identity", &crtc_to_fb, &fb_to_crtc);
    if (rotation != RR_Rotate_0)
    {
	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
	xFixed	scale_x, scale_y, scale_dx, scale_dy;
	int	mode_w = crtc->mode.HDisplay;
	int	mode_h = crtc->mode.VDisplay;
	
	/* rotation */
	switch (rotation & 0xf) {
	default:
	case RR_Rotate_0:
	    rot_cos = F ( 1);	    rot_sin = F ( 0);
	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
	    break;
	case RR_Rotate_90:
	    rot_cos = F ( 0);	    rot_sin = F ( 1);
	    rot_dx =  F ( mode_h);  rot_dy  = F (0);
	    break;
	case RR_Rotate_180:
	    rot_cos = F (-1);	    rot_sin = F ( 0);
	    rot_dx  = F (mode_w);   rot_dy  = F ( mode_h);
	    break;
	case RR_Rotate_270:
	    rot_cos = F ( 0);	    rot_sin = F (-1);
	    rot_dx  = F ( 0);	    rot_dy  = F ( mode_w);
	    break;
	}
	
	PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin);
	PictureTransformIsInverse ("rotate", &crtc_to_fb, &fb_to_crtc);

	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy);
	PictureTransformIsInverse ("rotate translate", &crtc_to_fb, &fb_to_crtc);

	/* reflection */
	scale_x = F (1);
	scale_dx = 0;
	scale_y = F (1);
	scale_dy = 0;
	if (rotation & RR_Reflect_X)
	{
	    scale_x = F(-1);
	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
		scale_dx = F(mode_w);
	    else
		scale_dx = F(mode_h);
	}
	if (rotation & RR_Reflect_Y)
	{
	    scale_y = F(-1);
	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
		scale_dy = F(mode_h);
	    else
		scale_dy = F(mode_w);
	}
	
	PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y);
	PictureTransformIsInverse ("scale", &crtc_to_fb, &fb_to_crtc);

	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy);
	PictureTransformIsInverse ("scale translate", &crtc_to_fb, &fb_to_crtc);

    }
    
    /*
     * If the untranslated transformation is the identity,
     * disable the shadow buffer
     */
    if (PictureTransformIsIdentity (&crtc_to_fb))
    {
	crtc->transform_in_use = FALSE;
	PictureTransformInitTranslate (&crtc->crtc_to_framebuffer, 
				       F (-crtc->x), F (-crtc->y));
	PictureTransformInitTranslate (&crtc->framebuffer_to_crtc,
				       F ( crtc->x), F ( crtc->y));
	xf86RotateDestroy (crtc);
    }
    else
    {
	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, F(crtc->x), F(crtc->y));
	PictureTransformIsInverse ("offset", &crtc_to_fb, &fb_to_crtc);

	/* 
	 * these are the size of the shadow pixmap, which
	 * matches the mode, not the pre-rotated copy in the
	 * frame buffer
	 */
	int	    width = mode->HDisplay;
	int	    height = mode->VDisplay;
	void	    *shadowData = crtc->rotatedData;
	PixmapPtr   shadow = crtc->rotatedPixmap;
	int	    old_width = shadow ? shadow->drawable.width : 0;
	int	    old_height = shadow ? shadow->drawable.height : 0;
	
	/* Allocate memory for rotation */
	if (old_width != width || old_height != height)
	{
	    if (shadow || shadowData)
	    {
		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
		crtc->rotatedPixmap = NULL;
		crtc->rotatedData = NULL;
	    }
	    shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
	    if (!shadowData)
		goto bail1;
	    crtc->rotatedData = shadowData;
	    /* shadow will be damaged in xf86RotatePrepare */
	}
	else
	{
	    /* mark shadowed area as damaged so it will be repainted */
	    xf86CrtcDamageShadow (crtc);
	}
	
	if (!xf86_config->rotation_damage)
	{
	    /* Create damage structure */
	    xf86_config->rotation_damage = DamageCreate (NULL, NULL,
						DamageReportNone,
						TRUE, pScreen, pScreen);
	    if (!xf86_config->rotation_damage)
		goto bail2;
	    
	    /* Wrap block handler */
	    xf86_config->BlockHandler = pScreen->BlockHandler;
	    pScreen->BlockHandler = xf86RotateBlockHandler;
	}
	if (0)
	{
    bail2:
	    if (shadow || shadowData)
	    {
		crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
		crtc->rotatedPixmap = NULL;
		crtc->rotatedData = NULL;
	    }
    bail1:
	    if (old_width && old_height)
		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
								  NULL,
								  old_width,
								  old_height);
	    return FALSE;
	}
	crtc->transform_in_use = TRUE;
	crtc->crtc_to_framebuffer = crtc_to_fb;
	crtc->framebuffer_to_crtc = fb_to_crtc;
	crtc->bounds.x1 = 0;
	crtc->bounds.x2 = crtc->mode.HDisplay;
	crtc->bounds.y1 = 0;
	crtc->bounds.y2 = crtc->mode.VDisplay;
	PictureTransformBounds (&crtc->bounds, &crtc_to_fb);
    }
    
    /* All done */
    return TRUE;
}
Beispiel #16
0
static Bool
xf86RandR12CrtcSet (ScreenPtr	    pScreen,
		    RRCrtcPtr	    randr_crtc,
		    RRModePtr	    randr_mode,
		    int		    x,
		    int		    y,
		    Rotation	    rotation,
		    int		    num_randr_outputs,
		    RROutputPtr	    *randr_outputs)
{
    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
    RRTransformPtr	transform;
    Bool		changed = FALSE;
    int			o, ro;
    xf86CrtcPtr		*save_crtcs;
    Bool		save_enabled = crtc->enabled;

    if (!crtc->scrn->vtSema)
	return FALSE;

    save_crtcs = xalloc(config->num_output * sizeof (xf86CrtcPtr));
    if ((randr_mode != NULL) != crtc->enabled)
	changed = TRUE;
    else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
	changed = TRUE;
    
    if (rotation != crtc->rotation)
	changed = TRUE;

    transform = RRCrtcGetTransform (randr_crtc);
    if ((transform != NULL) != crtc->transformPresent)
	changed = TRUE;
    else if (transform && memcmp (&transform->transform, &crtc->transform.transform,
				  sizeof (transform->transform)) != 0)
	changed = TRUE;

    if (x != crtc->x || y != crtc->y)
	changed = TRUE;
    for (o = 0; o < config->num_output; o++) 
    {
	xf86OutputPtr  output = config->output[o];
	xf86CrtcPtr    new_crtc;

	save_crtcs[o] = output->crtc;
	
	if (output->crtc == crtc)
	    new_crtc = NULL;
	else
	    new_crtc = output->crtc;
	for (ro = 0; ro < num_randr_outputs; ro++) 
	    if (output->randr_output == randr_outputs[ro])
	    {
		new_crtc = crtc;
		break;
	    }
	if (new_crtc != output->crtc)
	{
	    changed = TRUE;
	    output->crtc = new_crtc;
	}
    }
    for (ro = 0; ro < num_randr_outputs; ro++) 
        if (randr_outputs[ro]->pendingProperties)
	    changed = TRUE;

    /* XXX need device-independent mode setting code through an API */
    if (changed)
    {
	crtc->enabled = randr_mode != NULL;

	if (randr_mode)
	{
	    DisplayModeRec  mode;
	    RRTransformPtr  transform = RRCrtcGetTransform (randr_crtc);

	    xf86RandRModeConvert (pScrn, randr_mode, &mode);
	    if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y))
	    {
		crtc->enabled = save_enabled;
		for (o = 0; o < config->num_output; o++)
		{
		    xf86OutputPtr	output = config->output[o];
		    output->crtc = save_crtcs[o];
		}
		xfree(save_crtcs);
		return FALSE;
	    }
	    xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height);
	    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
	    /*
	     * Save the last successful setting for EnterVT
	     */
	    crtc->desiredMode = mode;
	    crtc->desiredRotation = rotation;
	    if (transform) {
		crtc->desiredTransform = *transform;
		crtc->desiredTransformPresent = TRUE;
	    } else
		crtc->desiredTransformPresent = FALSE;

	    crtc->desiredX = x;
	    crtc->desiredY = y;
	}
	xf86DisableUnusedFunctions (pScrn);
    }
    xfree(save_crtcs);
    return xf86RandR12CrtcNotify (randr_crtc);
}
Beispiel #17
0
Bool
xf86CrtcRotate(xf86CrtcPtr crtc)
{
    ScrnInfoPtr pScrn = crtc->scrn;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    PictTransform crtc_to_fb;
    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
    xFixed *new_params = NULL;
    int new_nparams = 0;
    PictFilterPtr new_filter = NULL;
    int new_width = 0;
    int new_height = 0;
    RRTransformPtr transform = NULL;
    Bool damage = FALSE;

    if (crtc->transformPresent)
        transform = &crtc->transform;

    if (!RRTransformCompute(crtc->x, crtc->y,
                            crtc->mode.HDisplay, crtc->mode.VDisplay,
                            crtc->rotation,
                            transform,
                            &crtc_to_fb,
                            &f_crtc_to_fb,
                            &f_fb_to_crtc) &&
        xf86CrtcFitsScreen(crtc, &f_crtc_to_fb)) {
        /*
         * If the untranslated transformation is the identity,
         * disable the shadow buffer
         */
        xf86RotateDestroy(crtc);
        crtc->transform_in_use = FALSE;
        free(new_params);
        new_params = NULL;
        new_nparams = 0;
        new_filter = NULL;
        new_width = 0;
        new_height = 0;
    }
    else {
        if (crtc->driverIsPerformingTransform) {
            xf86RotateDestroy(crtc);
        }
        else {
            /*
             * these are the size of the shadow pixmap, which
             * matches the mode, not the pre-rotated copy in the
             * frame buffer
             */
            int width = crtc->mode.HDisplay;
            int height = crtc->mode.VDisplay;
            void *shadowData = crtc->rotatedData;
            PixmapPtr shadow = crtc->rotatedPixmap;
            int old_width = shadow ? shadow->drawable.width : 0;
            int old_height = shadow ? shadow->drawable.height : 0;

            /* Allocate memory for rotation */
            if (old_width != width || old_height != height) {
                if (shadow || shadowData) {
                    crtc->funcs->shadow_destroy(crtc, shadow, shadowData);
                    crtc->rotatedPixmap = NULL;
                    crtc->rotatedData = NULL;
                }
                shadowData = crtc->funcs->shadow_allocate(crtc, width, height);
                if (!shadowData)
                    goto bail1;
                crtc->rotatedData = shadowData;
                /* shadow will be damaged in xf86RotatePrepare */
            }
            else {
                /* mark shadowed area as damaged so it will be repainted */
                damage = TRUE;
            }

            if (!xf86_config->rotation_damage) {
                /* Create damage structure */
                xf86_config->rotation_damage = DamageCreate(NULL, NULL,
                                                            DamageReportNone,
                                                            TRUE, pScreen,
                                                            pScreen);
                if (!xf86_config->rotation_damage)
                    goto bail2;

                /* Wrap block handler */
                if (!xf86_config->BlockHandler) {
                    xf86_config->BlockHandler = pScreen->BlockHandler;
                    pScreen->BlockHandler = xf86RotateBlockHandler;
                }
            }

            if (0) {
 bail2:
                if (shadow || shadowData) {
                    crtc->funcs->shadow_destroy(crtc, shadow, shadowData);
                    crtc->rotatedPixmap = NULL;
                    crtc->rotatedData = NULL;
                }
 bail1:
                if (old_width && old_height)
                    crtc->rotatedPixmap =
                        crtc->funcs->shadow_create(crtc, NULL, old_width,
                                                   old_height);
                return FALSE;
            }
        }
#ifdef RANDR_12_INTERFACE
        if (transform) {
            if (transform->nparams) {
                new_params = malloc(transform->nparams * sizeof(xFixed));
                if (new_params) {
                    memcpy(new_params, transform->params,
                           transform->nparams * sizeof(xFixed));
                    new_nparams = transform->nparams;
                    new_filter = transform->filter;
                }
            }
            else
                new_filter = transform->filter;
            if (new_filter) {
                new_width = new_filter->width;
                new_height = new_filter->height;
            }
        }
#endif
        crtc->transform_in_use = TRUE;
    }
    crtc->crtc_to_framebuffer = crtc_to_fb;
    crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
    crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
    free(crtc->params);
    crtc->params = new_params;
    crtc->nparams = new_nparams;
    crtc->filter = new_filter;
    crtc->filter_width = new_width;
    crtc->filter_height = new_height;
    crtc->bounds.x1 = 0;
    crtc->bounds.x2 = crtc->mode.HDisplay;
    crtc->bounds.y1 = 0;
    crtc->bounds.y2 = crtc->mode.VDisplay;
    pixman_f_transform_bounds(&f_crtc_to_fb, &crtc->bounds);

    if (damage)
        xf86CrtcDamageShadow(crtc);

    /* All done */
    return TRUE;
}
xf86CrtcPtr
radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
		      int x1, int x2, int y1, int y2)
{
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    int			coverage, best_coverage, c;
    BoxRec		box, crtc_box, cover_box;
    RROutputPtr         primary_output = NULL;
    xf86CrtcPtr         best_crtc = NULL, primary_crtc = NULL;

    if (!pScrn->vtSema)
	return NULL;

    box.x1 = x1;
    box.x2 = x2;
    box.y1 = y1;
    box.y2 = y2;
    best_coverage = 0;

    /* Prefer the CRTC of the primary output */
#ifdef HAS_DIXREGISTERPRIVATEKEY
    if (dixPrivateKeyRegistered(rrPrivKey))
#endif
    {
	primary_output = RRFirstOutput(pScrn->pScreen);
    }
    if (primary_output && primary_output->crtc)
	primary_crtc = primary_output->crtc->devPrivate;

    /* first consider only enabled CRTCs */
    for (c = 0; c < xf86_config->num_crtc; c++) {
	xf86CrtcPtr crtc = xf86_config->crtc[c];

	if (!radeon_crtc_is_enabled(crtc))
	    continue;

	radeon_crtc_box(crtc, &crtc_box);
	radeon_box_intersect(&cover_box, &crtc_box, &box);
	coverage = radeon_box_area(&cover_box);
	if (coverage > best_coverage ||
	    (coverage == best_coverage && crtc == primary_crtc)) {
	    best_crtc = crtc;
	    best_coverage = coverage;
	}
    }
    if (best_crtc || !consider_disabled)
	return best_crtc;

    /* if we found nothing, repeat the search including disabled CRTCs */
    for (c = 0; c < xf86_config->num_crtc; c++) {
	xf86CrtcPtr crtc = xf86_config->crtc[c];

	radeon_crtc_box(crtc, &crtc_box);
	radeon_box_intersect(&cover_box, &crtc_box, &box);
	coverage = radeon_box_area(&cover_box);
	if (coverage > best_coverage ||
	    (coverage == best_coverage && crtc == primary_crtc)) {
	    best_crtc = crtc;
	    best_coverage = coverage;
	}
    }
    return best_crtc;
}