pm2_exa.c revision b3d5324c
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	GLINT_WRITE_REG(0, ScissorMinXY);
145	GLINT_WRITE_REG(0x0fff0fff, ScissorMaxXY);
146}
147
148STATIC Bool
149Pm2PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color)
150{
151	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
152	GLINTPtr pGlint = GLINTPTR(pScrn);
153
154	ENTER;
155
156	REPLICATE(color);
157
158	GLINT_WAIT(6);
159	DO_PLANEMASK(planemask);
160	if (rop == GXcopy) {
161		GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
162		GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
163		GLINT_WRITE_REG(color, FBBlockColor);
164	} else {
165		GLINT_WRITE_REG(UNIT_ENABLE, ColorDDAMode);
166      		GLINT_WRITE_REG(color, ConstantColor);
167		/* We can use Packed mode for filling solid non-GXcopy rasters */
168		GLINT_WRITE_REG(pGlint->pprod|FBRM_DstEnable|FBRM_Packed, FBReadMode);
169	}
170	LOADROP(rop);
171
172	return TRUE;
173}
174
175STATIC void
176Pm2Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
177{
178	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
179	GLINTPtr pGlint = GLINTPTR(pScrn);
180	int offset = exaGetPixmapOffset(pPixmap);
181	int pitch = exaGetPixmapPitch(pPixmap);
182	int w = x2 - x1, h = y2 - y1;
183	int speed = 0;
184
185	ENTER;
186
187	y1 += offset / pitch;
188	if (pGlint->ROP == GXcopy) {
189		GLINT_WAIT(3);
190        	Permedia2LoadCoord(pScrn, x1, y1, w, h);
191		speed = FastFillEnable;
192	} else {
193		GLINT_WAIT(4);
194		Permedia2LoadCoord(pScrn, x1 >> pGlint->BppShift, y1,
195					(w + 7) >> pGlint->BppShift, h);
196  		GLINT_WRITE_REG(x1 << 16 | (x1 + w), PackedDataLimits);
197  		speed = 0;
198	}
199	GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | speed, Render);
200
201	exaMarkSync(pPixmap->drawable.pScreen);
202}
203
204/*
205 * Memcpy-based UTS.
206 */
207STATIC Bool
208Pm2UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
209    char *src, int src_pitch)
210{
211	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
212	GLINTPtr pGlint = GLINTPTR(pScrn);
213	char  *dst        = pGlint->FbBase + exaGetPixmapOffset(pDst);
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
220	ENTER;
221	dst += (x * cpp) + (y * dst_pitch);
222
223	Permedia3Sync(pScrn);
224
225	while (h--) {
226		memcpy(dst, src, wBytes);
227		src += src_pitch;
228		dst += dst_pitch;
229	}
230	return TRUE;
231}
232
233/*
234 * Memcpy-based DFS.
235 */
236STATIC Bool
237Pm2DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
238    char *dst, int dst_pitch)
239{
240 	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
241	GLINTPtr pGlint = GLINTPTR(pScrn);
242	char  *src        = pGlint->FbBase + exaGetPixmapOffset(pSrc);
243	int    src_pitch  = exaGetPixmapPitch(pSrc);
244
245	ENTER;
246	int bpp    = pSrc->drawable.bitsPerPixel;
247	int cpp    = (bpp + 7) >> 3;
248	int wBytes = w * cpp;
249
250	src += (x * cpp) + (y * src_pitch);
251
252	Permedia3Sync(pScrn);
253
254	while (h--) {
255		memcpy(dst, src, wBytes);
256		src += src_pitch;
257		dst += dst_pitch;
258	}
259
260	return TRUE;
261}
262
263Bool
264Pm2InitEXA(ScreenPtr pScreen)
265{
266	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
267	GLINTPtr pGlint = GLINTPTR(pScrn);
268	ExaDriverPtr pExa;
269	int stride;
270
271	ENTER;
272
273	pExa = exaDriverAlloc();
274	if (!pExa)
275		return FALSE;
276
277	pGlint->pExa = pExa;
278
279	pExa->exa_major = EXA_VERSION_MAJOR;
280	pExa->exa_minor = EXA_VERSION_MINOR;
281
282	pExa->memoryBase = pGlint->FbBase;
283	stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
284	pExa->memorySize = min(pGlint->FbMapSize, 2047 * stride);
285	DPRINTF(X_ERROR, "stride: %d\n", stride);
286	DPRINTF(X_ERROR, "pprod: %08x\n", pGlint->pprod);
287	pExa->offScreenBase = stride * pScrn->virtualY;
288
289	/* for now, until I figure out how to do variable stride */
290	pExa->pixmapOffsetAlign = stride;
291	pExa->pixmapPitchAlign = stride;
292
293	pExa->flags = EXA_OFFSCREEN_PIXMAPS
294		      /* | EXA_SUPPORTS_OFFSCREEN_OVERLAPS |*/
295		      | EXA_MIXED_PIXMAPS;
296
297	pExa->maxX = 2047;
298	pExa->maxY = 2047;
299
300	pExa->WaitMarker = Pm2WaitMarker;
301
302	pExa->PrepareSolid = Pm2PrepareSolid;
303	pExa->Solid = Pm2Solid;
304	pExa->DoneSolid = Pm2DoneCopy;
305	pExa->PrepareCopy = Pm2PrepareCopy;
306	pExa->Copy = Pm2Copy;
307	pExa->DoneCopy = Pm2DoneCopy;
308
309	/* EXA hits more optimized paths when it does not have to fallback
310	 * because of missing UTS/DFS, hook memcpy-based UTS/DFS.
311	 */
312	pExa->UploadToScreen = Pm2UploadToScreen;
313	pExa->DownloadFromScreen = Pm2DownloadFromScreen;
314
315	Permedia2InitializeEngine(pScrn);
316
317	return exaDriverInit(pScreen, pExa);
318}
319