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