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