pm2_exa.c revision c2fa0f52
1b3d5324cSmacallan/*
2b3d5324cSmacallan * Copyright 1997-2001 by Alan Hourihane, Wigan, England.
3b3d5324cSmacallan * Copyright 2016 by Michael Lorenz
4b3d5324cSmacallan *
5b3d5324cSmacallan * Permission to use, copy, modify, distribute, and sell this software and its
6b3d5324cSmacallan * documentation for any purpose is hereby granted without fee, provided that
7b3d5324cSmacallan * the above copyright notice appear in all copies and that both that
8b3d5324cSmacallan * copyright notice and this permission notice appear in supporting
9b3d5324cSmacallan * documentation, and that the name of Alan Hourihane not be used in
10b3d5324cSmacallan * advertising or publicity pertaining to distribution of the software without
11b3d5324cSmacallan * specific, written prior permission.  Alan Hourihane makes no representations
12b3d5324cSmacallan * about the suitability of this software for any purpose.  It is provided
13b3d5324cSmacallan * "as is" without express or implied warranty.
14b3d5324cSmacallan *
15b3d5324cSmacallan * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16b3d5324cSmacallan * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17b3d5324cSmacallan * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18b3d5324cSmacallan * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19b3d5324cSmacallan * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20b3d5324cSmacallan * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21b3d5324cSmacallan * PERFORMANCE OF THIS SOFTWARE.
22b3d5324cSmacallan *
23b3d5324cSmacallan * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
24b3d5324cSmacallan *           Dirk Hohndel, <hohndel@suse.de>
25b3d5324cSmacallan *           Stefan Dirsch, <sndirsch@suse.de>
26b3d5324cSmacallan *           Mark Vojkovich, <mvojkovi@ucsd.edu>
27b3d5324cSmacallan *           Michel Dänzer, <michdaen@iiic.ethz.ch>
28b3d5324cSmacallan *
29b3d5324cSmacallan * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and
30b3d5324cSmacallan * Siemens Nixdorf Informationssysteme
31b3d5324cSmacallan *
32b3d5324cSmacallan * Permedia 2 accelerated options, EXA style.
33b3d5324cSmacallan */
34b3d5324cSmacallan
35b3d5324cSmacallan#ifdef HAVE_CONFIG_H
36b3d5324cSmacallan#include "config.h"
37b3d5324cSmacallan#endif
38b3d5324cSmacallan
39b3d5324cSmacallan#include <X11/Xarch.h>
40b3d5324cSmacallan#include "xf86.h"
41b3d5324cSmacallan#include "xf86_OSproc.h"
42b3d5324cSmacallan
43b3d5324cSmacallan#include "xf86Pci.h"
44b3d5324cSmacallan
45b3d5324cSmacallan#include "glint_regs.h"
46b3d5324cSmacallan#include "glint.h"
47b3d5324cSmacallan
48b3d5324cSmacallan//#define PM2_DEBUG
49b3d5324cSmacallan
50b3d5324cSmacallan#ifdef PM2_DEBUG
51b3d5324cSmacallan#define STATIC static
52b3d5324cSmacallan#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__);
53b3d5324cSmacallan#define DPRINTF xf86Msg
54b3d5324cSmacallan#else
55b3d5324cSmacallan#define ENTER
56b3d5324cSmacallan#define STATIC
57b3d5324cSmacallan#define DPRINTF while (0) xf86Msg
58b3d5324cSmacallan#endif
59b3d5324cSmacallan
60b3d5324cSmacallanSTATIC void
61b3d5324cSmacallanPm2WaitMarker(ScreenPtr pScreen, int Marker)
62b3d5324cSmacallan{
63b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
64b3d5324cSmacallan
65b3d5324cSmacallan	Permedia2Sync(pScrn);
66b3d5324cSmacallan}
67b3d5324cSmacallan
68b3d5324cSmacallanSTATIC Bool
69b3d5324cSmacallanPm2PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
70b3d5324cSmacallan		int xdir, int ydir, int rop, Pixel planemask)
71b3d5324cSmacallan{
72b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
73b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
74b3d5324cSmacallan
75b3d5324cSmacallan	ENTER;
76b3d5324cSmacallan
77b3d5324cSmacallan	pGlint->BltScanDirection = 0;
78b3d5324cSmacallan	if (xdir == 1) pGlint->BltScanDirection |= XPositive;
79b3d5324cSmacallan	if (ydir == 1) pGlint->BltScanDirection |= YPositive;
80b3d5324cSmacallan
81b3d5324cSmacallan	GLINT_WAIT(4);
82b3d5324cSmacallan	DO_PLANEMASK(planemask);
83b3d5324cSmacallan
84b3d5324cSmacallan	GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
85b3d5324cSmacallan	if ((rop == GXset) || (rop == GXclear)) {
86b3d5324cSmacallan		pGlint->FrameBufferReadMode = pGlint->pprod;
87b3d5324cSmacallan	} else
88b3d5324cSmacallan	if ((rop == GXcopy) || (rop == GXcopyInverted)) {
89b3d5324cSmacallan		pGlint->FrameBufferReadMode = pGlint->pprod |FBRM_SrcEnable;
90b3d5324cSmacallan	} else {
91b3d5324cSmacallan		pGlint->FrameBufferReadMode = pGlint->pprod | FBRM_SrcEnable |
92b3d5324cSmacallan							FBRM_DstEnable;
93b3d5324cSmacallan	}
94b3d5324cSmacallan	LOADROP(rop);
95b3d5324cSmacallan	pGlint->srcoff = exaGetPixmapOffset(pSrcPixmap);
96b3d5324cSmacallan	return TRUE;
97b3d5324cSmacallan}
98b3d5324cSmacallan
99b3d5324cSmacallanSTATIC void
100b3d5324cSmacallanPm2Copy(PixmapPtr pDstPixmap,
101b3d5324cSmacallan         int srcX, int srcY, int dstX, int dstY, int w, int h)
102b3d5324cSmacallan{
103b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
104b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
105b3d5324cSmacallan	int align;
106b3d5324cSmacallan	int dstoff = exaGetPixmapOffset(pDstPixmap);
107b3d5324cSmacallan	int pitch = exaGetPixmapPitch(pDstPixmap);
108b3d5324cSmacallan
109b3d5324cSmacallan	ENTER;
110b3d5324cSmacallan
111b3d5324cSmacallan	/* assuming constant pitch for now */
112b3d5324cSmacallan	srcY += pGlint->srcoff / pitch;
113b3d5324cSmacallan	dstY += dstoff / pitch;
114b3d5324cSmacallan
115b3d5324cSmacallan	/* We can only use GXcopy for Packed modes */
116b3d5324cSmacallan	if ((pGlint->ROP != GXcopy) || (pScrn->bitsPerPixel != 8)) {
117b3d5324cSmacallan		GLINT_WAIT(5);
118b3d5324cSmacallan		GLINT_WRITE_REG(pGlint->FrameBufferReadMode, FBReadMode);
119b3d5324cSmacallan        	Permedia2LoadCoord(pScrn, dstX, dstY, w, h);
120b3d5324cSmacallan        	GLINT_WRITE_REG(((srcY - dstY) & 0x0FFF) << 16 |
121b3d5324cSmacallan        			((srcX - dstX) & 0x0FFF), FBSourceDelta);
122b3d5324cSmacallan	} else {
123b3d5324cSmacallan  		align = (dstX & pGlint->bppalign) - (srcX & pGlint->bppalign);
124b3d5324cSmacallan		GLINT_WAIT(6);
125b3d5324cSmacallan		GLINT_WRITE_REG(pGlint->FrameBufferReadMode|FBRM_Packed, FBReadMode);
126b3d5324cSmacallan        	Permedia2LoadCoord(pScrn, dstX >> pGlint->BppShift, dstY,
127b3d5324cSmacallan					(w + 7) >> pGlint->BppShift, h);
128b3d5324cSmacallan  		GLINT_WRITE_REG(align << 29 | dstX << 16 | (dstX + w), PackedDataLimits);
129b3d5324cSmacallan        	GLINT_WRITE_REG(((srcX - dstX) & 0x0FFF) << 16 |
130b3d5324cSmacallan        		       (((srcX & ~pGlint->bppalign) - (dstX & ~pGlint->bppalign)) & 0x0FFF),
131b3d5324cSmacallan        		       FBSourceDelta);
132b3d5324cSmacallan	}
133b3d5324cSmacallan	GLINT_WRITE_REG(PrimitiveRectangle | pGlint->BltScanDirection, Render);
134b3d5324cSmacallan
135b3d5324cSmacallan	exaMarkSync(pDstPixmap->drawable.pScreen);
136b3d5324cSmacallan}
137b3d5324cSmacallan
138b3d5324cSmacallanSTATIC void
139b3d5324cSmacallanPm2DoneCopy(PixmapPtr pPixmap)
140b3d5324cSmacallan{
141b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
142b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
143b3d5324cSmacallan
144b3d5324cSmacallan}
145b3d5324cSmacallan
146b3d5324cSmacallanSTATIC Bool
147b3d5324cSmacallanPm2PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color)
148b3d5324cSmacallan{
149b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
150b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
151b3d5324cSmacallan
152b3d5324cSmacallan	ENTER;
153b3d5324cSmacallan
154b3d5324cSmacallan	REPLICATE(color);
155b3d5324cSmacallan
156b3d5324cSmacallan	GLINT_WAIT(6);
157b3d5324cSmacallan	DO_PLANEMASK(planemask);
158b3d5324cSmacallan	if (rop == GXcopy) {
159b3d5324cSmacallan		GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
160b3d5324cSmacallan		GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
161b3d5324cSmacallan		GLINT_WRITE_REG(color, FBBlockColor);
162b3d5324cSmacallan	} else {
163b3d5324cSmacallan		GLINT_WRITE_REG(UNIT_ENABLE, ColorDDAMode);
164b3d5324cSmacallan      		GLINT_WRITE_REG(color, ConstantColor);
165b3d5324cSmacallan		/* We can use Packed mode for filling solid non-GXcopy rasters */
166b3d5324cSmacallan		GLINT_WRITE_REG(pGlint->pprod|FBRM_DstEnable|FBRM_Packed, FBReadMode);
167b3d5324cSmacallan	}
168b3d5324cSmacallan	LOADROP(rop);
169b3d5324cSmacallan
170b3d5324cSmacallan	return TRUE;
171b3d5324cSmacallan}
172b3d5324cSmacallan
173b3d5324cSmacallanSTATIC void
174b3d5324cSmacallanPm2Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
175b3d5324cSmacallan{
176b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
177b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
178b3d5324cSmacallan	int offset = exaGetPixmapOffset(pPixmap);
179b3d5324cSmacallan	int pitch = exaGetPixmapPitch(pPixmap);
180b3d5324cSmacallan	int w = x2 - x1, h = y2 - y1;
181b3d5324cSmacallan	int speed = 0;
182b3d5324cSmacallan
183b3d5324cSmacallan	ENTER;
184b3d5324cSmacallan
185b3d5324cSmacallan	y1 += offset / pitch;
186b3d5324cSmacallan	if (pGlint->ROP == GXcopy) {
187b3d5324cSmacallan		GLINT_WAIT(3);
188b3d5324cSmacallan        	Permedia2LoadCoord(pScrn, x1, y1, w, h);
189b3d5324cSmacallan		speed = FastFillEnable;
190b3d5324cSmacallan	} else {
191b3d5324cSmacallan		GLINT_WAIT(4);
192b3d5324cSmacallan		Permedia2LoadCoord(pScrn, x1 >> pGlint->BppShift, y1,
193b3d5324cSmacallan					(w + 7) >> pGlint->BppShift, h);
194b3d5324cSmacallan  		GLINT_WRITE_REG(x1 << 16 | (x1 + w), PackedDataLimits);
195b3d5324cSmacallan  		speed = 0;
196b3d5324cSmacallan	}
197b3d5324cSmacallan	GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | speed, Render);
198b3d5324cSmacallan
199b3d5324cSmacallan	exaMarkSync(pPixmap->drawable.pScreen);
200b3d5324cSmacallan}
201b3d5324cSmacallan
202b3d5324cSmacallan/*
203b3d5324cSmacallan * Memcpy-based UTS.
204b3d5324cSmacallan */
205b3d5324cSmacallanSTATIC Bool
206b3d5324cSmacallanPm2UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
207b3d5324cSmacallan    char *src, int src_pitch)
208b3d5324cSmacallan{
209b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
210b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
211c2fa0f52Smacallan	int    offset	   = exaGetPixmapOffset(pDst);
212c2fa0f52Smacallan	unsigned char *dst = pGlint->FbBase + offset;
213c2fa0f52Smacallan	CARD32 *s;
214c2fa0f52Smacallan	int    dst_pitch   = exaGetPixmapPitch(pDst);
215b3d5324cSmacallan
216b3d5324cSmacallan	int bpp    = pDst->drawable.bitsPerPixel;
217b3d5324cSmacallan	int cpp    = (bpp + 7) >> 3;
218b3d5324cSmacallan	int wBytes = w * cpp;
219a2587576Smacallan	int xx, i, fs = pGlint->FIFOSize, chunk, adr;
220b3d5324cSmacallan
221b3d5324cSmacallan	ENTER;
222b3d5324cSmacallan
223a2587576Smacallan	if (bpp < 24) {
224a2587576Smacallan		/* for now */
225a2587576Smacallan		dst += (x * cpp) + (y * dst_pitch);
226b3d5324cSmacallan
227a2587576Smacallan		Permedia2Sync(pScrn);
228a2587576Smacallan
229a2587576Smacallan		while (h--) {
230a2587576Smacallan			memcpy(dst, src, wBytes);
231a2587576Smacallan			src += src_pitch;
232a2587576Smacallan			dst += dst_pitch;
233a2587576Smacallan		}
234a2587576Smacallan	} else {
235a2587576Smacallan		/* use host blit */
236a2587576Smacallan		y += offset / dst_pitch;
237a2587576Smacallan		adr = y * (dst_pitch >> 2) + x;
238a2587576Smacallan        	while (h--) {
239c2fa0f52Smacallan        		s = (CARD32 *)src;
240a2587576Smacallan        		xx = w;
241a2587576Smacallan        		GLINT_WAIT(1);
242a2587576Smacallan        		GLINT_WRITE_REG(adr, TextureDownloadOffset);
243a2587576Smacallan			while (xx > 0) {
244a2587576Smacallan				chunk = min(fs - 1, xx);
245a2587576Smacallan	        		GLINT_WAIT(chunk);
246a2587576Smacallan	        	      	GLINT_WRITE_REG(((chunk - 1) << 16) | (0x11 << 4) |
247a2587576Smacallan					0x0d, OutputFIFO);
248a2587576Smacallan				GLINT_MoveDWORDS(
249a2587576Smacallan					(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
250a2587576Smacallan	 				s, chunk);
251a2587576Smacallan	 			xx -= chunk;
252a2587576Smacallan	 			s += chunk;
253a2587576Smacallan			}
254a2587576Smacallan			adr += (dst_pitch >> 2);
255a2587576Smacallan			src += src_pitch;
256a2587576Smacallan		}
257a2587576Smacallan		exaMarkSync(pDst->drawable.pScreen);
258b3d5324cSmacallan	}
259b3d5324cSmacallan	return TRUE;
260b3d5324cSmacallan}
261b3d5324cSmacallan
262b3d5324cSmacallan/*
263b3d5324cSmacallan * Memcpy-based DFS.
264b3d5324cSmacallan */
265b3d5324cSmacallanSTATIC Bool
266b3d5324cSmacallanPm2DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
267b3d5324cSmacallan    char *dst, int dst_pitch)
268b3d5324cSmacallan{
269b3d5324cSmacallan 	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
270c2fa0f52Smacallan	GLINTPtr pGlint    = GLINTPTR(pScrn);
271c2fa0f52Smacallan	unsigned char *src = pGlint->FbBase + exaGetPixmapOffset(pSrc);
272c2fa0f52Smacallan	int    src_pitch   = exaGetPixmapPitch(pSrc);
273b3d5324cSmacallan
274b3d5324cSmacallan	ENTER;
275b3d5324cSmacallan	int bpp    = pSrc->drawable.bitsPerPixel;
276b3d5324cSmacallan	int cpp    = (bpp + 7) >> 3;
277b3d5324cSmacallan	int wBytes = w * cpp;
278b3d5324cSmacallan
279b3d5324cSmacallan	src += (x * cpp) + (y * src_pitch);
280b3d5324cSmacallan
2814bd90d63Smacallan	Permedia2Sync(pScrn);
282b3d5324cSmacallan
283b3d5324cSmacallan	while (h--) {
284b3d5324cSmacallan		memcpy(dst, src, wBytes);
285b3d5324cSmacallan		src += src_pitch;
286b3d5324cSmacallan		dst += dst_pitch;
287b3d5324cSmacallan	}
288b3d5324cSmacallan
289b3d5324cSmacallan	return TRUE;
290b3d5324cSmacallan}
291b3d5324cSmacallan
292b3d5324cSmacallanBool
293b3d5324cSmacallanPm2InitEXA(ScreenPtr pScreen)
294b3d5324cSmacallan{
295b3d5324cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
296b3d5324cSmacallan	GLINTPtr pGlint = GLINTPTR(pScrn);
297b3d5324cSmacallan	ExaDriverPtr pExa;
298eaa0d4a1Smacallan	int stride, lines;
299b3d5324cSmacallan
300b3d5324cSmacallan	ENTER;
301b3d5324cSmacallan
302b3d5324cSmacallan	pExa = exaDriverAlloc();
303b3d5324cSmacallan	if (!pExa)
304b3d5324cSmacallan		return FALSE;
305b3d5324cSmacallan
306b3d5324cSmacallan	pGlint->pExa = pExa;
307b3d5324cSmacallan
308b3d5324cSmacallan	pExa->exa_major = EXA_VERSION_MAJOR;
309b3d5324cSmacallan	pExa->exa_minor = EXA_VERSION_MINOR;
310b3d5324cSmacallan
311b3d5324cSmacallan	pExa->memoryBase = pGlint->FbBase;
312b3d5324cSmacallan	stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
313eaa0d4a1Smacallan	lines = min(pGlint->FbMapSize / stride, 2047);
314eaa0d4a1Smacallan	pExa->memorySize = lines * stride;
315b3d5324cSmacallan	DPRINTF(X_ERROR, "stride: %d\n", stride);
316b3d5324cSmacallan	DPRINTF(X_ERROR, "pprod: %08x\n", pGlint->pprod);
317b3d5324cSmacallan	pExa->offScreenBase = stride * pScrn->virtualY;
318b3d5324cSmacallan
319b3d5324cSmacallan	/* for now, until I figure out how to do variable stride */
320b3d5324cSmacallan	pExa->pixmapOffsetAlign = stride;
321b3d5324cSmacallan	pExa->pixmapPitchAlign = stride;
322b3d5324cSmacallan
323eaa0d4a1Smacallan	pExa->flags = EXA_OFFSCREEN_PIXMAPS;
324b3d5324cSmacallan
3254bd90d63Smacallan	pExa->maxX = 2048;
3264bd90d63Smacallan	pExa->maxY = 2048;
327b3d5324cSmacallan
328b3d5324cSmacallan	pExa->WaitMarker = Pm2WaitMarker;
329b3d5324cSmacallan
330b3d5324cSmacallan	pExa->PrepareSolid = Pm2PrepareSolid;
331b3d5324cSmacallan	pExa->Solid = Pm2Solid;
332b3d5324cSmacallan	pExa->DoneSolid = Pm2DoneCopy;
333b3d5324cSmacallan	pExa->PrepareCopy = Pm2PrepareCopy;
334b3d5324cSmacallan	pExa->Copy = Pm2Copy;
335b3d5324cSmacallan	pExa->DoneCopy = Pm2DoneCopy;
336b3d5324cSmacallan
337b3d5324cSmacallan	/* EXA hits more optimized paths when it does not have to fallback
338b3d5324cSmacallan	 * because of missing UTS/DFS, hook memcpy-based UTS/DFS.
339b3d5324cSmacallan	 */
340b3d5324cSmacallan	pExa->UploadToScreen = Pm2UploadToScreen;
341b3d5324cSmacallan	pExa->DownloadFromScreen = Pm2DownloadFromScreen;
342b3d5324cSmacallan
343b3d5324cSmacallan	Permedia2InitializeEngine(pScrn);
344b3d5324cSmacallan
345b3d5324cSmacallan	return exaDriverInit(pScreen, pExa);
346b3d5324cSmacallan}
347