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