pm2_exa.c revision eaa0d4a1
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	char  *dst        = pGlint->FbBase + exaGetPixmapOffset(pDst);
212	int    dst_pitch  = exaGetPixmapPitch(pDst);
213
214	int bpp    = pDst->drawable.bitsPerPixel;
215	int cpp    = (bpp + 7) >> 3;
216	int wBytes = w * cpp;
217
218	ENTER;
219	dst += (x * cpp) + (y * dst_pitch);
220
221	Permedia2Sync(pScrn);
222
223	while (h--) {
224		memcpy(dst, src, wBytes);
225		src += src_pitch;
226		dst += dst_pitch;
227	}
228	return TRUE;
229}
230
231/*
232 * Memcpy-based DFS.
233 */
234STATIC Bool
235Pm2DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
236    char *dst, int dst_pitch)
237{
238 	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
239	GLINTPtr pGlint = GLINTPTR(pScrn);
240	char  *src        = pGlint->FbBase + exaGetPixmapOffset(pSrc);
241	int    src_pitch  = exaGetPixmapPitch(pSrc);
242
243	ENTER;
244	int bpp    = pSrc->drawable.bitsPerPixel;
245	int cpp    = (bpp + 7) >> 3;
246	int wBytes = w * cpp;
247
248	src += (x * cpp) + (y * src_pitch);
249
250	Permedia2Sync(pScrn);
251
252	while (h--) {
253		memcpy(dst, src, wBytes);
254		src += src_pitch;
255		dst += dst_pitch;
256	}
257
258	return TRUE;
259}
260
261Bool
262Pm2InitEXA(ScreenPtr pScreen)
263{
264	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
265	GLINTPtr pGlint = GLINTPTR(pScrn);
266	ExaDriverPtr pExa;
267	int stride, lines;
268
269	ENTER;
270
271	pExa = exaDriverAlloc();
272	if (!pExa)
273		return FALSE;
274
275	pGlint->pExa = pExa;
276
277	pExa->exa_major = EXA_VERSION_MAJOR;
278	pExa->exa_minor = EXA_VERSION_MINOR;
279
280	pExa->memoryBase = pGlint->FbBase;
281	stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
282	lines = min(pGlint->FbMapSize / stride, 2047);
283	pExa->memorySize = lines * stride;
284	DPRINTF(X_ERROR, "stride: %d\n", stride);
285	DPRINTF(X_ERROR, "pprod: %08x\n", pGlint->pprod);
286	pExa->offScreenBase = stride * pScrn->virtualY;
287
288	/* for now, until I figure out how to do variable stride */
289	pExa->pixmapOffsetAlign = stride;
290	pExa->pixmapPitchAlign = stride;
291
292	pExa->flags = EXA_OFFSCREEN_PIXMAPS;
293
294	pExa->maxX = 2048;
295	pExa->maxY = 2048;
296
297	pExa->WaitMarker = Pm2WaitMarker;
298
299	pExa->PrepareSolid = Pm2PrepareSolid;
300	pExa->Solid = Pm2Solid;
301	pExa->DoneSolid = Pm2DoneCopy;
302	pExa->PrepareCopy = Pm2PrepareCopy;
303	pExa->Copy = Pm2Copy;
304	pExa->DoneCopy = Pm2DoneCopy;
305
306	/* EXA hits more optimized paths when it does not have to fallback
307	 * because of missing UTS/DFS, hook memcpy-based UTS/DFS.
308	 */
309	pExa->UploadToScreen = Pm2UploadToScreen;
310	pExa->DownloadFromScreen = Pm2DownloadFromScreen;
311
312	Permedia2InitializeEngine(pScrn);
313
314	return exaDriverInit(pScreen, pExa);
315}
316