pm2_exa.c revision c2fa0f52
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	unsigned char *dst = pGlint->FbBase + offset;
213	CARD32 *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		y += offset / dst_pitch;
237		adr = y * (dst_pitch >> 2) + x;
238        	while (h--) {
239        		s = (CARD32 *)src;
240        		xx = w;
241        		GLINT_WAIT(1);
242        		GLINT_WRITE_REG(adr, TextureDownloadOffset);
243			while (xx > 0) {
244				chunk = min(fs - 1, xx);
245	        		GLINT_WAIT(chunk);
246	        	      	GLINT_WRITE_REG(((chunk - 1) << 16) | (0x11 << 4) |
247					0x0d, OutputFIFO);
248				GLINT_MoveDWORDS(
249					(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
250	 				s, chunk);
251	 			xx -= chunk;
252	 			s += chunk;
253			}
254			adr += (dst_pitch >> 2);
255			src += src_pitch;
256		}
257		exaMarkSync(pDst->drawable.pScreen);
258	}
259	return TRUE;
260}
261
262/*
263 * Memcpy-based DFS.
264 */
265STATIC Bool
266Pm2DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
267    char *dst, int dst_pitch)
268{
269 	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
270	GLINTPtr pGlint    = GLINTPTR(pScrn);
271	unsigned char *src = pGlint->FbBase + exaGetPixmapOffset(pSrc);
272	int    src_pitch   = exaGetPixmapPitch(pSrc);
273
274	ENTER;
275	int bpp    = pSrc->drawable.bitsPerPixel;
276	int cpp    = (bpp + 7) >> 3;
277	int wBytes = w * cpp;
278
279	src += (x * cpp) + (y * src_pitch);
280
281	Permedia2Sync(pScrn);
282
283	while (h--) {
284		memcpy(dst, src, wBytes);
285		src += src_pitch;
286		dst += dst_pitch;
287	}
288
289	return TRUE;
290}
291
292Bool
293Pm2InitEXA(ScreenPtr pScreen)
294{
295	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
296	GLINTPtr pGlint = GLINTPTR(pScrn);
297	ExaDriverPtr pExa;
298	int stride, lines;
299
300	ENTER;
301
302	pExa = exaDriverAlloc();
303	if (!pExa)
304		return FALSE;
305
306	pGlint->pExa = pExa;
307
308	pExa->exa_major = EXA_VERSION_MAJOR;
309	pExa->exa_minor = EXA_VERSION_MINOR;
310
311	pExa->memoryBase = pGlint->FbBase;
312	stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
313	lines = min(pGlint->FbMapSize / stride, 2047);
314	pExa->memorySize = lines * stride;
315	DPRINTF(X_ERROR, "stride: %d\n", stride);
316	DPRINTF(X_ERROR, "pprod: %08x\n", pGlint->pprod);
317	pExa->offScreenBase = stride * pScrn->virtualY;
318
319	/* for now, until I figure out how to do variable stride */
320	pExa->pixmapOffsetAlign = stride;
321	pExa->pixmapPitchAlign = stride;
322
323	pExa->flags = EXA_OFFSCREEN_PIXMAPS;
324
325	pExa->maxX = 2048;
326	pExa->maxY = 2048;
327
328	pExa->WaitMarker = Pm2WaitMarker;
329
330	pExa->PrepareSolid = Pm2PrepareSolid;
331	pExa->Solid = Pm2Solid;
332	pExa->DoneSolid = Pm2DoneCopy;
333	pExa->PrepareCopy = Pm2PrepareCopy;
334	pExa->Copy = Pm2Copy;
335	pExa->DoneCopy = Pm2DoneCopy;
336
337	/* EXA hits more optimized paths when it does not have to fallback
338	 * because of missing UTS/DFS, hook memcpy-based UTS/DFS.
339	 */
340	pExa->UploadToScreen = Pm2UploadToScreen;
341	pExa->DownloadFromScreen = Pm2DownloadFromScreen;
342
343	Permedia2InitializeEngine(pScrn);
344
345	return exaDriverInit(pScreen, pExa);
346}
347