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