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