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