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