xfree86/modes: Let the driver handle the transform

If a driver can use hardware to handle the crtc transform, then
there's no need for the server's shadow layer to do it.  Add a crtc
flag that lets the driver indicate that it is handling the transform.
If it's set, consider the transformed size of the screen but don't
actually enable the shadow layer.  Also stop adjusting the cursor
image and position.

Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
This commit is contained in:
Aaron Plattner 2011-08-25 10:19:48 -07:00 committed by Keith Packard
parent e089737fb1
commit 245cb8e94f
3 changed files with 106 additions and 70 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright © 2006 Keith Packard
* Copyright © 2011 Aaron Plattner
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -223,7 +224,7 @@ typedef struct _xf86CrtcFuncs {
} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
#define XF86_CRTC_VERSION 3
#define XF86_CRTC_VERSION 4
struct _xf86Crtc {
/**
@ -361,6 +362,19 @@ struct _xf86Crtc {
* Clear the shadow
*/
Bool shadowClear;
/**
* Indicates that the driver is handling the transform, so the shadow
* surface should be disabled. The driver writes this field before calling
* xf86CrtcRotate to indicate that it is handling the transform (including
* rotation and reflection).
*
* Setting this flag also causes the server to stop adjusting the cursor
* image and position.
*
* Added in ABI version 4
*/
Bool driverIsPerformingTransform;
};
typedef struct _xf86OutputFuncs {

View File

@ -1,6 +1,6 @@
/*
* Copyright © 2007 Keith Packard
* Copyright © 2010 Aaron Plattner
* Copyright © 2010-2011 Aaron Plattner
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -46,6 +46,18 @@
#include "cursorstr.h"
#include "inputstr.h"
/*
* Returns the rotation being performed by the server. If the driver indicates
* that it's handling the screen transform, then this returns RR_Rotate_0.
*/
static Rotation
xf86_crtc_cursor_rotation (xf86CrtcPtr crtc)
{
if (crtc->driverIsPerformingTransform)
return RR_Rotate_0;
return crtc->rotation;
}
/*
* Given a screen coordinate, rotate back to a cursor source coordinate
*/
@ -214,6 +226,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
int xin, yin;
int flags = cursor_info->Flags;
CARD32 bits;
const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
#ifdef ARGB_CURSOR
crtc->cursor_argb = FALSE;
@ -222,7 +235,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
for (y = 0; y < cursor_info->MaxHeight; y++)
for (x = 0; x < cursor_info->MaxWidth; x++)
{
xf86_crtc_rotate_coord (crtc->rotation,
xf86_crtc_rotate_coord (rotation,
cursor_info->MaxWidth,
cursor_info->MaxHeight,
x, y, &xin, &yin);
@ -338,7 +351,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
/*
* Transform position of cursor on screen
*/
if (crtc->transform_in_use)
if (crtc->transform_in_use && !crtc->driverIsPerformingTransform)
{
ScreenPtr screen = scrn->pScreen;
xf86CursorScreenPtr ScreenPriv =
@ -420,12 +433,13 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
CARD8 *cursor_image;
const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
#ifdef ARGB_CURSOR
crtc->cursor_argb = FALSE;
#endif
if (crtc->rotation == RR_Rotate_0)
if (rotation == RR_Rotate_0)
cursor_image = src;
else
{
@ -439,7 +453,7 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
for (y = 0; y < cursor_info->MaxHeight; y++)
for (x = 0; x < cursor_info->MaxWidth; x++)
{
xf86_crtc_rotate_coord (crtc->rotation,
xf86_crtc_rotate_coord (rotation,
cursor_info->MaxWidth,
cursor_info->MaxHeight,
x, y, &xin, &yin);
@ -532,12 +546,13 @@ xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
int source_height = cursor->bits->height;
int image_width = cursor_info->MaxWidth;
int image_height = cursor_info->MaxHeight;
const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
for (y = 0; y < image_height; y++)
for (x = 0; x < image_width; x++)
{
xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
x, y, &xin, &yin);
xf86_crtc_rotate_coord (rotation, image_width, image_height, x, y,
&xin, &yin);
if (xin < source_width && yin < source_height)
bits = cursor_source[yin * source_width + xin];
else

View File

@ -1,5 +1,6 @@
/*
* Copyright © 2006 Keith Packard
* Copyright © 2011 Aaron Plattner
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -84,7 +85,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
int n = RegionNumRects(region);
BoxPtr b = RegionRects(region);
XID include_inferiors = IncludeInferiors;
if (crtc->driverIsPerformingTransform)
return;
src = CreatePicture (None,
&root->drawable,
format,
@ -290,7 +294,7 @@ xf86RotateDestroy (xf86CrtcPtr crtc)
}
for (c = 0; c < xf86_config->num_crtc; c++)
if (xf86_config->crtc[c]->transform_in_use)
if (xf86_config->crtc[c]->rotatedData)
return;
/*
@ -414,52 +418,73 @@ xf86CrtcRotate (xf86CrtcPtr 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;
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)
/* Allocate memory for rotation */
if (old_width != width || old_height != height)
{
crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
crtc->rotatedPixmap = NULL;
crtc->rotatedData = NULL;
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;
}
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;
{
/* 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
@ -482,24 +507,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
}
}
#endif
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;