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