rotation support for randr-1.2

This patch trys to resolve rotation regression with randr-1.2.
Tested with Crestline VGA output. See bug 83.
This commit is contained in:
Wang Zhenyu 2006-12-29 10:47:52 +08:00
parent a1796bfb51
commit fbd3f588f0
6 changed files with 328 additions and 14 deletions

View File

@ -196,6 +196,8 @@ extern const char *i830_output_type_names[];
typedef struct _I830CrtcPrivateRec {
int pipe;
Bool gammaEnabled;
Rotation rotation; /* current rotation, mirror from pI830->rotation */
Rotation rotations; /* all */
} I830CrtcPrivateRec, *I830CrtcPrivatePtr;
#define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)

View File

@ -821,7 +821,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
((adjusted_mode->CrtcVBlankEnd - 1) << 16));
OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
((adjusted_mode->CrtcVSyncEnd - 1) << 16));
OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
/* XXX we might always set real line stride, rotation can change it */
// OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
OUTREG(dspstride_reg, pI830->displayWidth * pI830->cpp);
/* pipesrc and dspsize control the size that is scaled from, which should
* always be the user's requested size.
*/

View File

@ -2950,11 +2950,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
shadowSetup(pScreen);
/* support all rotations */
xf86RandR12Init (pScreen);
if (IS_I965G(pI830)) {
xf86RandR12SetRotations (pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
} else {
xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
}
xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
pI830->PointerMoved = pScrn->PointerMoved;
pScrn->PointerMoved = I830PointerMoved;
pI830->CreateScreenResources = pScreen->CreateScreenResources;

View File

@ -333,6 +333,14 @@ xf86RandR12GetRotation(ScreenPtr pScreen)
return randrp->rotation;
}
Rotation
xf86RandR12GetRotation12(RRCrtcPtr randr_crtc)
{
xf86CrtcPtr crtc = randr_crtc->devPrivate;
I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
return intel_crtc->rotation;
}
Bool
xf86RandR12CreateScreenResources (ScreenPtr pScreen)
{
@ -422,12 +430,29 @@ xf86RandR12Init (ScreenPtr pScreen)
return TRUE;
}
/* RandR12 should have been initialized, so we might set rotations
to Crtc object.
*/
void
xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
#if RANDR_12_INTERFACE
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
#endif
randrp->supported_rotations = rotations;
#if RANDR_12_INTERFACE
for (c = 0; c < config->num_crtc ; c++) {
xf86CrtcPtr crtc = config->crtc[c];
I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
crtc->randr_crtc->rotations = rotations;
intel_crtc->rotations = rotations;
intel_crtc->rotation = RR_Rotate_0; /*XXX initial rotation fix */
}
#endif
}
void
@ -468,11 +493,13 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
}
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
pScrn->virtualX = width;
pScrn->virtualY = height;
pScreen->width = pScrn->virtualX;
pScreen->height = pScrn->virtualY;
/* XXX don't change the actual draw window size */
/*pScrn->virtualX = width;
*pScrn->virtualY = height;
*pScreen->width = pScrn->virtualX;
*pScreen->height = pScrn->virtualY;*/
pScreen->width = width;
pScreen->height = height;
pScreen->mmWidth = mmWidth;
pScreen->mmHeight = mmHeight;
@ -509,7 +536,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
return FALSE;
x = crtc->x;
y = crtc->y;
rotation = RR_Rotate_0;
rotation = xf86RandR12GetRotation12(randr_crtc);
numOutputs = 0;
randr_mode = NULL;
for (i = 0; i < config->num_output; i++)
@ -540,6 +567,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
return ret;
}
extern Bool i830RandR12Rotate(ScreenPtr pScreen, RRCrtcPtr randr_crtc,
DisplayModePtr mode, Rotation rotation);
static Bool
xf86RandR12CrtcSet (ScreenPtr pScreen,
RRCrtcPtr randr_crtc,
@ -556,6 +586,8 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL;
Bool changed = FALSE;
Bool pos_changed;
Bool rotation_changed = FALSE;
Rotation old_rotation;
int o, ro;
xf86CrtcPtr *save_crtcs;
Bool save_enabled = crtc->enabled;
@ -569,6 +601,14 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
pos_changed = changed;
if (x != crtc->x || y != crtc->y)
pos_changed = TRUE;
old_rotation = xf86RandR12GetRotation12(randr_crtc);
if (rotation != old_rotation) {
changed = TRUE;
rotation_changed = TRUE;
pos_changed = TRUE;
}
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
@ -604,6 +644,14 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
pI830->AccelInfoRec->NeedToSync = FALSE;
}
/* rotation should take effect when crtc enabled*/
if (rotation_changed && crtc->enabled) {
randr_crtc->rotation = rotation;
if (!i830RandR12Rotate(pScreen, randr_crtc, mode, rotation)) {
randr_crtc->rotation = old_rotation;
}
}
if (mode)
{
if (!i830PipeSetMode (crtc, mode, TRUE))

View File

@ -60,9 +60,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "i830.h"
#include "i915_reg.h"
#include "i915_3d.h"
#include "i830_xf86Crtc.h"
#include "i830_randr.h"
#include "brw_defines.h"
#include "brw_structs.h"
#ifdef XF86DRI
#include "dri.h"
#endif
@ -1341,6 +1343,268 @@ I830UpdateRotate (ScreenPtr pScreen,
#endif
}
static
Bool i830_setup_shadowfb(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
{
I830Ptr pI830 = I830PTR(pScrn);
I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
ShadowUpdateProc func = NULL;
if (pI830->noAccel)
func = LoaderSymbol("shadowUpdateRotatePacked");
else {
if (IS_I9XX(pI830)) {
if (IS_I965G(pI830))
func = I965UpdateRotate;
else
func = I915UpdateRotate;
} else
func = I830UpdateRotate;
}
if (!func)
return FALSE;
shadowRemove (pScrn->pScreen, NULL);
if (intel_crtc->rotation != RR_Rotate_0) {
shadowAdd (pScrn->pScreen,
(*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen),
func, I830WindowLinear, intel_crtc->rotation, 0);
}
if (intel_crtc->rotation != RR_Rotate_0)
pScrn->fbOffset = pI830->RotatedMem.Start;
else
pScrn->fbOffset = pI830->FrontBuffer.Start;
I830SelectBuffer(pScrn, I830_SELECT_FRONT);
pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen),
pScrn->pScreen->width,
pScrn->pScreen->height,
pScrn->pScreen->rootDepth, pScrn->bitsPerPixel,
PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth),
(pointer)(pI830->FbBase + pScrn->fbOffset));
(*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE);
(*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE);
return TRUE;
}
static
Bool i830_rotate_mem_realloc(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
{
I830Ptr pI830 = I830PTR(pScrn);
I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
#ifdef XF86DRI
Bool didLock = FALSE;
#endif
int i;
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
didLock = I830DRILock(pScrn);
/* Do heap teardown here
*/
if (pI830->mmModeFlags & I830_KERNEL_TEX) {
drmI830MemDestroyHeap destroy;
destroy.region = I830_MEM_REGION_AGP;
if (drmCommandWrite(pI830->drmSubFD,
DRM_I830_DESTROY_HEAP,
&destroy, sizeof(destroy))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"[dri] I830 destroy heap failed\n");
}
}
if (pI830->mmModeFlags & I830_KERNEL_TEX) {
if (pI830->TexMem.Key != -1)
xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->TexMem.Key);
I830FreeVidMem(pScrn, &(pI830->TexMem));
}
if (pI830->StolenPool.Allocated.Key != -1) {
xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key);
xf86DeallocateGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key);
}
if (pI830->DepthBuffer.Key != -1)
xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->DepthBuffer.Key);
I830FreeVidMem(pScrn, &(pI830->DepthBuffer));
if (pI830->BackBuffer.Key != -1)
xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->BackBuffer.Key);
I830FreeVidMem(pScrn, &(pI830->BackBuffer));
}
#endif
if (pI830->RotatedMem.Key != -1)
xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->RotatedMem.Key);
I830FreeVidMem(pScrn, &(pI830->RotatedMem));
memset(&(pI830->RotatedMem), 0, sizeof(pI830->RotatedMem));
pI830->RotatedMem.Key = -1;
if (IS_I965G(pI830)) {
if (pI830->RotateStateMem.Key != -1)
xf86UnbindGARTMemory(pScrn->scrnIndex, pI830->RotateStateMem.Key);
I830FreeVidMem(pScrn, &(pI830->RotateStateMem));
memset(&(pI830->RotateStateMem), 0, sizeof(pI830->RotateStateMem));
pI830->RotateStateMem.Key = -1;
}
if (intel_crtc->rotation != RR_Rotate_0) {
if (!I830AllocateRotatedBuffer(pScrn, pI830->disableTiling ? ALLOC_NO_TILING : 0))
goto BAIL1;
I830FixOffset(pScrn, &(pI830->RotatedMem));
if (pI830->RotatedMem.Key != -1)
xf86BindGARTMemory(pScrn->scrnIndex, pI830->RotatedMem.Key, pI830->RotatedMem.Offset);
if (IS_I965G(pI830)) {
I830FixOffset(pScrn, &(pI830->RotateStateMem));
if (pI830->RotateStateMem.Key != -1)
xf86BindGARTMemory(pScrn->scrnIndex, pI830->RotateStateMem.Key,
pI830->RotateStateMem.Offset);
}
}
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
if (!I830AllocateBackBuffer(pScrn,
pI830->disableTiling ? ALLOC_NO_TILING : 0))
goto BAIL2;
if (!I830AllocateDepthBuffer(pScrn,
pI830->disableTiling ? ALLOC_NO_TILING : 0))
goto BAIL3;
if (pI830->mmModeFlags & I830_KERNEL_TEX) {
if (!I830AllocateTextureMemory(pScrn,
pI830->disableTiling ? ALLOC_NO_TILING : 0))
goto BAIL4;
}
I830DoPoolAllocation(pScrn, &(pI830->StolenPool));
I830FixOffset(pScrn, &(pI830->BackBuffer));
I830FixOffset(pScrn, &(pI830->DepthBuffer));
if (pI830->BackBuffer.Key != -1)
xf86BindGARTMemory(pScrn->scrnIndex, pI830->BackBuffer.Key, pI830->BackBuffer.Offset);
if (pI830->DepthBuffer.Key != -1)
xf86BindGARTMemory(pScrn->scrnIndex, pI830->DepthBuffer.Key, pI830->DepthBuffer.Offset);
if (pI830->StolenPool.Allocated.Key != -1)
xf86BindGARTMemory(pScrn->scrnIndex, pI830->StolenPool.Allocated.Key, pI830->StolenPool.Allocated.Offset);
if (pI830->mmModeFlags & I830_KERNEL_TEX) {
if (pI830->TexMem.Key != -1)
xf86BindGARTMemory(pScrn->scrnIndex, pI830->TexMem.Key, pI830->TexMem.Offset);
}
I830SetupMemoryTiling(pScrn);
/* update fence registers */
if (IS_I965G(pI830)) {
for (i = 0; i < FENCE_NEW_NR; i++) {
OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]);
OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]);
}
} else {
for (i = 0; i < 8; i++)
OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
}
{
drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn->pScreen);
I830UpdateDRIBuffers(pScrn, sarea );
}
if (didLock)
I830DRIUnlock(pScrn);
}
#endif
return TRUE;
BAIL1:
BAIL2:
BAIL3:
BAIL4:
//XXX alloc failure
return FALSE;
}
Bool
i830RandR12Rotate(ScreenPtr pScreen, RRCrtcPtr randr_crtc,
DisplayModePtr mode, Rotation rotation)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcPtr crtc = randr_crtc->devPrivate;
I830CrtcPrivatePtr intel_crtc = I830CrtcPrivate(crtc);
Rotation old_rotation = intel_crtc->rotation;
if (old_rotation == rotation)
return TRUE;
intel_crtc->rotation = rotation;
pI830->rotation = rotation;
*pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */
/* user should have already changed screen size. */
/* pI830->displayWidth should always trigger current width in use,
pScrn->displayWidth is current config in use. */
switch (intel_crtc->rotation) {
case RR_Rotate_0:
ErrorF("Rotating Screen to 0 degrees\n");
pScrn->displayWidth = pI830->displayWidth;
break;
case RR_Rotate_90:
ErrorF("Rotating Screen to 90 degrees\n");
pScrn->displayWidth = pScrn->pScreen->width;
break;
case RR_Rotate_180:
ErrorF("Rotating Screen to 180 degrees\n");
pScrn->displayWidth = pI830->displayWidth;
break;
case RR_Rotate_270:
ErrorF("Rotating Screen to 270 degrees\n");
pScrn->displayWidth = pScrn->pScreen->width;
break;
}
ErrorF("pScrn->displayWidth %d\n", pScrn->displayWidth);
if (!i830_rotate_mem_realloc(pScrn, crtc)) {
intel_crtc->rotation = old_rotation;
return FALSE;
}
if (!i830_setup_shadowfb(pScrn, crtc)) {
intel_crtc->rotation = old_rotation;
return FALSE;
}
#ifdef I830_USE_XAA
if (pI830->AccelInfoRec != NULL) {
/* Don't allow pixmap cache or offscreen pixmaps when rotated */
/* XAA needs some serious fixing for this to happen */
if (intel_crtc->rotation == RR_Rotate_0) {
pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS |
PIXMAP_CACHE;
pI830->AccelInfoRec->UsingPixmapCache = TRUE;
/* funny as it seems this will enable XAA's createpixmap */
pI830->AccelInfoRec->maxOffPixWidth = 0;
pI830->AccelInfoRec->maxOffPixHeight = 0;
} else {
pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
pI830->AccelInfoRec->UsingPixmapCache = FALSE;
/* funny as it seems this will disable XAA's createpixmap */
pI830->AccelInfoRec->maxOffPixWidth = 1;
pI830->AccelInfoRec->maxOffPixHeight = 1;
}
}
#endif
return TRUE;
}
Bool
I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode)
{

View File

@ -517,6 +517,7 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
xf86CrtcPtr crtc;
DisplayModePtr last, mode;
int originalVirtualX, originalVirtualY;
I830Ptr pI830 = I830PTR(pScrn);
output = config->output[config->compat_output];
if (!output->crtc)
@ -549,9 +550,10 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
/* Disable modes in the XFree86 DDX list that are larger than the current
* virtual size.
*/
/* pass real line pitch, rotation might change this */
i830xf86ValidateModesSize(pScrn, pScrn->modes,
originalVirtualX, originalVirtualY,
pScrn->displayWidth);
pI830->displayWidth);
/* Strip out anything that we threw out for virtualX/Y. */
i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);