ffb_exa.c revision f1295e53
1/* $NetBSD: ffb_exa.c,v 1.3 2016/08/19 19:16:01 mrg Exp $ */
2/*
3 * Copyright (c) 2015 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#include <sys/types.h>
33
34#include "ffb_fifo.h"
35#include "ffb_rcache.h"
36#include "ffb.h"
37#include "ffb_regs.h"
38
39/* all driver need this */
40#include "xf86.h"
41#include "xf86_OSproc.h"
42#include "compiler.h"
43#include "exa.h"
44
45extern void VISmoveImageRL(unsigned char *, unsigned char *, long, long, long, long);
46extern void VISmoveImageLR(unsigned char *, unsigned char *, long, long, long, long);
47
48/*#define FFB_DEBUG*/
49
50#ifdef FFB_DEBUG
51#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__);
52#define DPRINTF xf86Msg
53#else
54#define ENTER
55#define DPRINTF while (0) xf86Msg
56#endif
57
58#define arraysize(ary)        (sizeof(ary) / sizeof(ary[0]))
59
60int src_formats[] = {PICT_a8r8g8b8, PICT_x8r8g8b8,
61		     PICT_a8b8g8r8, PICT_x8b8g8r8, PICT_a8};
62int tex_formats[] = {PICT_a8r8g8b8, PICT_a8b8g8r8, PICT_a8};
63
64static void
65FFBWaitMarker(ScreenPtr pScreen, int Marker)
66{
67	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
68	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
69	ffb_fbcPtr ffb = pFfb->regs;
70
71	FFBWait(pFfb, ffb);
72}
73
74static Bool
75FFBPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
76		int xdir, int ydir, int alu, Pixel planemask)
77{
78	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
79	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
80	ffb_fbcPtr ffb = pFfb->regs;
81
82	ENTER;
83	pFfb->srcpitch = exaGetPixmapPitch(pSrcPixmap);
84	pFfb->srcoff = exaGetPixmapOffset(pSrcPixmap);
85	pFfb->xdir = xdir;
86	pFfb->ydir = ydir;
87	pFfb->rop = alu;
88	pFfb->planemask = planemask;
89	return TRUE;
90}
91
92static void
93FFBCopy(PixmapPtr pDstPixmap,
94         int srcX, int srcY, int dstX, int dstY, int w, int h)
95{
96	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
97	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
98	ffb_fbcPtr ffb = pFfb->regs;
99	unsigned char *src, *dst, *sfb32;
100	int psz_shift = 2;
101	int sdkind;
102
103	ENTER;
104	if ((srcX == dstX) && (srcY != dstY) && (pFfb->rop == GXcopy)) {
105		/* we can use the vscroll command */
106		FFB_ATTR_VSCROLL_XAA(pFfb, pFfb->planemask);
107		FFBFifo(pFfb, 7);
108		ffb->drawop = FFB_DRAWOP_VSCROLL;
109		FFB_WRITE64(&ffb->by, srcY, srcX);
110                       FFB_WRITE64_2(&ffb->dy, dstY, dstX);
111                       FFB_WRITE64_3(&ffb->bh, h, w);
112		exaMarkSync(pDstPixmap->drawable.pScreen);
113		return;
114	}
115	FFB_ATTR_SFB_VAR_XAA(pFfb, pFfb->planemask, pFfb->rop);
116	if (pFfb->use_blkread_prefetch) {
117		FFBFifo(pFfb, 1);
118		if (pFfb->xdir < 0)
119			ffb->mer = FFB_MER_EDRA;
120		else
121			ffb->mer = FFB_MER_EIRA;
122	}
123	FFBWait(pFfb, ffb);
124	sfb32 = (unsigned char *) pFfb->sfb32;
125	src = sfb32 + (srcY * (2048 << psz_shift)) + (srcX << psz_shift);
126	dst = sfb32 + (dstY * (2048 << psz_shift)) + (dstX << psz_shift);
127	sdkind = (2048 << psz_shift);
128
129	if (pFfb->ydir < 0) {
130		src += ((h - 1) * (2048 << psz_shift));
131		dst += ((h - 1) * (2048 << psz_shift));
132		sdkind = -sdkind;
133	}
134	w <<= psz_shift;
135	if (pFfb->xdir < 0)
136		VISmoveImageRL(src, dst, w, h, sdkind, sdkind);
137	else
138		VISmoveImageLR(src, dst, w, h, sdkind, sdkind);
139	if (pFfb->use_blkread_prefetch) {
140		FFBFifo(pFfb, 1);
141		ffb->mer = FFB_MER_DRA;
142	}
143}
144
145static void
146FFBDoneCopy(PixmapPtr pDstPixmap)
147{
148}
149
150static Bool
151FFBPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
152{
153	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
154	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
155	ffb_fbcPtr ffb = pFfb->regs;
156	unsigned int ppc, ppc_mask, fbc;
157
158	ENTER;
159	FFBWait(pFfb, ffb);
160	pFfb->planemask = planemask;
161	pFfb->rop = alu;
162
163	fbc = pFfb->fbc;
164	if (pFfb->ffb_res == ffb_res_high)
165		fbc |= FFB_FBC_WB_B;
166	ppc = FFB_PPC_ABE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID;
167	ppc_mask = FFB_PPC_ABE_MASK | FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK;
168
169	FFB_ATTR_RAW(pFfb, ppc, ppc_mask, planemask,
170                    (FFB_ROP_EDIT_BIT | alu) | (FFB_ROP_NEW << 8),
171                    FFB_DRAWOP_RECTANGLE, fg, fbc, pFfb->wid);
172
173	return TRUE;
174}
175
176static void
177FFBSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
178{
179	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
180	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
181	ffb_fbcPtr ffb = pFfb->regs;
182
183	ENTER;
184	FFBFifo(pFfb, 4);
185	FFB_WRITE64(&ffb->by, y1, x1);
186	FFB_WRITE64_2(&ffb->bh, y2 - y1, x2 - x1);
187	exaMarkSync(pPixmap->drawable.pScreen);
188}
189
190static Bool
191FFBUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
192    char *src, int src_pitch)
193{
194	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
195	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
196	unsigned char *dst, *sfb32;
197	int psz_shift = 2;
198	ffb_fbcPtr ffb = pFfb->regs;
199
200	ENTER;
201	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
202	FFBWait(pFfb, ffb);
203
204	sfb32 = (unsigned char *) pFfb->sfb32;
205	dst = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift);
206	VISmoveImageLR(src, dst, w << psz_shift, h,
207		src_pitch, (2048 << psz_shift));
208	return TRUE;
209}
210
211static Bool
212FFBDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
213    char *dst, int dst_pitch)
214{
215	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
216	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
217	unsigned char *src, *sfb32;
218	int psz_shift = 2;
219	ffb_fbcPtr ffb = pFfb->regs;
220
221	ENTER;
222	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
223	if (pFfb->use_blkread_prefetch) {
224		FFBFifo(pFfb, 1);
225		ffb->mer = FFB_MER_EIRA;
226	}
227	FFBWait(pFfb, ffb);
228
229	sfb32 = (unsigned char *) pFfb->sfb32;
230	src = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift);
231	VISmoveImageLR(src, dst, w << psz_shift, h,
232		(2048 << psz_shift), dst_pitch);
233	if (pFfb->use_blkread_prefetch) {
234		FFBFifo(pFfb, 1);
235		ffb->mer = FFB_MER_DRA;
236	}
237	return TRUE;
238}
239
240static Bool
241FFBCheckComposite(int op, PicturePtr pSrcPicture,
242                           PicturePtr pMaskPicture,
243                           PicturePtr pDstPicture)
244{
245	int i, ok = FALSE;
246
247	ENTER;
248
249	i = 0;
250	while ((i < arraysize(src_formats)) && (!ok)) {
251		ok =  (pSrcPicture->format == src_formats[i]);
252		i++;
253	}
254
255	if (!ok) {
256		xf86Msg(X_ERROR, "%s: unsupported src format %x\n",
257		    __func__, pSrcPicture->format);
258		return FALSE;
259	}
260
261	DPRINTF(X_ERROR, "src is %x, %d: %d %d\n", pSrcPicture->format, op,
262	    pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height);
263
264	if (pMaskPicture != NULL) {
265		DPRINTF(X_ERROR, "mask is %x %d %d\n", pMaskPicture->format,
266		    pMaskPicture->pDrawable->width,
267		    pMaskPicture->pDrawable->height);
268	}
269	return TRUE;
270}
271
272static Bool
273FFBPrepareComposite(int op, PicturePtr pSrcPicture,
274                             PicturePtr pMaskPicture,
275                             PicturePtr pDstPicture,
276                             PixmapPtr  pSrc,
277                             PixmapPtr  pMask,
278                             PixmapPtr  pDst)
279{
280	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
281	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
282
283	ENTER;
284
285	pFfb->no_source_pixmap = FALSE;
286	pFfb->source_is_solid = FALSE;
287
288	if (pSrcPicture->format == PICT_a1) {
289		xf86Msg(X_ERROR, "src mono, dst %x, op %d\n",
290		    pDstPicture->format, op);
291		if (pMaskPicture != NULL) {
292			xf86Msg(X_ERROR, "msk %x\n", pMaskPicture->format);
293		}
294	}
295	if (pSrcPicture->pSourcePict != NULL) {
296		if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
297			pFfb->fillcolour =
298			    pSrcPicture->pSourcePict->solidFill.color;
299			DPRINTF(X_ERROR, "%s: solid src %08x\n",
300			    __func__, pFfb->fillcolour);
301			pFfb->no_source_pixmap = TRUE;
302			pFfb->source_is_solid = TRUE;
303		}
304	}
305	if ((pMaskPicture != NULL) && (pMaskPicture->pSourcePict != NULL)) {
306		if (pMaskPicture->pSourcePict->type ==
307		    SourcePictTypeSolidFill) {
308			pFfb->fillcolour =
309			   pMaskPicture->pSourcePict->solidFill.color;
310			xf86Msg(X_ERROR, "%s: solid mask %08x\n",
311			    __func__, pFfb->fillcolour);
312		}
313	}
314	if (pMaskPicture != NULL) {
315		pFfb->mskoff = exaGetPixmapOffset(pMask);
316		pFfb->mskpitch = exaGetPixmapPitch(pMask);
317		pFfb->mskformat = pMaskPicture->format;
318	} else {
319		pFfb->mskoff = 0;
320		pFfb->mskpitch = 0;
321		pFfb->mskformat = 0;
322	}
323	if (pSrc != NULL) {
324		pFfb->source_is_solid =
325		   ((pSrc->drawable.width == 1) && (pSrc->drawable.height == 1));
326		pFfb->srcoff = exaGetPixmapOffset(pSrc);
327		pFfb->srcpitch = exaGetPixmapPitch(pSrc);
328		if (pFfb->source_is_solid) {
329			pFfb->fillcolour = *(uint32_t *)(pFfb->fb + pFfb->srcoff);
330		}
331	}
332	pFfb->srcformat = pSrcPicture->format;
333	pFfb->dstformat = pDstPicture->format;
334
335	if (pFfb->source_is_solid) {
336		uint32_t temp;
337
338		/* swap solid source as needed */
339		switch (pFfb->srcformat) {
340			case PICT_a8r8g8b8:
341			case PICT_x8r8g8b8:
342				temp = (pFfb->fillcolour & 0x000000ff) << 16;
343				temp |= (pFfb->fillcolour & 0x00ff0000) >> 16;
344				temp |= (pFfb->fillcolour & 0xff00ff00);
345				pFfb->fillcolour = temp;
346				break;
347		}
348	}
349	pFfb->op = op;
350	return TRUE;
351}
352
353static void
354FFBComposite(PixmapPtr pDst, int srcX, int srcY,
355                              int maskX, int maskY,
356                              int dstX, int dstY,
357                              int width, int height)
358{
359	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
360	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
361	exaMarkSync(pDst->drawable.pScreen);
362}
363
364static Bool
365FFBPrepareAccess(PixmapPtr pPix, int index)
366{
367	ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
368	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
369	ffb_fbcPtr ffb = pFfb->regs;
370
371	ENTER;
372	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
373	FFBWait(pFfb, ffb);
374
375	return TRUE;
376}
377
378static void
379FFBFinishAccess(PixmapPtr pPix, int index)
380{
381}
382
383Bool
384FFBInitEXA(ScreenPtr pScreen)
385{
386	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
387	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
388	ffb_fbcPtr ffb = pFfb->regs;
389	ExaDriverPtr pExa;
390
391	pFfb->fbc = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A |
392			 FFB_FBC_WE_FORCEON |
393			 FFB_FBC_SB_BOTH |
394			 FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF |
395			 FFB_FBC_RGBE_MASK |
396			 FFB_FBC_XE_ON);
397	pFfb->wid = FFBWidAlloc(pFfb, TrueColor, 0, TRUE);
398	if (pFfb->wid == (unsigned int) -1)
399		return FALSE;
400
401	pFfb->ppc_cache = (FFB_PPC_FW_DISABLE |
402			   FFB_PPC_VCE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST |
403			   FFB_PPC_XS_WID | FFB_PPC_YS_CONST | FFB_PPC_ZS_CONST |
404			   FFB_PPC_DCE_DISABLE | FFB_PPC_ABE_DISABLE | FFB_PPC_TBE_OPAQUE);
405	pFfb->wid_cache = pFfb->wid;
406	pFfb->pmask_cache = ~0;
407	pFfb->rop_cache = (FFB_ROP_NEW | (FFB_ROP_NEW << 8));
408	pFfb->drawop_cache = FFB_DRAWOP_RECTANGLE;
409	pFfb->fg_cache = pFfb->bg_cache = 0;
410	pFfb->fontw_cache = 32;
411	pFfb->fontinc_cache = (1 << 16) | 0;
412	pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A |
413			   FFB_FBC_WE_FORCEON |
414			   FFB_FBC_SB_BOTH |
415			   FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF |
416			   FFB_FBC_RGBE_OFF |
417			   FFB_FBC_XE_ON);
418
419	/* We will now clear the screen: we'll draw a rectangle covering all the
420	 * viewscreen, using a 'blackness' ROP.
421	 */
422	FFBFifo(pFfb, 22);
423	ffb->fbc = pFfb->fbc_cache;
424	ffb->ppc = pFfb->ppc_cache;
425	ffb->wid = pFfb->wid_cache;
426	ffb->xpmask = 0xff;
427	ffb->pmask = pFfb->pmask_cache;
428	ffb->rop = pFfb->rop_cache;
429	ffb->drawop = pFfb->drawop_cache;
430	ffb->fg = pFfb->fg_cache;
431	ffb->bg = pFfb->bg_cache;
432	ffb->fontw = pFfb->fontw_cache;
433	ffb->fontinc = pFfb->fontinc_cache;
434	ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
435	ffb->cmp = 0x80808080;
436	ffb->matchab = 0x80808080;
437	ffb->magnab = 0x80808080;
438	ffb->blendc = (FFB_BLENDC_FORCE_ONE |
439		       FFB_BLENDC_DF_ONE_M_A |
440		       FFB_BLENDC_SF_A);
441	ffb->blendc1 = 0;
442	ffb->blendc2 = 0;
443	FFB_WRITE64(&ffb->by, 0, 0);
444	FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width);
445	FFBWait(pFfb, ffb);
446
447	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
448	FFBWait(pFfb, ffb);
449
450	FFB_HardwareSetup(pFfb);
451	pExa = exaDriverAlloc();
452	if (!pExa)
453		return FALSE;
454
455	pFfb->pExa = pExa;
456
457	pExa->exa_major = EXA_VERSION_MAJOR;
458	pExa->exa_minor = EXA_VERSION_MINOR;
459
460
461	pExa->memoryBase = (char *)pFfb->sfb32;
462	/*
463	 * we don't have usable off-screen memory but EXA craps out if we don't
464	 * pretend that we do, so register a ridiculously small amount and
465	 * cross fingers
466	 */
467	pExa->memorySize = 8192 * pFfb->psdp->height + 4;
468	pExa->offScreenBase = pExa->memorySize - 4;
469
470	/* we want to use 64bit aligned accesses */
471	pExa->pixmapOffsetAlign = 8;
472	pExa->pixmapPitchAlign = 8;
473
474	pExa->flags = EXA_OFFSCREEN_PIXMAPS |
475		      /*EXA_SUPPORTS_OFFSCREEN_OVERLAPS |*/
476		      EXA_MIXED_PIXMAPS;
477
478	pExa->maxX = 2048;
479	pExa->maxY = 2048;
480
481	pExa->WaitMarker = FFBWaitMarker;
482
483	pExa->PrepareSolid = FFBPrepareSolid;
484	pExa->Solid = FFBSolid;
485	pExa->DoneSolid = FFBDoneCopy;
486
487	pExa->PrepareCopy = FFBPrepareCopy;
488	pExa->Copy = FFBCopy;
489	pExa->DoneCopy = FFBDoneCopy;
490
491	pExa->UploadToScreen = FFBUploadToScreen;
492	pExa->DownloadFromScreen = FFBDownloadFromScreen;
493
494	pExa->PrepareAccess = FFBPrepareAccess;
495	pExa->FinishAccess = FFBFinishAccess;
496
497if(0) {
498	pExa->CheckComposite = FFBCheckComposite;
499	pExa->PrepareComposite = FFBPrepareComposite;
500	pExa->Composite = FFBComposite;
501	pExa->DoneComposite = FFBDoneCopy;
502}
503	return exaDriverInit(pScreen, pExa);
504}
505