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