summaryrefslogtreecommitdiff
path: root/src/amd_lx_shadow.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/amd_lx_shadow.c')
-rw-r--r--src/amd_lx_shadow.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/src/amd_lx_shadow.c b/src/amd_lx_shadow.c
new file mode 100644
index 0000000..0e251ee
--- /dev/null
+++ b/src/amd_lx_shadow.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2006 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ */
+
+/*
+ * File Contents: Direct graphics display routines are implemented and
+ * graphics rendering are all done in memory.
+ *
+ * Project: Geode Xfree Frame buffer device driver.
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "amd.h"
+#include "shadowfb.h"
+#include "servermd.h"
+
+#define CLIP(sip,bp,u1,v1,u2,v2) \
+ u1 = bp->x1; v1 = bp->y1; \
+ u2 = bp->x2; v2 = bp->y2; \
+ if( u1 < 0 ) u1 = 0; \
+ if( v1 < 0 ) v1 = 0; \
+ if( u1 > sip->virtualX ) u1 = sip->virtualX; \
+ if( v1 > sip->virtualY ) v1 = sip->virtualY; \
+ if( u2 < 0 ) u2 = 0; \
+ if( v2 < 0 ) v2 = 0; \
+ if( u2 > sip->virtualX ) u2 = sip->virtualX; \
+ if( v2 > sip->virtualY ) v2 = sip->virtualY;
+
+void LXAccelSync(ScrnInfoPtr pScrni);
+
+void
+LXRotation0(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = x;
+ *newY = y;
+}
+
+void
+LXRotation1(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = (h - 1) - y;
+ *newY = x;
+}
+
+void
+LXRotation2(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = (w - 1) - x;
+ *newY = (h - 1) - y;
+}
+
+void
+LXRotation3(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newY = (w - 1) - x;
+ *newX = y;
+}
+
+void
+LXRBltXlat0(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = x;
+ *newY = y;
+}
+
+void
+LXRBltXlat1(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = x - (h - 1);
+ *newY = y;
+}
+
+void
+LXRBltXlat2(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = x - (w - 1);
+ *newY = y - (h - 1);
+}
+
+void
+LXRBltXlat3(int x, int y, int w, int h, int *newX, int *newY)
+{
+ *newX = x;
+ *newY = y - (w - 1);
+}
+
+/*----------------------------------------------------------------------------
+ * LXPointerMoved.
+ *
+ * Description :This function moves one screen memory from one area to other.
+ *
+ * Parameters.
+ * index :Pointer to screen index.
+ * x :Specifies the new x co-ordinates of new area.
+ * y :Specifies the new y co-ordinates of new area.
+ * Returns :none
+ *
+ * Comments :none
+ *
+*----------------------------------------------------------------------------
+*/
+void
+LXPointerMoved(int index, int x, int y)
+{
+ ScrnInfoPtr pScrni = xf86Screens[index];
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ Bool frameChanged = FALSE;
+
+ if (x < 0)
+ x = 0;
+ else if (x >= pScrni->virtualX)
+ x = pScrni->virtualX - 1;
+
+ if (y < 0)
+ y = 0;
+ else if (y >= pScrni->virtualY)
+ y = pScrni->virtualY - 1;
+
+ if (pScrni->frameX0 > x) {
+ pScrni->frameX0 = x;
+ pScrni->frameX1 = x + pGeode->HDisplay - 1;
+ frameChanged = TRUE;
+ }
+
+ if (pScrni->frameX1 < x) {
+ pScrni->frameX1 = x + 1;
+ pScrni->frameX0 = x - pGeode->HDisplay + 1;
+ frameChanged = TRUE;
+ }
+
+ if (pScrni->frameY0 > y) {
+ pScrni->frameY0 = y;
+ pScrni->frameY1 = y + pGeode->VDisplay - 1;
+ frameChanged = TRUE;
+ }
+
+ if (pScrni->frameY1 < y) {
+ pScrni->frameY1 = y;
+ pScrni->frameY0 = y - pGeode->VDisplay + 1;
+ frameChanged = TRUE;
+ }
+
+ if (frameChanged && pScrni->AdjustFrame != NULL)
+ pScrni->AdjustFrame(pScrni->scrnIndex, pScrni->frameX0,
+ pScrni->frameY0, 0);
+}
+
+void
+LXRefreshArea_Cpy(ScrnInfoPtr pScrni, int num, BoxPtr pbox)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ int x1, y1, x2, y2, width, height;
+ unsigned long src, dst;
+ int Bpp = pScrni->bitsPerPixel >> 3;
+
+ gp_declare_blt(0);
+ gp_set_raster_operation(0xcc); /* copy dst=src */
+ gp_write_parameters();
+ for (; --num >= 0; ++pbox) {
+ CLIP(pScrni, pbox, x1, y1, x2, y2);
+ if ((width = x2 - x1) <= 0 || (height = y2 - y1) <= 0)
+ continue;
+ src = y1 * pGeode->ShadowPitch + x1 * Bpp;
+ dst = pGeode->FBOffset + y1 * pGeode->Pitch + x1 * Bpp;
+ gp_declare_blt(0);
+ gp_set_strides(pGeode->Pitch, pGeode->ShadowPitch);
+ gp_screen_to_screen_blt(dst, src, width, height, 0);
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * LXRefreshArea8.
+ *
+ * Description :This function copies the memory to be displayed from the
+ * shadow pointer by 8bpp.
+ * Parameters.
+ * pScrni :Pointer to ScrnInfo structure.
+ * num :Specifies the num of squarebox area to be displayed.
+ * pbox :Points to square of memory to be displayed.
+ * Returns :none
+ *
+ * Comments :none
+ *
+*----------------------------------------------------------------------------
+*/
+
+static int lx_shdw_fmt[4] = {
+ CIMGP_SOURCE_FMT_3_3_2,
+ CIMGP_SOURCE_FMT_0_5_6_5,
+ CIMGP_SOURCE_FMT_24BPP,
+ CIMGP_SOURCE_FMT_8_8_8_8
+};
+
+void
+LXRefreshArea_Blt(ScrnInfoPtr pScrni, int num, BoxPtr pbox)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ int width, height, x1, y1, x2, y2, newX, newY;
+ unsigned long src, dst;
+ int Bpp = pScrni->bitsPerPixel >> 3;
+
+ gp_set_source_format(lx_shdw_fmt[Bpp - 1]);
+ gp_declare_blt(0);
+ gp_set_raster_operation(0xcc); /* copy dst=src */
+ gp_write_parameters();
+ for (; --num >= 0; ++pbox) {
+ CLIP(pScrni, pbox, x1, y1, x2, y2);
+ if ((width = x2 - x1) <= 0 || (height = y2 - y1) <= 0)
+ continue;
+ (*pGeode->Rotation) (x1, y1, pScrni->virtualX, pScrni->virtualY,
+ &newX, &newY);
+ (*pGeode->RBltXlat) (newX, newY, width, height, &newX, &newY);
+ src = y1 * pGeode->ShadowPitch + x1 * Bpp;
+ dst = pGeode->FBOffset + newY * pGeode->Pitch + newX * Bpp;
+ gp_declare_blt(0);
+ gp_set_strides(pGeode->Pitch, pGeode->ShadowPitch);
+ gp_rotate_blt(dst, src, width, height, pGeode->Rotate * 90);
+ }
+}
+
+void
+LXRefreshArea0_Cpu(ScrnInfoPtr pScrni, int num, BoxPtr pbox)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ int width, height, x1, y1, x2, y2;
+ unsigned char *src, *dst;
+ int Bpp = pScrni->bitsPerPixel >> 3;
+
+ LXAccelSync(pScrni);
+ for (; --num >= 0; ++pbox) {
+ CLIP(pScrni, pbox, x1, y1, x2, y2);
+ if ((width = x2 - x1) <= 0 || (height = y2 - y1) <= 0)
+ continue;
+ src = pGeode->ShadowPtr + y1 * pGeode->ShadowPitch + x1 * Bpp;
+ dst = pGeode->FBBase + pGeode->FBOffset + y1 * pGeode->Pitch + x1 *
+ Bpp;
+ width *= Bpp;
+ while (--height >= 0) {
+ memcpy(dst, src, width);
+ dst += pGeode->Pitch;
+ src += pGeode->ShadowPitch;
+ }
+ }
+}
+
+#define RefreshArea1_Cpu(nm,typ) \
+void LXRefreshArea1_Cpu##nm(ScrnInfoPtr pScrni, int num, BoxPtr pbox) \
+{ \
+ GeodeRec *pGeode = GEODEPTR(pScrni); \
+ int l, width, height, x1, y1, x2, y2, newX, newY; \
+ unsigned long src, dst, dp; \
+ typ *sp; \
+ LXAccelSync(pScrni); \
+ for (; --num>=0; ++pbox) { \
+ CLIP(pScrni,pbox,x1,y1,x2,y2); \
+ if ((width=x2-x1) <=0 || (height=y2-y1) <= 0) continue; \
+ src = y1*pGeode->ShadowPitch + x1*sizeof(typ); \
+ newX = pScrni->virtualY-1 - y1; \
+ newY = x1; \
+ dst = pGeode->FBOffset + newY*pGeode->Pitch + newX*sizeof(typ); \
+ while (--height >= 0) { \
+ sp = (typ *)(pGeode->ShadowPtr + src); \
+ dp = (unsigned long)(pGeode->FBBase + dst); \
+ for (l=width; --l>=0;) { \
+ *(typ *)dp = *sp++; \
+ dp += pGeode->Pitch; \
+ } \
+ dst -= sizeof(typ); \
+ src += pGeode->ShadowPitch; \
+ } \
+ } \
+}
+
+RefreshArea1_Cpu(8, unsigned char)
+RefreshArea1_Cpu(16, unsigned short)
+RefreshArea1_Cpu(32, unsigned int)
+#define RefreshArea2_Cpu(nm,typ) \
+void LXRefreshArea2_Cpu##nm(ScrnInfoPtr pScrni, int num, BoxPtr pbox) \
+{ \
+ GeodeRec *pGeode = GEODEPTR(pScrni); \
+ int l, width, height, x1, y1, x2, y2, newX, newY; \
+ unsigned long src, dst, dp; \
+ typ *sp; \
+ LXAccelSync(pScrni); \
+ for (; --num>=0; ++pbox) { \
+ CLIP(pScrni,pbox,x1,y1,x2,y2); \
+ if ((width=x2-x1) <=0 || (height=y2-y1) <= 0) continue; \
+ src = y1*pGeode->ShadowPitch + x1*sizeof(typ); \
+ newX = pScrni->virtualX-1 - x1; \
+ newY = pScrni->virtualY-1 - y1; \
+ dst = pGeode->FBOffset + newY*pGeode->Pitch + newX*sizeof(typ); \
+ while (--height >= 0) { \
+ sp = (typ *)(pGeode->ShadowPtr + src); \
+ dp = (unsigned long)(pGeode->FBBase + dst); \
+ for( l=width; --l>=0; ) { \
+ *(typ *)dp = *sp++; \
+ dp -= sizeof(typ); \
+ } \
+ src += pGeode->ShadowPitch; \
+ dst -= pGeode->Pitch; \
+ } \
+ } \
+}
+RefreshArea2_Cpu(8, unsigned char)
+RefreshArea2_Cpu(16, unsigned short)
+RefreshArea2_Cpu(32, unsigned int)
+#define RefreshArea3_Cpu(nm,typ) \
+void LXRefreshArea3_Cpu##nm(ScrnInfoPtr pScrni, int num, BoxPtr pbox) \
+{ \
+ GeodeRec *pGeode = GEODEPTR(pScrni); \
+ int l, width, height, x1, y1, x2, y2, newX, newY; \
+ unsigned long src, dst, dp; \
+ typ *sp; \
+ LXAccelSync(pScrni); \
+ for (; --num>=0; ++pbox) { \
+ CLIP(pScrni,pbox,x1,y1,x2,y2); \
+ if ((width=x2-x1) <=0 || (height=y2-y1) <= 0) continue; \
+ src = y1*pGeode->ShadowPitch + x1*sizeof(typ); \
+ newX = y1; \
+ newY = pScrni->virtualX-1 - x1; \
+ dst = pGeode->FBOffset + newY*pGeode->Pitch + newX*sizeof(typ); \
+ while (--height >= 0) { \
+ sp = (typ *)(pGeode->ShadowPtr + src); \
+ dp = (unsigned long)(pGeode->FBBase + dst); \
+ for( l=width; --l>=0; ) { \
+ *(typ *)dp = *sp++; \
+ dp -= pGeode->Pitch; \
+ } \
+ dst += sizeof(typ); \
+ src += pGeode->ShadowPitch; \
+ } \
+ } \
+}
+RefreshArea3_Cpu(8, unsigned char)
+RefreshArea3_Cpu(16, unsigned short)
+RefreshArea3_Cpu(32, unsigned int)
+
+ void LXRotationInit(ScrnInfoPtr pScrni)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ switch (pGeode->Rotate) {
+ case 1:
+ pGeode->Rotation = LXRotation1;
+ pGeode->RBltXlat = LXRBltXlat1;
+ break;
+ case 2:
+ pGeode->Rotation = LXRotation2;
+ pGeode->RBltXlat = LXRBltXlat2;
+ break;
+ case 3:
+ pGeode->Rotation = LXRotation3;
+ pGeode->RBltXlat = LXRBltXlat3;
+ break;
+ default:
+ pGeode->Rotation = LXRotation0;
+ pGeode->RBltXlat = LXRBltXlat0;
+ break;
+ }
+}
+
+void
+LXShadowFBInit(ScreenPtr pScrn, GeodeRec *pGeode, int bytpp)
+{
+ RefreshAreaFuncPtr refreshArea;
+
+ if (pGeode->NoAccel || !pGeode->ShadowInFBMem || 0) {
+ switch (bytpp) {
+ case 2:
+ switch (pGeode->Rotate) {
+ case 1:
+ refreshArea = LXRefreshArea1_Cpu16;
+ break;
+ case 2:
+ refreshArea = LXRefreshArea2_Cpu16;
+ break;
+ case 3:
+ refreshArea = LXRefreshArea3_Cpu16;
+ break;
+ default:
+ refreshArea = LXRefreshArea0_Cpu;
+ break;
+ }
+ break;
+ case 4:
+ switch (pGeode->Rotate) {
+ case 1:
+ refreshArea = LXRefreshArea1_Cpu32;
+ break;
+ case 2:
+ refreshArea = LXRefreshArea2_Cpu32;
+ break;
+ case 3:
+ refreshArea = LXRefreshArea3_Cpu32;
+ break;
+ default:
+ refreshArea = LXRefreshArea0_Cpu;
+ break;
+ }
+ break;
+ default:
+ switch (pGeode->Rotate) {
+ case 1:
+ refreshArea = LXRefreshArea1_Cpu8;
+ break;
+ case 2:
+ refreshArea = LXRefreshArea2_Cpu8;
+ break;
+ case 3:
+ refreshArea = LXRefreshArea3_Cpu8;
+ break;
+ default:
+ refreshArea = LXRefreshArea0_Cpu;
+ break;
+ }
+ break;
+ }
+ } else {
+ refreshArea = pGeode->Rotate ? LXRefreshArea_Blt : LXRefreshArea_Cpy;
+ }
+ ShadowFBInit(pScrn, refreshArea);
+}