gx_accel.c revision f29dbc25
1/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * File Contents:   This file is consists of main Xfree acceleration supported
28 *                  routines like solid fill used here.
29 *
30 * Project:         Geode Xfree Frame buffer device driver.
31 * */
32
33/* #undef OPT_ACCEL */
34
35/* Xfree86 header files */
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
40#include "vgaHW.h"
41#include "xf86.h"
42#include "xaalocal.h"
43#include "xf86fbman.h"
44#include "miline.h"
45#include "xaarop.h"
46#include "servermd.h"
47#include "picture.h"
48#include "xf86.h"
49#include "xf86_OSproc.h"
50#include "xf86Pci.h"
51#include "xf86PciInfo.h"
52#include "geode.h"
53#include "gfx_defs.h"
54#include "gfx_regs.h"
55
56/* Common macros for blend operations are here */
57
58#include "geode_blend.h"
59
60#undef ulong
61typedef unsigned long ulong;
62
63#undef uint
64typedef unsigned int uint;
65
66#undef ushort
67typedef unsigned short ushort;
68
69#undef uchar
70typedef unsigned char uchar;
71
72#define CALC_FBOFFSET(x, y) \
73	        (((ulong)(y) * gu2_pitch + ((ulong)(x) << gu2_xshift)))
74
75#define FBADDR(x,y)				\
76		((unsigned char *)pGeode->FBBase + CALC_FBOFFSET(x, y))
77
78#define OS_UDELAY 0
79#if OS_UDELAY > 0
80#define OS_USLEEP(usec) usleep(usec);
81#else
82#define OS_USLEEP(usec)
83#endif
84
85#ifdef OPT_ACCEL
86static unsigned int BPP;
87static unsigned int BLT_MODE, VEC_MODE;
88static unsigned int ACCEL_STRIDE;
89
90#define GU2_WAIT_PENDING while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING)
91#define GU2_WAIT_BUSY    while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY)
92#endif
93
94#define HOOK(fn) localRecPtr->fn = GX##fn
95
96#define DLOG(l, fmt, args...) ErrorF(fmt, ##args)
97
98/* static storage declarations */
99
100typedef struct sGBltBox
101{
102    ulong x, y;
103    ulong w, h;
104    ulong color;
105    int bpp, transparent;
106} GBltBox;
107
108#if GX_SCANLINE_SUPPORT
109static GBltBox giwr;
110#endif
111#if GX_CPU2SCREXP_SUPPORT
112static GBltBox gc2s;
113#endif
114#if GX_CLREXP_8X8_PAT_SUPPORT
115static ulong *gc8x8p;
116#endif
117
118#if GX_DASH_LINE_SUPPORT
119typedef struct sGDashLine
120{
121    ulong pat[2];
122    int len;
123    int fg;
124    int bg;
125} GDashLine;
126
127static GDashLine gdln;
128#endif
129
130static unsigned int gu2_xshift, gu2_yshift;
131static unsigned int gu2_pitch;
132
133static XAAInfoRecPtr localRecPtr;
134
135/* pat  0xF0 */
136/* src  0xCC */
137/* dst  0xAA */
138
139/* (src FUNC dst) */
140
141static const int SDfn[16] = {
142    0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE,
143    0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF
144};
145
146/* ((src FUNC dst) AND pat-mask) OR (dst AND (NOT pat-mask)) */
147
148static const int SDfn_PM[16] = {
149    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
150    0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA
151};
152
153/* (pat FUNC dst) */
154
155static const int PDfn[16] = {
156    0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA,
157    0x05, 0xA5, 0x55, 0xF5, 0x0F, 0xAF, 0x5F, 0xFF
158};
159
160/* ((pat FUNC dst) AND src-mask) OR (dst AND (NOT src-mask)) */
161
162static const int PDfn_SM[16] = {
163    0x22, 0xA2, 0x62, 0xE2, 0x2A, 0xAA, 0x6A, 0xEA,
164    0x26, 0xA6, 0x66, 0xE6, 0x2E, 0xAE, 0x6E, 0xEE
165};
166
167#ifdef OPT_ACCEL
168static inline CARD32
169amd_gx_BppToRasterMode(int bpp)
170{
171    switch (bpp) {
172    case 16:
173	return MGP_RM_BPPFMT_565;
174    case 32:
175	return MGP_RM_BPPFMT_8888;
176    case 8:
177	return MGP_RM_BPPFMT_332;
178    default:
179	return 0;
180    }
181}
182#endif /* OPT_ACCEL */
183
184/*----------------------------------------------------------------------------
185 * GXAccelSync.
186 *
187 * Description  :This function is called to synchronize with the graphics
188 *               engine and it waits the graphic engine is idle.  This is
189 *               required before allowing direct access to the framebuffer.
190 *
191 *    Arg        Type     Comment
192 *  pScrni   ScrnInfoPtr  pointer to Screeen info
193 *
194 * Returns              :none
195 *---------------------------------------------------------------------------*/
196void
197GXAccelSync(ScrnInfoPtr pScrni)
198{
199    //ErrorF("GXAccelSync()\n");
200#ifndef OPT_ACCEL
201    gfx_wait_until_idle();
202#else
203    GU2_WAIT_BUSY;
204#endif
205}
206
207#if GX_FILL_RECT_SUPPORT
208/*----------------------------------------------------------------------------
209 * GXSetupForSolidFill.
210 *
211 * Description  :The SetupFor and Subsequent SolidFill(Rect) provide
212 *               filling rectangular areas of the screen with a
213 *               foreground color.
214 *
215 * Parameters.
216 *    Arg        Type     Comment
217 *  pScrni   ScrnInfoPtr  pointer to Screeen info
218 *   color        int     foreground fill color
219 *    rop         int     unmapped raster op
220 * planemask     uint     -1 (fill) or pattern data
221 *
222 * Returns              :none
223 *--------------------------------------------------------------------------*/
224static void
225GXSetupForSolidFill(ScrnInfoPtr pScrni,
226    int color, int rop, unsigned int planemask)
227{
228    //ErrorF("GXSetupForSolidFill(%#x,%#x,%#x)\n", color, rop, planemask);
229    rop &= 0x0F;
230#ifndef OPT_ACCEL
231    gfx_set_solid_pattern(planemask);
232    gfx_set_solid_source(color);
233    gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
234#else
235    {
236	unsigned int ROP =
237	    BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
238	BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
239	if (((ROP ^ (ROP >> 1)) & 0x55) != 0)
240	    BLT_MODE |= MGP_BM_DST_REQ;
241	GU2_WAIT_PENDING;
242	WRITE_GP32(MGP_RASTER_MODE, ROP);
243	WRITE_GP32(MGP_PAT_COLOR_0, planemask);
244	WRITE_GP32(MGP_SRC_COLOR_FG, color);
245	WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
246    }
247#endif
248}
249
250/*----------------------------------------------------------------------------
251 * GXSubsequentSolidFillRect.
252 *
253 * Description  :see GXSetupForSolidFill.
254 *
255 * Parameters.
256 *    Arg        Type     Comment
257 *  pScrni   ScrnInfoPtr  pointer to Screeen info
258 *     x          int     destination x offset
259 *     y          int     destination y offset
260 *     w          int     fill area width (pixels)
261 *     h          int     fill area height (pixels)
262 *
263 * Returns      :none
264 *
265 * Sample application uses:
266 *   - Window backgrounds.
267 *   - pull down highlighting.
268 *   - x11perf: rectangle tests (-rect500).
269 *   - x11perf: fill trapezoid tests (-trap100).
270 *   - x11perf: horizontal line segments (-hseg500).
271 *----------------------------------------------------------------------------*/
272static void
273GXSubsequentSolidFillRect(ScrnInfoPtr pScrni, int x, int y, int w, int h)
274{
275    //ErrorF("GXSubsequentSolidFillRect() at %d,%d %dx%d\n", x, y, w, h);
276#ifndef OPT_ACCEL
277    gfx_pattern_fill(x, y, w, h);
278#else
279    {
280	unsigned int offset = CALC_FBOFFSET(x, y);
281	unsigned int size = (w << 16) | h;
282
283	GU2_WAIT_PENDING;
284	WRITE_GP32(MGP_DST_OFFSET, offset);
285	WRITE_GP32(MGP_WID_HEIGHT, size);
286	WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
287    }
288#endif
289}
290
291#endif /* if GX_FILL_RECT_SUPPORT */
292
293#if GX_CLREXP_8X8_PAT_SUPPORT
294/*----------------------------------------------------------------------------
295 * GXSetupForColor8x8PatternFill
296 *
297 * Description  :8x8 color pattern data is 64 pixels of full color data
298 *               stored linearly in offscreen video memory.  These patterns
299 *               are useful as a substitute for 8x8 mono patterns when tiling,
300 *               doing opaque stipples, or regular stipples.
301 *
302 *    Arg        Type     Comment
303 *  pScrni   ScrnInfoPtr  pointer to Screeen info
304 *    patx        int     x offset to pattern data
305 *    paty        int     y offset to pattern data
306 *    rop         int     unmapped raster operation
307 * planemask     uint     -1 (copy) or pattern data
308 * trans_color    int     -1 (copy) or transparent color (not enabled)
309 *                         trans color only supported on source channel
310 *                         or in monochrome pattern channel
311 *
312 * Returns      :none.
313 *
314 *---------------------------------------------------------------------------*/
315
316static void
317GXSetupForColor8x8PatternFill(ScrnInfoPtr pScrni, int patx, int paty, int rop,
318    uint planemask, int trans_color)
319{
320    GeodeRec *pGeode = GEODEPTR(pScrni);
321
322    //ErrorF("GXSetupForColor8x8PatternFill() pat %#x,%#x rop %#x %#x %#x\n",
323    //    patx, paty, rop, planemask, trans_color);
324    rop &= 0x0F;
325    gc8x8p = (unsigned long *)FBADDR(patx, paty);
326    /* gfx_set_solid_pattern is needed to clear src/pat transparency */
327    gfx_set_solid_pattern(0);
328    gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
329	(gfx_set_solid_source(planemask), PDfn_SM[rop]));
330    gfx2_set_source_stride(pGeode->Pitch);
331    gfx2_set_destination_stride(pGeode->Pitch);
332    if (trans_color == -1)
333	gfx2_set_source_transparency(0, 0);
334    else
335	gfx2_set_source_transparency(trans_color, ~0);
336}
337
338/*----------------------------------------------------------------------------
339 * GXSubsequentColor8x8PatternFillRect
340 *
341 * Description  :see GXSetupForColor8x8PatternFill.
342 *
343 *    Arg        Type     Comment
344 *  pScrni   ScrnInfoPtr  pointer to Screeen info
345 *   patx         int     pattern phase x offset
346 *   paty         int     pattern phase y offset
347 *      x         int     destination x offset
348 *      y         int     destination y offset
349 *      w         int     fill area width (pixels)
350 *      h         int     fill area height (pixels)
351 *
352 * Returns      :none
353 *
354 * Sample application uses:
355 *   - Patterned desktops
356 *   - x11perf: stippled rectangle tests (-srect500).
357 *   - x11perf: opaque stippled rectangle tests (-osrect500).
358 *--------------------------------------------------------------------------*/
359static void
360GXSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrni, int patx, int paty,
361    int x, int y, int w, int h)
362{
363    //ErrorF(
364    //    "GXSubsequentColor8x8PatternFillRect() patxy %d,%d at %d,%d %dsx%d\n",
365    //    patx, paty, x, y, w, h);
366    gfx2_set_pattern_origin(patx, paty);
367    gfx2_color_pattern_fill(CALC_FBOFFSET(x, y), w, h, gc8x8p);
368}
369
370/* GX_CLREXP_8X8_PAT_SUPPORT */
371#endif
372
373#if GX_MONO_8X8_PAT_SUPPORT
374/*----------------------------------------------------------------------------
375 * GXSetupForMono8x8PatternFill
376 *
377 * Description  :8x8 mono pattern data is 64 bits of color expansion data
378 *               with ones indicating the foreground color and zeros
379 *               indicating the background color.  These patterns are
380 *               useful when tiling, doing opaque stipples, or regular
381 *               stipples.
382 *
383 *    Arg        Type     Comment
384 *  pScrni   ScrnInfoPtr  pointer to Screeen info
385 *    patx        int     x offset to pattern data
386 *    paty        int     y offset to pattern data
387 *     fg         int     foreground color
388 *     bg         int     -1 (transparent) or background color
389 *    rop         int     unmapped raster operation
390 * planemask     uint     -1 (copy) or pattern data
391 *
392 * Returns      :none.
393 *
394 * Comments     :none.
395 *
396 *--------------------------------------------------------------------------*/
397static void
398GXSetupForMono8x8PatternFill(ScrnInfoPtr pScrni, int patx, int paty,
399    int fg, int bg, int rop, uint planemask)
400{
401    //ErrorF(
402    //"GXSetupForMono8x8PatternFill() pat %#x,%#x fg %#x bg %#x %#x %#x\n",
403    //patx, paty, fg, bg, rop, planemask);
404    rop &= 0x0F;
405#ifndef OPT_ACCEL
406    gfx_set_mono_pattern(bg, fg, patx, paty, bg == -1 ? 1 : 0);
407    gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
408	(gfx_set_solid_source(planemask), PDfn_SM[rop]));
409#else
410    {
411	unsigned int ROP = BPP |
412	    (bg ==
413	    -1 ? MGP_RM_PAT_MONO | MGP_RM_PAT_TRANS : MGP_RM_PAT_MONO) |
414	    (planemask == ~0U ? PDfn[rop] : PDfn_SM[rop]);
415	BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
416	if (((ROP ^ (ROP >> 1)) & 0x55) != 0)
417	    BLT_MODE |= MGP_BM_DST_REQ;
418	GU2_WAIT_PENDING;
419	WRITE_GP32(MGP_RASTER_MODE, ROP);
420	WRITE_GP32(MGP_SRC_COLOR_FG, planemask);
421	WRITE_GP32(MGP_PAT_COLOR_0, bg);
422	WRITE_GP32(MGP_PAT_COLOR_1, fg);
423	WRITE_GP32(MGP_PAT_DATA_0, patx);
424	WRITE_GP32(MGP_PAT_DATA_1, paty);
425	WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
426    }
427#endif
428}
429
430/*----------------------------------------------------------------------------
431 * GXSubsequentMono8x8PatternFillRect
432 *
433 * Description  :see GXSetupForMono8x8PatternFill
434 *
435 *    Arg        Type     Comment
436 *  pScrni   ScrnInfoPtr  pointer to Screeen info
437 *   patx         int     pattern phase x offset
438 *   paty         int     pattern phase y offset
439 *      x         int     destination x offset
440 *      y         int     destination y offset
441 *      w         int     fill area width (pixels)
442 *      h         int     fill area height (pixels)
443
444 * Returns      :none
445 *
446 * Sample application uses:
447 *   - Patterned desktops
448 *   - x11perf: stippled rectangle tests (-srect500).
449 *   - x11perf: opaque stippled rectangle tests (-osrect500).
450 *--------------------------------------------------------------------------*/
451static void
452GXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrni, int patx, int paty,
453    int x, int y, int w, int h)
454{
455    DEBUGMSG(1, (0, X_INFO, "%s() pat %#x,%#x at %d,%d %dx%d\n",
456	    __func__, patx, paty, x, y, w, h));
457#ifndef OPT_ACCEL
458    gfx_pattern_fill(x, y, w, h);
459#else
460    {
461	unsigned int offset =
462	    CALC_FBOFFSET(x, y) | ((x & 7) << 26) | ((y & 7) << 29);
463	unsigned int size = (w << 16) | h;
464
465	GU2_WAIT_PENDING;
466	WRITE_GP32(MGP_DST_OFFSET, offset);
467	WRITE_GP32(MGP_WID_HEIGHT, size);
468	WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
469    }
470#endif
471}
472
473#endif /* GX_MONO_8X8_PAT_SUPPORT */
474
475#if GX_SCR2SCRCPY_SUPPORT
476/*----------------------------------------------------------------------------
477 * GXSetupForScreenToScreenCopy
478 *
479 * Description  :SetupFor and Subsequent ScreenToScreenCopy functions
480 *               provide an interface for copying rectangular areas from
481 *               video memory to video memory.
482 *
483 *    Arg        Type     Comment
484 *  pScrni   ScrnInfoPtr  pointer to Screeen info
485 *   xdir         int     x copy direction (up/dn)
486 *   ydir         int     y copy direction (up/dn)
487 *    rop         int     unmapped raster operation
488 * planemask     uint     -1 (copy) or pattern data
489 * trans_color    int     -1 (copy) or transparent color
490 *
491 * Returns      :none
492 *---------------------------------------------------------------------------*/
493static void
494GXSetupForScreenToScreenCopy(ScrnInfoPtr pScrni, int xdir, int ydir, int rop,
495    uint planemask, int trans_color)
496{
497    DEBUGMSG(1, (0, X_INFO, "%s() xd%d yd%d rop %#x %#x %#x\n",
498	    __func__, xdir, ydir, rop, planemask, trans_color));
499    rop &= 0x0F;
500#ifndef OPT_ACCEL
501    {
502	GeodeRec *pGeode = GEODEPTR(pScrni);
503
504	gfx_set_solid_pattern(planemask);
505	/* transparency is a parameter to set_rop, but set...pattern clears
506	 * transparency */
507	if (trans_color == -1)
508	    gfx2_set_source_transparency(0, 0);
509	else
510	    gfx2_set_source_transparency(trans_color, ~0);
511	gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
512	gfx2_set_source_stride(pGeode->Pitch);
513	gfx2_set_destination_stride(pGeode->Pitch);
514    }
515#else
516    {
517	unsigned int ROP =
518	    BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
519	if (trans_color != -1)
520	    ROP |= MGP_RM_SRC_TRANS;
521	BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
522	    MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
523	GU2_WAIT_PENDING;
524	WRITE_GP32(MGP_RASTER_MODE, ROP);
525	WRITE_GP32(MGP_PAT_COLOR_0, planemask);
526	WRITE_GP32(MGP_SRC_COLOR_FG, trans_color);
527	WRITE_GP32(MGP_SRC_COLOR_BG, ~0);
528	WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
529    }
530#endif
531}
532
533/*----------------------------------------------------------------------------
534 * GXSubsquentScreenToScreenCopy
535 *
536 * Description  :see GXSetupForScreenToScreenCopy.
537 *
538 *    Arg        Type     Comment
539 *  pScrni   ScrnInfoPtr  pointer to Screeen info
540 *     x1         int     source x offset
541 *     y1         int     source y offset
542 *     x2         int     destination x offset
543 *     y2         int     destination y offset
544 *      w         int     copy area width (pixels)
545 *      h         int     copy area height (pixels)
546 *
547 * Returns      :none
548 *
549 * Sample application uses (non-transparent):
550 *   - Moving windows.
551 *   - x11perf: scroll tests (-scroll500).
552 *   - x11perf: copy from window to window (-copywinwin500).
553 *---------------------------------------------------------------------------*/
554static void
555GXSubsequentScreenToScreenCopy(ScrnInfoPtr pScrni,
556    int x1, int y1, int x2, int y2, int w, int h)
557{
558    DEBUGMSG(1, (0, X_INFO, "%s() from %d,%d to %d,%d %dx%d\n",
559	    __func__, x1, y1, x2, y2, w, h));
560#ifndef OPT_ACCEL
561    {
562	int flags = 0;
563
564	if (x2 > x1)
565	    flags |= 1;
566	if (y2 > y1)
567	    flags |= 2;
568	gfx2_screen_to_screen_blt(CALC_FBOFFSET(x1, y1), CALC_FBOFFSET(x2,
569		y2), w, h, flags);
570    }
571#else
572    {
573	GeodeRec *pGeode = GEODEPTR(pScrni);
574	unsigned int src = CALC_FBOFFSET(x1, y1);
575	unsigned int dst = CALC_FBOFFSET(x2, y2);
576	unsigned int size = (w << 16) | h;
577	unsigned int blt_mode = BLT_MODE;
578
579	if (x2 > x1) {
580	    int n = (w << gu2_xshift) - 1;
581
582	    src += n;
583	    dst += n;
584	    blt_mode |= MGP_BM_NEG_XDIR;
585	}
586	if (y2 > y1) {
587	    int n = (h - 1) * pGeode->Pitch;
588
589	    src += n;
590	    dst += n;
591	    blt_mode |= MGP_BM_NEG_YDIR;
592	}
593	GU2_WAIT_PENDING;
594	WRITE_GP32(MGP_SRC_OFFSET, src);
595	WRITE_GP32(MGP_DST_OFFSET, dst);
596	WRITE_GP32(MGP_WID_HEIGHT, size);
597	WRITE_GP16(MGP_BLT_MODE, blt_mode);
598    }
599#endif
600}
601
602#endif /* if GX_SCR2SCRCPY_SUPPORT */
603
604#if GX_SCANLINE_SUPPORT
605/*----------------------------------------------------------------------------
606 * GXSetupForScanlineImageWrite
607 *
608 * Description  :SetupFor/Subsequent ScanlineImageWrite and ImageWriteScanline
609 *               transfer full color pixel data from system memory to video
610 *               memory.  This is useful for dealing with alignment issues and
611 *               performing raster ops on the data.
612 *
613 *    Arg        Type     Comment
614 *  pScrni   ScrnInfoPtr  pointer to Screeen info
615 *    rop         int     unmapped raster operation
616 * planemask     uint     -1 (copy) or pattern data
617 *    bpp         int     bits per pixel (unused)
618 *  depth         int     color depth (unused)
619 *
620 * Returns      :none
621 *
622 *  x11perf -putimage10
623 *  x11perf -putimage100
624 *  x11perf -putimage500
625 *----------------------------------------------------------------------------
626 */
627static void
628GXSetupForScanlineImageWrite(ScrnInfoPtr pScrni, int rop, uint planemask,
629    int trans_color, int bpp, int depth)
630{
631    GeodeRec *pGeode = GEODEPTR(pScrni);
632
633    DEBUGMSG(1, (0, X_INFO, "%s() rop %#x %#x %#x %d %d\n",
634	    __func__, rop, planemask, trans_color, bpp, depth));
635    rop &= 0x0F;
636    /* transparency is a parameter to set_rop, but set...pattern clears
637     * transparency */
638    gfx_set_solid_pattern(planemask);
639    if (trans_color == -1)
640	gfx2_set_source_transparency(0, 0);
641    else
642	gfx2_set_source_transparency(trans_color, ~0);
643    gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
644    gfx2_set_source_stride(pGeode->Pitch);
645    gfx2_set_destination_stride(pGeode->Pitch);
646}
647
648/*----------------------------------------------------------------------------
649 * GXSubsequentScanlineImageWriteRect
650 *
651 * Description  : see GXSetupForScanlineImageWrite.
652 *
653 *    Arg        Type     Comment
654 *  pScrni   ScrnInfoPtr  pointer to Screeen info
655 *      x         int     destination x offset
656 *      y         int     destination y offset
657 *      w         int     copy area width (pixels)
658 *      h         int     copy area height (pixels)
659 * skipleft       int     x margin (pixels) to skip (not enabled)
660 *
661 * Returns      :none
662 *---------------------------------------------------------------------------*/
663static void
664GXSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrni,
665    int x, int y, int w, int h, int skipleft)
666{
667    DEBUGMSG(1, (0, X_INFO, "%s() rop %d,%d %dx%d %d\n",
668	    __func__, x, y, w, h, skipleft));
669    giwr.x = x;
670    giwr.y = y;
671    giwr.w = w;
672    giwr.h = h;
673#if !GX_USE_OFFSCRN_MEM
674#if !GX_ONE_LINE_AT_A_TIME
675    GXAccelSync(pScrni);
676#endif
677#endif
678}
679
680/*----------------------------------------------------------------------------
681 * GXSubsquentImageWriteScanline
682 *
683 * Description  : see GXSetupForScanlineImageWrite.
684 *
685 *    Arg        Type     Comment
686 *  pScrni   ScrnInfoPtr  pointer to Screeen info
687 *  bufno         int     scanline number in write group
688 *
689 * Returns      :none
690 *
691 * Sample application uses (non-transparent):
692 *   - Moving windows.
693 *   - x11perf: scroll tests (-scroll500).
694 *   - x11perf: copy from window to window (-copywinwin500).
695 *
696 *---------------------------------------------------------------------------*/
697static void
698GXSubsequentImageWriteScanline(ScrnInfoPtr pScrni, int bufno)
699{
700    GeodeRec *pGeode = GEODEPTR(pScrni);
701
702#if !GX_USE_OFFSCRN_MEM
703    unsigned long offset;
704#endif
705
706#if GX_ONE_LINE_AT_A_TIME
707    DEBUGMSG(1, (0, X_INFO, "%s() %d\n", __func__, bufno));
708#if !GX_USE_OFFSCRN_MEM
709    offset = pGeode->AccelImageWriteBuffers[bufno] - pGeode->FBBase;
710    gfx2_screen_to_screen_blt(offset, CALC_FBOFFSET(giwr.x, giwr.y), giwr.w,
711	1, 0);
712#else /* if !GX_USE_OFFSCRN_MEM */
713    gfx2_color_bitmap_to_screen_blt(0, 0, CALC_FBOFFSET(giwr.x, giwr.y),
714	giwr.w, 1, pGeode->AccelImageWriteBuffers[bufno], pGeode->Pitch);
715#endif /* if !GX_USE_OFFSCRN_MEM */
716    ++giwr.y;
717#else /* if GX_ONE_LINE_AT_A_TIME */
718    int blt_height;
719
720    DEBUGMSG(1, (0, X_INFO, "%s() %d\n", __func__, bufno));
721
722    if ((blt_height = pGeode->NoOfImgBuffers) > giwr.h)
723	blt_height = giwr.h;
724    if (++bufno < blt_height)
725	return;
726#if !GX_USE_OFFSCRN_MEM
727    offset = pGeode->AccelImageWriteBuffers[0] - pGeode->FBBase;
728    gfx2_screen_to_screen_blt(offset, CALC_FBOFFSET(giwr.x, giwr.y), giwr.w,
729	blt_height, 0);
730    GXAccelSync(pScrni);
731#else /* if !GX_USE_OFFSCRN_MEM */
732    gfx2_color_bitmap_to_screen_blt(0, 0, CALC_FBOFFSET(giwr.x, giwr.y),
733	giwr.w, blt_height, pGeode->AccelImageWriteBuffers[0], pGeode->Pitch);
734#endif /* if !GX_USE_OFFSCRN_MEM */
735    giwr.h -= blt_height;
736    giwr.y += blt_height;
737#endif /* if GX_ONE_LINE_AT_A_TIME */
738}
739#endif /* GX_SCANLINE_SUPPORT */
740
741#if GX_CPU2SCREXP_SUPPORT
742/*----------------------------------------------------------------------------
743 * GXSetupForScanlineCPUToScreenColorExpandFill
744 *
745 * Description  :SetupFor/Subsequent CPUToScreenColorExpandFill and
746 *               ColorExpandScanline routines provide an interface for
747 *               doing expansion blits from source patterns stored in
748 *               system memory.
749 *
750 *    Arg        Type     Comment
751 *  pScrni   ScrnInfoPtr  pointer to Screeen info
752 *     fg         int     foreground color
753 *     bg         int     -1 (transparent) or background color
754 *    rop         int     unmapped raster operation
755 * planemask     uint     -1 (copy) or pattern data
756 *
757 * Returns      :none.
758 *---------------------------------------------------------------------------*/
759
760static void
761GXSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrni,
762    int fg, int bg, int rop, uint planemask)
763{
764    GeodeRec *pGeode = GEODEPTR(pScrni);
765    ulong srcpitch;
766
767    DEBUGMSG(1, (0, X_INFO, "%s() fg %#x bg %#x rop %#x %#x\n",
768	    __func__, fg, bg, rop, planemask));
769    rop &= 0x0F;
770    srcpitch = ((pGeode->Pitch + 31) >> 5) << 2;
771#ifndef OPT_ACCEL
772    gfx_set_solid_pattern(planemask);
773    gfx_set_mono_source(bg, fg, bg == -1 ? 1 : 0);
774    gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
775    gfx2_set_source_stride(srcpitch);
776    gfx2_set_destination_stride(pGeode->Pitch);
777#else
778    {
779	unsigned int stride = (srcpitch << 16) | pGeode->Pitch;
780	unsigned int ROP =
781	    BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
782	if (bg == -1)
783	    ROP |= MGP_RM_SRC_TRANS;
784	BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
785	    MGP_BM_SRC_MONO | MGP_BM_SRC_FB | MGP_BM_DST_REQ :
786	    MGP_BM_SRC_MONO | MGP_BM_SRC_FB;
787	GU2_WAIT_PENDING;
788	WRITE_GP32(MGP_RASTER_MODE, ROP);
789	WRITE_GP32(MGP_PAT_COLOR_0, planemask);
790	WRITE_GP32(MGP_SRC_COLOR_BG, bg);
791	WRITE_GP32(MGP_SRC_COLOR_FG, fg);
792	WRITE_GP32(MGP_STRIDE, stride);
793    }
794#endif
795}
796
797/*----------------------------------------------------------------------------
798 * GXSubsequentScanlineCPUToScreenColorExpandFill
799 *
800  Description  :see GXSetupForScanlineCPUToScreenColorExpandFill
801 *
802 * Parameters:
803 *    Arg        Type     Comment
804 *  pScrni   ScrnInfoPtr  pointer to Screeen info
805 *     x          int     destination x offset
806 *     y          int     destination y offset
807 *     w          int     fill area width (pixels)
808 *     h          int     fill area height (pixels)
809 *
810 * Returns      :none
811 *
812 *---------------------------------------------------------------------------*/
813static void
814GXSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrni,
815    int x, int y, int w, int h, int skipleft)
816{
817    DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %dx%d %d\n",
818	    __func__, x, y, w, h, skipleft));
819    gc2s.x = x;
820    gc2s.y = y;
821    gc2s.w = w;
822    gc2s.h = h;
823#ifdef OPT_ACCEL
824    {
825#if GX_ONE_LINE_AT_A_TIME
826	unsigned int size = (gc2s.w << 16) | 1;
827
828	GU2_WAIT_PENDING;
829	WRITE_GP32(MGP_WID_HEIGHT, size);
830#else
831	GeodeRec *pGeode = GEODEPTR(pScrni);
832	unsigned int src =
833	    pGeode->AccelColorExpandBuffers[0] - pGeode->FBBase;
834	GU2_WAIT_PENDING;
835	WRITE_GP32(MGP_SRC_OFFSET, src);
836#endif
837    }
838#endif
839}
840
841/*----------------------------------------------------------------------------
842 * GXSubsequentColorExpandScanline
843 *
844 * Description  :see GXSetupForScanlineCPUToScreenColorExpandFill
845 *
846 *    Arg        Type     Comment
847 *  pScrni   ScrnInfoPtr  pointer to Screeen info
848 *  bufno         int     scanline number in write group
849 *
850 * Returns      :none
851 *----------------------------------------------------------------------------
852 */
853static void
854GXSubsequentColorExpandScanline(ScrnInfoPtr pScrni, int bufno)
855{
856    GeodeRec *pGeode = GEODEPTR(pScrni);
857
858    DEBUGMSG(1, (0, X_INFO, "%s() %d\n", __func__, bufno));
859#ifndef OPT_ACCEL
860    {
861#if GX_ONE_LINE_AT_A_TIME
862	ulong offset =
863	    pGeode->AccelColorExpandBuffers[bufno] - pGeode->FBBase;
864	gfx2_mono_expand_blt(offset, 0, 0, CALC_FBOFFSET(gc2s.x, gc2s.y),
865	    gc2s.w, 1, 0);
866	++gc2s.y;
867#else /* if GX_ONE_LINE_AT_A_TIME */
868	ulong srcpitch;
869	int blt_height;
870
871	if ((blt_height = pGeode->NoOfImgBuffers) > gc2s.h)
872	    blt_height = gc2s.h;
873	if (++bufno < blt_height)
874	    return;
875
876	/* convert from bits to dwords */
877	srcpitch = ((pGeode->Pitch + 31) >> 5) << 2;
878	gfx2_mono_bitmap_to_screen_blt(0, 0, CALC_FBOFFSET(gc2s.x, gc2s.y),
879	    gc2s.w, blt_height, pGeode->AccelColorExpandBuffers[0], srcpitch);
880	gc2s.h -= blt_height;
881	gc2s.y += blt_height;
882#endif /* if GX_ONE_LINE_AT_A_TIME */
883    }
884#else /* ifndef OPT_ACCEL */
885    {
886#if GX_ONE_LINE_AT_A_TIME
887	unsigned int src =
888	    pGeode->AccelColorExpandBuffers[bufno] - pGeode->FBBase;
889	unsigned int dst = CALC_FBOFFSET(gc2s.x, gc2s.y);
890
891	++gc2s.y;
892	GU2_WAIT_PENDING;
893	WRITE_GP32(MGP_SRC_OFFSET, src);
894	WRITE_GP32(MGP_DST_OFFSET, dst);
895	WRITE_GP16(MGP_BLT_MODE, BLT_MODE);
896#else /* if GX_ONE_LINE_AT_A_TIME */
897	unsigned int dst, size;
898	int blt_height;
899
900	GU2_WAIT_BUSY;
901	if ((blt_height = pGeode->NoOfImgBuffers) > gc2s.h)
902	    blt_height = gc2s.h;
903	if (++bufno < blt_height)
904	    return;
905	dst = CALC_FBOFFSET(gc2s.x, gc2s.y);
906	size = (gc2s.w << 16) | blt_height;
907	gc2s.h -= blt_height;
908	gc2s.y += blt_height;
909	GU2_WAIT_PENDING;
910	WRITE_GP32(MGP_DST_OFFSET, dst);
911	WRITE_GP32(MGP_WID_HEIGHT, size);
912	WRITE_GP16(MGP_BLT_MODE, BLT_MODE);
913#endif /* if GX_ONE_LINE_AT_A_TIME */
914    }
915#endif /* ifndef OPT_ACCEL */
916}
917#endif /* GX_CPU2SCREXP_SUPPORT */
918
919#if GX_SCR2SCREXP_SUPPORT
920/*----------------------------------------------------------------------------
921 * GXSetupForScreenToScreenColorExpandFill
922 *
923 * Description  :SetupFor/Subsequent ScreenToScreenColorExpandFill and
924 *               ColorExpandScanline routines provide an interface for
925 *               doing expansion blits from source patterns stored in
926 *               video memory.
927 *
928 *    Arg        Type     Comment
929 *  pScrni   ScrnInfoPtr  pointer to Screeen info
930 *     fg         int     foreground color
931 *     bg         int     -1 (transparent) or background color
932 *    rop         int     unmapped raster operation
933 * planemask     uint     -1 (copy) or pattern data
934 *
935 * Returns      :none.
936 *---------------------------------------------------------------------------*/
937
938static void
939GXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrni, int fg, int bg,
940    int rop, uint planemask)
941{
942    DEBUGMSG(1, (0, X_INFO, "%s() fg %#x bg %#x rop %#x %#x\n",
943	    __func__, fg, bg, rop, planemask));
944    rop &= 0x0F;
945#ifndef OPT_ACCEL
946    {
947	GeodeRec *pGeode = GEODEPTR(pScrni);
948
949	gfx_set_solid_pattern(planemask);
950	gfx_set_mono_source(bg, fg, bg == -1 ? 1 : 0);
951	gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
952	gfx2_set_source_stride(pGeode->Pitch);
953	gfx2_set_destination_stride(pGeode->Pitch);
954    }
955#else
956    {
957	unsigned int ROP =
958	    BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
959	if (bg == -1)
960	    ROP |= MGP_RM_SRC_TRANS;
961	BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
962	    MGP_BM_SRC_MONO | MGP_BM_SRC_FB | MGP_BM_DST_REQ :
963	    MGP_BM_SRC_MONO | MGP_BM_SRC_FB;
964	GU2_WAIT_PENDING;
965	WRITE_GP32(MGP_RASTER_MODE, ROP);
966	WRITE_GP32(MGP_PAT_COLOR_0, planemask);
967	WRITE_GP32(MGP_SRC_COLOR_BG, bg);
968	WRITE_GP32(MGP_SRC_COLOR_FG, fg);
969	WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
970    }
971#endif
972}
973
974/*----------------------------------------------------------------------------
975 * GXSubsequentScreenToScreenColorExpandFill
976 *
977 * Description  :see GXSetupForScreenToScreenColorExpandFill
978 *
979 * Parameters:
980 *    Arg        Type     Comment
981 *  pScrni   ScrnInfoPtr  pointer to Screeen info
982 *     x          int     destination x offset
983 *     y          int     destination y offset
984 *     w          int     fill area width (pixels)
985 *     h          int     fill area height (pixels)
986 * offset         int     initial x offset
987 *
988 * Returns      :none
989 *
990 *---------------------------------------------------------------------------*/
991static void
992GXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrni,
993    int x, int y, int w, int h, int srcx, int srcy, int offset)
994{
995    DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %dx%d %d,%d %d\n",
996	    __func__, x, y, w, h, srcx, srcy, offset));
997#ifndef OPT_ACCEL
998    gfx2_mono_expand_blt(CALC_FBOFFSET(srcx, srcy), offset, 0,
999	CALC_FBOFFSET(x, y), w, h, 0);
1000#else
1001    {
1002	unsigned int src = (CALC_FBOFFSET(srcx,
1003		srcy) + (offset >> 3)) | ((offset & 7) << 26);
1004	unsigned int dst = CALC_FBOFFSET(x, y);
1005	unsigned int size = (w << 16) | h;
1006
1007	GU2_WAIT_PENDING;
1008	WRITE_GP32(MGP_SRC_OFFSET, src);
1009	WRITE_GP32(MGP_DST_OFFSET, dst);
1010	WRITE_GP32(MGP_WID_HEIGHT, size);
1011	WRITE_GP16(MGP_BLT_MODE, BLT_MODE);
1012    }
1013#endif
1014}
1015#endif /* GX_SCR2SCREXP_SUPPORT */
1016
1017#define VM_MAJOR_DEC 0
1018#define VM_MINOR_DEC 0
1019
1020static unsigned short vmode[] = {
1021    VM_X_MAJOR | VM_MAJOR_INC | VM_MINOR_INC,
1022    /* !XDECREASING !YDECREASING !YMAJOR */
1023    VM_Y_MAJOR | VM_MAJOR_INC | VM_MINOR_INC,
1024    /* !XDECREASING !YDECREASING  YMAJOR */
1025    VM_X_MAJOR | VM_MAJOR_INC | VM_MINOR_DEC,
1026    /* !XDECREASING  YDECREASING !YMAJOR */
1027    VM_Y_MAJOR | VM_MAJOR_DEC | VM_MINOR_INC,
1028    /* !XDECREASING  YDECREASING  YMAJOR */
1029    VM_X_MAJOR | VM_MAJOR_DEC | VM_MINOR_INC,
1030    /*  XDECREASING !YDECREASING !YMAJOR */
1031    VM_Y_MAJOR | VM_MAJOR_INC | VM_MINOR_DEC,
1032    /*  XDECREASING !YDECREASING  YMAJOR */
1033    VM_X_MAJOR | VM_MAJOR_DEC | VM_MINOR_DEC,
1034    /*  XDECREASING  YDECREASING !YMAJOR */
1035    VM_Y_MAJOR | VM_MAJOR_DEC | VM_MINOR_DEC,
1036    /*  XDECREASING  YDECREASING  YMAJOR */
1037};
1038
1039#if GX_BRES_LINE_SUPPORT
1040/*----------------------------------------------------------------------------
1041 * GXSetupForSolidLine
1042 *
1043 * Description  :SetupForSolidLine and Subsequent HorVertLine TwoPointLine
1044 *               BresenhamLine provides an interface for drawing thin
1045 *               solid lines.
1046 *
1047 *    Arg        Type     Comment
1048 *  pScrni   ScrnInfoPtr  pointer to Screeen info
1049 *   color        int     foreground fill color
1050 *    rop         int     unmapped raster op
1051 * planemask     uint     -1 (fill) or pattern data (not enabled)
1052 *
1053 * Returns		:none
1054 *---------------------------------------------------------------------------*/
1055static void
1056GXSetupForSolidLine(ScrnInfoPtr pScrni, int color, int rop, uint planemask)
1057{
1058    DEBUGMSG(1, (0, X_INFO, "%s() %#x %#x %#x\n",
1059	    __func__, color, rop, planemask));
1060    rop &= 0x0F;
1061#ifndef OPT_ACCEL
1062    gfx_set_solid_pattern(color);
1063    gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
1064	(gfx_set_solid_source(planemask), PDfn_SM[rop]));
1065#else
1066    {
1067	unsigned int ROP =
1068	    BPP | (planemask == ~0U ? PDfn[rop] : PDfn_SM[rop]);
1069	BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
1070	VEC_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ? ((BLT_MODE |=
1071		MGP_BM_DST_REQ), MGP_VM_DST_REQ) : 0;
1072	GU2_WAIT_PENDING;
1073	WRITE_GP32(MGP_RASTER_MODE, ROP);
1074	WRITE_GP32(MGP_PAT_COLOR_0, color);
1075	WRITE_GP32(MGP_SRC_COLOR_FG, planemask);
1076	WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
1077    }
1078#endif
1079}
1080
1081/*---------------------------------------------------------------------------
1082 * GXSubsequentSolidBresenhamLine
1083 *
1084 * Description  :see GXSetupForSolidLine
1085 *
1086 *    Arg        Type     Comment
1087 *  pScrni   ScrnInfoPtr  pointer to Screeen info
1088 *     x1         int     destination x offset
1089 *     y1         int     destination y offset
1090 * absmaj         int     Bresenman absolute major
1091 * absmin         int     Bresenman absolute minor
1092 *    err         int     Bresenman initial error term
1093 *    len         int     length of the vector (pixels)
1094 * octant         int     specifies sign and magnitude relationships
1095 *                         used to determine axis of magor rendering
1096 *                         and direction of vector progress.
1097 *
1098 * Returns      :none
1099 *
1100 *   - Window outlines on window move.
1101 *   - x11perf: line segments (-line500).
1102 *   - x11perf: line segments (-seg500).
1103 *---------------------------------------------------------------------------*/
1104static void
1105GXSubsequentSolidBresenhamLine(ScrnInfoPtr pScrni, int x1, int y1,
1106    int absmaj, int absmin, int err, int len, int octant)
1107{
1108    long axial, diagn;
1109
1110    DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %d %d, %d %d, %d\n",
1111	    __func__, x1, y1, absmaj, absmin, err, len, octant));
1112    if (len <= 0)
1113	return;
1114    axial = absmin;
1115    err += axial;
1116    diagn = absmin - absmaj;
1117#ifndef OPT_ACCEL
1118    gfx_bresenham_line(x1, y1, len, err, axial, diagn, vmode[octant]);
1119#else
1120    {
1121	unsigned int offset = CALC_FBOFFSET(x1, y1);
1122	unsigned int vec_err = (axial << 16) | (unsigned short)diagn;
1123	unsigned int vec_len = (len << 16) | (unsigned short)err;
1124	unsigned int vec_mode = VEC_MODE | vmode[octant];
1125
1126	GU2_WAIT_PENDING;
1127	WRITE_GP32(MGP_DST_OFFSET, offset);
1128	WRITE_GP32(MGP_VEC_ERR, vec_err);
1129	WRITE_GP32(MGP_VEC_LEN, vec_len);
1130	WRITE_GP32(MGP_VECTOR_MODE, vec_mode);
1131    }
1132#endif
1133}
1134
1135/*---------------------------------------------------------------------------
1136 * GXSubsequentSolidTwoPointLine
1137 *
1138 * Description  :see GXSetupForSolidLine
1139 *
1140 *    Arg        Type     Comment
1141 *  pScrni   ScrnInfoPtr  pointer to Screeen info
1142 *     x0         int     destination x start offset
1143 *     y0         int     destination y start offset
1144 *     x1         int     destination x end offset
1145 *     y1         int     destination y end offset
1146 *  flags         int     OMIT_LAST, dont draw last pixel (not used)
1147 *
1148 * Returns      :none
1149 *---------------------------------------------------------------------------*/
1150static void
1151GXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrni, int x0, int y0,
1152    int x1, int y1, int flags)
1153{
1154    long dx, dy, dmaj, dmin, octant, bias;
1155    long axial, diagn, err, len;
1156
1157    DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %d,%d, %#x\n",
1158	    __func__, x0, y0, x1, y1, flags));
1159
1160    if ((dx = x1 - x0) < 0)
1161	dx = -dx;
1162    if ((dy = y1 - y0) < 0)
1163	dy = -dy;
1164    if (dy >= dx) {
1165	dmaj = dy;
1166	dmin = dx;
1167	octant = YMAJOR;
1168    } else {
1169	dmaj = dx;
1170	dmin = dy;
1171	octant = 0;
1172    }
1173    len = dmaj;
1174    if ((flags & OMIT_LAST) == 0)
1175	++len;
1176    if (len <= 0)
1177	return;
1178    if (x1 < x0)
1179	octant |= XDECREASING;
1180    if (y1 < y0)
1181	octant |= YDECREASING;
1182
1183    axial = dmin << 1;
1184    bias = miGetZeroLineBias(pScrni->pScreen);
1185    err = axial - dmaj - ((bias >> octant) & 1);
1186    diagn = (dmin - dmaj) << 1;
1187
1188#ifndef OPT_ACCEL
1189    gfx_bresenham_line(x0, y0, len, err, axial, diagn, vmode[octant]);
1190#else
1191    {
1192	unsigned int offset = CALC_FBOFFSET(x0, y0);
1193	unsigned int vec_err = (axial << 16) | (unsigned short)diagn;
1194	unsigned int vec_len = (len << 16) | (unsigned short)err;
1195	unsigned int vec_mode = VEC_MODE | vmode[octant];
1196
1197	GU2_WAIT_PENDING;
1198	WRITE_GP32(MGP_DST_OFFSET, offset);
1199	WRITE_GP32(MGP_VEC_ERR, vec_err);
1200	WRITE_GP32(MGP_VEC_LEN, vec_len);
1201	WRITE_GP32(MGP_VECTOR_MODE, vec_mode);
1202    }
1203#endif
1204}
1205
1206/*---------------------------------------------------------------------------
1207 * GXSubsequentSolidHorVertLine
1208 *
1209 * Description  :see GXSetupForSolidLine
1210 *
1211 *    Arg        Type     Comment
1212 *  pScrni   ScrnInfoPtr  pointer to Screeen info
1213 *     x          int     destination x offset
1214 *     y          int     destination y offset
1215 *    len         int     length of the vector (pixels)
1216 *    dir         int     DEGREES_270 or DEGREES_0 line direction
1217 *
1218 * Sample application uses:
1219 *   - Window outlines on window move.
1220 *   - x11perf: line segments (-hseg500).
1221 *   - x11perf: line segments (-vseg500).
1222 *---------------------------------------------------------------------------
1223 */
1224static void
1225GXSubsequentSolidHorVertLine(ScrnInfoPtr pScrni,
1226    int x, int y, int len, int dir)
1227{
1228    DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %d %d\n", __func__, x, y, len, dir));
1229#ifndef OPT_ACCEL
1230    if (dir == DEGREES_0)
1231	gfx_pattern_fill(x, y, len, 1);
1232    else
1233	gfx_pattern_fill(x, y, 1, len);
1234#else
1235    {
1236	unsigned int offset = CALC_FBOFFSET(x, y);
1237	unsigned int size =
1238	    dir == DEGREES_0 ? (len << 16) | 1 : (1 << 16) | len;
1239	GU2_WAIT_PENDING;
1240	WRITE_GP32(MGP_DST_OFFSET, offset);
1241	WRITE_GP32(MGP_WID_HEIGHT, size);
1242	WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
1243    }
1244#endif
1245}
1246#endif /* GX_BRES_LINE_SUPPORT */
1247
1248#if GX_DASH_LINE_SUPPORT
1249/*----------------------------------------------------------------------------
1250 * GXSetupForDashedLine
1251 *
1252 * Description  :SetupForDashedLine and Subsequent TwoPointLine
1253 *               BresenhamLine provides an interface for drawing thin
1254 *               dashed lines.
1255 *
1256 *    Arg        Type     Comment
1257 *  pScrni   ScrnInfoPtr  pointer to Screeen info
1258 *     fg         int     foreground fill color
1259 *     bg         int     -1 (transp) or background fill color
1260 *    rop         int     unmapped raster op
1261 * planemask     uint     -1 (fill) or pattern data (not enabled)
1262 *  length        int     pattern length (bits)
1263 * pattern     uchar*     dash pattern mask
1264 *
1265 * Returns              :none
1266 *---------------------------------------------------------------------------*/
1267static void
1268GXSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
1269    unsigned int planemask, int length, unsigned char *pattern)
1270{
1271    int i, l, n, m;
1272    CARD32 pat = *pattern;
1273    CARD32 pat8x8[2];
1274
1275    if (length <= 0)
1276	return;
1277    i = l = m = 0;
1278    while (i < 2) {
1279	m |= pat >> l;
1280	l += length;
1281	if ((n = l - 32) >= 0) {
1282	    pat8x8[i++] = m;
1283	    m = pat << (length - n);
1284	    l = n;
1285	}
1286    }
1287    gdln.pat[0] = pat8x8[0];
1288    gdln.pat[1] = pat8x8[1];
1289    gdln.len = length;
1290    gdln.fg = fg;
1291    gdln.bg = bg;
1292    rop &= 0x0F;
1293    gfx_set_solid_pattern(0);
1294    gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
1295	(gfx_set_solid_source(planemask), PDfn_SM[rop]));
1296}
1297
1298/*---------------------------------------------------------------------------
1299 * GXSubsequentDashedBresenhamLine
1300 *
1301 * Description:		This function is used to render a vector using the
1302 *                 	specified bresenham parameters.
1303 *
1304 * Parameters:
1305 *		pScrni:		Screen handler pointer having screen information.
1306 *      x1:  		Specifies the starting x position
1307 *      y1:      	Specifies starting y possition
1308 *      absmaj:		Specfies the Bresenman absolute major.
1309 *		absmin:		Specfies the Bresenman absolute minor.
1310 *		err:     	Specifies the bresenham err term.
1311 *		len:     	Specifies the length of the vector interms of pixels.
1312 *		octant:  	not used in this function,may be added for standard
1313 *               	interface.
1314 *
1315 * Returns:			none
1316 *
1317 * Comments:		none
1318 *
1319 * Sample application uses:
1320 *   - Window outlines on window move.
1321 *   - x11perf: line segments (-line500).
1322 *   - x11perf: line segments (-seg500).
1323 *----------------------------------------------------------------------------
1324 */
1325static void
1326GXSubsequentDashedBresenhamLine(ScrnInfoPtr pScrni,
1327    int x1, int y1, int absmaj, int absmin,
1328    int err, int len, int octant, int phase)
1329{
1330    int i, n;
1331    int axial, diagn;
1332    int trans = (gdln.bg == -1);
1333    unsigned long pat8x8[2];
1334
1335    //ErrorF("BLine %d, %d, %d, %d, %d, %d, %d\n" x1, y1, absmaj, absmin,
1336    //err, len, octant);
1337
1338    i = phase >= 32 ? (phase -= 32, 1) : 0;
1339    n = 32 - phase;
1340    pat8x8[0] =
1341	((gdln.pat[i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[1 - i] << n);
1342    pat8x8[1] =
1343	((gdln.pat[1 - i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[i] << n);
1344    axial = absmin;
1345    err += axial;
1346    diagn = absmin - absmaj;
1347    gfx_set_mono_pattern(gdln.bg, gdln.fg, pat8x8[0], pat8x8[1], trans);
1348    gfx2_set_pattern_origin(x1, y1);
1349    gfx2_bresenham_line(CALC_FBOFFSET(x1, y1), len, err, axial, diagn,
1350	vmode[octant]);
1351}
1352
1353/*---------------------------------------------------------------------------
1354 * GXSubsequentDashedTwoPointLine
1355 *
1356 * Description  :see GXSetupForDashedLine
1357 *
1358 *    Arg        Type     Comment
1359 *  pScrni   ScrnInfoPtr  pointer to Screeen info
1360 *     x0         int     destination x start offset
1361 *     y0         int     destination y start offset
1362 *     x1         int     destination x end offset
1363 *     y1         int     destination y end offset
1364 *  flags         int     OMIT_LAST, dont draw last pixel (not used)
1365 *  phase         int     initial pattern offset at x1,y1
1366 *
1367 * Returns      :none
1368 *---------------------------------------------------------------------------*/
1369static void
1370GXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrni, int x0, int y0,
1371    int x1, int y1, int flags, int phase)
1372{
1373    int i, n;
1374    long dx, dy, dmaj, dmin, octant, bias;
1375    long axial, diagn, err, len, pat8x8[2];
1376
1377    //ErrorF("GXSubsequentDashedTwoPointLine() %d,%d %d,%d, %#x %d\n",
1378    //   x0, y0, x1, y1, flags, phase);
1379
1380    i = phase >= 32 ? (phase -= 32, 1) : 0;
1381    n = 32 - phase;
1382    pat8x8[0] =
1383	((gdln.pat[i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[1 - i] << n);
1384    pat8x8[1] =
1385	((gdln.pat[1 - i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[i] << n);
1386
1387    if ((dx = x1 - x0) < 0)
1388	dx = -dx;
1389    if ((dy = y1 - y0) < 0)
1390	dy = -dy;
1391    if (dy >= dx) {
1392	dmaj = dy;
1393	dmin = dx;
1394	octant = YMAJOR;
1395    } else {
1396	dmaj = dx;
1397	dmin = dy;
1398	octant = 0;
1399    }
1400    len = dmaj;
1401    if ((flags & OMIT_LAST) == 0)
1402	++len;
1403    if (len <= 0)
1404	return;
1405    if (x1 < x0)
1406	octant |= XDECREASING;
1407    if (y1 < y0)
1408	octant |= YDECREASING;
1409
1410    axial = dmin << 1;
1411    bias = miGetZeroLineBias(pScrni->pScreen);
1412    err = axial - dmaj - ((bias >> octant) & 1);
1413    diagn = (dmin - dmaj) << 1;
1414
1415    gfx2_set_pattern_origin(x0, y0);
1416    gfx2_bresenham_line(CALC_FBOFFSET(x0, y0), len, err, axial, diagn,
1417	vmode[octant]);
1418
1419}
1420#endif /* GX_DASH_LINE_SUPPORT */
1421
1422#if GX_WRITE_PIXMAP_SUPPORT
1423static void
1424GXWritePixmap(ScrnInfoPtr pScrni, int x, int y, int w, int h,
1425    unsigned char *src, int srcwidth, int rop, unsigned int planemask,
1426    int trans, int bpp, int depth)
1427{
1428    GeodeRec *pGeode = GEODEPTR(pScrni);
1429
1430    //ErrorF("GXWritePixmap() %d,%d %dx%d, s%#x sp%d %#x %#x %#x %d %d\n",
1431    //    x, y, w, h, src, srcwidth, rop, planemask, trans, bpp, depth);
1432
1433    if (bpp == pScrni->bitsPerPixel) {
1434	rop &= 0x0F;
1435	if (rop == GXcopy && trans == -1) {
1436	    gfx_wait_until_idle();
1437	    geode_memory_to_screen_blt((unsigned long)src,
1438		(unsigned long)FBADDR(x, y), srcwidth, pGeode->Pitch, w,
1439		h, bpp);
1440	} else {
1441	    gfx_set_solid_pattern(planemask);
1442	    gfx_set_raster_operation(planemask ==
1443		~0U ? SDfn[rop] : SDfn_PM[rop]);
1444	    if (trans != -1)
1445		gfx_color_bitmap_to_screen_xblt(0, 0, x, y, w, h, src,
1446		    srcwidth, trans);
1447	    else
1448		gfx_color_bitmap_to_screen_blt(0, 0, x, y, w, h, src,
1449		    srcwidth);
1450	    SET_SYNC_FLAG(pGeode->AccelInfoRec);
1451	}
1452    } else
1453	pGeode->WritePixmap(pScrni, x, y, w, h, src, srcwidth, rop, planemask,
1454	    trans, bpp, depth);
1455}
1456#endif /* if GX_WRITE_PIXMAP_SUPPORT */
1457
1458#if XF86EXA
1459
1460static void
1461amd_gx_exa_WaitMarker(ScreenPtr pScreen, int Marker)
1462{
1463    GU2_WAIT_BUSY;
1464}
1465
1466static void
1467amd_gx_exa_Done(PixmapPtr p)
1468{
1469}
1470
1471static Bool
1472amd_gx_exa_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
1473    char *src, int src_pitch)
1474{
1475    char *dst = pDst->devPrivate.ptr;
1476    int dst_pitch = exaGetPixmapPitch(pDst);
1477    int bpp = pDst->drawable.bitsPerPixel;
1478
1479    dst += y * dst_pitch + x * (bpp >> 3);
1480    GU2_WAIT_BUSY;
1481    geode_memory_to_screen_blt((unsigned long)src, (unsigned long)dst,
1482	src_pitch, dst_pitch, w, h, bpp);
1483    return TRUE;
1484}
1485
1486static Bool
1487amd_gx_exa_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
1488    char *dst, int dst_pitch)
1489{
1490    char *src = pSrc->devPrivate.ptr;
1491    int src_pitch = exaGetPixmapPitch(pSrc);
1492    int bpp = pSrc->drawable.bitsPerPixel;
1493
1494    src += (y * src_pitch) + (x * (bpp >> 3));
1495    GU2_WAIT_BUSY;
1496    geode_memory_to_screen_blt((unsigned long)src, (unsigned long)dst,
1497	src_pitch, dst_pitch, w, h, bpp);
1498    return TRUE;
1499}
1500
1501/* Solid */
1502
1503static Bool
1504amd_gx_exa_PrepareSolid(PixmapPtr pxMap, int alu, Pixel planemask, Pixel fg)
1505{
1506    int dstPitch = exaGetPixmapPitch(pxMap);
1507    unsigned int ROP = amd_gx_BppToRasterMode(pxMap->drawable.bitsPerPixel)
1508	| (planemask == ~0U ? SDfn[alu] : SDfn_PM[alu]);
1509
1510    //  FIXME: this should go away -- workaround for the blockparty icon corruption
1511    //if (pxMap->drawable.bitsPerPixel == 32)
1512    //  return FALSE;
1513
1514    BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
1515    if (((ROP ^ (ROP >> 1)) & 0x55) != 0)
1516	BLT_MODE |= MGP_BM_DST_REQ;
1517    //ErrorF("amd_gx_exa_PrepareSolid(%#x,%#x,%#x - ROP=%x,BLT_MODE=%x)\n", alu, planemask, fg, ROP, BLT_MODE);
1518    GU2_WAIT_PENDING;
1519    WRITE_GP32(MGP_RASTER_MODE, ROP);
1520    WRITE_GP32(MGP_PAT_COLOR_0, planemask);
1521    WRITE_GP32(MGP_SRC_COLOR_FG, fg);
1522    WRITE_GP32(MGP_STRIDE, dstPitch);
1523    return TRUE;
1524}
1525
1526static void
1527amd_gx_exa_Solid(PixmapPtr pxMap, int x1, int y1, int x2, int y2)
1528{
1529    int bpp = (pxMap->drawable.bitsPerPixel + 7) / 8;
1530    int pitch = exaGetPixmapPitch(pxMap);
1531    unsigned int offset = exaGetPixmapOffset(pxMap) + pitch * y1 + bpp * x1;
1532    unsigned int size = ((x2 - x1) << 16) | (y2 - y1);
1533
1534    //ErrorF("amd_gx_exa_Solid() at %d,%d %d,%d - offset=%d, bpp=%d\n", x1, y1, x2, y2, offset, bpp);
1535
1536    GU2_WAIT_PENDING;
1537    WRITE_GP32(MGP_DST_OFFSET, offset);
1538    WRITE_GP32(MGP_WID_HEIGHT, size);
1539    WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
1540}
1541
1542/* Copy */
1543
1544static Bool
1545amd_gx_exa_PrepareCopy(PixmapPtr pxSrc, PixmapPtr pxDst, int dx, int dy,
1546    int alu, Pixel planemask)
1547{
1548    GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
1549    int dstPitch = exaGetPixmapPitch(pxDst);
1550    unsigned int ROP;
1551
1552    /* Punt if the color formats aren't the same */
1553
1554    if (pxSrc->drawable.bitsPerPixel != pxDst->drawable.bitsPerPixel)
1555	return FALSE;
1556
1557    //ErrorF("amd_gx_exa_PrepareCopy() dx%d dy%d alu %#x %#x\n",
1558    //  dx, dy, alu, planemask);
1559
1560    pGeode->cpySrcOffset = exaGetPixmapOffset(pxSrc);
1561    pGeode->cpySrcPitch = exaGetPixmapPitch(pxSrc);
1562    pGeode->cpySrcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8;
1563    pGeode->cpyDx = dx;
1564    pGeode->cpyDy = dy;
1565    ROP = amd_gx_BppToRasterMode(pxSrc->drawable.bitsPerPixel) |
1566	(planemask == ~0U ? SDfn[alu] : SDfn_PM[alu]);
1567
1568    BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
1569	MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
1570    GU2_WAIT_PENDING;
1571    WRITE_GP32(MGP_RASTER_MODE, ROP);
1572    WRITE_GP32(MGP_PAT_COLOR_0, planemask);
1573    WRITE_GP32(MGP_SRC_COLOR_FG, ~0);
1574    WRITE_GP32(MGP_SRC_COLOR_BG, ~0);
1575    WRITE_GP32(MGP_STRIDE, (pGeode->cpySrcPitch << 16) | dstPitch);
1576    return TRUE;
1577}
1578
1579static void
1580amd_gx_exa_Copy(PixmapPtr pxDst, int srcX, int srcY, int dstX, int dstY,
1581    int w, int h)
1582{
1583    GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
1584    int dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8;
1585    int dstPitch = exaGetPixmapPitch(pxDst);
1586    unsigned int srcOffset =
1587	pGeode->cpySrcOffset + (pGeode->cpySrcPitch * srcY) +
1588	(pGeode->cpySrcBpp * srcX);
1589    unsigned int dstOffset =
1590	exaGetPixmapOffset(pxDst) + (dstPitch * dstY) + (dstBpp * dstX);
1591    unsigned int size = (w << 16) | h;
1592    unsigned int blt_mode = BLT_MODE;
1593
1594    //ErrorF("amd_gx_exa_Copy() from %d,%d to %d,%d %dx%d\n", srcX, srcY,
1595    //   dstX, dstY, w, h);
1596
1597    if (pGeode->cpyDx < 0) {
1598	srcOffset += w * pGeode->cpySrcBpp - 1;
1599	dstOffset += w * dstBpp - 1;
1600	blt_mode |= MGP_BM_NEG_XDIR;
1601    }
1602    if (pGeode->cpyDy < 0) {
1603	srcOffset += (h - 1) * pGeode->cpySrcPitch;
1604	dstOffset += (h - 1) * dstPitch;
1605	blt_mode |= MGP_BM_NEG_YDIR;
1606    }
1607    GU2_WAIT_PENDING;
1608    WRITE_GP32(MGP_SRC_OFFSET, srcOffset);
1609    WRITE_GP32(MGP_DST_OFFSET, dstOffset);
1610    WRITE_GP32(MGP_WID_HEIGHT, size);
1611    WRITE_GP16(MGP_BLT_MODE, blt_mode);
1612}
1613
1614/* A=SRC, B=DST */
1615#define SRC_DST 0
1616/* B=SRC, A=DST */
1617#define DST_SRC MGP_RM_DEST_FROM_CHAN_A
1618/* A*alpha + B*0         */
1619#define Aa_B0   MGP_RM_ALPHA_TIMES_A
1620/* A*0     + B*(1-alpha) */
1621#define A0_B1a  MGP_RM_BETA_TIMES_B
1622/* A*1     + B*(1-alpha) */
1623#define A1_B1a  MGP_RM_A_PLUS_BETA_B
1624/* A*alpha + B*(1-alpha) */
1625#define Aa_B1a  MGP_RM_ALPHA_A_PLUS_BETA_B
1626/* alpha from A */
1627#define a_A MGP_RM_SELECT_ALPHA_A
1628/* alpha from B */
1629#define a_B MGP_RM_SELECT_ALPHA_B
1630/* alpha from const */
1631#define a_C MGP_RM_SELECT_ALPHA_R
1632/* alpha = 1 */
1633#define a_1 MGP_RM_SELECT_ALPHA_1
1634
1635#define MGP_RM_ALPHA_TO_ARGB (MGP_RM_ALPHA_TO_ALPHA | MGP_RM_ALPHA_TO_RGB)
1636#define gxPictOpMAX PictOpAdd	       /* highest accelerated op */
1637
1638unsigned int amd_gx_exa_alpha_ops[] =
1639/*    A   B      OP     AS           const = 0 */
1640{
1641    (SRC_DST | Aa_B0 | a_C), 0,	       /* clear    (src*0) */
1642    (SRC_DST | Aa_B0 | a_1), 0,	       /* src      (src*1) */
1643    (DST_SRC | Aa_B0 | a_1), 0,	       /* dst      (dst*1) */
1644    (SRC_DST | A1_B1a | a_A), 0,       /* src-over (src*1 + dst(1-A)) */
1645    (DST_SRC | A1_B1a | a_A), 0,       /* dst-over (dst*1 + src(1-B)) */
1646    (SRC_DST | Aa_B0 | a_B), 0,	       /* src-in   (src*B) */
1647    (DST_SRC | Aa_B0 | a_B), 0,	       /* dst-in   (dst*A) */
1648    (DST_SRC | A0_B1a | a_A), 0,       /* src-out  (src*(1-B)) */
1649    (SRC_DST | A0_B1a | a_A), 0,       /* dst-out  (dst*(1-A)) */
1650/* pass1 (SRC=dst DST=scr=src), pass2 (SRC=src, DST=dst) */
1651    (DST_SRC | Aa_B0 | a_B),	       /* srcatop  (src*B) */
1652    (SRC_DST | A0_B1a | a_A),	       /*                  + (dst(1-A)) */
1653    (SRC_DST | Aa_B0 | a_B),	       /* dstatop  (dst*A) */
1654    (DST_SRC | A0_B1a | a_A),	       /*                  + (src(1-B) */
1655    (SRC_DST | A0_B1a | a_A),	       /* xor      (src*(1-B) */
1656    (SRC_DST | A0_B1a | a_A),	       /*                  + (dst(1-A) */
1657    (SRC_DST | A1_B1a | a_C), 0,       /* add      (src*1 + dst*1) */
1658};
1659
1660typedef struct
1661{
1662    int exa_fmt;
1663    int bpp;
1664    int gx_fmt;
1665    int alpha_bits;
1666} amd_gx_exa_fmt_t;
1667
1668amd_gx_exa_fmt_t amd_gx_exa_fmts[] = {
1669    {PICT_a8r8g8b8, 32, MGP_RM_BPPFMT_8888, 8},
1670    {PICT_x8r8g8b8, 32, MGP_RM_BPPFMT_8888, 0},
1671    {PICT_a4r4g4b4, 16, MGP_RM_BPPFMT_4444, 4},
1672    {PICT_a1r5g5b5, 16, MGP_RM_BPPFMT_1555, 1},
1673    {PICT_r5g6b5, 16, MGP_RM_BPPFMT_565, 0},
1674    {PICT_r3g3b2, 8, MGP_RM_BPPFMT_332, 0},
1675};
1676
1677static amd_gx_exa_fmt_t *
1678amd_gx_exa_check_format(PicturePtr p)
1679{
1680    int i;
1681    int bpp = p->pDrawable ? p->pDrawable->bitsPerPixel : 0;
1682    amd_gx_exa_fmt_t *fp = &amd_gx_exa_fmts[0];
1683
1684    for (i = sizeof(amd_gx_exa_fmts) / sizeof(amd_gx_exa_fmts[0]); --i >= 0;
1685	++fp) {
1686	if (fp->bpp < bpp)
1687	    return NULL;
1688	if (fp->bpp != bpp)
1689	    continue;
1690	if (fp->exa_fmt == p->format)
1691	    break;
1692    }
1693    return i < 0 ? NULL : fp;
1694}
1695
1696/* Composite */
1697
1698static Bool
1699amd_gx_exa_CheckComposite(int op, PicturePtr pSrc, PicturePtr pMsk,
1700    PicturePtr pDst)
1701{
1702    GeodeRec *pGeode = GEODEPTR_FROM_PICTURE(pDst);
1703
1704    if (op > gxPictOpMAX)
1705	return FALSE;
1706    if (pMsk)
1707	return FALSE;
1708    if (usesPasses(op) && pGeode->exaBfrSz == 0)
1709	return FALSE;
1710    if (pSrc->filter != PictFilterNearest &&
1711	pSrc->filter != PictFilterFast &&
1712	pSrc->filter != PictFilterGood && pSrc->filter != PictFilterBest)
1713	return FALSE;
1714    if (pSrc->repeat)
1715	return FALSE;
1716    if (pSrc->transform)
1717	return FALSE;
1718    return TRUE;
1719}
1720
1721static Bool
1722amd_gx_exa_PrepareComposite(int op, PicturePtr pSrc, PicturePtr pMsk,
1723    PicturePtr pDst, PixmapPtr pxSrc, PixmapPtr pxMsk, PixmapPtr pxDst)
1724{
1725    int srcPitch;
1726
1727    GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
1728    amd_gx_exa_fmt_t *sfp, *dfp;
1729
1730    //ErrorF("amd_gx_exa_PrepareComposite()\n");
1731
1732    if ((sfp = amd_gx_exa_check_format(pSrc)) == NULL)
1733	return FALSE;
1734    if (sfp->alpha_bits == 0 && usesSrcAlpha(op))
1735	return FALSE;
1736    if ((dfp = amd_gx_exa_check_format(pDst)) == NULL)
1737	return FALSE;
1738    if (dfp->alpha_bits == 0 && usesDstAlpha(op))
1739	return FALSE;
1740    if (sfp->gx_fmt != dfp->gx_fmt)
1741	return FALSE;
1742    srcPitch = exaGetPixmapPitch(pxSrc);
1743    if (usesPasses(op) && srcPitch > pGeode->exaBfrSz)
1744	return FALSE;
1745    pGeode->cmpSrcPitch = srcPitch;
1746    pGeode->cmpOp = op;
1747    pGeode->cmpSrcOffset = exaGetPixmapOffset(pxSrc);
1748    pGeode->cmpSrcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8;
1749    pGeode->cmpSrcFmt = sfp->gx_fmt;
1750    pGeode->cmpDstFmt = dfp->gx_fmt | (dfp->alpha_bits == 0 ?
1751	MGP_RM_ALPHA_TO_RGB : MGP_RM_ALPHA_TO_ARGB);
1752    return TRUE;
1753}
1754
1755static void
1756amd_gx_exa_Composite(PixmapPtr pxDst, int srcX, int srcY, int maskX,
1757    int maskY, int dstX, int dstY, int width, int height)
1758{
1759    int op, current_line, max_lines, lines, pass, scratchPitch;
1760    unsigned int srcOffset, srcOfs = 0, srcPitch, srcPch = 0, srcBpp;
1761    unsigned int dstOffset, dstOfs = 0, dstPitch, dstPch = 0, dstBpp;
1762    unsigned int sizes, strides, blt_mode = 0, rop = 0;
1763    GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
1764
1765    //ErrorF("amd_gx_exa_Composite() from %d,%d to %d,%d %dx%d\n",
1766    //    srcX, srcY, dstX, dstY, width, height);
1767
1768    op = pGeode->cmpOp;
1769    if (usesPasses(op)) {
1770	int cacheLineSz = 32;
1771	int cachelines =
1772	    (width * pGeode->cmpSrcBpp + cacheLineSz - 1) / cacheLineSz;
1773	scratchPitch = cachelines * cacheLineSz;
1774	if (scratchPitch > pGeode->cmpSrcPitch)
1775	    scratchPitch = pGeode->cmpSrcPitch;
1776	max_lines = pGeode->exaBfrSz / scratchPitch;
1777    } else {
1778	scratchPitch = 0;
1779	max_lines = height;
1780    }
1781
1782    dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8;
1783    dstPitch = exaGetPixmapPitch(pxDst);
1784    dstOffset = exaGetPixmapOffset(pxDst) + dstPitch * dstY + dstBpp * dstX;
1785    srcBpp = pGeode->cmpSrcBpp;
1786    srcPitch = pGeode->cmpSrcPitch;
1787    srcOffset = pGeode->cmpSrcOffset + srcPitch * srcY + srcBpp * srcX;
1788
1789    current_line = pass = 0;
1790    while (current_line < height) {
1791	if (usesPasses(op)) {
1792	    lines = height - current_line;
1793	    if (lines > max_lines)
1794		lines = max_lines;
1795	    switch (pass) {
1796	    case 0:		       /* copy src to scratch */
1797		srcPch = srcPitch;
1798		srcOfs = srcOffset + current_line * srcPch;
1799		dstPch = scratchPitch;
1800		dstOfs = pGeode->exaBfrOffset;
1801		rop = pGeode->cmpSrcFmt | MGP_RM_ALPHA_TO_ARGB;
1802		rop |= amd_gx_exa_alpha_ops[PictOpSrc * 2];
1803		blt_mode = usesChanB0(PictOpSrc) ?
1804		    MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
1805		++pass;
1806		break;
1807	    case 1:		       /* pass1 */
1808		srcPch = dstPitch;
1809		srcOfs = dstOffset + current_line * srcPch;
1810		dstPch = scratchPitch;
1811		dstOfs = pGeode->exaBfrOffset;
1812		rop = pGeode->cmpSrcFmt | MGP_RM_ALPHA_TO_ARGB;
1813		rop |= amd_gx_exa_alpha_ops[op * 2];
1814		blt_mode = usesChanB1(op) ?
1815		    MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
1816		++pass;
1817		break;
1818	    case 2:		       /* pass2 */
1819		srcPch = srcPitch;
1820		srcOfs = srcOffset + current_line * srcPch;
1821		dstPch = dstPitch;
1822		dstOfs = dstOffset + current_line * dstPch;
1823		rop = pGeode->cmpSrcFmt | MGP_RM_ALPHA_TO_ARGB;
1824		rop |= amd_gx_exa_alpha_ops[op * 2 + 1];
1825		blt_mode = usesChanB2(op) ?
1826		    MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
1827		++pass;
1828		break;
1829	    case 3:		       /* add */
1830		srcPch = scratchPitch;
1831		srcOfs = pGeode->exaBfrOffset;
1832		dstPch = dstPitch;
1833		dstOfs = dstOffset + current_line * dstPch;
1834		rop = pGeode->cmpDstFmt;
1835		rop |= amd_gx_exa_alpha_ops[PictOpAdd * 2];
1836		blt_mode = usesChanB0(PictOpAdd) ?
1837		    MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
1838		current_line += lines;
1839		pass = 0;
1840		break;
1841	    }
1842	    strides = (srcPch << 16) | dstPch;
1843	} else {		       /* not multi pass */
1844	    srcOfs = srcOffset;
1845	    dstOfs = dstOffset;
1846	    current_line = lines = height;
1847	    strides = (srcPitch << 16) | dstPitch;
1848	    rop = pGeode->cmpDstFmt | amd_gx_exa_alpha_ops[op * 2];
1849	    blt_mode = usesChanB0(op) ?
1850		MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
1851	}
1852	sizes = (width << 16) | lines;
1853	if (srcOfs < dstOfs) {
1854	    srcOfs += (lines - 1) * srcPitch + width * srcBpp - 1;
1855	    dstOfs += (lines - 1) * dstPitch + width * dstBpp - 1;
1856	    blt_mode |= MGP_BM_NEG_XDIR | MGP_BM_NEG_YDIR;
1857	}
1858	GU2_WAIT_PENDING;
1859	WRITE_GP32(MGP_RASTER_MODE, rop);
1860	WRITE_GP32(MGP_SRC_OFFSET, srcOfs);
1861	WRITE_GP32(MGP_DST_OFFSET, dstOfs);
1862	WRITE_GP32(MGP_WID_HEIGHT, sizes);
1863	WRITE_GP32(MGP_STRIDE, strides);
1864	WRITE_GP16(MGP_BLT_MODE, blt_mode);
1865    }
1866}
1867#endif /* #if XF86EXA */
1868
1869/*----------------------------------------------------------------------------
1870 * GXAccelInit.
1871 *
1872 * Description:	This function sets up the supported acceleration routines and
1873 *              appropriate flags.
1874 *
1875 * Parameters:
1876 *      pScrn:	Screeen pointer structure.
1877 *
1878 * Returns:		TRUE on success and FALSE on Failure
1879 *
1880 * Comments:	This function is called in GXScreenInit in
1881 *              geode_driver.c to set  * the acceleration.
1882 *----------------------------------------------------------------------------
1883 */
1884Bool
1885GXAccelInit(ScreenPtr pScrn)
1886{
1887    ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
1888    GeodeRec *pGeode = GEODEPTR(pScrni);
1889
1890#if XF86EXA
1891    ExaDriverPtr pExa = pGeode->pExa;
1892#endif
1893
1894    gu2_xshift = pScrni->bitsPerPixel >> 4;
1895
1896    /* XXX - fixme - this will change - we'll need to update it */
1897
1898    gu2_pitch = pGeode->Pitch;
1899
1900    switch (pGeode->Pitch) {
1901    case 1024:
1902	gu2_yshift = 10;
1903	break;
1904    case 2048:
1905	gu2_yshift = 11;
1906	break;
1907    case 4096:
1908	gu2_yshift = 12;
1909	break;
1910    default:
1911	gu2_yshift = 13;
1912	break;
1913    }
1914
1915#ifdef OPT_ACCEL
1916    ACCEL_STRIDE = (pGeode->Pitch << 16) | pGeode->Pitch;
1917    BPP = amd_gx_BppToRasterMode(pScrni->bitsPerPixel);
1918#endif
1919
1920#if XF86EXA
1921    if (pExa && pGeode->useEXA) {
1922	pExa->exa_major = EXA_VERSION_MAJOR;
1923	pExa->exa_minor = EXA_VERSION_MINOR;
1924
1925	/* Sync */
1926	pExa->WaitMarker = amd_gx_exa_WaitMarker;
1927	/* UploadToScreen */
1928	pExa->UploadToScreen = amd_gx_exa_UploadToScreen;
1929	pExa->DownloadFromScreen = amd_gx_exa_DownloadFromScreen;
1930
1931	/* Solid fill */
1932	pExa->PrepareSolid = amd_gx_exa_PrepareSolid;
1933	pExa->Solid = amd_gx_exa_Solid;
1934	pExa->DoneSolid = amd_gx_exa_Done;
1935
1936	/* Copy */
1937	pExa->PrepareCopy = amd_gx_exa_PrepareCopy;
1938	pExa->Copy = amd_gx_exa_Copy;
1939	pExa->DoneCopy = amd_gx_exa_Done;
1940
1941	/* Composite */
1942	pExa->CheckComposite = amd_gx_exa_CheckComposite;
1943	pExa->PrepareComposite = amd_gx_exa_PrepareComposite;
1944	pExa->Composite = amd_gx_exa_Composite;
1945	pExa->DoneComposite = amd_gx_exa_Done;
1946
1947	return exaDriverInit(pScrn, pGeode->pExa);
1948    }
1949#endif
1950
1951    /* Getting the pointer for acceleration Inforecord */
1952    pGeode->AccelInfoRec = localRecPtr = XAACreateInfoRec();
1953    if (!pGeode->AccelInfoRec)
1954	return FALSE;
1955
1956    /* SET ACCELERATION FLAGS */
1957    localRecPtr->Flags =
1958	PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
1959
1960    /* HOOK SYNCRONIZARION ROUTINE */
1961    localRecPtr->Sync = GXAccelSync;
1962
1963#if GX_FILL_RECT_SUPPORT
1964    /* HOOK FILLED RECTANGLES */
1965    HOOK(SetupForSolidFill);
1966    HOOK(SubsequentSolidFillRect);
1967    localRecPtr->SolidFillFlags = 0;
1968#endif
1969
1970#if GX_MONO_8X8_PAT_SUPPORT
1971    /* Color expansion */
1972    HOOK(SetupForMono8x8PatternFill);
1973    HOOK(SubsequentMono8x8PatternFillRect);
1974/*         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY | */
1975    localRecPtr->Mono8x8PatternFillFlags = BIT_ORDER_IN_BYTE_MSBFIRST |
1976	HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN;
1977#endif
1978
1979#if GX_CLREXP_8X8_PAT_SUPPORT
1980    /* Color expansion */
1981    HOOK(SetupForColor8x8PatternFill);
1982    HOOK(SubsequentColor8x8PatternFillRect);
1983/*         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY | */
1984    localRecPtr->Color8x8PatternFillFlags =
1985	BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD |
1986	HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_PROGRAMMED_ORIGIN;
1987#endif
1988
1989#if GX_SCR2SCRCPY_SUPPORT
1990    /* HOOK SCREEN TO SCREEN COPIES
1991     * Set flag to only allow copy if transparency is enabled.
1992     */
1993    HOOK(SetupForScreenToScreenCopy);
1994    HOOK(SubsequentScreenToScreenCopy);
1995    localRecPtr->ScreenToScreenCopyFlags =
1996	BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
1997#endif
1998
1999#if GX_BRES_LINE_SUPPORT
2000    /* HOOK BRESENHAM SOLID LINES */
2001    localRecPtr->SolidLineFlags = NO_PLANEMASK;
2002    HOOK(SetupForSolidLine);
2003    HOOK(SubsequentSolidBresenhamLine);
2004    HOOK(SubsequentSolidHorVertLine);
2005    HOOK(SubsequentSolidTwoPointLine);
2006    localRecPtr->SolidBresenhamLineErrorTermBits = 15;
2007#endif
2008
2009#if GX_DASH_LINE_SUPPORT
2010    /* HOOK BRESENHAM DASHED LINES */
2011    HOOK(SetupForDashedLine);
2012    HOOK(SubsequentDashedBresenhamLine);
2013    HOOK(SubsequentDashedTwoPointLine);
2014    localRecPtr->DashedBresenhamLineErrorTermBits = 15;
2015    localRecPtr->DashPatternMaxLength = 64;
2016    localRecPtr->DashedLineFlags = NO_PLANEMASK |	/* TRANSPARENCY_ONLY | */
2017	LINE_PATTERN_POWER_OF_2_ONLY | LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
2018#endif
2019
2020#if GX_SCR2SCREXP_SUPPORT
2021    /* Color expansion */
2022    HOOK(SetupForScreenToScreenColorExpandFill);
2023    HOOK(SubsequentScreenToScreenColorExpandFill);
2024    localRecPtr->ScreenToScreenColorExpandFillFlags =
2025	BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY;
2026#endif
2027
2028    if (pGeode->AccelImageWriteBuffers) {
2029#if GX_SCANLINE_SUPPORT
2030	localRecPtr->ScanlineImageWriteBuffers =
2031	    pGeode->AccelImageWriteBuffers;
2032	localRecPtr->NumScanlineImageWriteBuffers = pGeode->NoOfImgBuffers;
2033	HOOK(SetupForScanlineImageWrite);
2034	HOOK(SubsequentScanlineImageWriteRect);
2035	HOOK(SubsequentImageWriteScanline);
2036	localRecPtr->ScanlineImageWriteFlags = NO_PLANEMASK | NO_GXCOPY |
2037	    BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
2038#endif
2039
2040    } else {
2041	localRecPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES;
2042    }
2043
2044    if (pGeode->AccelColorExpandBuffers) {
2045#if GX_CPU2SCREXP_SUPPORT
2046	/* Color expansion */
2047	localRecPtr->ScanlineColorExpandBuffers =
2048	    pGeode->AccelColorExpandBuffers;
2049	localRecPtr->NumScanlineColorExpandBuffers =
2050	    pGeode->NoOfColorExpandLines;
2051	HOOK(SetupForScanlineCPUToScreenColorExpandFill);
2052	HOOK(SubsequentScanlineCPUToScreenColorExpandFill);
2053	HOOK(SubsequentColorExpandScanline);
2054	localRecPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
2055	    BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
2056#endif
2057    }
2058#if GX_WRITE_PIXMAP_SUPPORT
2059    pGeode->WritePixmap = localRecPtr->WritePixmap;
2060    HOOK(WritePixmap);
2061#endif
2062
2063    return (XAAInit(pScrn, localRecPtr));
2064}
2065
2066/* END OF FILE */
2067