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