diff options
Diffstat (limited to 'src/i830_rotate.c')
-rw-r--r-- | src/i830_rotate.c | 1181 |
1 files changed, 1181 insertions, 0 deletions
diff --git a/src/i830_rotate.c b/src/i830_rotate.c new file mode 100644 index 00000000..f60d64fe --- /dev/null +++ b/src/i830_rotate.c @@ -0,0 +1,1181 @@ +/************************************************************************** + +Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. + +All Rights Reserved. + +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, sub license, 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 NON-INFRINGEMENT. +IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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. + +**************************************************************************/ + +/* + * Reformatted with GNU indent (2.2.8), using the following options: + * + * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78 + * -lp -npcs -psl -sob -ss -br -ce -sc -hnl + * + * This provides a good match with the original i810 code and preferred + * XFree86 formatting conventions. + * + * When editing this driver, please follow the existing formatting, and edit + * with <TAB> characters expanded at 8-column intervals. + */ + +/* + * Authors: + * Alan Hourihane <alanh@tungstengraphics.com> + * Brian Paul <brian.paul@tungstengraphics.com> + * Keith Whitwell <keith@tungstengraphics.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "servermd.h" +#include "shadow.h" + +#include "i830.h" + +#ifdef XF86DRI +#include "dri.h" +#endif + +static void * +I830WindowLinear (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + CARD8 *ptr; + + *size = (pScrn->bitsPerPixel * pI830->displayWidth >> 3); + if (I830IsPrimary(pScrn)) + ptr = (CARD8 *) (pI830->FbBase + pI830->FrontBuffer.Start) + row * (*size) + offset; + else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + ptr = (CARD8 *) (pI830->FbBase + pI8301->FrontBuffer2.Start) + row * (*size) + offset; + } + return (void *)ptr; +} + +struct matrix23 +{ + int m00, m01, m02; + int m10, m11, m12; +}; + +static void +matrix23Set(struct matrix23 *m, + int m00, int m01, int m02, + int m10, int m11, int m12) +{ + m->m00 = m00; m->m01 = m01; m->m02 = m02; + m->m10 = m10; m->m11 = m11; m->m12 = m12; +} + + +/* + * Transform (x,y) coordinate by the given matrix. + */ +static void +matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y) +{ + const float x0 = *x; + const float y0 = *y; + + *x = m->m00 * x0 + m->m01 * y0 + m->m02; + *y = m->m10 * x0 + m->m11 * y0 + m->m12; +} + +/* + * Make rotation matrix for width X height screen. + */ +static void +matrix23Rotate(struct matrix23 *m, int width, int height, int angle) +{ + switch (angle) { + case 0: + matrix23Set(m, 1, 0, 0, 0, 1, 0); + break; + case 90: + matrix23Set(m, 0, 1, 0, -1, 0, width); + break; + case 180: + matrix23Set(m, -1, 0, width, 0, -1, height); + break; + case 270: + matrix23Set(m, 0, -1, height, 1, 0, 0); + break; + default: + break; + } +} + +/* Doesn't matter on the order for our purposes */ +typedef struct { + unsigned char red, green, blue, alpha; +} intel_color_t; + +/* Vertex format */ +typedef union { + struct { + float x, y, z, w; + intel_color_t color; + intel_color_t specular; + float u0, v0; + float u1, v1; + float u2, v2; + float u3, v3; + } v; + float f[24]; + unsigned int ui[24]; + unsigned char ub4[24][4]; +} intelVertex, *intelVertexPtr; + +static void draw_poly(CARD32 *vb, + float verts[][2], + float texcoords[][2]) +{ + int vertex_size = 8; + intelVertex tmp; + int i, k; + + /* initial constant vertex fields */ + tmp.v.z = 1.0; + tmp.v.w = 1.0; + tmp.v.color.red = 255; + tmp.v.color.green = 255; + tmp.v.color.blue = 255; + tmp.v.color.alpha = 255; + tmp.v.specular.red = 0; + tmp.v.specular.green = 0; + tmp.v.specular.blue = 0; + tmp.v.specular.alpha = 0; + + for (k = 0; k < 4; k++) { + tmp.v.x = verts[k][0]; + tmp.v.y = verts[k][1]; + tmp.v.u0 = texcoords[k][0]; + tmp.v.v0 = texcoords[k][1]; + + for (i = 0 ; i < vertex_size ; i++) + vb[i] = tmp.ui[i]; + + vb += vertex_size; + } +} + +static void +I915UpdateRotate (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn1 = pScrn; + I830Ptr pI8301 = NULL; + RegionPtr damage = shadowDamage(pBuf); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + int box_x1, box_x2, box_y1, box_y2; + CARD32 vb[32]; /* 32 dword vertex buffer */ + float verts[4][2], tex[4][2]; + struct matrix23 rotMatrix; + int j; + int use_fence; + Bool updateInvarient = FALSE; +#ifdef XF86DRI + drmI830Sarea *sarea = NULL; + drm_context_t myContext = 0; +#endif + Bool didLock = FALSE; + + if (I830IsPrimary(pScrn)) { + pI8301 = pI830; + } else { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn1 = pI830->entityPrivate->pScrn_1; + } + + switch (pI830->rotation) { + case RR_Rotate_90: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 90); + break; + case RR_Rotate_180: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 180); + break; + case RR_Rotate_270: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 270); + break; + default: + break; + } + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) { + sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + myContext = DRIGetContext(pScrn1->pScreen); + didLock = I830DRILock(pScrn1); + } +#endif + + if (pScrn->scrnIndex != *pI830->used3D) + updateInvarient = TRUE; + +#ifdef XF86DRI + if (sarea->ctxOwner != myContext) + updateInvarient = TRUE; +#endif + + if (updateInvarient) { + *pI830->used3D = pScrn->scrnIndex; +#ifdef XF86DRI + if (sarea) + sarea->ctxOwner = myContext; +#endif + BEGIN_LP_RING(64); + /* invarient state */ + OUT_RING(MI_NOOP); + OUT_RING(0x66014140); + OUT_RING(0x7d990000); + OUT_RING(0x00000000); + OUT_RING(0x7d9a0000); + OUT_RING(0x00000000); + OUT_RING(0x7d980000); + OUT_RING(0x00000000); + OUT_RING(0x76fac688); + OUT_RING(0x6700a770); + OUT_RING(0x7d040081); + OUT_RING(0x00000000); + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + /* draw rect */ + OUT_RING(0x7d800003); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + /* scissor */ + OUT_RING(0x7c800002); + OUT_RING(0x7d810001); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x7c000003); + OUT_RING(0x7d070000); + OUT_RING(0x00000000); + OUT_RING(0x68000002); + /* context setup */ + OUT_RING(0x6db3ffff); + OUT_RING(0x7d040744); + OUT_RING(0xfffffff0); + OUT_RING(0x00902c80); + OUT_RING(0x00000000); + OUT_RING(0x00020216); + OUT_RING(0x6ba008a1); + OUT_RING(0x7d880000); + OUT_RING(0x00000000); + /* dv0 */ + OUT_RING(0x7d850000); + /* dv1 */ + if (pI830->cpp == 1) + OUT_RING(0x10880000); + else if (pI830->cpp == 2) + OUT_RING(0x10880200); + else + OUT_RING(0x10880308); + /* stipple */ + OUT_RING(0x7d830000); + OUT_RING(0x00000000); + /* fragment program - texture blend replace*/ + OUT_RING(0x7d050008); + OUT_RING(0x19180000); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x19083c00); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x15200000); + OUT_RING(0x01000000); + OUT_RING(0x00000000); + /* texture sampler state */ + OUT_RING(0x7d010003); + OUT_RING(0x00000001); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + /* front buffer, pitch, offset */ + OUT_RING(0x7d8e0001); + OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2)); + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->FrontBuffer.Start); + else + OUT_RING(pI8301->FrontBuffer2.Start); + + /* Set the entire frontbuffer up as a texture */ + OUT_RING(0x7d000003); + OUT_RING(0x00000001); + + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->RotatedMem.Start); + else + OUT_RING(pI8301->RotatedMem2.Start); + + if (pI830->disableTiling) + use_fence = 0; + else + use_fence = 4; + + if (pI830->cpp == 1) + use_fence |= 0x80; /* MAPSURF_8BIT */ + else + if (pI830->cpp == 2) + use_fence |= 0x100; /* MAPSURF_16BIT */ + else + use_fence |= 0x180; /* MAPSURF_32BIT */ + OUT_RING(use_fence | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + OUT_RING(((((pScrn->displayWidth * pI830->cpp) / 4) - 1) << 21)); + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + + while (nbox--) + { + box_x1 = pbox->x1; + box_y1 = pbox->y1; + box_x2 = pbox->x2; + box_y2 = pbox->y2; + pbox++; + + BEGIN_LP_RING(40); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + /* vertex data */ + OUT_RING(0x7f0c001f); + verts[0][0] = box_x1; verts[0][1] = box_y1; + verts[1][0] = box_x2; verts[1][1] = box_y1; + verts[2][0] = box_x2; verts[2][1] = box_y2; + verts[3][0] = box_x1; verts[3][1] = box_y2; + tex[0][0] = box_x1; tex[0][1] = box_y1; + tex[1][0] = box_x2; tex[1][1] = box_y1; + tex[2][0] = box_x2; tex[2][1] = box_y2; + tex[3][0] = box_x1; tex[3][1] = box_y2; + + /* transform coordinates to rotated versions, but leave texcoords unchanged */ + for (j = 0; j < 4; j++) + matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]); + + /* emit vertex buffer */ + draw_poly(vb, verts, tex); + for (j = 0; j < 32; j++) + OUT_RING(vb[j]); + + ADVANCE_LP_RING(); + } + +#ifdef XF86DRI + if (didLock) + I830DRIUnlock(pScrn1); +#endif +} + +static void +I830UpdateRotate (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + I830Ptr pI8301 = NULL; + ScrnInfoPtr pScrn1 = pScrn; + RegionPtr damage = shadowDamage(pBuf); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + int box_x1, box_x2, box_y1, box_y2; + CARD32 vb[32]; /* 32 dword vertex buffer */ + float verts[4][2], tex[4][2]; + struct matrix23 rotMatrix; + Bool updateInvarient = FALSE; + int use_fence; + int j; +#ifdef XF86DRI + drmI830Sarea *sarea = NULL; + drm_context_t myContext = 0; +#endif + Bool didLock = FALSE; + + if (I830IsPrimary(pScrn)) { + pI8301 = pI830; + } else { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn1 = pI830->entityPrivate->pScrn_1; + } + + switch (pI830->rotation) { + case RR_Rotate_90: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 90); + break; + case RR_Rotate_180: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 180); + break; + case RR_Rotate_270: + matrix23Rotate(&rotMatrix, + pScreen->width, pScreen->height, + 270); + break; + default: + break; + } + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) { + sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + myContext = DRIGetContext(pScrn1->pScreen); + didLock = I830DRILock(pScrn1); + } +#endif + + if (pScrn->scrnIndex != *pI830->used3D) + updateInvarient = TRUE; + +#ifdef XF86DRI + if (sarea->ctxOwner != myContext) + updateInvarient = TRUE; +#endif + + if (updateInvarient) { + *pI830->used3D = pScrn->scrnIndex; +#ifdef XF86DRI + if (sarea) + sarea->ctxOwner = myContext; +#endif + + BEGIN_LP_RING(48); + OUT_RING(0x682008a1); + OUT_RING(0x6f402100); + OUT_RING(0x62120aa9); + OUT_RING(0x76b3ffff); + OUT_RING(0x6c818a01); + OUT_RING(0x6ba008a1); + OUT_RING(0x69802100); + OUT_RING(0x63a00aaa); + OUT_RING(0x6423070e); + OUT_RING(0x66014142); + OUT_RING(0x75000000); + OUT_RING(0x7d880000); + OUT_RING(0x00000000); + OUT_RING(0x650001c4); + OUT_RING(0x6a000000); + OUT_RING(0x7d020000); + OUT_RING(0x0000ba98); + + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + /* draw rect */ + OUT_RING(0x7d800003); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + + /* front buffer */ + OUT_RING(0x7d8e0001); + OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2)); + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->FrontBuffer.Start); + else + OUT_RING(pI8301->FrontBuffer2.Start); + OUT_RING(0x7d850000); + if (pI830->cpp == 1) + OUT_RING(0x00880000); + else + if (pI830->cpp == 2) + OUT_RING(0x00880200); + else + OUT_RING(0x00880308); + /* scissor */ + OUT_RING(0x7c800002); + OUT_RING(0x7d810001); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + /* stipple */ + OUT_RING(0x7d830000); + OUT_RING(0x00000000); + + /* texture blend replace */ + OUT_RING(0x7c088088); + OUT_RING(0x00000000); + OUT_RING(0x6d021181); + OUT_RING(0x6d060101); + OUT_RING(0x6e008046); + OUT_RING(0x6e048046); + + + /* Set the entire frontbuffer up as a texture */ + OUT_RING(0x7d030804); + + if (pI830->disableTiling) + use_fence = 0; + else + use_fence = 2; + + if (I830IsPrimary(pScrn)) + OUT_RING(pI830->RotatedMem.Start | use_fence); + else + OUT_RING(pI8301->RotatedMem2.Start | use_fence); + + if (pI830->cpp == 1) + OUT_RING(0x00 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + else if (pI830->cpp == 2) + OUT_RING(0x40 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + else + OUT_RING(0xc0 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); + + OUT_RING((((pScrn->displayWidth * pI830->cpp / 4) - 1) << 21)); + OUT_RING(0x00000000); + OUT_RING(0x00000000); + + + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + + while (nbox--) + { + box_x1 = pbox->x1; + box_y1 = pbox->y1; + box_x2 = pbox->x2; + box_y2 = pbox->y2; + pbox++; + + BEGIN_LP_RING(40); + + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + /* vertex data */ + OUT_RING(0x7f0c001f); + verts[0][0] = box_x1; verts[0][1] = box_y1; + verts[1][0] = box_x2; verts[1][1] = box_y1; + verts[2][0] = box_x2; verts[2][1] = box_y2; + verts[3][0] = box_x1; verts[3][1] = box_y2; + tex[0][0] = box_x1; tex[0][1] = box_y1; + tex[1][0] = box_x2; tex[1][1] = box_y1; + tex[2][0] = box_x2; tex[2][1] = box_y2; + tex[3][0] = box_x1; tex[3][1] = box_y2; + + /* transform coordinates to rotated versions, but leave texcoords unchanged */ + for (j = 0; j < 4; j++) + matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]); + + /* emit vertex buffer */ + draw_poly(vb, verts, tex); + for (j = 0; j < 32; j++) + OUT_RING(vb[j]); + + OUT_RING(0x05000000); + OUT_RING(0x00000000); + + ADVANCE_LP_RING(); + } + + { + BEGIN_LP_RING(2); + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + +#ifdef XF86DRI + if (didLock) + I830DRIUnlock(pScrn1); +#endif +} + +Bool +I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830Ptr pI8301 = NULL; + I830Ptr pI8302 = NULL; + ScrnInfoPtr pScrn1 = NULL; + ScrnInfoPtr pScrn2 = NULL; + int i; + ShadowUpdateProc func = NULL; + Rotation oldRotation = pI830->rotation; /* save old state */ + int displayWidth = pScrn->displayWidth; /* save displayWidth */ + Bool reAllocate = TRUE; + Bool didLock = FALSE; + + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + static const int pitches[] = { +/* + 128 * 2, + 128 * 4, +*/ + 128 * 8, + 128 * 16, + 128 * 32, + 128 * 64, + 0 + }; + + if (pI830->noAccel) + func = LoaderSymbol("shadowUpdateRotatePacked"); + else + if (IS_I9XX(pI830)) + func = I915UpdateRotate; + else + func = I830UpdateRotate; + + if (I830IsPrimary(pScrn)) { + pI8301 = pI830; + pScrn1 = pScrn; + if (pI830->entityPrivate) { + pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); + pScrn2 = pI830->entityPrivate->pScrn_2; + } + } else { + pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pScrn1 = pI830->entityPrivate->pScrn_1; + pI8302 = pI830; + pScrn2 = pScrn; + } + + pI830->rotation = I830GetRotation(pScrn->pScreen); + + /* Check if we've still got the same orientation, or same mode */ + if (pI830->rotation == oldRotation && pI830->currentMode == mode) +#if 0 + reAllocate = FALSE; +#else + return TRUE; +#endif + + /* + * We grab the DRI lock when reallocating buffers to avoid DRI clients + * getting bogus information. + */ +#ifdef XF86DRI + if (pI8301->directRenderingEnabled && reAllocate) { + didLock = I830DRILock(pScrn1); + + /* Do heap teardown here + */ + { + drmI830MemDestroyHeap destroy; + destroy.region = I830_MEM_REGION_AGP; + + if (drmCommandWrite(pI8301->drmSubFD, + DRM_I830_DESTROY_HEAP, + &destroy, sizeof(destroy))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] I830 destroy heap failed\n"); + } + } + + if (pI8301->TexMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key); + I830FreeVidMem(pScrn1, &(pI8301->TexMem)); + if (pI8301->StolenPool.Allocated.Key != -1) { + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key); + xf86DeallocateGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key); + } + if (pI8301->DepthBuffer.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key); + I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer)); + if (pI8301->BackBuffer.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key); + I830FreeVidMem(pScrn1, &(pI8301->BackBuffer)); + } +#endif + + if (reAllocate) { + *pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */ + + if (pI8301->RotatedMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem)); + memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem)); + pI8301->RotatedMem.Key = -1; + + if (pI830->entityPrivate) { + if (pI8301->RotatedMem2.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem2)); + memset(&(pI8301->RotatedMem2), 0, sizeof(pI8301->RotatedMem2)); + pI8301->RotatedMem2.Key = -1; + } + } + + switch (pI830->rotation) { + case RR_Rotate_0: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 0 degrees\n"); + pScrn->displayWidth = pI830->displayWidth; + break; + case RR_Rotate_90: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 90 degrees\n"); + pScrn->displayWidth = pScrn->pScreen->width; + break; + case RR_Rotate_180: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 180 degrees\n"); + pScrn->displayWidth = pI830->displayWidth; + break; + case RR_Rotate_270: + if (reAllocate) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen to 270 degrees\n"); + pScrn->displayWidth = pScrn->pScreen->width; + break; + } + + /* As DRI doesn't run on the secondary head, we know that disableTiling + * is always TRUE. + */ + if (I830IsPrimary(pScrn) && !pI830->disableTiling) { +#if 0 + int dWidth = pScrn->displayWidth; /* save current displayWidth */ +#endif + + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= pScrn->displayWidth) { + pScrn->displayWidth = pitches[i]; + break; + } + } + + /* + * If the displayWidth is a tilable pitch, test if there's enough + * memory available to enable tiling. + */ + if (pScrn->displayWidth == pitches[i]) { + /* TODO */ + } + } + + if (reAllocate) { + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) { + if (!I830AllocateRotated2Buffer(pScrn1, + pI8302->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL0; + + I830FixOffset(pScrn1, &(pI8301->RotatedMem2)); + if (pI8301->RotatedMem2.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset); + } + } + + if (pI8301->rotation != RR_Rotate_0) { + if (!I830AllocateRotatedBuffer(pScrn1, + (pI8301->disableTiling ? ALLOC_NO_TILING : 0))) + goto BAIL1; + + I830FixOffset(pScrn1, &(pI8301->RotatedMem)); + if (pI8301->RotatedMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset); + } + } + + shadowRemove (pScrn->pScreen, NULL); + if (pI830->rotation != RR_Rotate_0) + shadowAdd (pScrn->pScreen, + (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), + func, I830WindowLinear, pI830->rotation, 0); + + if (I830IsPrimary(pScrn)) { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI830->RotatedMem.Start; + else + pScrn->fbOffset = pI830->FrontBuffer.Start; + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) + pScrn2->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn2->fbOffset = pI8301->FrontBuffer2.Start; + I830SelectBuffer(pScrn2, I830_SELECT_FRONT); + } + } else { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + if (pI8301->rotation != RR_Rotate_0) + pScrn1->fbOffset = pI8301->RotatedMem.Start; + else + pScrn1->fbOffset = pI8301->FrontBuffer.Start; + I830SelectBuffer(pScrn1, I830_SELECT_FRONT); + } + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled && reAllocate) { + if (!I830AllocateBackBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL2; + + if (!I830AllocateDepthBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL3; + + if (!I830AllocateTextureMemory(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + goto BAIL4; + + I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool)); + + I830FixOffset(pScrn1, &(pI8301->BackBuffer)); + I830FixOffset(pScrn1, &(pI8301->DepthBuffer)); + + if (pI8301->BackBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset); + if (pI8301->DepthBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset); + if (pI8301->StolenPool.Allocated.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset); + if (pI8301->TexMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset); + I830SetupMemoryTiling(pScrn1); + /* update fence registers */ + for (i = 0; i < 8; i++) + OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]); + { + drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + I830UpdateDRIBuffers(pScrn1, sarea ); + } + + if (didLock) + I830DRIUnlock(pScrn1); + } +#endif + +#if 0 + if (I830IsPrimary(pScrn)) { + pI830->xoffset = (pI830->FrontBuffer.Start / pI830->cpp) % pI830->displayWidth; + pI830->yoffset = (pI830->FrontBuffer.Start / pI830->cpp) / pI830->displayWidth; + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + pI830->xoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) % pI830->displayWidth; + pI830->yoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) / pI830->displayWidth; + } +#endif + + 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)(pI8301->FbBase + pScrn->fbOffset)); + + if (pI830->entityPrivate) { + if (I830IsPrimary(pScrn)) { + if (!pI830->starting) { + pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width, + pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel, + PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn2->fbOffset)); + + /* Repaint the second head */ + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); + } + } else { + if (!pI830->starting) { + pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width, + pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel, + PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn1->fbOffset)); + + /* Repaint the first head */ + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE); + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE); + } + } + } + + /* Don't allow pixmap cache or offscreen pixmaps when rotated */ + /* XAA needs some serious fixing for this to happen */ + if (pI830->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; + } + + return TRUE; + +BAIL4: +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) + I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer)); +#endif +BAIL3: +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) + I830FreeVidMem(pScrn1, &(pI8301->BackBuffer)); +#endif +BAIL2: + if (pI8301->rotation != RR_Rotate_0) { + if (pI8301->RotatedMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem)); + memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem)); + pI8301->RotatedMem.Key = -1; + } +BAIL1: + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) { + if (pI8301->RotatedMem.Key != -1) + xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key); + + I830FreeVidMem(pScrn1, &(pI8301->RotatedMem)); + memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem)); + pI8301->RotatedMem.Key = -1; + } + } +BAIL0: + pScrn->displayWidth = displayWidth; + + /* must flip mmWidth & mmHeight */ + if ( ((oldRotation & (RR_Rotate_90 | RR_Rotate_270)) && + (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))) || + ((oldRotation & (RR_Rotate_0 | RR_Rotate_180)) && + (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270))) ) { + int tmp = pScrn->pScreen->mmWidth; + pScrn->pScreen->mmWidth = pScrn->pScreen->mmHeight; + pScrn->pScreen->mmHeight = tmp; + } + + if (oldRotation & (RR_Rotate_0 | RR_Rotate_180)) { + pScrn->pScreen->width = pScrn->virtualX; + pScrn->pScreen->height = pScrn->virtualY; + } else { + pScrn->pScreen->width = pScrn->virtualY; + pScrn->pScreen->height = pScrn->virtualX; + } + + pI830->rotation = oldRotation; + + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) { + if (!I830AllocateRotated2Buffer(pScrn1, + pI8302->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Oh dear, the rotated2 buffer failed - badness\n"); + + I830FixOffset(pScrn1, &(pI8301->RotatedMem2)); + if (pI8301->RotatedMem2.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset); + } + } + + if (pI8301->rotation != RR_Rotate_0) { + if (!I830AllocateRotatedBuffer(pScrn1, + (pI8301->disableTiling ? ALLOC_NO_TILING : 0))) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Oh dear, the rotated buffer failed - badness\n"); + + I830FixOffset(pScrn1, &(pI8301->RotatedMem)); + if (pI8301->RotatedMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset); + } + + shadowRemove (pScrn->pScreen, NULL); + if (pI830->rotation != RR_Rotate_0) + shadowAdd (pScrn->pScreen, + (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), + func, I830WindowLinear, pI830->rotation, 0); + + if (I830IsPrimary(pScrn)) { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI830->RotatedMem.Start; + else + pScrn->fbOffset = pI830->FrontBuffer.Start; + if (pI830->entityPrivate) { + if (pI8302->rotation != RR_Rotate_0) + pScrn2->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn2->fbOffset = pI8301->FrontBuffer2.Start; + I830SelectBuffer(pScrn2, I830_SELECT_FRONT); + } + } else { + if (pI830->rotation != RR_Rotate_0) + pScrn->fbOffset = pI8301->RotatedMem2.Start; + else + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + if (pI8301->rotation != RR_Rotate_0) + pScrn1->fbOffset = pI8301->RotatedMem.Start; + else + pScrn1->fbOffset = pI8301->FrontBuffer.Start; + I830SelectBuffer(pScrn1, I830_SELECT_FRONT); + } + I830SelectBuffer(pScrn, I830_SELECT_FRONT); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Reverting to previous configured mode\n"); + + switch (oldRotation) { + case RR_Rotate_0: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 0 degrees\n"); + break; + case RR_Rotate_90: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 90 degrees\n"); + break; + case RR_Rotate_180: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 180 degrees\n"); + break; + case RR_Rotate_270: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Rotating Screen back to 270 degrees\n"); + break; + } + +#ifdef XF86DRI + if (pI8301->directRenderingEnabled) { + if (!I830AllocateBackBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Oh dear, the back buffer failed - badness\n"); + + if (!I830AllocateDepthBuffer(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Oh dear, the depth buffer failed - badness\n"); + + if (!I830AllocateTextureMemory(pScrn1, + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Oh dear, the texture cache failed - badness\n"); + + I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool)); + + I830FixOffset(pScrn1, &(pI8301->BackBuffer)); + I830FixOffset(pScrn1, &(pI8301->DepthBuffer)); + + if (pI8301->BackBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset); + if (pI8301->DepthBuffer.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset); + if (pI8301->StolenPool.Allocated.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset); + if (pI8301->TexMem.Key != -1) + xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset); + I830SetupMemoryTiling(pScrn1); + /* update fence registers */ + for (i = 0; i < 8; i++) + OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]); + { + drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen); + I830UpdateDRIBuffers(pScrn1, sarea ); + } + + if (didLock) + I830DRIUnlock(pScrn1); + } +#endif + + 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)(pI8301->FbBase + pScrn->fbOffset)); + + if (pI830->entityPrivate) { + if (I830IsPrimary(pScrn)) { + pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width, + pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel, + PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn2->fbOffset)); + + /* Repaint the second head */ + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); + (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); + } else { + pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width, + pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel, + PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), + (pointer)(pI8301->FbBase + pScrn1->fbOffset)); + + /* Repaint the first head */ + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE); + (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE); + } + } + + return FALSE; +} |