pm3_exa.c revision eaa0d4a1
1eaa0d4a1Smacallan/* $NetBSD: pm3_exa.c,v 1.3 2016/12/10 07:23:38 macallan Exp $ */ 2bdc97df9Smacallan 3d038a282Smacallan/* 4d038a282Smacallan * Copyright (c) 2016 Michael Lorenz 5d038a282Smacallan * All rights reserved. 6bdc97df9Smacallan */ 7bdc97df9Smacallan 8bdc97df9Smacallan/* much of this is based on pm3_accel.c, therefore... */ 9bdc97df9Smacallan/* 10bdc97df9Smacallan * Copyright 2000-2001 by Sven Luther <luther@dpt-info.u-strasbg.fr>. 11d038a282Smacallan * 12bdc97df9Smacallan * Permission to use, copy, modify, distribute, and sell this software and its 13bdc97df9Smacallan * documentation for any purpose is hereby granted without fee, provided that 14bdc97df9Smacallan * the above copyright notice appear in all copies and that both that 15bdc97df9Smacallan * copyright notice and this permission notice appear in supporting 16bdc97df9Smacallan * documentation, and that the name of Sven Luther not be used in 17bdc97df9Smacallan * advertising or publicity pertaining to distribution of the software without 18bdc97df9Smacallan * specific, written prior permission. Sven Luther makes no representations 19bdc97df9Smacallan * about the suitability of this software for any purpose. It is provided 20bdc97df9Smacallan * "as is" without express or implied warranty. 21d038a282Smacallan * 22bdc97df9Smacallan * SVEN LUTHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 23bdc97df9Smacallan * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 24bdc97df9Smacallan * EVENT SHALL SVEN LUTHER BE LIABLE FOR ANY SPECIAL, INDIRECT OR 25bdc97df9Smacallan * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 26bdc97df9Smacallan * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 27bdc97df9Smacallan * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28bdc97df9Smacallan * PERFORMANCE OF THIS SOFTWARE. 29d038a282Smacallan * 30bdc97df9Smacallan * Authors: Sven Luther, <luther@dpt-info.u-strasbg.fr> 31bdc97df9Smacallan * Alan Hourihane, <alanh@fairlite.demon.co.uk> 32d038a282Smacallan * 33bdc97df9Smacallan * this work is sponsored by Appian Graphics. 34bdc97df9Smacallan * 35bdc97df9Smacallan * Permedia 3 accelerated options. 36d038a282Smacallan */ 37d038a282Smacallan 38d038a282Smacallan#ifdef HAVE_CONFIG_H 39d038a282Smacallan#include "config.h" 40d038a282Smacallan#endif 41d038a282Smacallan 42d038a282Smacallan/* all driver need this */ 43d038a282Smacallan#include "xf86.h" 44d038a282Smacallan#include "xf86_OSproc.h" 45d038a282Smacallan#include "compiler.h" 46d038a282Smacallan#include "exa.h" 47d038a282Smacallan 48d038a282Smacallan#include "glint_regs.h" 49d038a282Smacallan#include "pm3_regs.h" 50d038a282Smacallan#include "glint.h" 51d038a282Smacallan 52d038a282Smacallan/*#define PM3_DEBUG*/ 53d038a282Smacallan 54d038a282Smacallan#ifdef PM3_DEBUG 55d038a282Smacallan#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__); 56d038a282Smacallan#define DPRINTF xf86Msg 57d038a282Smacallan#else 58d038a282Smacallan#define ENTER 59d038a282Smacallan#define DPRINTF while (0) xf86Msg 60d038a282Smacallan#endif 61d038a282Smacallan 62d038a282Smacallanstatic void 63d038a282SmacallanPm3WaitMarker(ScreenPtr pScreen, int Marker) 64d038a282Smacallan{ 65d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 66d038a282Smacallan 67d038a282Smacallan Permedia3Sync(pScrn); 68d038a282Smacallan} 69d038a282Smacallan 70d038a282Smacallanstatic Bool 71d038a282SmacallanPm3PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, 72d038a282Smacallan int xdir, int ydir, int rop, Pixel planemask) 73d038a282Smacallan{ 74d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 75d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 76d038a282Smacallan 77d038a282Smacallan ENTER; 78d038a282Smacallan 79d038a282Smacallan pGlint->PM3_Render2D = 80d038a282Smacallan PM3Render2D_SpanOperation | 81d038a282Smacallan PM3Render2D_Operation_Normal; 82d038a282Smacallan 83d038a282Smacallan pGlint->PM3_Config2D = 84d038a282Smacallan PM3Config2D_UserScissorEnable | 85d038a282Smacallan PM3Config2D_ForegroundROPEnable | 86d038a282Smacallan PM3Config2D_ForegroundROP(rop) | 87d038a282Smacallan PM3Config2D_FBWriteEnable; 88d038a282Smacallan 89d038a282Smacallan if (xdir == 1) pGlint->PM3_Render2D |= PM3Render2D_XPositive; 90d038a282Smacallan if (ydir == 1) pGlint->PM3_Render2D |= PM3Render2D_YPositive; 91d038a282Smacallan 92d038a282Smacallan if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXnoop)&&(rop!=GXinvert)) { 93d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_FBSourceReadEnable; 94d038a282Smacallan pGlint->PM3_Config2D |= PM3Config2D_Blocking; 95d038a282Smacallan } 96d038a282Smacallan 97d038a282Smacallan if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted)) 98d038a282Smacallan pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable; 99d038a282Smacallan 100d038a282Smacallan pGlint->srcoff = exaGetPixmapOffset(pSrcPixmap); 101d038a282Smacallan 102d038a282Smacallan GLINT_WAIT(2); 103d038a282Smacallan PM3_PLANEMASK(planemask); 104d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D); 105d038a282Smacallan return TRUE; 106d038a282Smacallan} 107d038a282Smacallan 108d038a282Smacallanstatic void 109d038a282SmacallanPm3Copy(PixmapPtr pDstPixmap, 110d038a282Smacallan int srcX, int srcY, int dstX, int dstY, int w, int h) 111d038a282Smacallan{ 112d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 113d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 114d038a282Smacallan /* Spans needs to be 32 bit aligned. */ 115d038a282Smacallan int x_align = srcX & 0x1f; 116d038a282Smacallan int dstoff = exaGetPixmapOffset(pDstPixmap); 117d038a282Smacallan int pitch = exaGetPixmapPitch(pDstPixmap); 118d038a282Smacallan 119d038a282Smacallan ENTER; 120d038a282Smacallan 121d038a282Smacallan /* assuming constant pitch for now */ 122d038a282Smacallan srcY += pGlint->srcoff / pitch; 123d038a282Smacallan dstY += dstoff / pitch; 124d038a282Smacallan 125d038a282Smacallan GLINT_WAIT(5); 126d038a282Smacallan GLINT_WRITE_REG(((dstY & 0x0fff) << 16) | (dstX & 0x0fff), ScissorMinXY); 127d038a282Smacallan GLINT_WRITE_REG((((dstY + h) & 0x0fff) << 16) | ((dstX + w) & 0x0fff), ScissorMaxXY); 128d038a282Smacallan GLINT_WRITE_REG( 129d038a282Smacallan PM3RectanglePosition_XOffset(dstX - x_align) | 130d038a282Smacallan PM3RectanglePosition_YOffset(dstY), 131d038a282Smacallan PM3RectanglePosition); 132d038a282Smacallan GLINT_WRITE_REG( 133d038a282Smacallan PM3FBSourceReadBufferOffset_XOffset(srcX - dstX)| 134d038a282Smacallan PM3FBSourceReadBufferOffset_YOffset(srcY - dstY), 135d038a282Smacallan PM3FBSourceReadBufferOffset); 136d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Render2D | 137d038a282Smacallan PM3Render2D_Width(w + x_align)| 138d038a282Smacallan PM3Render2D_Height(h), 139d038a282Smacallan PM3Render2D); 140d038a282Smacallan exaMarkSync(pDstPixmap->drawable.pScreen); 141d038a282Smacallan} 142d038a282Smacallan 143d038a282Smacallanstatic void 144d038a282SmacallanPm3DoneCopy(PixmapPtr pPixmap) 145d038a282Smacallan{ 146d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 147d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 148d038a282Smacallan 149d038a282Smacallan GLINT_WRITE_REG(0, ScissorMinXY); 150d038a282Smacallan GLINT_WRITE_REG(0x0fff0fff, ScissorMaxXY); 151d038a282Smacallan} 152d038a282Smacallan 153d038a282Smacallanstatic Bool 154d038a282SmacallanPm3PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color) 155d038a282Smacallan{ 156d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 157d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 158d038a282Smacallan 159d038a282Smacallan ENTER; 160d038a282Smacallan 161d038a282Smacallan /* Prepare Common Render2D & Config2D data */ 162d038a282Smacallan pGlint->PM3_Render2D = 163d038a282Smacallan PM3Render2D_XPositive | 164d038a282Smacallan PM3Render2D_YPositive | 165d038a282Smacallan PM3Render2D_Operation_Normal; 166d038a282Smacallan pGlint->PM3_Config2D = 167d038a282Smacallan PM3Config2D_UseConstantSource | 168d038a282Smacallan PM3Config2D_ForegroundROPEnable | 169d038a282Smacallan PM3Config2D_ForegroundROP(rop) | 170d038a282Smacallan PM3Config2D_FBWriteEnable; 171d038a282Smacallan GLINT_WAIT(3); 172d038a282Smacallan REPLICATE(color); 173d038a282Smacallan 174d038a282Smacallan /* We can't do block fills properly at 32bpp, so we can stick the chip 175d038a282Smacallan * into 16bpp and double the width and xcoord, but it seems that at 176d038a282Smacallan * extremely high resolutions (above 1600) it doesn't fill. 177d038a282Smacallan * so, we fall back to the slower span filling method. 178d038a282Smacallan */ 179d038a282Smacallan#if 0 180d038a282Smacallan if ((rop == GXcopy) && (pScrn->bitsPerPixel == 32) && 181d038a282Smacallan (pScrn->displayWidth <= 1600)) { 182d038a282Smacallan pGlint->AccelInfoRec->SubsequentSolidFillRect = 183d038a282Smacallan Permedia3SubsequentFillRectSolid32bpp; 184d038a282Smacallan 185d038a282Smacallan if (pGlint->PM3_UsingSGRAM) { 186d038a282Smacallan GLINT_WRITE_REG(color, PM3FBBlockColor); 187d038a282Smacallan } else { 188d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_SpanOperation; 189d038a282Smacallan GLINT_WRITE_REG(color, PM3ForegroundColor); 190d038a282Smacallan } 191d038a282Smacallan } else { 192d038a282Smacallan pGlint->AccelInfoRec->SubsequentSolidFillRect = 193d038a282Smacallan Permedia3SubsequentFillRectSolid; 194d038a282Smacallan#endif 195d038a282Smacallan /* Can't do block fills at 8bpp either */ 196d038a282Smacallan if ((rop == GXcopy) && (pScrn->bitsPerPixel == 16)) { 197d038a282Smacallan if (pGlint->PM3_UsingSGRAM) { 198d038a282Smacallan GLINT_WRITE_REG(color, PM3FBBlockColor); 199d038a282Smacallan } else { 200d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_SpanOperation; 201d038a282Smacallan GLINT_WRITE_REG(color, PM3ForegroundColor); 202d038a282Smacallan } 203d038a282Smacallan } else { 204d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_SpanOperation; 205d038a282Smacallan GLINT_WRITE_REG(color, PM3ForegroundColor); 206d038a282Smacallan } 207d038a282Smacallan#if 0 208d038a282Smacallan } 209d038a282Smacallan#endif 210d038a282Smacallan PM3_PLANEMASK(planemask); 211d038a282Smacallan if (((rop != GXclear) && 212d038a282Smacallan (rop != GXset) && 213d038a282Smacallan (rop != GXcopy) && 214d038a282Smacallan (rop != GXcopyInverted)) || 215d038a282Smacallan ((planemask != 0xffffffff) && !(pGlint->PM3_UsingSGRAM))) 216d038a282Smacallan pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable; 217d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D); 218d038a282Smacallan return TRUE; 219d038a282Smacallan} 220d038a282Smacallan 221d038a282Smacallanstatic void 222d038a282SmacallanPm3Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 223d038a282Smacallan{ 224d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 225d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 226d038a282Smacallan int offset = exaGetPixmapOffset(pPixmap); 227d038a282Smacallan int pitch = exaGetPixmapPitch(pPixmap); 228d038a282Smacallan int w = x2 - x1, h = y2 - y1; 229d038a282Smacallan 230d038a282Smacallan ENTER; 231d038a282Smacallan 232d038a282Smacallan y1 += offset / pitch; 233d038a282Smacallan 234d038a282Smacallan GLINT_WAIT(2); 235d038a282Smacallan GLINT_WRITE_REG( 236d038a282Smacallan PM3RectanglePosition_XOffset(x1) | 237d038a282Smacallan PM3RectanglePosition_YOffset(y1), 238d038a282Smacallan PM3RectanglePosition); 239d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Render2D | 240d038a282Smacallan PM3Render2D_Width(w) | PM3Render2D_Height(h), 241d038a282Smacallan PM3Render2D); 242d038a282Smacallan 243d038a282Smacallan exaMarkSync(pPixmap->drawable.pScreen); 244d038a282Smacallan} 245d038a282Smacallan 246d038a282Smacallan/* 247d038a282Smacallan * Memcpy-based UTS. 248d038a282Smacallan */ 249d038a282Smacallanstatic Bool 250d038a282SmacallanPm3UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 251d038a282Smacallan char *src, int src_pitch) 252d038a282Smacallan{ 253d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 254d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 255d038a282Smacallan char *dst = pGlint->FbBase + exaGetPixmapOffset(pDst); 256d038a282Smacallan int dst_pitch = exaGetPixmapPitch(pDst); 257d038a282Smacallan 258d038a282Smacallan int bpp = pDst->drawable.bitsPerPixel; 259d038a282Smacallan int cpp = (bpp + 7) >> 3; 260d038a282Smacallan int wBytes = w * cpp; 261d038a282Smacallan 262d038a282Smacallan ENTER; 263d038a282Smacallan dst += (x * cpp) + (y * dst_pitch); 264d038a282Smacallan 265d038a282Smacallan Permedia3Sync(pScrn); 266d038a282Smacallan 267d038a282Smacallan while (h--) { 268d038a282Smacallan memcpy(dst, src, wBytes); 269d038a282Smacallan src += src_pitch; 270d038a282Smacallan dst += dst_pitch; 271d038a282Smacallan } 272d038a282Smacallan return TRUE; 273d038a282Smacallan} 274d038a282Smacallan 275d038a282Smacallan/* 276d038a282Smacallan * Memcpy-based DFS. 277d038a282Smacallan */ 278d038a282Smacallanstatic Bool 279d038a282SmacallanPm3DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 280d038a282Smacallan char *dst, int dst_pitch) 281d038a282Smacallan{ 282d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 283d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 284d038a282Smacallan char *src = pGlint->FbBase + exaGetPixmapOffset(pSrc); 285d038a282Smacallan int src_pitch = exaGetPixmapPitch(pSrc); 286d038a282Smacallan 287d038a282Smacallan ENTER; 288d038a282Smacallan int bpp = pSrc->drawable.bitsPerPixel; 289d038a282Smacallan int cpp = (bpp + 7) >> 3; 290d038a282Smacallan int wBytes = w * cpp; 291d038a282Smacallan 292d038a282Smacallan src += (x * cpp) + (y * src_pitch); 293d038a282Smacallan 294d038a282Smacallan Permedia3Sync(pScrn); 295d038a282Smacallan 296d038a282Smacallan while (h--) { 297d038a282Smacallan memcpy(dst, src, wBytes); 298d038a282Smacallan src += src_pitch; 299d038a282Smacallan dst += dst_pitch; 300d038a282Smacallan } 301d038a282Smacallan 302d038a282Smacallan return TRUE; 303d038a282Smacallan} 304d038a282Smacallan 305d038a282SmacallanBool 306d038a282SmacallanPm3InitEXA(ScreenPtr pScreen) 307d038a282Smacallan{ 308d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 309d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 310d038a282Smacallan ExaDriverPtr pExa; 311eaa0d4a1Smacallan int stride, lines; 312d038a282Smacallan 313d038a282Smacallan ENTER; 314d038a282Smacallan 315d038a282Smacallan pExa = exaDriverAlloc(); 316d038a282Smacallan if (!pExa) 317d038a282Smacallan return FALSE; 318d038a282Smacallan 319d038a282Smacallan pGlint->pExa = pExa; 320d038a282Smacallan 321d038a282Smacallan pExa->exa_major = EXA_VERSION_MAJOR; 322d038a282Smacallan pExa->exa_minor = EXA_VERSION_MINOR; 323d038a282Smacallan 324d038a282Smacallan pExa->memoryBase = pGlint->FbBase; 325d038a282Smacallan stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); 326eaa0d4a1Smacallan lines = min(pGlint->FbMapSize / stride, 4095); 327eaa0d4a1Smacallan pExa->memorySize = lines * stride; 328d038a282Smacallan xf86Msg(X_ERROR, "stride: %d\n", stride); 329d038a282Smacallan pExa->offScreenBase = stride * pScrn->virtualY; 330d038a282Smacallan 331d038a282Smacallan /* for now, until I figure out how to do variable stride */ 332d038a282Smacallan pExa->pixmapOffsetAlign = stride; 333d038a282Smacallan pExa->pixmapPitchAlign = stride; 334d038a282Smacallan 335eaa0d4a1Smacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS; 336d038a282Smacallan 337d038a282Smacallan pExa->maxX = 4095; 338d038a282Smacallan pExa->maxY = 4095; 339d038a282Smacallan 340d038a282Smacallan pExa->WaitMarker = Pm3WaitMarker; 341d038a282Smacallan 342d038a282Smacallan pExa->PrepareSolid = Pm3PrepareSolid; 343d038a282Smacallan pExa->Solid = Pm3Solid; 344d038a282Smacallan pExa->DoneSolid = Pm3DoneCopy; 345d038a282Smacallan pExa->PrepareCopy = Pm3PrepareCopy; 346d038a282Smacallan pExa->Copy = Pm3Copy; 347d038a282Smacallan pExa->DoneCopy = Pm3DoneCopy; 348d038a282Smacallan 349d038a282Smacallan /* EXA hits more optimized paths when it does not have to fallback 350d038a282Smacallan * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 351d038a282Smacallan */ 352d038a282Smacallan pExa->UploadToScreen = Pm3UploadToScreen; 353d038a282Smacallan pExa->DownloadFromScreen = Pm3DownloadFromScreen; 354d038a282Smacallan 355d038a282Smacallan Permedia3InitializeEngine(pScrn); 356d038a282Smacallan 357d038a282Smacallan return exaDriverInit(pScreen, pExa); 358d038a282Smacallan} 359