11af24eb0Smacallan/* $NetBSD: pm3_exa.c,v 1.6 2017/01/13 20:54:48 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); 76a0bb6d97Smacallan int dstoff = exaGetPixmapOffset(pDstPixmap); 77a0bb6d97Smacallan int dstpitch = exaGetPixmapPitch(pDstPixmap); 78a0bb6d97Smacallan int srcoff = exaGetPixmapOffset(pSrcPixmap); 79a0bb6d97Smacallan int srcpitch = exaGetPixmapPitch(pSrcPixmap); 80d038a282Smacallan 81d038a282Smacallan ENTER; 82d038a282Smacallan 83d038a282Smacallan pGlint->PM3_Render2D = 84d038a282Smacallan PM3Render2D_SpanOperation | 85d038a282Smacallan PM3Render2D_Operation_Normal; 86d038a282Smacallan 87d038a282Smacallan pGlint->PM3_Config2D = 88d038a282Smacallan PM3Config2D_UserScissorEnable | 89d038a282Smacallan PM3Config2D_ForegroundROPEnable | 90d038a282Smacallan PM3Config2D_ForegroundROP(rop) | 91d038a282Smacallan PM3Config2D_FBWriteEnable; 92d038a282Smacallan 93d038a282Smacallan if (xdir == 1) pGlint->PM3_Render2D |= PM3Render2D_XPositive; 94d038a282Smacallan if (ydir == 1) pGlint->PM3_Render2D |= PM3Render2D_YPositive; 95d038a282Smacallan 96d038a282Smacallan if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXnoop)&&(rop!=GXinvert)) { 97d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_FBSourceReadEnable; 98d038a282Smacallan pGlint->PM3_Config2D |= PM3Config2D_Blocking; 99d038a282Smacallan } 100d038a282Smacallan 101d038a282Smacallan if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted)) 102d038a282Smacallan pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable; 103d038a282Smacallan 104d038a282Smacallan pGlint->srcoff = exaGetPixmapOffset(pSrcPixmap); 105d038a282Smacallan 106a0bb6d97Smacallan GLINT_WAIT(10); 107a0bb6d97Smacallan GLINT_WRITE_REG(dstoff, PM3FBWriteBufferAddr0); 108a0bb6d97Smacallan GLINT_WRITE_REG(dstpitch >> 2, PM3FBWriteBufferWidth0); 109a0bb6d97Smacallan GLINT_WRITE_REG(dstoff, PM3FBDestReadBufferAddr0); 110a0bb6d97Smacallan GLINT_WRITE_REG(dstpitch >> 2, PM3FBDestReadBufferWidth0); 111a0bb6d97Smacallan GLINT_WRITE_REG(srcoff, PM3FBSourceReadBufferAddr); 112a0bb6d97Smacallan GLINT_WRITE_REG(srcpitch >> 2, PM3FBSourceReadBufferWidth); 113a0bb6d97Smacallan GLINT_WRITE_REG(PM3FBWriteMode_WriteEnable| 114a0bb6d97Smacallan PM3FBWriteMode_OpaqueSpan| 115a0bb6d97Smacallan PM3FBWriteMode_Enable0, 116a0bb6d97Smacallan PM3FBWriteMode); 117a0bb6d97Smacallan GLINT_WRITE_REG( 118a0bb6d97Smacallan PM3FBDestReadMode_ReadEnable | 119a0bb6d97Smacallan PM3FBDestReadMode_Enable0, 120a0bb6d97Smacallan PM3FBDestReadMode); 121d038a282Smacallan PM3_PLANEMASK(planemask); 122d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D); 123d038a282Smacallan return TRUE; 124d038a282Smacallan} 125d038a282Smacallan 126d038a282Smacallanstatic void 127d038a282SmacallanPm3Copy(PixmapPtr pDstPixmap, 128d038a282Smacallan int srcX, int srcY, int dstX, int dstY, int w, int h) 129d038a282Smacallan{ 130d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 131d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 132d038a282Smacallan /* Spans needs to be 32 bit aligned. */ 133d038a282Smacallan int x_align = srcX & 0x1f; 134d038a282Smacallan 135d038a282Smacallan ENTER; 136d038a282Smacallan 137d038a282Smacallan GLINT_WAIT(5); 138d038a282Smacallan GLINT_WRITE_REG(((dstY & 0x0fff) << 16) | (dstX & 0x0fff), ScissorMinXY); 139d038a282Smacallan GLINT_WRITE_REG((((dstY + h) & 0x0fff) << 16) | ((dstX + w) & 0x0fff), ScissorMaxXY); 140d038a282Smacallan GLINT_WRITE_REG( 141d038a282Smacallan PM3RectanglePosition_XOffset(dstX - x_align) | 142d038a282Smacallan PM3RectanglePosition_YOffset(dstY), 143d038a282Smacallan PM3RectanglePosition); 144d038a282Smacallan GLINT_WRITE_REG( 145d038a282Smacallan PM3FBSourceReadBufferOffset_XOffset(srcX - dstX)| 146d038a282Smacallan PM3FBSourceReadBufferOffset_YOffset(srcY - dstY), 147d038a282Smacallan PM3FBSourceReadBufferOffset); 148d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Render2D | 149d038a282Smacallan PM3Render2D_Width(w + x_align)| 150d038a282Smacallan PM3Render2D_Height(h), 151d038a282Smacallan PM3Render2D); 152d038a282Smacallan exaMarkSync(pDstPixmap->drawable.pScreen); 153d038a282Smacallan} 154d038a282Smacallan 155d038a282Smacallanstatic void 156d038a282SmacallanPm3DoneCopy(PixmapPtr pPixmap) 157d038a282Smacallan{ 158d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 159d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 160d038a282Smacallan 161d038a282Smacallan GLINT_WRITE_REG(0, ScissorMinXY); 162d038a282Smacallan GLINT_WRITE_REG(0x0fff0fff, ScissorMaxXY); 163d038a282Smacallan} 164d038a282Smacallan 165d038a282Smacallanstatic Bool 166d038a282SmacallanPm3PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color) 167d038a282Smacallan{ 168d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 169d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 170a0bb6d97Smacallan int offset = exaGetPixmapOffset(pPixmap); 171a0bb6d97Smacallan int pitch = exaGetPixmapPitch(pPixmap); 172d038a282Smacallan 173d038a282Smacallan ENTER; 174d038a282Smacallan 175a0bb6d97Smacallan GLINT_WAIT(6); 176a0bb6d97Smacallan GLINT_WRITE_REG(offset, PM3FBWriteBufferAddr0); 177a0bb6d97Smacallan GLINT_WRITE_REG(pitch >> 2, PM3FBWriteBufferWidth0); 178a0bb6d97Smacallan GLINT_WRITE_REG(offset, PM3FBDestReadBufferAddr0); 179a0bb6d97Smacallan GLINT_WRITE_REG(pitch >> 2, PM3FBDestReadBufferWidth0); 180a0bb6d97Smacallan GLINT_WRITE_REG(PM3FBWriteMode_WriteEnable| 181a0bb6d97Smacallan PM3FBWriteMode_OpaqueSpan| 182a0bb6d97Smacallan PM3FBWriteMode_Enable0, 183a0bb6d97Smacallan PM3FBWriteMode); 184a0bb6d97Smacallan GLINT_WRITE_REG( 185a0bb6d97Smacallan PM3FBDestReadMode_ReadEnable | 186a0bb6d97Smacallan PM3FBDestReadMode_Enable0, 187a0bb6d97Smacallan PM3FBDestReadMode); 188d038a282Smacallan /* Prepare Common Render2D & Config2D data */ 189d038a282Smacallan pGlint->PM3_Render2D = 190d038a282Smacallan PM3Render2D_XPositive | 191d038a282Smacallan PM3Render2D_YPositive | 192d038a282Smacallan PM3Render2D_Operation_Normal; 193d038a282Smacallan pGlint->PM3_Config2D = 194d038a282Smacallan PM3Config2D_UseConstantSource | 195d038a282Smacallan PM3Config2D_ForegroundROPEnable | 196d038a282Smacallan PM3Config2D_ForegroundROP(rop) | 197d038a282Smacallan PM3Config2D_FBWriteEnable; 198d038a282Smacallan GLINT_WAIT(3); 199d038a282Smacallan REPLICATE(color); 200d038a282Smacallan 201d038a282Smacallan /* We can't do block fills properly at 32bpp, so we can stick the chip 202d038a282Smacallan * into 16bpp and double the width and xcoord, but it seems that at 203d038a282Smacallan * extremely high resolutions (above 1600) it doesn't fill. 204d038a282Smacallan * so, we fall back to the slower span filling method. 205d038a282Smacallan */ 206d038a282Smacallan#if 0 207d038a282Smacallan if ((rop == GXcopy) && (pScrn->bitsPerPixel == 32) && 208d038a282Smacallan (pScrn->displayWidth <= 1600)) { 209d038a282Smacallan pGlint->AccelInfoRec->SubsequentSolidFillRect = 210d038a282Smacallan Permedia3SubsequentFillRectSolid32bpp; 211d038a282Smacallan 212d038a282Smacallan if (pGlint->PM3_UsingSGRAM) { 213d038a282Smacallan GLINT_WRITE_REG(color, PM3FBBlockColor); 214d038a282Smacallan } else { 215d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_SpanOperation; 216d038a282Smacallan GLINT_WRITE_REG(color, PM3ForegroundColor); 217d038a282Smacallan } 218d038a282Smacallan } else { 219d038a282Smacallan pGlint->AccelInfoRec->SubsequentSolidFillRect = 220d038a282Smacallan Permedia3SubsequentFillRectSolid; 221d038a282Smacallan#endif 222d038a282Smacallan /* Can't do block fills at 8bpp either */ 223d038a282Smacallan if ((rop == GXcopy) && (pScrn->bitsPerPixel == 16)) { 224d038a282Smacallan if (pGlint->PM3_UsingSGRAM) { 225d038a282Smacallan GLINT_WRITE_REG(color, PM3FBBlockColor); 226d038a282Smacallan } else { 227d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_SpanOperation; 228d038a282Smacallan GLINT_WRITE_REG(color, PM3ForegroundColor); 229d038a282Smacallan } 230d038a282Smacallan } else { 231d038a282Smacallan pGlint->PM3_Render2D |= PM3Render2D_SpanOperation; 232d038a282Smacallan GLINT_WRITE_REG(color, PM3ForegroundColor); 233d038a282Smacallan } 234d038a282Smacallan#if 0 235d038a282Smacallan } 236d038a282Smacallan#endif 237d038a282Smacallan PM3_PLANEMASK(planemask); 238d038a282Smacallan if (((rop != GXclear) && 239d038a282Smacallan (rop != GXset) && 240d038a282Smacallan (rop != GXcopy) && 241d038a282Smacallan (rop != GXcopyInverted)) || 242d038a282Smacallan ((planemask != 0xffffffff) && !(pGlint->PM3_UsingSGRAM))) 243d038a282Smacallan pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable; 244d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D); 245d038a282Smacallan return TRUE; 246d038a282Smacallan} 247d038a282Smacallan 248d038a282Smacallanstatic void 249d038a282SmacallanPm3Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 250d038a282Smacallan{ 251d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 252d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 253d038a282Smacallan int w = x2 - x1, h = y2 - y1; 254d038a282Smacallan 255d038a282Smacallan ENTER; 256d038a282Smacallan 257d038a282Smacallan GLINT_WAIT(2); 258d038a282Smacallan GLINT_WRITE_REG( 259d038a282Smacallan PM3RectanglePosition_XOffset(x1) | 260d038a282Smacallan PM3RectanglePosition_YOffset(y1), 261d038a282Smacallan PM3RectanglePosition); 262d038a282Smacallan GLINT_WRITE_REG(pGlint->PM3_Render2D | 263d038a282Smacallan PM3Render2D_Width(w) | PM3Render2D_Height(h), 264d038a282Smacallan PM3Render2D); 265d038a282Smacallan 266d038a282Smacallan exaMarkSync(pPixmap->drawable.pScreen); 267d038a282Smacallan} 268d038a282Smacallan 269d038a282Smacallan/* 270d038a282Smacallan * Memcpy-based UTS. 271d038a282Smacallan */ 272d038a282Smacallanstatic Bool 273d038a282SmacallanPm3UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 274d038a282Smacallan char *src, int src_pitch) 275d038a282Smacallan{ 276d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 277c2fa0f52Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 278c2fa0f52Smacallan unsigned char *dst = pGlint->FbBase + exaGetPixmapOffset(pDst); 279c2fa0f52Smacallan int dst_pitch = exaGetPixmapPitch(pDst); 280d038a282Smacallan 281d038a282Smacallan int bpp = pDst->drawable.bitsPerPixel; 282d038a282Smacallan int cpp = (bpp + 7) >> 3; 283d038a282Smacallan int wBytes = w * cpp; 284d038a282Smacallan 285d038a282Smacallan ENTER; 286d038a282Smacallan dst += (x * cpp) + (y * dst_pitch); 287d038a282Smacallan 288d038a282Smacallan Permedia3Sync(pScrn); 289d038a282Smacallan 290d038a282Smacallan while (h--) { 291d038a282Smacallan memcpy(dst, src, wBytes); 292d038a282Smacallan src += src_pitch; 293d038a282Smacallan dst += dst_pitch; 294d038a282Smacallan } 295d038a282Smacallan return TRUE; 296d038a282Smacallan} 297d038a282Smacallan 298d038a282Smacallan/* 299d038a282Smacallan * Memcpy-based DFS. 300d038a282Smacallan */ 301d038a282Smacallanstatic Bool 302d038a282SmacallanPm3DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 303d038a282Smacallan char *dst, int dst_pitch) 304d038a282Smacallan{ 305d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 306c2fa0f52Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 307c2fa0f52Smacallan unsigned char *src = pGlint->FbBase + exaGetPixmapOffset(pSrc); 308c2fa0f52Smacallan int src_pitch = exaGetPixmapPitch(pSrc); 309d038a282Smacallan 310d038a282Smacallan ENTER; 311d038a282Smacallan int bpp = pSrc->drawable.bitsPerPixel; 312d038a282Smacallan int cpp = (bpp + 7) >> 3; 313d038a282Smacallan int wBytes = w * cpp; 314d038a282Smacallan 315d038a282Smacallan src += (x * cpp) + (y * src_pitch); 316d038a282Smacallan 317d038a282Smacallan Permedia3Sync(pScrn); 318d038a282Smacallan 319d038a282Smacallan while (h--) { 320d038a282Smacallan memcpy(dst, src, wBytes); 321d038a282Smacallan src += src_pitch; 322d038a282Smacallan dst += dst_pitch; 323d038a282Smacallan } 324d038a282Smacallan 325d038a282Smacallan return TRUE; 326d038a282Smacallan} 327d038a282Smacallan 328d038a282SmacallanBool 329d038a282SmacallanPm3InitEXA(ScreenPtr pScreen) 330d038a282Smacallan{ 331d038a282Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 332d038a282Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 333d038a282Smacallan ExaDriverPtr pExa; 334a0bb6d97Smacallan int stride; 335d038a282Smacallan 336d038a282Smacallan ENTER; 337d038a282Smacallan 338d038a282Smacallan pExa = exaDriverAlloc(); 339d038a282Smacallan if (!pExa) 340d038a282Smacallan return FALSE; 341d038a282Smacallan 342d038a282Smacallan pGlint->pExa = pExa; 343d038a282Smacallan 344d038a282Smacallan pExa->exa_major = EXA_VERSION_MAJOR; 345d038a282Smacallan pExa->exa_minor = EXA_VERSION_MINOR; 346d038a282Smacallan 347d038a282Smacallan pExa->memoryBase = pGlint->FbBase; 348d038a282Smacallan stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); 349a0bb6d97Smacallan pExa->offScreenBase = stride * pScrn->virtualY; 350a0bb6d97Smacallan pExa->memorySize = pGlint->FbMapSize; 351d038a282Smacallan 352a0bb6d97Smacallan pExa->pixmapOffsetAlign = 32; 353a0bb6d97Smacallan pExa->pixmapPitchAlign = 32; 354d038a282Smacallan 355eaa0d4a1Smacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS; 356d038a282Smacallan 357d038a282Smacallan pExa->maxX = 4095; 358d038a282Smacallan pExa->maxY = 4095; 359d038a282Smacallan 360d038a282Smacallan pExa->WaitMarker = Pm3WaitMarker; 361d038a282Smacallan 362d038a282Smacallan pExa->PrepareSolid = Pm3PrepareSolid; 363d038a282Smacallan pExa->Solid = Pm3Solid; 364d038a282Smacallan pExa->DoneSolid = Pm3DoneCopy; 365d038a282Smacallan pExa->PrepareCopy = Pm3PrepareCopy; 366d038a282Smacallan pExa->Copy = Pm3Copy; 367d038a282Smacallan pExa->DoneCopy = Pm3DoneCopy; 368d038a282Smacallan 369d038a282Smacallan /* EXA hits more optimized paths when it does not have to fallback 370d038a282Smacallan * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 371d038a282Smacallan */ 372d038a282Smacallan pExa->UploadToScreen = Pm3UploadToScreen; 373d038a282Smacallan pExa->DownloadFromScreen = Pm3DownloadFromScreen; 374d038a282Smacallan 375d038a282Smacallan Permedia3InitializeEngine(pScrn); 376d038a282Smacallan 377d038a282Smacallan return exaDriverInit(pScreen, pExa); 378d038a282Smacallan} 379