~ubuntu-branches/ubuntu/trusty/xserver-xorg-video-geode-lts-utopic/trusty-proposed

« back to all changes in this revision

Viewing changes to src/gfx/rndr_gu2.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2015-01-06 10:39:17 UTC
  • Revision ID: package-import@ubuntu.com-20150106103917-bumwel1243pseqs6
Tags: upstream-2.11.16
ImportĀ upstreamĀ versionĀ 2.11.16

Show diffs side-by-side

added added

removed removed

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