pm3_exa.c revision eaa0d4a1
1/* $NetBSD: pm3_exa.c,v 1.3 2016/12/10 07:23:38 macallan Exp $ */
2
3/*
4 * Copyright (c) 2016 Michael Lorenz
5 * All rights reserved.
6 */
7
8/* much of this is based on pm3_accel.c, therefore... */
9/*
10 * Copyright 2000-2001 by Sven Luther <luther@dpt-info.u-strasbg.fr>.
11 *
12 * Permission to use, copy, modify, distribute, and sell this software and its
13 * documentation for any purpose is hereby granted without fee, provided that
14 * the above copyright notice appear in all copies and that both that
15 * copyright notice and this permission notice appear in supporting
16 * documentation, and that the name of Sven Luther not be used in
17 * advertising or publicity pertaining to distribution of the software without
18 * specific, written prior permission. Sven Luther makes no representations
19 * about the suitability of this software for any purpose. It is provided
20 * "as is" without express or implied warranty.
21 *
22 * SVEN LUTHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
23 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
24 * EVENT SHALL SVEN LUTHER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
25 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
26 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 * PERFORMANCE OF THIS SOFTWARE.
29 *
30 * Authors:  Sven Luther, <luther@dpt-info.u-strasbg.fr>
31 *           Alan Hourihane, <alanh@fairlite.demon.co.uk>
32 *
33 * this work is sponsored by Appian Graphics.
34 *
35 * Permedia 3 accelerated options.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42/* all driver need this */
43#include "xf86.h"
44#include "xf86_OSproc.h"
45#include "compiler.h"
46#include "exa.h"
47
48#include "glint_regs.h"
49#include "pm3_regs.h"
50#include "glint.h"
51
52/*#define PM3_DEBUG*/
53
54#ifdef PM3_DEBUG
55#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__);
56#define DPRINTF xf86Msg
57#else
58#define ENTER
59#define DPRINTF while (0) xf86Msg
60#endif
61
62static void
63Pm3WaitMarker(ScreenPtr pScreen, int Marker)
64{
65	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
66
67	Permedia3Sync(pScrn);
68}
69
70static Bool
71Pm3PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
72		int xdir, int ydir, int rop, Pixel planemask)
73{
74	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
75	GLINTPtr pGlint = GLINTPTR(pScrn);
76
77	ENTER;
78
79	pGlint->PM3_Render2D =
80		PM3Render2D_SpanOperation |
81		PM3Render2D_Operation_Normal;
82
83	pGlint->PM3_Config2D =
84		PM3Config2D_UserScissorEnable |
85		PM3Config2D_ForegroundROPEnable |
86		PM3Config2D_ForegroundROP(rop) |
87		PM3Config2D_FBWriteEnable;
88
89	if (xdir == 1) pGlint->PM3_Render2D |= PM3Render2D_XPositive;
90	if (ydir == 1) pGlint->PM3_Render2D |= PM3Render2D_YPositive;
91
92	if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXnoop)&&(rop!=GXinvert)) {
93		pGlint->PM3_Render2D |= PM3Render2D_FBSourceReadEnable;
94		pGlint->PM3_Config2D |= PM3Config2D_Blocking;
95	}
96
97	if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
98		pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
99
100	pGlint->srcoff = exaGetPixmapOffset(pSrcPixmap);
101
102	GLINT_WAIT(2);
103	PM3_PLANEMASK(planemask);
104	GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
105	return TRUE;
106}
107
108static void
109Pm3Copy(PixmapPtr pDstPixmap,
110         int srcX, int srcY, int dstX, int dstY, int w, int h)
111{
112	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
113	GLINTPtr pGlint = GLINTPTR(pScrn);
114	/* Spans needs to be 32 bit aligned. */
115	int x_align = srcX & 0x1f;
116	int dstoff = exaGetPixmapOffset(pDstPixmap);
117	int pitch = exaGetPixmapPitch(pDstPixmap);
118
119	ENTER;
120
121	/* assuming constant pitch for now */
122	srcY += pGlint->srcoff / pitch;
123	dstY += dstoff / pitch;
124
125	GLINT_WAIT(5);
126	GLINT_WRITE_REG(((dstY & 0x0fff) << 16) | (dstX & 0x0fff), ScissorMinXY);
127	GLINT_WRITE_REG((((dstY + h) & 0x0fff) << 16) | ((dstX + w) & 0x0fff), ScissorMaxXY);
128	GLINT_WRITE_REG(
129		PM3RectanglePosition_XOffset(dstX - x_align) |
130		PM3RectanglePosition_YOffset(dstY),
131		PM3RectanglePosition);
132	GLINT_WRITE_REG(
133		PM3FBSourceReadBufferOffset_XOffset(srcX - dstX)|
134		PM3FBSourceReadBufferOffset_YOffset(srcY - dstY),
135		PM3FBSourceReadBufferOffset);
136	GLINT_WRITE_REG(pGlint->PM3_Render2D |
137		PM3Render2D_Width(w + x_align)|
138		PM3Render2D_Height(h),
139		PM3Render2D);
140	exaMarkSync(pDstPixmap->drawable.pScreen);
141}
142
143static void
144Pm3DoneCopy(PixmapPtr pPixmap)
145{
146	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
147	GLINTPtr pGlint = GLINTPTR(pScrn);
148
149	GLINT_WRITE_REG(0, ScissorMinXY);
150	GLINT_WRITE_REG(0x0fff0fff, ScissorMaxXY);
151}
152
153static Bool
154Pm3PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color)
155{
156	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
157	GLINTPtr pGlint = GLINTPTR(pScrn);
158
159	ENTER;
160
161	/* Prepare Common Render2D & Config2D data */
162	pGlint->PM3_Render2D =
163		PM3Render2D_XPositive |
164		PM3Render2D_YPositive |
165		PM3Render2D_Operation_Normal;
166	pGlint->PM3_Config2D =
167		PM3Config2D_UseConstantSource |
168		PM3Config2D_ForegroundROPEnable |
169		PM3Config2D_ForegroundROP(rop) |
170		PM3Config2D_FBWriteEnable;
171	GLINT_WAIT(3);
172	REPLICATE(color);
173
174	/* We can't do block fills properly at 32bpp, so we can stick the chip
175	 * into 16bpp and double the width and xcoord, but it seems that at
176	 * extremely high resolutions (above 1600) it doesn't fill.
177	 * so, we fall back to the slower span filling method.
178	 */
179#if 0
180	if ((rop == GXcopy) && (pScrn->bitsPerPixel == 32) &&
181	    (pScrn->displayWidth <= 1600)) {
182		pGlint->AccelInfoRec->SubsequentSolidFillRect =
183		    Permedia3SubsequentFillRectSolid32bpp;
184
185		if (pGlint->PM3_UsingSGRAM) {
186			GLINT_WRITE_REG(color, PM3FBBlockColor);
187		} else {
188			pGlint->PM3_Render2D |= PM3Render2D_SpanOperation;
189			GLINT_WRITE_REG(color, PM3ForegroundColor);
190		}
191	} else {
192	    	pGlint->AccelInfoRec->SubsequentSolidFillRect =
193			Permedia3SubsequentFillRectSolid;
194#endif
195	    	/* Can't do block fills at 8bpp either */
196	    	if ((rop == GXcopy) && (pScrn->bitsPerPixel == 16)) {
197			if (pGlint->PM3_UsingSGRAM) {
198				GLINT_WRITE_REG(color, PM3FBBlockColor);
199			} else {
200	        		pGlint->PM3_Render2D |= PM3Render2D_SpanOperation;
201				GLINT_WRITE_REG(color, PM3ForegroundColor);
202			}
203        	} else {
204			pGlint->PM3_Render2D |= PM3Render2D_SpanOperation;
205			GLINT_WRITE_REG(color, PM3ForegroundColor);
206    		}
207#if 0
208	}
209#endif
210	PM3_PLANEMASK(planemask);
211	if (((rop != GXclear) &&
212	     (rop != GXset) &&
213	     (rop != GXcopy) &&
214	     (rop != GXcopyInverted)) ||
215	    ((planemask != 0xffffffff) && !(pGlint->PM3_UsingSGRAM)))
216		pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
217	GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
218	return TRUE;
219}
220
221static void
222Pm3Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
223{
224	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
225	GLINTPtr pGlint = GLINTPTR(pScrn);
226	int offset = exaGetPixmapOffset(pPixmap);
227	int pitch = exaGetPixmapPitch(pPixmap);
228	int w = x2 - x1, h = y2 - y1;
229
230	ENTER;
231
232	y1 += offset / pitch;
233
234	GLINT_WAIT(2);
235	GLINT_WRITE_REG(
236		PM3RectanglePosition_XOffset(x1) |
237		PM3RectanglePosition_YOffset(y1),
238		PM3RectanglePosition);
239	GLINT_WRITE_REG(pGlint->PM3_Render2D |
240		PM3Render2D_Width(w) | PM3Render2D_Height(h),
241		PM3Render2D);
242
243	exaMarkSync(pPixmap->drawable.pScreen);
244}
245
246/*
247 * Memcpy-based UTS.
248 */
249static Bool
250Pm3UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
251    char *src, int src_pitch)
252{
253	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
254	GLINTPtr pGlint = GLINTPTR(pScrn);
255	char  *dst        = pGlint->FbBase + exaGetPixmapOffset(pDst);
256	int    dst_pitch  = exaGetPixmapPitch(pDst);
257
258	int bpp    = pDst->drawable.bitsPerPixel;
259	int cpp    = (bpp + 7) >> 3;
260	int wBytes = w * cpp;
261
262	ENTER;
263	dst += (x * cpp) + (y * dst_pitch);
264
265	Permedia3Sync(pScrn);
266
267	while (h--) {
268		memcpy(dst, src, wBytes);
269		src += src_pitch;
270		dst += dst_pitch;
271	}
272	return TRUE;
273}
274
275/*
276 * Memcpy-based DFS.
277 */
278static Bool
279Pm3DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
280    char *dst, int dst_pitch)
281{
282 	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
283	GLINTPtr pGlint = GLINTPTR(pScrn);
284	char  *src        = pGlint->FbBase + exaGetPixmapOffset(pSrc);
285	int    src_pitch  = exaGetPixmapPitch(pSrc);
286
287	ENTER;
288	int bpp    = pSrc->drawable.bitsPerPixel;
289	int cpp    = (bpp + 7) >> 3;
290	int wBytes = w * cpp;
291
292	src += (x * cpp) + (y * src_pitch);
293
294	Permedia3Sync(pScrn);
295
296	while (h--) {
297		memcpy(dst, src, wBytes);
298		src += src_pitch;
299		dst += dst_pitch;
300	}
301
302	return TRUE;
303}
304
305Bool
306Pm3InitEXA(ScreenPtr pScreen)
307{
308	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
309	GLINTPtr pGlint = GLINTPTR(pScrn);
310	ExaDriverPtr pExa;
311	int stride, lines;
312
313	ENTER;
314
315	pExa = exaDriverAlloc();
316	if (!pExa)
317		return FALSE;
318
319	pGlint->pExa = pExa;
320
321	pExa->exa_major = EXA_VERSION_MAJOR;
322	pExa->exa_minor = EXA_VERSION_MINOR;
323
324	pExa->memoryBase = pGlint->FbBase;
325	stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
326	lines = min(pGlint->FbMapSize / stride, 4095);
327	pExa->memorySize = lines * stride;
328	xf86Msg(X_ERROR, "stride: %d\n", stride);
329	pExa->offScreenBase = stride * pScrn->virtualY;
330
331	/* for now, until I figure out how to do variable stride */
332	pExa->pixmapOffsetAlign = stride;
333	pExa->pixmapPitchAlign = stride;
334
335	pExa->flags = EXA_OFFSCREEN_PIXMAPS;
336
337	pExa->maxX = 4095;
338	pExa->maxY = 4095;
339
340	pExa->WaitMarker = Pm3WaitMarker;
341
342	pExa->PrepareSolid = Pm3PrepareSolid;
343	pExa->Solid = Pm3Solid;
344	pExa->DoneSolid = Pm3DoneCopy;
345	pExa->PrepareCopy = Pm3PrepareCopy;
346	pExa->Copy = Pm3Copy;
347	pExa->DoneCopy = Pm3DoneCopy;
348
349	/* EXA hits more optimized paths when it does not have to fallback
350	 * because of missing UTS/DFS, hook memcpy-based UTS/DFS.
351	 */
352	pExa->UploadToScreen = Pm3UploadToScreen;
353	pExa->DownloadFromScreen = Pm3DownloadFromScreen;
354
355	Permedia3InitializeEngine(pScrn);
356
357	return exaDriverInit(pScreen, pExa);
358}
359