rndr_gu2.c revision f29dbc25
1/* Copyright (c) 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 * This file contains routines to program the 2D acceleration hardware for
28 * the second generation graphics unit.
29 *
30 * Basic rendering routines (common to all Geode processors):
31 *    gfx_set_bpp
32 *    gfx_set_solid_pattern
33 *    gfx_set_mono_pattern
34 *    gfx_set_color_pattern
35 *    gfx_set_solid_source
36 *    gfx_set_mono_source
37 *    gfx_set_raster_operation
38 *    gfx_pattern_fill
39 *    gfx_color_pattern_fill
40 *    gfx_screen_to_screen_blt
41 *    gfx_screen_to_screen_xblt
42 *    gfx_color_bitmap_to_screen_blt
43 *    gfx_color_bitmap_to_screen_xblt
44 *    gfx_mono_bitmap_to_screen_blt
45 *    gfx_bresenham_line
46 *    gfx_wait_until_idle
47 *
48 * Extended rendering routines for second generation functionality:
49 *    gfx2_set_source_stride
50 *    gfx2_set_destination_stride
51 *    gfx2_set_pattern_origins
52 *    gfx2_set_source_transparency
53 *    gfx2_set_alpha_mode
54 *    gfx2_set_alpha_value
55 *    gfx2_pattern_fill
56 *    gfx2_color_pattern_fill
57 *    gfx2_screen_to_screen_blt
58 *    gfx2_mono_expand_blt
59 *    gfx2_color_bitmap_to_screen_blt
60 *    gfx2_mono_bitmap_to_screen_blt
61 *    gfx2_bresenham_line
62 *    gfx2_sync_to_vblank
63 * */
64
65#define GU2_WAIT_PENDING		\
66		while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING)
67#define GU2_WAIT_BUSY			\
68		while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY)
69#define GU2_WAIT_HALF_EMPTY		\
70		while(!(READ_GP32(MGP_BLT_STATUS) & MGP_BS_HALF_EMPTY))
71
72/* PATTERN SWIZZLES */
73
74#define WORD_SWIZZLE(x) (((x) << 16) | ((x) >> 16))
75#define BYTE_SWIZZLE(x) (((x) << 24) | ((x) >> 24) | (((x) << 8) & 	\
76						0x00FF0000) | (((x) >> 8) & 0x0000FF00))
77
78/* GLOBAL VARIABLES USED BY THE RENDERING ROUTINES */
79
80unsigned long gu2_bpp;
81unsigned long gu2_pitch = 1280;
82unsigned long gu2_src_pitch = 1280;
83unsigned long gu2_dst_pitch = 1280;
84unsigned long gu2_xshift = 1;
85unsigned long gu2_pattern_origin = 0;
86unsigned long gu2_rop32;
87unsigned long gu2_alpha32 = 0;
88unsigned long gu2_alpha_value = 0;
89unsigned long gu2_alpha_mode = 0;
90unsigned long gu2_alpha_active = 0;
91unsigned short gu2_alpha_blt_mode = 0;
92unsigned short gu2_alpha_vec_mode = 0;
93unsigned short gu2_blt_mode = 0;
94unsigned short gu2_vector_mode = 0;
95unsigned short gu2_bm_throttle = 0;
96unsigned short gu2_vm_throttle = 0;
97int gu2_current_line = 0;
98
99/* Kill a warning */
100void gfx_reset_pitch(unsigned short pitch);
101
102/*---------------------------------------------------------------------------
103 * GFX_RESET_PITCH (PRIVATE ROUTINE - NOT PART OF API)
104 *
105 * This routine resets all pitches in the graphics engine to one value.
106 *---------------------------------------------------------------------------
107 */
108#if GFX_2DACCEL_DYNAMIC
109void
110gu2_reset_pitch(unsigned short pitch)
111#else
112void
113gfx_reset_pitch(unsigned short pitch)
114#endif
115{
116    gu2_pitch = pitch;
117    gu2_dst_pitch = pitch;
118    gu2_src_pitch = pitch;
119}
120
121/*---------------------------------------------------------------------------
122 * GFX_SET_BPP
123 *
124 * This routine sets the bits per pixel value in the graphics engine.
125 * It is also stored in the static variable "gu2_bpp" to use in the future
126 * calls to the rendering routines.  That variable contains the hardware
127 * specific value to load into the MGP_RASTER_MODE register.
128 *---------------------------------------------------------------------------
129 */
130#if GFX_2DACCEL_DYNAMIC
131void
132gu2_set_bpp(unsigned short bpp)
133#else
134void
135gfx_set_bpp(unsigned short bpp)
136#endif
137{
138    GFXbpp = bpp;
139
140    /* COVERT TO BPP/FORMAT VALUE */
141    /* Save in global to combine with ROP later. */
142    /* Could write register here and then use byte access for */
143    /* the ROP, but would need to set other 24 bits to make */
144    /* sure all are set to their appropriate values. */
145
146    switch (bpp) {
147    case 8:
148        gu2_bpp = MGP_RM_BPPFMT_332;
149        gu2_xshift = 0;
150        break;
151    case 12:
152        gu2_bpp = MGP_RM_BPPFMT_4444;
153        gu2_xshift = 1;
154        break;
155    case 15:
156        gu2_bpp = MGP_RM_BPPFMT_1555;
157        gu2_xshift = 1;
158        break;
159    case 16:
160        gu2_bpp = MGP_RM_BPPFMT_565;
161        gu2_xshift = 1;
162        break;
163    case 32:
164        gu2_bpp = MGP_RM_BPPFMT_8888;
165        gu2_xshift = 2;
166        break;
167    }
168
169    /* SET INITIAL ROP BASED ONLY ON BPP */
170    /* Needs to be set before loading any pattern or source colors. */
171    /* We must wait for BUSY because these bits are not pipelined   */
172    /* in the hardware.                                             */
173
174    GU2_WAIT_BUSY;
175    WRITE_GP32(MGP_RASTER_MODE, gu2_bpp);
176}
177
178/*
179 *---------------------------------------------------------------------------
180 * GFX_SET_SOLID_SOURCE
181 *
182 * This routine is used to specify a solid source color.  For the Xfree96
183 * display driver, the source color is used to specify a planemask and the
184 * ROP is adjusted accordingly.
185 *---------------------------------------------------------------------------
186 */
187#if GFX_2DACCEL_DYNAMIC
188void
189gu2_set_solid_source(unsigned long color)
190#else
191void
192gfx_set_solid_source(unsigned long color)
193#endif
194{
195    /* CLEAR TRANSPARENCY FLAG */
196
197    GFXsourceFlags = 0;
198
199    /* WRITE REGISTERS TO SPECIFY SOURCE COLOR */
200
201    GU2_WAIT_PENDING;
202    WRITE_GP32(MGP_SRC_COLOR_FG, color);
203}
204
205/*
206 *---------------------------------------------------------------------------
207 * GFX_SET_MONO_SOURCE
208 *
209 * This routine is used to specify the monochrome source colors.
210 * It must be called *after* loading any pattern data (those routines
211 * clear the source flags).
212 *---------------------------------------------------------------------------
213 */
214#if GFX_2DACCEL_DYNAMIC
215void
216gu2_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
217    unsigned short transparent)
218#else
219void
220gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
221    unsigned short transparent)
222#endif
223{
224    /* SET TRANSPARENCY FLAG */
225
226    GFXsourceFlags = transparent ? MGP_RM_SRC_TRANS : 0;
227
228    /* WRITE COLOR VALUES */
229
230    GU2_WAIT_PENDING;
231    WRITE_GP32(MGP_SRC_COLOR_FG, fgcolor);
232    WRITE_GP32(MGP_SRC_COLOR_BG, bgcolor);
233}
234
235/*
236 *---------------------------------------------------------------------------
237 * GFX_SET_SOLID_PATTERN
238 *
239 * This routine is used to specify a solid pattern color.  It is called
240 * before performing solid rectangle fills or more complicated BLTs that
241 * use a solid pattern color.
242 *
243 * The driver should always call "gfx_load_raster_operation" after a call
244 * to this routine to make sure that the pattern flags are set appropriately.
245 *---------------------------------------------------------------------------
246 */
247#if GFX_2DACCEL_DYNAMIC
248void
249gu2_set_solid_pattern(unsigned long color)
250#else
251void
252gfx_set_solid_pattern(unsigned long color)
253#endif
254{
255    /* CLEAR TRANSPARENCY FLAG */
256
257    GFXsourceFlags = 0;
258
259    /* SET PATTERN FLAGS */
260
261    GFXpatternFlags = 0;
262
263    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
264
265    GU2_WAIT_PENDING;
266    WRITE_GP32(MGP_RASTER_MODE, gu2_bpp);
267    WRITE_GP32(MGP_PAT_COLOR_0, color);
268}
269
270/*
271 *---------------------------------------------------------------------------
272 * GFX_SET_MONO_PATTERN
273 *
274 * This routine is used to specify a monochrome pattern.
275 *---------------------------------------------------------------------------
276 */
277#if GFX_2DACCEL_DYNAMIC
278void
279gu2_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
280    unsigned long data0, unsigned long data1, unsigned char transparent)
281#else
282void
283gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
284    unsigned long data0, unsigned long data1, unsigned char transparent)
285#endif
286{
287    /* CLEAR TRANSPARENCY FLAG */
288
289    GFXsourceFlags = 0;
290
291    /* SET PATTERN FLAGS */
292
293    if (transparent)
294        GFXpatternFlags = MGP_RM_PAT_MONO | MGP_RM_PAT_TRANS;
295    else
296        GFXpatternFlags = MGP_RM_PAT_MONO;
297
298    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
299
300    GU2_WAIT_PENDING;
301    WRITE_GP32(MGP_RASTER_MODE, gu2_bpp | GFXpatternFlags);
302    WRITE_GP32(MGP_PAT_COLOR_0, bgcolor);
303    WRITE_GP32(MGP_PAT_COLOR_1, fgcolor);
304    WRITE_GP32(MGP_PAT_DATA_0, data0);
305    WRITE_GP32(MGP_PAT_DATA_1, data1);
306}
307
308/*
309 *---------------------------------------------------------------------------
310 * GFX_SET_COLOR_PATTERN
311 *
312 * This routine is used to specify a color pattern.
313 *---------------------------------------------------------------------------
314 */
315#if GFX_2DACCEL_DYNAMIC
316void
317gu2_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
318    unsigned long data0, unsigned long data1, unsigned long data2,
319    unsigned long data3, unsigned char transparent)
320#else
321void
322gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
323    unsigned long data0, unsigned long data1, unsigned long data2,
324    unsigned long data3, unsigned char transparent)
325#endif
326{
327    /* REMOVE */
328}
329
330/*
331 *---------------------------------------------------------------------------
332 * GFX_LOAD_COLOR_PATTERN_LINE
333 *
334 * This routine is used to load a single line of a 8x8 color pattern.
335 *---------------------------------------------------------------------------  */
336#if GFX_2DACCEL_DYNAMIC
337void
338gu2_load_color_pattern_line(short y, unsigned long *pattern_8x8)
339#else
340void
341gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8)
342#endif
343{
344    unsigned long temp1, temp2, temp3, temp4;
345
346    /* CLEAR TRANSPARENCY FLAG */
347
348    GFXsourceFlags = 0;
349
350    /* SET PATTERN FLAGS */
351
352    GFXpatternFlags = MGP_RM_PAT_COLOR;
353
354    /* OVERRIDE THE RASTER MODE REGISTER */
355    /* If the pattern format is set to anything but color  */
356    /* before loading the registers, some of the data will */
357    /* be duplicated according to the current mode.        */
358
359    GU2_WAIT_PENDING;
360    WRITE_GP32(MGP_RASTER_MODE,
361        (gu2_rop32 & ~MGP_RM_PAT_FLAGS) | MGP_RM_PAT_COLOR);
362
363    /* LOAD THE PATTERN DATA */
364    /* This routine is designed to work in tandem with gfx_pattern_fill.  */
365    /* It is used for cases when multiple BLTs with color pattern data    */
366    /* are desired on the same line.  It would be inefficient to          */
367    /* repeatedly call gfx_color_pattern_fill for each single-line BLT.   */
368    /* So, we will simply replicate the pattern data across all available */
369    /* lines such that the pattern y origin plays no part in the BLT.     */
370
371    /* 8 BPP */
372
373    if (gu2_xshift == 0) {
374        pattern_8x8 += (y & 7) << 1;
375        temp1 = BYTE_SWIZZLE(pattern_8x8[0]);
376        temp2 = BYTE_SWIZZLE(pattern_8x8[1]);
377        WRITE_GP32(MGP_PAT_DATA_1, temp1);
378        WRITE_GP32(MGP_PAT_DATA_0, temp2);
379        WRITE_GP32(MGP_PAT_COLOR_1, temp1);
380        WRITE_GP32(MGP_PAT_COLOR_0, temp2);
381
382        GU2_WAIT_BUSY;
383        WRITE_GP32(MGP_PAT_COLOR_3, temp1);
384        WRITE_GP32(MGP_PAT_COLOR_2, temp2);
385        WRITE_GP32(MGP_PAT_COLOR_5, temp1);
386        WRITE_GP32(MGP_PAT_COLOR_4, temp2);
387    } else if (gu2_xshift == 1) {
388        pattern_8x8 += (y & 7) << 2;
389        temp1 = WORD_SWIZZLE(pattern_8x8[0]);
390        temp2 = WORD_SWIZZLE(pattern_8x8[1]);
391        temp3 = WORD_SWIZZLE(pattern_8x8[2]);
392        temp4 = WORD_SWIZZLE(pattern_8x8[3]);
393
394        WRITE_GP32(MGP_PAT_COLOR_1, temp1);
395        WRITE_GP32(MGP_PAT_COLOR_0, temp2);
396        WRITE_GP32(MGP_PAT_DATA_1, temp3);
397        WRITE_GP32(MGP_PAT_DATA_0, temp4);
398
399        GU2_WAIT_BUSY;
400        WRITE_GP32(MGP_PAT_COLOR_5, temp1);
401        WRITE_GP32(MGP_PAT_COLOR_4, temp2);
402        WRITE_GP32(MGP_PAT_COLOR_3, temp3);
403        WRITE_GP32(MGP_PAT_COLOR_2, temp4);
404    } else {
405        pattern_8x8 += (y & 7) << 3;
406
407        WRITE_GP32(MGP_PAT_COLOR_1, pattern_8x8[4]);
408        WRITE_GP32(MGP_PAT_COLOR_0, pattern_8x8[5]);
409        WRITE_GP32(MGP_PAT_DATA_1, pattern_8x8[6]);
410        WRITE_GP32(MGP_PAT_DATA_0, pattern_8x8[7]);
411
412        GU2_WAIT_BUSY;
413        WRITE_GP32(MGP_PAT_COLOR_5, pattern_8x8[0]);
414        WRITE_GP32(MGP_PAT_COLOR_4, pattern_8x8[1]);
415        WRITE_GP32(MGP_PAT_COLOR_3, pattern_8x8[2]);
416        WRITE_GP32(MGP_PAT_COLOR_2, pattern_8x8[3]);
417    }
418}
419
420/*
421 *---------------------------------------------------------------------------
422 * GFX_SET_RASTER_OPERATION
423 *
424 * This routine loads the specified raster operation.  It sets the pattern
425 * flags appropriately.
426 *---------------------------------------------------------------------------
427 */
428#if GFX_2DACCEL_DYNAMIC
429void
430gu2_set_raster_operation(unsigned char rop)
431#else
432void
433gfx_set_raster_operation(unsigned char rop)
434#endif
435{
436    gu2_blt_mode = 0;
437
438    /* DISABLE ALPHA BLENDING */
439
440    gu2_alpha_active = 0;
441
442    /* GENERATE 32-BIT VERSION OF ROP WITH PATTERN FLAGS */
443
444    gu2_rop32 = (unsigned long)rop | GFXpatternFlags | gu2_bpp;
445
446    /* CHECK IF SOURCE FLAGS SHOULD BE MERGED */
447
448    if ((rop & 0x33) ^ ((rop >> 2) & 0x33))
449        gu2_rop32 |= GFXsourceFlags;
450    else
451        gu2_blt_mode = 0x40;
452
453    /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */
454    /* True if even bits (0:2:4:6) do not equal the corresponding */
455    /* even bits (1:3:5:7). */
456
457    if ((rop & 0x55) ^ ((rop >> 1) & 0x55)) {
458        gu2_blt_mode |= MGP_BM_DST_REQ;
459        gu2_vector_mode = MGP_VM_DST_REQ;
460    } else {
461        gu2_vector_mode = 0;
462    }
463}
464
465/*
466 *----------------------------------------------------------------------------
467 * GFX_PATTERN_FILL
468 *
469 * This routine is used to fill a rectangular region.  The pattern must
470 * be previously loaded using one of GFX_load_*_pattern routines.  Also, the
471 * raster operation must be previously specified using the
472 * "GFX_load_raster_operation" routine.
473 *
474 *      X               screen X position (left)
475 *      Y               screen Y position (top)
476 *      WIDTH           width of rectangle, in pixels
477 *      HEIGHT          height of rectangle, in scanlines
478 *----------------------------------------------------------------------------
479 */
480#if GFX_2DACCEL_DYNAMIC
481void
482gu2_pattern_fill(unsigned short x, unsigned short y,
483    unsigned short width, unsigned short height)
484#else
485void
486gfx_pattern_fill(unsigned short x, unsigned short y,
487    unsigned short width, unsigned short height)
488#endif
489{
490    unsigned long offset = 0, size;
491
492    size = (((unsigned long)width) << 16) | height;
493
494    /* CALCULATE STARTING OFFSET */
495
496    offset = (unsigned long)y *gu2_pitch + (((unsigned long)x) << gu2_xshift);
497
498    /* CHECK IF PATTERN ORIGINS NEED TO BE SET */
499
500    if (GFXpatternFlags) {
501        /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */
502
503        offset |= ((unsigned long)(x & 7)) << 26;
504        offset |= ((unsigned long)(y & 7)) << 29;
505    }
506
507    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
508    /* Put off poll for as long as possible (do most calculations first). */
509
510    GU2_WAIT_PENDING;
511    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32);
512    WRITE_GP32(MGP_DST_OFFSET, offset);
513    WRITE_GP32(MGP_WID_HEIGHT, size);
514    WRITE_GP32(MGP_STRIDE, gu2_pitch);
515    WRITE_GP32(MGP_BLT_MODE, gu2_blt_mode);
516}
517
518/*
519 *----------------------------------------------------------------------------
520 * GFX_COLOR_PATTERN_FILL
521 *
522 * This routine is used to render a rectangle using the current raster
523 * operation and the specified color pattern.  It allows an 8x8 color
524 * pattern to be rendered without multiple calls to the gfx_set_color_pattern
525 * and gfx_pattern_fill routines.
526 *
527 *      X               screen X position (left)
528 *      Y               screen Y position (top)
529 *      WIDTH           width of rectangle, in pixels
530 *      HEIGHT          height of rectangle, in scanlines
531 *      *PATTERN		pointer to 8x8 color pattern data
532 *----------------------------------------------------------------------------
533 */
534#if GFX_2DACCEL_DYNAMIC
535void
536gu2_color_pattern_fill(unsigned short x, unsigned short y,
537    unsigned short width, unsigned short height, unsigned long *pattern)
538#else
539void
540gfx_color_pattern_fill(unsigned short x, unsigned short y,
541    unsigned short width, unsigned short height, unsigned long *pattern)
542#endif
543{
544    /* CALL GFX2 ROUTINE TO AVOID DUPLICATION OF CODE */
545
546    unsigned long offset = (unsigned long)y * gu2_pitch +
547        (((unsigned long)x) << gu2_xshift);
548    unsigned long origin = gu2_pattern_origin;
549    unsigned long pitch = gu2_dst_pitch;
550
551    gfx2_set_pattern_origin(x, y);
552    gfx2_set_destination_stride((unsigned short)gu2_pitch);
553    gfx2_color_pattern_fill(offset, width, height, pattern);
554
555    /* RESTORE GFX2 VALUES */
556
557    gu2_pattern_origin = origin;
558    gu2_dst_pitch = pitch;
559}
560
561/*
562 *----------------------------------------------------------------------------
563 * SCREEN TO SCREEN BLT
564 *
565 * This routine should be used to perform a screen to screen BLT when the
566 * ROP does not require destination data.
567 *
568 *      SRCX            screen X position to copy from
569 *      SRCY            screen Y position to copy from
570 *      DSTX            screen X position to copy to
571 *      DSTY            screen Y position to copy to
572 *      WIDTH           width of rectangle, in pixels
573 *      HEIGHT          height of rectangle, in scanlines
574 *----------------------------------------------------------------------------
575 */
576#if GFX_2DACCEL_DYNAMIC
577void
578gu2_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
579    unsigned short dstx, unsigned short dsty, unsigned short width,
580    unsigned short height)
581#else
582void
583gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
584    unsigned short dstx, unsigned short dsty, unsigned short width,
585    unsigned short height)
586#endif
587{
588    unsigned long srcoffset, dstoffset, size;
589    unsigned short blt_mode;
590
591    size = (((unsigned long)width) << 16) | height;
592
593    /* CALCULATE THE DIRECTION OF THE BLT */
594
595    blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB;
596    if (dstx > srcx) {
597        blt_mode |= MGP_BM_NEG_XDIR;
598        srcx += width - 1;
599        dstx += width - 1;
600    }
601    if (dsty > srcy) {
602        blt_mode |= MGP_BM_NEG_YDIR;
603        srcy += height - 1;
604        dsty += height - 1;
605    }
606
607    /* CALCULATE STARTING OFFSETS */
608
609    srcoffset = (unsigned long)srcy *gu2_pitch +
610        (((unsigned long)srcx) << gu2_xshift);
611    dstoffset = ((unsigned long)dsty * gu2_pitch +
612        (((unsigned long)dstx) << gu2_xshift)) & 0xFFFFFF;
613
614    /* MERGE PATTERN INFORMATION */
615    /* This must be done after the x and y coordinates have been updated,  */
616    /* as the x and y pattern origins correspond to the first ROPed pixel. */
617
618    if (GFXpatternFlags) {
619        /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */
620
621        dstoffset |= ((unsigned long)(dstx & 7)) << 26;
622        dstoffset |= ((unsigned long)(dsty & 7)) << 29;
623    }
624
625    /* TURN INTO BYTE ADDRESS IF NEGATIVE X DIRECTION */
626    /* This is a quirk of the hardware. */
627
628    if (blt_mode & MGP_BM_NEG_XDIR) {
629        srcoffset += (1 << gu2_xshift) - 1;
630        dstoffset += (1 << gu2_xshift) - 1;
631    }
632
633    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
634    /* Put off poll for as long as possible (do most calculations first). */
635
636    GU2_WAIT_PENDING;
637    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
638    WRITE_GP32(MGP_SRC_OFFSET, srcoffset);
639    WRITE_GP32(MGP_DST_OFFSET, dstoffset);
640    WRITE_GP32(MGP_WID_HEIGHT, size);
641    WRITE_GP32(MGP_STRIDE, gu2_pitch | (gu2_pitch << 16));
642    WRITE_GP16(MGP_BLT_MODE, blt_mode);
643}
644
645/*
646 *----------------------------------------------------------------------------
647 * SCREEN TO SCREEN TRANSPARENT BLT
648 *
649 * This routine should be used to perform a screen to screen BLT when a
650 * specified color should by transparent.  The only supported ROP is SRCCOPY.
651 *
652 *      SRCX            screen X position to copy from
653 *      SRCY            screen Y position to copy from
654 *      DSTX            screen X position to copy to
655 *      DSTY            screen Y position to copy to
656 *      WIDTH           width of rectangle, in pixels
657 *      HEIGHT          height of rectangle, in scanlines
658 *      COLOR           transparent color
659 *----------------------------------------------------------------------------
660 */
661#if GFX_2DACCEL_DYNAMIC
662void
663gu2_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
664    unsigned short dstx, unsigned short dsty, unsigned short width,
665    unsigned short height, unsigned long color)
666#else
667void
668gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
669    unsigned short dstx, unsigned short dsty, unsigned short width,
670    unsigned short height, unsigned long color)
671#endif
672{
673    unsigned long rop32;
674
675    /* SAVE ORIGINAL RASTER MODE SETTINGS */
676
677    rop32 = gu2_rop32;
678
679    /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */
680    /* Match GU1 implementation that only allows SRCCOPY for the ROP. */
681
682    GU2_WAIT_PENDING;
683    WRITE_GP32(MGP_SRC_COLOR_FG, color);
684    WRITE_GP32(MGP_SRC_COLOR_BG, 0xFFFFFFFF);
685
686    /* SET GLOBAL RASTER SETTINGS */
687    /* This is needed, as the screen-to-screen BLT      */
688    /* routine will overwrite the raster mode register. */
689
690    gu2_rop32 = gu2_bpp | MGP_RM_SRC_TRANS | 0xCC;
691
692    /* CALL NORMAL SCREEN TO SCREEN BLT ROUTINE */
693
694    gfx_screen_to_screen_blt(srcx, srcy, dstx, dsty, width, height);
695
696    /* RESTORE GLOBAL RASTER SETTINGS */
697
698    gu2_rop32 = rop32;
699}
700
701/*
702 *----------------------------------------------------------------------------
703 * COLOR BITMAP TO SCREEN BLT
704 *
705 * This routine transfers color bitmap data to the screen.
706 *
707 *      SRCX            X offset within source bitmap
708 *      SRCY            Y offset within source bitmap
709 *      DSTX            screen X position to render data
710 *      DSTY            screen Y position to render data
711 *      WIDTH           width of rectangle, in pixels
712 *      HEIGHT          height of rectangle, in scanlines
713 *      *DATA           pointer to bitmap data
714 *      PITCH           pitch of bitmap data (bytes between scanlines)
715 *
716 * Transparency is handled by another routine.
717 *----------------------------------------------------------------------------
718 */
719
720#if GFX_2DACCEL_DYNAMIC
721void
722gu2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
723    unsigned short dstx, unsigned short dsty, unsigned short width,
724    unsigned short height, unsigned char *data, long pitch)
725#else
726void
727gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
728    unsigned short dstx, unsigned short dsty, unsigned short width,
729    unsigned short height, unsigned char *data, long pitch)
730#endif
731{
732    unsigned long dstoffset, srcoffset, size, bytes;
733    unsigned long offset, temp_offset;
734    unsigned long dword_bytes, bytes_extra;
735    unsigned short blt_mode;
736
737    blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB;
738    size = (((unsigned long)width) << 16) | 1;
739
740    /* CALCULATE STARTING OFFSETS */
741
742    offset = (unsigned long)srcy *pitch + ((unsigned long)srcx << gu2_xshift);
743
744    dstoffset = (unsigned long)dsty *gu2_pitch +
745        (((unsigned long)dstx) << gu2_xshift);
746
747    /* CHECK IF PATTERN ORIGINS NEED TO BE SET */
748
749    if (GFXpatternFlags) {
750        /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */
751
752        dstoffset |= ((unsigned long)(dstx & 7)) << 26;
753        dstoffset |= ((unsigned long)(dsty & 7)) << 29;
754    }
755
756    bytes = width << gu2_xshift;
757    dword_bytes = bytes & ~0x3L;
758    bytes_extra = bytes & 0x3L;
759
760    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
761    /* Put off poll for as long as possible (do most calculations first).   */
762    /* The source offset is always 0 since we allow misaligned dword reads. */
763    /* We must wait for BLT busy because the GP may be executing a screen   */
764    /* to screen BLT from the scratchpad area.                              */
765
766    GU2_WAIT_BUSY;
767    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
768    WRITE_GP32(MGP_WID_HEIGHT, size);
769    WRITE_GP32(MGP_STRIDE, gu2_pitch);
770
771    /* WRITE DATA ONE LINE AT A TIME */
772    /* For speed reasons, data is written to an offscreen scratch area and then        */
773    /* BLTed using a screen to screen BLT. This is similar to the GX1 BLT buffers, but */
774    /* slightly more efficient in that we can queue up data while the GP is rendering  */
775    /* a line.                                                                         */
776
777    while (height--) {
778        temp_offset = offset;
779        srcoffset = gfx_gx2_scratch_base;
780        if (gu2_current_line)
781            srcoffset += 8192;
782
783        GU2_WAIT_PENDING;
784        WRITE_GP32(MGP_SRC_OFFSET, srcoffset);
785        WRITE_GP32(MGP_DST_OFFSET, dstoffset);
786        dstoffset += gu2_pitch;
787        dstoffset += 0x20000000;
788
789        WRITE_FRAME_BUFFER_STRING32(srcoffset, dword_bytes, data,
790            temp_offset);
791        if (bytes_extra) {
792            temp_offset += dword_bytes;
793            srcoffset += dword_bytes;
794            WRITE_FRAME_BUFFER_STRING8(srcoffset, bytes_extra, data,
795                temp_offset);
796        }
797        WRITE_GP16(MGP_BLT_MODE, blt_mode);
798        offset += pitch;
799        gu2_current_line = 1 - gu2_current_line;
800    }
801}
802
803/*
804 *----------------------------------------------------------------------------
805 * COLOR BITMAP TO SCREEN TRANSPARENT BLT
806 *
807 * This routine transfers color bitmap data to the screen with transparency.
808 * The transparent color is specified.  The only supported ROP is SRCCOPY,
809 * meaning that transparency cannot be applied if the ROP requires
810 * destination data (this is a hardware restriction).
811 *
812 *      SRCX            X offset within source bitmap
813 *      SRCY            Y offset within source bitmap
814 *      DSTX            screen X position to render data
815 *      DSTY            screen Y position to render data
816 *      WIDTH           width of rectangle, in pixels
817 *      HEIGHT          height of rectangle, in scanlines
818 *      *DATA           pointer to bitmap data
819 *      PITCH           pitch of bitmap data (bytes between scanlines)
820 *      COLOR           transparent color
821 *----------------------------------------------------------------------------
822 */
823#if GFX_2DACCEL_DYNAMIC
824void
825gu2_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
826    unsigned short dstx, unsigned short dsty, unsigned short width,
827    unsigned short height, unsigned char *data, long pitch,
828    unsigned long color)
829#else
830void
831gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
832    unsigned short dstx, unsigned short dsty, unsigned short width,
833    unsigned short height, unsigned char *data, long pitch,
834    unsigned long color)
835#endif
836{
837    unsigned long rop32;
838
839    /* SAVE EXISTING RASTER MODE SETTINGS */
840
841    rop32 = gu2_rop32;
842
843    /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */
844    /* Match GU1 implementation that only allows SRCCOPY for the ROP. */
845
846    GU2_WAIT_PENDING;
847    WRITE_GP32(MGP_SRC_COLOR_FG, color);
848    WRITE_GP32(MGP_SRC_COLOR_BG, 0xFFFFFFFF);
849
850    /* SET GLOBAL RASTER SETTINGS */
851    /* This is needed, as the screen-to-screen BLT      */
852    /* routine will overwrite the raster mode register. */
853
854    gu2_rop32 = gu2_bpp | MGP_RM_SRC_TRANS | 0xCC;
855
856    /* CALL NORMAL COLOR BITMAP TO SCREEN BLT ROUTINE */
857
858    gfx_color_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height,
859        data, pitch);
860
861    /* RESTORE RASTER SETTINGS */
862
863    gu2_rop32 = rop32;
864}
865
866/*
867 *----------------------------------------------------------------------------
868 * MONOCHROME BITMAP TO SCREEN BLT
869 *
870 * This routine transfers monochrome bitmap data to the screen.
871 *
872 *      SRCX            X offset within source bitmap
873 *      SRCY            Y offset within source bitmap
874 *      DSTX            screen X position to render data
875 *      DSTY            screen Y position to render data
876 *      WIDTH           width of rectangle, in pixels
877 *      HEIGHT          height of rectangle, in scanlines
878 *      *DATA           pointer to bitmap data
879 *      PITCH           pitch of bitmap data (bytes between scanlines)
880 *----------------------------------------------------------------------------
881 */
882#if GFX_2DACCEL_DYNAMIC
883void
884gu2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
885    unsigned short dstx, unsigned short dsty, unsigned short width,
886    unsigned short height, unsigned char *data, short pitch)
887#else
888void
889gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
890    unsigned short dstx, unsigned short dsty, unsigned short width,
891    unsigned short height, unsigned char *data, short pitch)
892#endif
893{
894    unsigned long dstoffset, size, bytes;
895    unsigned long offset, temp_offset, temp1 = 0, temp2 = 0;
896    unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra;
897    unsigned long shift = 0;
898
899    size = (((unsigned long)width) << 16) | height;
900
901    /* CALCULATE STARTING OFFSETS */
902
903    offset = (unsigned long)srcy *pitch + ((unsigned long)srcx >> 3);
904
905    dstoffset = (unsigned long)dsty *gu2_pitch +
906        (((unsigned long)dstx) << gu2_xshift);
907
908    /* CHECK IF PATTERN ORIGINS NEED TO BE SET */
909
910    if (GFXpatternFlags) {
911        /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */
912
913        dstoffset |= ((unsigned long)(dstx & 7)) << 26;
914        dstoffset |= ((unsigned long)(dsty & 7)) << 29;
915    }
916
917    bytes = ((srcx & 7) + width + 7) >> 3;
918    fifo_lines = bytes >> 5;
919    dwords_extra = (bytes & 0x0000001Cl) >> 2;
920    bytes_extra = bytes & 0x00000003l;
921
922    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
923    /* Put off poll for as long as possible (do most calculations first).   */
924    /* The source offset is always 0 since we allow misaligned dword reads. */
925    /* Need to wait for busy instead of pending, since hardware clears      */
926    /* the host data FIFO at the beginning of a BLT.                        */
927
928    GU2_WAIT_PENDING;
929    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
930    WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long)srcx & 7) << 26);
931    WRITE_GP32(MGP_DST_OFFSET, dstoffset);
932    WRITE_GP32(MGP_WID_HEIGHT, size);
933    WRITE_GP32(MGP_STRIDE, gu2_pitch);
934    WRITE_GP16(MGP_BLT_MODE,
935        (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_HOST |
936        MGP_BM_SRC_MONO);
937
938    /* WAIT FOR BLT TO BE LATCHED */
939
940    GU2_WAIT_PENDING;
941
942    /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */
943
944    while (height--) {
945        temp_offset = offset;
946
947        /* WRITE ALL FULL FIFO LINES */
948
949        for (i = 0; i < fifo_lines; i++) {
950            GU2_WAIT_HALF_EMPTY;
951            WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset,
952                temp1);
953            temp_offset += 32;
954        }
955
956        /* WRITE ALL FULL DWORDS */
957
958        GU2_WAIT_HALF_EMPTY;
959        if (dwords_extra) {
960            WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data,
961                temp_offset, temp1);
962            temp_offset += (dwords_extra << 2);
963        }
964
965        /* WRITE REMAINING BYTES */
966
967        shift = 0;
968        if (bytes_extra)
969            WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data,
970                temp_offset, temp1, temp2);
971
972        offset += pitch;
973    }
974}
975
976/*---------------------------------------------------------------------------
977 * GFX_TEXT_BLT
978 *
979 * This routine is similar to the gfx_mono_bitmap_to_screen_blt routine
980 * but assumes that source data is byte-packed.
981 *---------------------------------------------------------------------------
982 */
983#if GFX_2DACCEL_DYNAMIC
984void
985gu2_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
986    unsigned short height, unsigned char *data)
987#else
988void
989gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
990    unsigned short height, unsigned char *data)
991#endif
992{
993    unsigned long size, bytes;
994    unsigned long dstoffset, temp1 = 0, temp2 = 0, temp_offset = 0;
995    unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra;
996    unsigned long shift;
997
998    size = (((unsigned long)width) << 16) | height;
999
1000    dstoffset = (unsigned long)dsty *gu2_pitch +
1001        (((unsigned long)dstx) << gu2_xshift);
1002
1003    /* CHECK IF PATTERN ORIGINS NEED TO BE SET */
1004
1005    if (GFXpatternFlags) {
1006        /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */
1007
1008        dstoffset |= ((unsigned long)(dstx & 7)) << 26;
1009        dstoffset |= ((unsigned long)(dsty & 7)) << 29;
1010    }
1011
1012    /* CALCULATE STARTING OFFSETS */
1013
1014    bytes = ((width + 7) >> 3) * height;
1015    fifo_lines = bytes >> 5;
1016    dwords_extra = (bytes & 0x0000001Cl) >> 2;
1017    bytes_extra = bytes & 0x00000003l;
1018
1019    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1020
1021    GU2_WAIT_PENDING;
1022    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
1023    WRITE_GP32(MGP_SRC_OFFSET, 0);
1024    WRITE_GP32(MGP_DST_OFFSET, dstoffset);
1025    WRITE_GP32(MGP_WID_HEIGHT, size);
1026    WRITE_GP32(MGP_STRIDE, gu2_pitch);
1027    WRITE_GP16(MGP_BLT_MODE,
1028        (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_HOST |
1029        MGP_BM_SRC_BP_MONO);
1030
1031    /* WAIT FOR BLT TO BE LATCHED */
1032
1033    GU2_WAIT_PENDING;
1034
1035    /* WRITE ALL FULL FIFO LINES */
1036
1037    for (i = 0; i < fifo_lines; i++) {
1038        GU2_WAIT_HALF_EMPTY;
1039        WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, temp1);
1040        temp_offset += 32;
1041    }
1042
1043    /* WRITE ALL FULL DWORDS */
1044
1045    if (dwords_extra || bytes_extra) {
1046        GU2_WAIT_HALF_EMPTY;
1047        if (dwords_extra) {
1048            WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data,
1049                temp_offset, temp1);
1050            temp_offset += (dwords_extra << 2);
1051        }
1052        if (bytes_extra) {
1053            shift = 0;
1054            WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data,
1055                temp_offset, temp1, temp2);
1056        }
1057    }
1058}
1059
1060/*
1061 *----------------------------------------------------------------------------
1062 * BRESENHAM LINE
1063 *
1064 * This routine draws a vector using the specified Bresenham parameters.
1065 * Currently this file does not support a routine that accepts the two
1066 * endpoints of a vector and calculates the Bresenham parameters.  If it
1067 * ever does, this routine is still required for vectors that have been
1068 * clipped.
1069 *
1070 *      X               screen X position to start vector
1071 *      Y               screen Y position to start vector
1072 *      LENGTH          length of the vector, in pixels
1073 *      INITERR         Bresenham initial error term
1074 *      AXIALERR        Bresenham axial error term
1075 *      DIAGERR         Bresenham diagonal error term
1076 *      FLAGS           VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC
1077 *----------------------------------------------------------------------------
1078 */
1079#if GFX_2DACCEL_DYNAMIC
1080void
1081gu2_bresenham_line(unsigned short x, unsigned short y,
1082    unsigned short length, unsigned short initerr,
1083    unsigned short axialerr, unsigned short diagerr, unsigned short flags)
1084#else
1085void
1086gfx_bresenham_line(unsigned short x, unsigned short y,
1087    unsigned short length, unsigned short initerr,
1088    unsigned short axialerr, unsigned short diagerr, unsigned short flags)
1089#endif
1090{
1091    unsigned long offset;
1092    unsigned long data1 = (((unsigned long)axialerr) << 16) | diagerr;
1093    unsigned long data2 = (((unsigned long)length) << 16) | initerr;
1094    unsigned short vector_mode = gu2_vector_mode | flags;
1095
1096    /* CALCULATE STARTING OFFSET */
1097
1098    offset = (unsigned long)y *gu2_pitch + (((unsigned long)x) << gu2_xshift);
1099
1100    /* CHECK NULL LENGTH */
1101
1102    if (!length)
1103        return;
1104
1105    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1106    /* Put off poll for as long as possible (do most calculations first). */
1107
1108    GU2_WAIT_PENDING;
1109    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32);
1110    WRITE_GP32(MGP_DST_OFFSET, offset);
1111    WRITE_GP32(MGP_VEC_ERR, data1);
1112    WRITE_GP32(MGP_VEC_LEN, data2);
1113    WRITE_GP32(MGP_STRIDE, gu2_pitch);
1114    WRITE_GP32(MGP_VECTOR_MODE, vector_mode);
1115}
1116
1117/*---------------------------------------------------------------------------
1118 * GFX_WAIT_UNTIL_IDLE
1119 *
1120 * This routine waits until the graphics engine is idle.  This is required
1121 * before allowing direct access to the frame buffer.
1122 *---------------------------------------------------------------------------
1123 */
1124#if GFX_2DACCEL_DYNAMIC
1125void
1126gu2_wait_until_idle(void)
1127#else
1128void
1129gfx_wait_until_idle(void)
1130#endif
1131{
1132    while (READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY) ;
1133}
1134
1135/*---------------------------------------------------------------------------
1136 * GFX_TEST_BLT_PENDING
1137 *
1138 * This routine returns 1 if a BLT is pending, meaning that a call to
1139 * perform a rendering operation would stall.  Otherwise it returns 0.
1140 * It is used by Darwin during random testing to only start a BLT
1141 * operation when it knows the Durango routines won't spin on graphics
1142 * (so Darwin can continue to do frame buffer reads and writes).
1143 *---------------------------------------------------------------------------
1144 */
1145#if GFX_2DACCEL_DYNAMIC
1146int
1147gu2_test_blt_pending(void)
1148#else
1149int
1150gfx_test_blt_pending(void)
1151#endif
1152{
1153    if (READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING)
1154        return (1);
1155    return (0);
1156}
1157
1158/*---------------------------------------------------------------------------
1159 * NEW ROUTINES FOR REDCLOUD
1160 *---------------------------------------------------------------------------
1161 */
1162
1163/*---------------------------------------------------------------------------
1164 * GFX2_SET_SOURCE_STRIDE
1165 *
1166 * This routine sets the stride to be used in successive screen to screen
1167 * BLTs (used by gfx2_screen_to_screen_blt and gfx2_mono_expand_blt).
1168 *---------------------------------------------------------------------------
1169 */
1170#if GFX_2DACCEL_DYNAMIC
1171void
1172gu22_set_source_stride(unsigned short stride)
1173#else
1174void
1175gfx2_set_source_stride(unsigned short stride)
1176#endif
1177{
1178    /* SAVE STRIDE TO BE USED LATER */
1179
1180    gu2_src_pitch = (unsigned long)stride;
1181}
1182
1183/*---------------------------------------------------------------------------
1184 * GFX2_SET_DESTINATION_STRIDE
1185 *
1186 * This routine sets the stride used when rendering to the screen.
1187 *---------------------------------------------------------------------------
1188 */
1189#if GFX_2DACCEL_DYNAMIC
1190void
1191gu22_set_destination_stride(unsigned short stride)
1192#else
1193void
1194gfx2_set_destination_stride(unsigned short stride)
1195#endif
1196{
1197    /* SAVE STRIDE TO BE USED LATER */
1198
1199    gu2_dst_pitch = (unsigned long)stride;
1200}
1201
1202/*---------------------------------------------------------------------------
1203 * GFX2_SET_PATTERN_ORIGIN
1204 *
1205 * This routine sets the origin within an 8x8 pattern.  It is needed if
1206 * using a monochrome or color pattern (not used for a solid pattern).
1207 *---------------------------------------------------------------------------
1208 */
1209#if GFX_2DACCEL_DYNAMIC
1210void
1211gu22_set_pattern_origin(int x, int y)
1212#else
1213void
1214gfx2_set_pattern_origin(int x, int y)
1215#endif
1216{
1217    /* STORE IN FORMAT THAT CAN BE COMBINED WITH THE DESTINATION OFFSET */
1218
1219    gu2_pattern_origin = (((unsigned long)(x & 7)) << 26) |
1220        (((unsigned long)(y & 7)) << 29);
1221}
1222
1223/*---------------------------------------------------------------------------
1224 * GFX2_SET_SOURCE_TRANSPARENCY
1225 *
1226 * This routine sets the source transparency color and mask to be used
1227 * in future rendering operations.  If both the color and mask are set
1228 * to zero (normally completely transparent), those values indicate that
1229 * transparency should be disabled.
1230 *---------------------------------------------------------------------------
1231 */
1232#if GFX_2DACCEL_DYNAMIC
1233void
1234gu22_set_source_transparency(unsigned long color, unsigned long mask)
1235#else
1236void
1237gfx2_set_source_transparency(unsigned long color, unsigned long mask)
1238#endif
1239{
1240    /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */
1241
1242    GU2_WAIT_PENDING;
1243    WRITE_GP32(MGP_SRC_COLOR_FG, color);
1244    WRITE_GP32(MGP_SRC_COLOR_BG, mask);
1245
1246    /* SET TRANSPARENCY FLAG */
1247
1248    GFXsourceFlags = (color || mask) ? MGP_RM_SRC_TRANS : 0;
1249}
1250
1251/*---------------------------------------------------------------------------
1252 * GFX2_SET_ALPHA_MODE
1253 *
1254 * This routine sets the alpha blending mode to be used in successive
1255 * rendering operations.
1256 *---------------------------------------------------------------------------
1257 */
1258#if GFX_2DACCEL_DYNAMIC
1259void
1260gu22_set_alpha_mode(int mode)
1261#else
1262void
1263gfx2_set_alpha_mode(int mode)
1264#endif
1265{
1266    /* SAVE ALPHA MODE FOR LATER */
1267
1268    gu2_alpha_mode = mode;
1269}
1270
1271/*---------------------------------------------------------------------------
1272 * GFX2_SET_ALPHA_VALUE
1273 *
1274 * This routine sets the alpha value to be used with certain alpha blending
1275 * modes (ALPHA_MODE_BLEND).
1276 *---------------------------------------------------------------------------
1277 */
1278#if GFX_2DACCEL_DYNAMIC
1279void
1280gu22_set_alpha_value(unsigned char value)
1281#else
1282void
1283gfx2_set_alpha_value(unsigned char value)
1284#endif
1285{
1286    /* SAVE ALPHA VALUE TO BE USED LATER */
1287
1288    gu2_alpha_value = (unsigned long)value;
1289
1290    /* SET GLOBAL FLAG */
1291    /* gfx2_* routines will use this flag to program alpha values */
1292    /* appropriately.  Normal gfx_* routines will always write    */
1293    /* the current ROP settings.  In this way, the alpha mode     */
1294    /* affects only second generation routines.                   */
1295
1296    gu2_alpha_active = 1;
1297
1298    switch (gu2_alpha_mode) {
1299    case ALPHA_MODE_BLEND:
1300
1301        /* GENERATE 32-BIT VERSION OF RASTER MODE REGISTER */
1302        /* Pattern data is not involved in the operation.  */
1303
1304        gu2_alpha32 = gu2_alpha_value | gu2_bpp;
1305
1306        /* HANDLE SPECIAL CASES FOR ENDPOINTS              */
1307        /* The 8-bit hardware alpha value is always        */
1308        /* interpreted as a fraction.  Consequently, there */
1309        /* is no way to use values of 255 or 0 to exclude  */
1310        /* one of the inputs.                              */
1311
1312        switch (gu2_alpha_value) {
1313            /* DESTINATION ONLY                               */
1314            /* Operation is alpha * A, where A is destination */
1315            /* and alpha is 1.                                */
1316
1317        case 0:
1318
1319            gu2_alpha32 |= MGP_RM_SELECT_ALPHA_1 |
1320                MGP_RM_ALPHA_TIMES_A |
1321                MGP_RM_ALPHA_TO_RGB | MGP_RM_DEST_FROM_CHAN_A;
1322            break;
1323
1324            /* SOURCE ONLY                                    */
1325            /* Operation is alpha * A, where A is source and  */
1326            /* alpha is 1.                                    */
1327
1328        case 255:
1329
1330            gu2_alpha32 |= MGP_RM_SELECT_ALPHA_1 |
1331                MGP_RM_ALPHA_TO_RGB | MGP_RM_ALPHA_TIMES_A;
1332            break;
1333
1334            /* DEFAULT                                        */
1335            /* Operation is alpha * A + (1 - alpha) * B;      */
1336            /* A is source, B is destination and alpha is the */
1337            /* programmed 8-bit value.                        */
1338
1339        default:
1340
1341            gu2_alpha32 |= MGP_RM_SELECT_ALPHA_R |
1342                MGP_RM_ALPHA_TO_RGB | MGP_RM_ALPHA_A_PLUS_BETA_B;
1343
1344        }
1345
1346        /* CHECK IF SOURCE INFORMATION SHOULD BE MERGED    */
1347        /* Alpha value of 0 indicates destination only.    */
1348
1349        if (gu2_alpha_value != 0)
1350            gu2_alpha32 |= GFXsourceFlags;
1351
1352        /* SET FLAG FOR DESTINATION DATA IF NECESSARY      */
1353        /* Alpha value of 255 indicates no destination     */
1354
1355        if (gu2_alpha_value != 255) {
1356            gu2_alpha_blt_mode = MGP_BM_DST_REQ;
1357            gu2_alpha_vec_mode = MGP_VM_DST_REQ;
1358        }
1359
1360        break;
1361    }
1362}
1363
1364/*---------------------------------------------------------------------------
1365 * GFX2_PATTERN_FILL
1366 *
1367 * This routine is similar to the gfx_pattern_fill routine, but allows the
1368 * use of an arbitrary destination stride.  The rendering position is
1369 * also specified as an offset instead of an (x,y) position.
1370 *---------------------------------------------------------------------------
1371 */
1372#if GFX_2DACCEL_DYNAMIC
1373void
1374gu22_pattern_fill(unsigned long dstoffset, unsigned short width,
1375    unsigned short height)
1376#else
1377void
1378gfx2_pattern_fill(unsigned long dstoffset, unsigned short width,
1379    unsigned short height)
1380#endif
1381{
1382    unsigned long size;
1383
1384    size = (((unsigned long)width) << 16) | height;
1385
1386    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1387    /* Put off poll for as long as possible (do most calculations first). */
1388
1389    GU2_WAIT_PENDING;
1390    WRITE_GP32(MGP_RASTER_MODE, gu2_rop32);
1391    WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin);
1392    WRITE_GP32(MGP_WID_HEIGHT, size);
1393    WRITE_GP32(MGP_STRIDE, gu2_dst_pitch);
1394    WRITE_GP32(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1395    gu2_bm_throttle = 0;
1396    gu2_vm_throttle = 0;
1397}
1398
1399/*---------------------------------------------------------------------------
1400 * GFX2_COLOR_PATTERN_FILL
1401 *
1402 * This routine is used to render a rectangle using the current raster
1403 * operation and the specified color pattern.  It allows an 8x8 color
1404 * pattern to be rendered without multiple calls to the gfx_set_color_pattern
1405 * and gfx_pattern_fill routines.
1406 *---------------------------------------------------------------------------
1407 */
1408#if GFX_2DACCEL_DYNAMIC
1409void
1410gu22_color_pattern_fill(unsigned long dstoffset, unsigned short width,
1411    unsigned short height, unsigned long *pattern)
1412#else
1413void
1414gfx2_color_pattern_fill(unsigned long dstoffset, unsigned short width,
1415    unsigned short height, unsigned long *pattern)
1416#endif
1417{
1418    int pass;
1419    unsigned long lines, size, patxorigin, patoffset;
1420
1421    /* ONLY USE HW PATTERN ORIGIN FOR THE X DIRECTION */
1422    /* Y direction handled by referencing proper location in pattern data. */
1423
1424    patxorigin = (gu2_pattern_origin) & 0x1C000000;
1425
1426    /* OVERRIDE PATTERN FLAGS IN ROP TO FORCE COLOR PATTERN */
1427
1428    GU2_WAIT_PENDING;
1429    WRITE_GP32(MGP_RASTER_MODE,
1430        (gu2_rop32 & ~MGP_RM_PAT_FLAGS) | MGP_RM_PAT_COLOR);
1431
1432    /* ATTEMPT TO OPTIMIZE */
1433    /* If possible, we can perform the pattern fill in only a few passes    */
1434    /* This is performed by multiplying the pitch by an appropriate amount. */
1435    /* Consequently, if the multiplied pitch exceeds 16 bits, this          */
1436    /* optimization is impossible.                                          */
1437
1438    if ((gu2_dst_pitch << (gu2_xshift + 1)) <= 0xFFFF) {
1439        /* HANDLE VARIOUS COLOR DEPTHS DIFFERENTLY */
1440
1441        switch (gu2_xshift) {
1442        case 0:                       /* 8 BPP */
1443
1444            /* TWO PASSES FOR 8 BPP */
1445            /* Render every other line per pass by doubling the pitch. */
1446
1447            patoffset = (gu2_pattern_origin >> 28) & 0x0E;
1448            for (pass = 0; pass < 2; pass++) {
1449                /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */
1450
1451                GU2_WAIT_PENDING;
1452                WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin);
1453                lines = (height + 1 - pass) >> 1;
1454                if (!lines)
1455                    break;
1456                size = (((unsigned long)width) << 16) | lines;
1457                WRITE_GP32(MGP_WID_HEIGHT, size);
1458                WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 1);
1459                WRITE_GP32(MGP_PAT_DATA_1, BYTE_SWIZZLE(pattern[patoffset]));
1460                WRITE_GP32(MGP_PAT_DATA_0,
1461                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1462                patoffset = (patoffset + 4) & 0x0E;
1463                WRITE_GP32(MGP_PAT_COLOR_1, BYTE_SWIZZLE(pattern[patoffset]));
1464                WRITE_GP32(MGP_PAT_COLOR_0,
1465                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1466                patoffset = (patoffset + 4) & 0x0E;
1467
1468                /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */
1469                /* Those registers are not pipelined. */
1470
1471                GU2_WAIT_BUSY;
1472                WRITE_GP32(MGP_PAT_COLOR_3, BYTE_SWIZZLE(pattern[patoffset]));
1473                WRITE_GP32(MGP_PAT_COLOR_2,
1474                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1475                patoffset = (patoffset + 4) & 0x0E;
1476                WRITE_GP32(MGP_PAT_COLOR_5, BYTE_SWIZZLE(pattern[patoffset]));
1477                WRITE_GP32(MGP_PAT_COLOR_4,
1478                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1479                WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1480                gu2_bm_throttle = 0;
1481                gu2_vm_throttle = 0;
1482
1483                /* ADJUST FOR NEXT PASS */
1484
1485                dstoffset += gu2_dst_pitch;
1486                patoffset = (patoffset + 6) & 0x0E;
1487            }
1488            break;
1489
1490        case 1:                       /* 12, 15, OR 16 BPP */
1491
1492            /* FOUR PASSES FOR 16 BPP */
1493            /* Render every 4th line per pass by quadrupling the pitch. */
1494
1495            patoffset = (gu2_pattern_origin >> 27) & 0x1C;
1496            for (pass = 0; pass < 4; pass++) {
1497                /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */
1498
1499                GU2_WAIT_PENDING;
1500                WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin);
1501                lines = (height + 3 - pass) >> 2;
1502                if (!lines)
1503                    break;
1504                size = (((unsigned long)width) << 16) | lines;
1505                WRITE_GP32(MGP_WID_HEIGHT, size);
1506                WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 2);
1507                WRITE_GP32(MGP_PAT_COLOR_1, WORD_SWIZZLE(pattern[patoffset]));
1508                WRITE_GP32(MGP_PAT_COLOR_0,
1509                    WORD_SWIZZLE(pattern[patoffset + 1]));
1510                WRITE_GP32(MGP_PAT_DATA_1,
1511                    WORD_SWIZZLE(pattern[patoffset + 2]));
1512                WRITE_GP32(MGP_PAT_DATA_0,
1513                    WORD_SWIZZLE(pattern[patoffset + 3]));
1514                patoffset = (patoffset + 16) & 0x1C;
1515
1516                /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */
1517                /* Those registers are not pipelined. */
1518
1519                GU2_WAIT_BUSY;
1520                WRITE_GP32(MGP_PAT_COLOR_5, WORD_SWIZZLE(pattern[patoffset]));
1521                WRITE_GP32(MGP_PAT_COLOR_4,
1522                    WORD_SWIZZLE(pattern[patoffset + 1]));
1523                WRITE_GP32(MGP_PAT_COLOR_3,
1524                    WORD_SWIZZLE(pattern[patoffset + 2]));
1525                WRITE_GP32(MGP_PAT_COLOR_2,
1526                    WORD_SWIZZLE(pattern[patoffset + 3]));
1527                WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1528                gu2_bm_throttle = 0;
1529                gu2_vm_throttle = 0;
1530
1531                /* ADJUST FOR NEXT PASS */
1532
1533                dstoffset += gu2_dst_pitch;
1534                patoffset = (patoffset + 20) & 0x1C;
1535            }
1536            break;
1537
1538        case 2:                       /* 32 BPP */
1539
1540            /* EIGHT PASSES FOR 32 BPP */
1541            /* Render every 8th line per pass by setting pitch * 8. */
1542
1543            patoffset = (gu2_pattern_origin >> 26) & 0x38;
1544            for (pass = 0; pass < 8; pass++) {
1545                /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */
1546
1547                GU2_WAIT_PENDING;
1548                WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin);
1549                lines = (height + 7 - pass) >> 3;
1550                if (!lines)
1551                    break;
1552                size = (((unsigned long)width) << 16) | lines;
1553                WRITE_GP32(MGP_WID_HEIGHT, size);
1554                WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 3);
1555                WRITE_GP32(MGP_PAT_COLOR_1, pattern[patoffset + 4]);
1556                WRITE_GP32(MGP_PAT_COLOR_0, pattern[patoffset + 5]);
1557                WRITE_GP32(MGP_PAT_DATA_1, pattern[patoffset + 6]);
1558                WRITE_GP32(MGP_PAT_DATA_0, pattern[patoffset + 7]);
1559
1560                /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */
1561                /* Those registers are not pipelined. */
1562
1563                GU2_WAIT_BUSY;
1564                WRITE_GP32(MGP_PAT_COLOR_5, pattern[patoffset]);
1565                WRITE_GP32(MGP_PAT_COLOR_4, pattern[patoffset + 1]);
1566                WRITE_GP32(MGP_PAT_COLOR_3, pattern[patoffset + 2]);
1567                WRITE_GP32(MGP_PAT_COLOR_2, pattern[patoffset + 3]);
1568                WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1569                gu2_bm_throttle = 0;
1570                gu2_vm_throttle = 0;
1571
1572                /* ADJUST FOR NEXT PASS */
1573
1574                dstoffset += gu2_dst_pitch;
1575                patoffset = (patoffset + 8) & 0x38;
1576            }
1577            break;
1578        }
1579    }
1580
1581    else {
1582        WRITE_GP32(MGP_STRIDE, gu2_dst_pitch);
1583
1584        switch (gu2_xshift) {
1585        case 0:                       /* 8 BPP - 4 LINES PER PASS */
1586
1587            patoffset = (gu2_pattern_origin >> 28) & 0x0E;
1588            while (height) {
1589                lines = height > 4 ? 4 : height;
1590
1591                /* CAN WRITE SOME REGISTERS WHILE PENDING */
1592
1593                WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin);
1594                WRITE_GP32(MGP_WID_HEIGHT,
1595                    (((unsigned long)width) << 16) | lines);
1596                WRITE_GP32(MGP_PAT_DATA_1, BYTE_SWIZZLE(pattern[patoffset]));
1597                WRITE_GP32(MGP_PAT_DATA_0,
1598                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1599                patoffset = (patoffset + 2) & 0x0E;
1600                WRITE_GP32(MGP_PAT_COLOR_1, BYTE_SWIZZLE(pattern[patoffset]));
1601                WRITE_GP32(MGP_PAT_COLOR_0,
1602                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1603                patoffset = (patoffset + 2) & 0x0E;
1604
1605                /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */
1606                /* Those registers are not pipelined.             */
1607
1608                GU2_WAIT_BUSY;
1609                WRITE_GP32(MGP_PAT_COLOR_3, BYTE_SWIZZLE(pattern[patoffset]));
1610                WRITE_GP32(MGP_PAT_COLOR_2,
1611                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1612                patoffset = (patoffset + 2) & 0x0E;
1613                WRITE_GP32(MGP_PAT_COLOR_5, BYTE_SWIZZLE(pattern[patoffset]));
1614                WRITE_GP32(MGP_PAT_COLOR_4,
1615                    BYTE_SWIZZLE(pattern[patoffset + 1]));
1616                patoffset = (patoffset + 2) & 0x0E;
1617                WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1618
1619                /* ADJUST FOR NEXT PASS */
1620
1621                dstoffset += gu2_dst_pitch << 2;
1622                height -= (unsigned short)lines;
1623            }
1624            break;
1625
1626        case 1:                       /* 12, 15 AND 16 BPP - 2 LINES PER PASS */
1627
1628            patoffset = (gu2_pattern_origin >> 27) & 0x1C;
1629            while (height) {
1630                lines = height > 2 ? 2 : height;
1631
1632                /* CAN WRITE SOME REGISTERS WHILE PENDING */
1633
1634                WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin);
1635                WRITE_GP32(MGP_WID_HEIGHT,
1636                    (((unsigned long)width) << 16) | lines);
1637                WRITE_GP32(MGP_PAT_COLOR_1, WORD_SWIZZLE(pattern[patoffset]));
1638                WRITE_GP32(MGP_PAT_COLOR_0,
1639                    WORD_SWIZZLE(pattern[patoffset + 1]));
1640                WRITE_GP32(MGP_PAT_DATA_1,
1641                    WORD_SWIZZLE(pattern[patoffset + 2]));
1642                WRITE_GP32(MGP_PAT_DATA_0,
1643                    WORD_SWIZZLE(pattern[patoffset + 3]));
1644                patoffset = (patoffset + 4) & 0x1C;
1645
1646                /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */
1647                /* Those registers are not pipelined.             */
1648
1649                GU2_WAIT_BUSY;
1650                WRITE_GP32(MGP_PAT_COLOR_5, WORD_SWIZZLE(pattern[patoffset]));
1651                WRITE_GP32(MGP_PAT_COLOR_4,
1652                    WORD_SWIZZLE(pattern[patoffset + 1]));
1653                WRITE_GP32(MGP_PAT_COLOR_3,
1654                    WORD_SWIZZLE(pattern[patoffset + 2]));
1655                WRITE_GP32(MGP_PAT_COLOR_2,
1656                    WORD_SWIZZLE(pattern[patoffset + 3]));
1657                patoffset = (patoffset + 4) & 0x1C;
1658                WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1659
1660                /* ADJUST FOR NEXT PASS */
1661
1662                dstoffset += gu2_dst_pitch << 1;
1663                height -= (unsigned short)lines;
1664            }
1665            break;
1666
1667        case 2:                       /* 32 BPP - 1 LINE PER PASS */
1668
1669            patoffset = (gu2_pattern_origin >> 26) & 0x38;
1670            while (height) {
1671                /* CAN WRITE SOME REGISTERS WHILE PENDING */
1672
1673                WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin);
1674                WRITE_GP32(MGP_WID_HEIGHT,
1675                    (((unsigned long)width) << 16) | 1l);
1676                WRITE_GP32(MGP_PAT_COLOR_1, pattern[patoffset + 4]);
1677                WRITE_GP32(MGP_PAT_COLOR_0, pattern[patoffset + 5]);
1678                WRITE_GP32(MGP_PAT_DATA_1, pattern[patoffset + 6]);
1679                WRITE_GP32(MGP_PAT_DATA_0, pattern[patoffset + 7]);
1680
1681                /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */
1682                /* Those registers are not pipelined.             */
1683
1684                GU2_WAIT_BUSY;
1685                WRITE_GP32(MGP_PAT_COLOR_5, pattern[patoffset]);
1686                WRITE_GP32(MGP_PAT_COLOR_4, pattern[patoffset + 1]);
1687                WRITE_GP32(MGP_PAT_COLOR_3, pattern[patoffset + 2]);
1688                WRITE_GP32(MGP_PAT_COLOR_2, pattern[patoffset + 3]);
1689                patoffset = (patoffset + 8) & 0x38;
1690                WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle);
1691
1692                /* ADJUST FOR NEXT PASS */
1693
1694                dstoffset += gu2_dst_pitch;
1695                height--;
1696            }
1697            break;
1698        }
1699
1700    }
1701
1702}
1703
1704/*---------------------------------------------------------------------------
1705 * GFX2_SCREEN_TO_SCREEN_BLT
1706 *
1707 * This routine is similar to the gfx_screen_to_screen_blt routine but
1708 * allows the use of arbitrary source and destination strides and alpha
1709 * blending.  It also allows the use of an arbitrary ROP with transparency.
1710 *---------------------------------------------------------------------------
1711 */
1712#if GFX_2DACCEL_DYNAMIC
1713void
1714gu22_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset,
1715    unsigned short width, unsigned short height, int flags)
1716#else
1717void
1718gfx2_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset,
1719    unsigned short width, unsigned short height, int flags)
1720#endif
1721{
1722    unsigned long size, xbytes;
1723    unsigned short blt_mode;
1724
1725    size = (((unsigned long)width) << 16) | height;
1726
1727    /* USE ALPHA SETTINGS, IF REQUESTED */
1728
1729    if (gu2_alpha_active)
1730        blt_mode = gu2_alpha_blt_mode | MGP_BM_SRC_FB;
1731
1732    else
1733        blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB;
1734
1735    /* CALCULATE THE DIRECTION OF THE BLT */
1736    /* Using offsets, so flags from the calling routine are needed. */
1737
1738    if (flags & 1) {
1739        xbytes = (width - 1) << gu2_xshift;
1740        srcoffset += xbytes;
1741        dstoffset += xbytes;
1742        blt_mode |= MGP_BM_NEG_XDIR;
1743    }
1744    if (flags & 2) {
1745        srcoffset += (height - 1) * gu2_src_pitch;
1746        dstoffset += (height - 1) * gu2_dst_pitch;
1747        blt_mode |= MGP_BM_NEG_YDIR;
1748    }
1749
1750    /* TURN INTO BYTE ADDRESS IF NEGATIVE X DIRECTION */
1751    /* This is a quirk of the hardware. */
1752
1753    if (blt_mode & MGP_BM_NEG_XDIR) {
1754        srcoffset += (1 << gu2_xshift) - 1;
1755        dstoffset += (1 << gu2_xshift) - 1;
1756    }
1757
1758    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1759    /* Put off poll for as long as possible (do most calculations first). */
1760
1761    GU2_WAIT_PENDING;
1762
1763    if (gu2_alpha_active) {
1764        WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32);
1765    } else {
1766        WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
1767    }
1768
1769    WRITE_GP32(MGP_SRC_OFFSET, srcoffset);
1770    WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin);
1771    WRITE_GP32(MGP_WID_HEIGHT, size);
1772    WRITE_GP32(MGP_STRIDE, gu2_dst_pitch | (gu2_src_pitch << 16));
1773    WRITE_GP16(MGP_BLT_MODE, blt_mode | gu2_bm_throttle);
1774    gu2_bm_throttle = 0;
1775    gu2_vm_throttle = 0;
1776}
1777
1778/*---------------------------------------------------------------------------
1779 * GFX2_MONO_EXPAND_BLT
1780 *
1781 * This routine is similar to the gfx2_screen_to_screen_blt routine but
1782 * expands monochrome data stored in graphics memory.
1783 * WARNING: This routine assumes that the regions in graphics memory
1784 * will not overlap, and therefore does not check the BLT direction.
1785 *---------------------------------------------------------------------------
1786 */
1787#if GFX_2DACCEL_DYNAMIC
1788void
1789gu22_mono_expand_blt(unsigned long srcbase, unsigned short srcx,
1790    unsigned short srcy, unsigned long dstoffset, unsigned short width,
1791    unsigned short height, int byte_packed)
1792#else
1793void
1794gfx2_mono_expand_blt(unsigned long srcbase, unsigned short srcx,
1795    unsigned short srcy, unsigned long dstoffset, unsigned short width,
1796    unsigned short height, int byte_packed)
1797#endif
1798{
1799    unsigned long size, srcoffset;
1800    unsigned short blt_mode;
1801
1802    size = (((unsigned long)width) << 16) | height;
1803
1804    /* CALCULATE SOURCE OFFSET */
1805
1806    srcoffset = srcbase + (unsigned long)srcy *gu2_src_pitch;
1807
1808    srcoffset += srcx >> 3;
1809    srcoffset |= ((unsigned long)srcx & 7) << 26;
1810
1811    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1812    /* Put off poll for as long as possible (do most calculations first). */
1813
1814    GU2_WAIT_PENDING;
1815
1816    if (gu2_alpha_active) {
1817        blt_mode = gu2_alpha_blt_mode;
1818
1819        WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32);
1820    } else {
1821        blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK);
1822
1823        WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
1824    }
1825
1826    if (byte_packed)
1827        blt_mode |= MGP_BM_SRC_FB | MGP_BM_SRC_BP_MONO | gu2_bm_throttle;
1828    else
1829        blt_mode |= MGP_BM_SRC_FB | MGP_BM_SRC_MONO | gu2_bm_throttle;
1830
1831    WRITE_GP32(MGP_SRC_OFFSET, srcoffset);
1832    WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin);
1833    WRITE_GP32(MGP_WID_HEIGHT, size);
1834    WRITE_GP32(MGP_STRIDE, gu2_dst_pitch | (gu2_src_pitch << 16));
1835    WRITE_GP16(MGP_BLT_MODE, blt_mode);
1836    gu2_bm_throttle = 0;
1837    gu2_vm_throttle = 0;
1838}
1839
1840/*---------------------------------------------------------------------------
1841 * GFX2_COLOR_BITMAP_TO_SCREEN_BLT
1842 *
1843 * This routine is similar to the gfx_color_bitmap_to_screen_blt routine
1844 * but allows the use of an arbitrary destination stride and alpha blending.
1845 * It also allows the use of an arbitrary ROP with transparency.
1846 *---------------------------------------------------------------------------
1847 */
1848#if GFX_2DACCEL_DYNAMIC
1849void
1850gu22_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1851    unsigned long dstoffset, unsigned short width,
1852    unsigned short height, unsigned char *data, short pitch)
1853#else
1854void
1855gfx2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1856    unsigned long dstoffset, unsigned short width,
1857    unsigned short height, unsigned char *data, short pitch)
1858#endif
1859{
1860    unsigned long size, bytes;
1861    unsigned long offset, temp_offset;
1862    unsigned long srcoffset, dword_bytes, bytes_extra;
1863    unsigned short blt_mode;
1864
1865    size = (((unsigned long)width) << 16) | 1;
1866
1867    /* CALCULATE STARTING OFFSETS */
1868
1869    offset = (unsigned long)srcy *pitch + ((unsigned long)srcx << gu2_xshift);
1870
1871    dstoffset |= gu2_pattern_origin;
1872
1873    bytes = width << gu2_xshift;
1874    dword_bytes = bytes & ~0x3L;
1875    bytes_extra = bytes & 0x3L;
1876
1877    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1878    /* Put off poll for as long as possible (do most calculations first).   */
1879    /* The source offset is always 0 since we allow misaligned dword reads. */
1880    /* We must wait for BLT busy because the GP may be executing a screen   */
1881    /* to screen BLT from the scratchpad area.                              */
1882
1883    GU2_WAIT_BUSY;
1884
1885    if (gu2_alpha_active) {
1886        blt_mode = gu2_alpha_blt_mode;
1887
1888        WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32);
1889    } else {
1890        blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK);
1891
1892        WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
1893    }
1894    blt_mode |= MGP_BM_SRC_FB | gu2_bm_throttle;
1895    gu2_bm_throttle = 0;
1896    gu2_vm_throttle = 0;
1897
1898    WRITE_GP32(MGP_WID_HEIGHT, size);
1899
1900    /* WRITE DATA ONE LINE AT A TIME */
1901    /* For speed reasons, data is written to an offscreen scratch area and
1902     * then BLTed using a screen to screen BLT. This is similar to the GX1 BLT
1903     * buffers, but slightly more efficient in that we can queue up data while
1904     * the GP is rendering a line.
1905     * */
1906
1907    while (height--) {
1908        temp_offset = offset;
1909        srcoffset = gfx_gx2_scratch_base;
1910        if (gu2_current_line)
1911            srcoffset += 8192;
1912
1913        GU2_WAIT_PENDING;
1914        WRITE_GP32(MGP_SRC_OFFSET, srcoffset);
1915        WRITE_GP32(MGP_DST_OFFSET, dstoffset);
1916        dstoffset += gu2_dst_pitch;
1917        dstoffset += 0x20000000;
1918
1919        WRITE_FRAME_BUFFER_STRING32(srcoffset, dword_bytes, data,
1920            temp_offset);
1921        if (bytes_extra) {
1922            temp_offset += dword_bytes;
1923            srcoffset += dword_bytes;
1924            WRITE_FRAME_BUFFER_STRING8(srcoffset, bytes_extra, data,
1925                temp_offset);
1926        }
1927        WRITE_GP16(MGP_BLT_MODE, blt_mode);
1928        offset += pitch;
1929        gu2_current_line = 1 - gu2_current_line;
1930    }
1931}
1932
1933/*---------------------------------------------------------------------------
1934 * GFX2_TEXT_BLT
1935 *
1936 * This routine is similar to the gfx2_mono_bitmap_to_screen_blt routine
1937 * but assumes that source data is byte-packed.
1938 *---------------------------------------------------------------------------
1939 */
1940#if GFX_2DACCEL_DYNAMIC
1941void
1942gu22_text_blt(unsigned long dstoffset, unsigned short width,
1943    unsigned short height, unsigned char *data)
1944#else
1945void
1946gfx2_text_blt(unsigned long dstoffset, unsigned short width,
1947    unsigned short height, unsigned char *data)
1948#endif
1949{
1950    unsigned long size, bytes;
1951    unsigned long temp1 = 0, temp2 = 0, temp_offset = 0;
1952    unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra;
1953    unsigned long shift;
1954    unsigned short blt_mode;
1955
1956    size = (((unsigned long)width) << 16) | height;
1957
1958    /* CALCULATE STARTING OFFSETS */
1959
1960    bytes = ((width + 7) >> 3) * height;
1961    fifo_lines = bytes >> 5;
1962    dwords_extra = (bytes & 0x0000001Cl) >> 2;
1963    bytes_extra = bytes & 0x00000003l;
1964
1965    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1966
1967    GU2_WAIT_PENDING;
1968
1969    if (gu2_alpha_active) {
1970        blt_mode = gu2_alpha_blt_mode;
1971
1972        WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32);
1973    } else {
1974        blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK);
1975
1976        WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
1977    }
1978
1979    WRITE_GP32(MGP_SRC_OFFSET, 0);
1980    WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin);
1981    WRITE_GP32(MGP_WID_HEIGHT, size);
1982    WRITE_GP32(MGP_STRIDE, gu2_dst_pitch);
1983    WRITE_GP16(MGP_BLT_MODE, blt_mode | MGP_BM_SRC_HOST |
1984        MGP_BM_SRC_BP_MONO | gu2_bm_throttle);
1985    gu2_bm_throttle = 0;
1986    gu2_vm_throttle = 0;
1987
1988    /* WAIT FOR BLT TO BE LATCHED */
1989
1990    GU2_WAIT_PENDING;
1991
1992    /* WRITE ALL FULL FIFO LINES */
1993
1994    for (i = 0; i < fifo_lines; i++) {
1995        GU2_WAIT_HALF_EMPTY;
1996        WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, temp1);
1997        temp_offset += 32;
1998    }
1999
2000    /* WRITE ALL FULL DWORDS */
2001
2002    if (dwords_extra || bytes_extra) {
2003        GU2_WAIT_HALF_EMPTY;
2004        if (dwords_extra) {
2005            WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data,
2006                temp_offset, temp1);
2007            temp_offset += (dwords_extra << 2);
2008        }
2009        if (bytes_extra) {
2010            shift = 0;
2011            WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data,
2012                temp_offset, temp1, temp2);
2013        }
2014    }
2015}
2016
2017/*---------------------------------------------------------------------------
2018 * GFX2_MONO_BITMAP_TO_SCREEN_BLT
2019 *
2020 * This routine is similar to the gfx_mono_bitmap_to_screen_blt routine
2021 * but allows the use of an arbitrary destination stride and alpha blending.
2022 *---------------------------------------------------------------------------
2023 */
2024#if GFX_2DACCEL_DYNAMIC
2025void
2026gu22_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
2027    unsigned long dstoffset, unsigned short width,
2028    unsigned short height, unsigned char *data, short pitch)
2029#else
2030void
2031gfx2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
2032    unsigned long dstoffset, unsigned short width,
2033    unsigned short height, unsigned char *data, short pitch)
2034#endif
2035{
2036    unsigned long size, bytes;
2037    unsigned long offset, temp_offset, temp1 = 0, temp2 = 0;
2038    unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra;
2039    unsigned long shift = 0;
2040    unsigned short blt_mode;
2041
2042    size = (((unsigned long)width) << 16) | height;
2043
2044    /* CALCULATE STARTING OFFSETS */
2045
2046    offset = (unsigned long)srcy *pitch + ((unsigned long)srcx >> 3);
2047
2048    bytes = ((srcx & 7) + width + 7) >> 3;
2049    fifo_lines = bytes >> 5;
2050    dwords_extra = (bytes & 0x0000001Cl) >> 2;
2051    bytes_extra = bytes & 0x00000003l;
2052
2053    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
2054
2055    GU2_WAIT_PENDING;
2056
2057    if (gu2_alpha_active) {
2058        blt_mode = gu2_alpha_blt_mode;
2059
2060        WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32);
2061    } else {
2062        blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK);
2063
2064        WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags);
2065    }
2066
2067    WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long)srcx & 7) << 26);
2068    WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin);
2069    WRITE_GP32(MGP_WID_HEIGHT, size);
2070    WRITE_GP32(MGP_STRIDE, gu2_dst_pitch);
2071    WRITE_GP16(MGP_BLT_MODE, blt_mode | MGP_BM_SRC_HOST |
2072        MGP_BM_SRC_MONO | gu2_bm_throttle);
2073    gu2_bm_throttle = 0;
2074    gu2_vm_throttle = 0;
2075
2076    /* WAIT FOR BLT TO BE LATCHED */
2077
2078    GU2_WAIT_PENDING;
2079
2080    /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */
2081
2082    while (height--) {
2083        temp_offset = offset;
2084
2085        /* WRITE ALL FULL FIFO LINES */
2086
2087        for (i = 0; i < fifo_lines; i++) {
2088            GU2_WAIT_HALF_EMPTY;
2089            WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset,
2090                temp1);
2091            temp_offset += 32;
2092        }
2093
2094        /* WRITE ALL FULL DWORDS */
2095
2096        GU2_WAIT_HALF_EMPTY;
2097        if (dwords_extra)
2098            WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data,
2099                temp_offset, temp1);
2100        temp_offset += (dwords_extra << 2);
2101
2102        /* WRITE REMAINING BYTES */
2103
2104        shift = 0;
2105        if (bytes_extra)
2106            WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data,
2107                temp_offset, temp1, temp2);
2108
2109        offset += pitch;
2110    }
2111}
2112
2113/*---------------------------------------------------------------------------
2114 * GFX2_BRESENHAM_LINE
2115 *
2116 * This routine is similar to the gfx_bresenam_line routine but allows
2117 * the use of an arbitrary destination stride.
2118 *---------------------------------------------------------------------------
2119 */
2120#if GFX_2DACCEL_DYNAMIC
2121void
2122gu22_bresenham_line(unsigned long dstoffset,
2123    unsigned short length, unsigned short initerr,
2124    unsigned short axialerr, unsigned short diagerr, unsigned short flags)
2125#else
2126void
2127gfx2_bresenham_line(unsigned long dstoffset,
2128    unsigned short length, unsigned short initerr,
2129    unsigned short axialerr, unsigned short diagerr, unsigned short flags)
2130#endif
2131{
2132    unsigned long vector_mode = gu2_vector_mode | flags;
2133    unsigned long data1 = (((unsigned long)axialerr) << 16) | diagerr;
2134    unsigned long data2 = (((unsigned long)length) << 16) | initerr;
2135
2136    /* CHECK NULL LENGTH */
2137
2138    if (!length)
2139        return;
2140
2141    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
2142    /* Put off poll for as long as possible (do most calculations first). */
2143
2144    GU2_WAIT_PENDING;
2145
2146    if (gu2_alpha_active) {
2147        vector_mode = gu2_alpha_vec_mode | flags;
2148
2149        WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32);
2150    } else
2151        WRITE_GP32(MGP_RASTER_MODE, gu2_rop32);
2152
2153    WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin);
2154    WRITE_GP32(MGP_VEC_ERR, data1);
2155    WRITE_GP32(MGP_VEC_LEN, data2);
2156    WRITE_GP32(MGP_STRIDE, gu2_dst_pitch);
2157    WRITE_GP32(MGP_VECTOR_MODE, vector_mode | gu2_vm_throttle);
2158    gu2_bm_throttle = 0;
2159    gu2_vm_throttle = 0;
2160}
2161
2162/*---------------------------------------------------------------------------
2163 * GFX2_SYNC_TO_VBLANK
2164 *
2165 * This routine sets a flag to synchronize the next rendering routine to
2166 * VBLANK.  The flag is cleared by the rendering routine.
2167 *---------------------------------------------------------------------------
2168 */
2169#if GFX_2DACCEL_DYNAMIC
2170void
2171gu22_sync_to_vblank(void)
2172#else
2173void
2174gfx2_sync_to_vblank(void)
2175#endif
2176{
2177    /* SET FLAGS TO THROTTLE NEXT RENDERING ROUTINE */
2178
2179    gu2_bm_throttle = MGP_BM_THROTTLE;
2180    gu2_vm_throttle = MGP_VM_THROTTLE;
2181}
2182
2183/* END OF FILE */
2184