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