summaryrefslogtreecommitdiff
path: root/src/gfx/rndr_gu1.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gfx/rndr_gu1.c')
-rw-r--r--src/gfx/rndr_gu1.c1584
1 files changed, 1584 insertions, 0 deletions
diff --git a/src/gfx/rndr_gu1.c b/src/gfx/rndr_gu1.c
new file mode 100644
index 0000000..5ad5af1
--- /dev/null
+++ b/src/gfx/rndr_gu1.c
@@ -0,0 +1,1584 @@
+/* Copyright (c) 2005 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * */
+
+/*
+ * This file contains routines to program the 2D acceleration hardware for
+ * the first generation graphics unit (GXLV, SC1200).
+ *
+ * gfx_set_bpp
+ * gfx_set_solid_pattern
+ * gfx_set_mono_pattern
+ * gfx_set_color_pattern
+ * gfx_set_solid_source
+ * gfx_set_mono_source
+ * gfx_set_raster_operation
+ * gfx_pattern_fill
+ * gfx_screen_to_screen_blt
+ * gfx_screen_to_screen_xblt
+ * gfx_color_bitmap_to_screen_blt
+ * gfx_color_bitmap_to_screen_xblt
+ * gfx_mono_bitmap_to_screen_blt
+ * gfx_bresenham_line
+ * gfx_wait_until_idle
+ * */
+
+#if GFX_NO_IO_IN_WAIT_MACROS
+#define GFX_WAIT_PENDING \
+ while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { ; }
+#define GFX_WAIT_BUSY \
+ while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { ; }
+#define GFX_WAIT_PIPELINE \
+ while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { ; }
+#else
+#define GFX_WAIT_PENDING \
+ while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { INB (0x80); }
+#define GFX_WAIT_BUSY \
+ while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { INB (0x80); }
+#define GFX_WAIT_PIPELINE \
+ while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { INB (0x80); }
+#endif
+
+void gu1_detect_blt_buffer_base(void);
+
+/*---------------------------------------------------------------------------
+ * GFX_SET_BPP
+ *
+ * This routine sets the bits per pixel value in the graphics engine.
+ * It is also stored in a static variable to use in the future calls to
+ * the rendering routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_bpp(unsigned short bpp)
+#else
+void
+gfx_set_bpp(unsigned short bpp)
+#endif
+{
+ int control = 0;
+ unsigned short pitch = gfx_get_display_pitch();
+
+ GFXbpp = bpp;
+
+ /* DETECT BASE ADDRESSES FOR BLT BUFFERS */
+ /* Different for 2K or 3K of scratchpad. Also need to calculate */
+ /* the number of pixels that can fit in a BLT buffer - need to */
+ /* subtract 16 for alignment considerations. The 2K case, for */
+ /* example, is 816 bytes wide, allowing 800 pixels in 8 BPP, which */
+ /* means rendering operations won't be split for 800x600. */
+
+ gu1_detect_blt_buffer_base();
+ GFXbufferWidthPixels = GFXbb1Base - GFXbb0Base - 16;
+ if (bpp > 8) {
+ /* If 16bpp, divide GFXbufferWidthPixels by 2 */
+ GFXbufferWidthPixels >>= 1;
+ }
+
+ /* SET THE GRAPHICS CONTROLLER BPP AND PITCH */
+ if (bpp > 8) {
+ /* Set the 16bpp bit if necessary */
+ control = BC_16BPP;
+ }
+ if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) {
+ control |= BC_FB_WIDTH_4096;
+ } else if (pitch > 1024) {
+ control |= BC_FB_WIDTH_2048;
+ }
+ GFX_WAIT_BUSY;
+ WRITE_REG32(GP_BLIT_STATUS, control);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SET_SOLID_SOURCE
+ *
+ * This routine is used to specify a solid source color. For the Xfree96
+ * display driver, the source color is used to specify a planemask and the
+ * ROP is adjusted accordingly.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_solid_source(unsigned long color)
+#else
+void
+gfx_set_solid_source(unsigned long color)
+#endif
+{
+ /* CLEAR TRANSPARENCY FLAG */
+
+ GFXsourceFlags = 0;
+
+ /* FORMAT 8 BPP COLOR */
+ /* GX requires 8BPP color data be duplicated into bits [15:8]. */
+
+ if (GFXbpp == 8) {
+ color &= 0x00FF;
+ color |= (color << 8);
+ }
+
+ /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)color);
+ WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)color);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SET_MONO_SOURCE
+ *
+ * This routine is used to specify the monochrome source colors.
+ * It must be called *after* loading any pattern data (those routines
+ * clear the source flags).
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
+ unsigned short transparent)
+#else
+void
+gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
+ unsigned short transparent)
+#endif
+{
+ /* SET TRANSPARENCY FLAG */
+
+ GFXsourceFlags = transparent ? RM_SRC_TRANSPARENT : 0;
+
+ /* FORMAT 8 BPP COLOR */
+ /* GX requires 8BPP color data be duplicated into bits [15:8]. */
+
+ if (GFXbpp == 8) {
+ bgcolor &= 0x00FF;
+ bgcolor |= (bgcolor << 8);
+ fgcolor &= 0x00FF;
+ fgcolor |= (fgcolor << 8);
+ }
+
+ /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)bgcolor);
+ WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)fgcolor);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SET_SOLID_PATTERN
+ *
+ * This routine is used to specify a solid pattern color. It is called
+ * before performing solid rectangle fills or more complicated BLTs that
+ * use a solid pattern color.
+ *
+ * The driver should always call "gfx_load_raster_operation" after a call
+ * to this routine to make sure that the pattern flags are set appropriately.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_solid_pattern(unsigned long color)
+#else
+void
+gfx_set_solid_pattern(unsigned long color)
+#endif
+{
+ /* CLEAR TRANSPARENCY FLAG */
+
+ GFXsourceFlags = 0;
+
+ /* SET PATTERN FLAGS */
+
+ GFXpatternFlags = 0;
+
+ /* FORMAT 8 BPP COLOR */
+ /* GX requires 8BPP color data be duplicated into bits [15:8]. */
+
+ if (GFXbpp == 8) {
+ color &= 0x00FF;
+ color |= (color << 8);
+ }
+
+ /* SAVE THE REFORMATTED COLOR FOR LATER */
+ /* Used to call the "GFX_solid_fill" routine for special cases. */
+
+ GFXsavedColor = color;
+
+ /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SET_MONO_PATTERN
+ *
+ * This routine is used to specify a monochrome pattern.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
+ unsigned long data0, unsigned long data1, unsigned char transparent)
+#else
+void
+gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
+ unsigned long data0, unsigned long data1, unsigned char transparent)
+#endif
+{
+ /* CLEAR TRANSPARENCY FLAG */
+
+ GFXsourceFlags = 0;
+
+ /* SET PATTERN FLAGS */
+
+ GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
+ RM_PAT_MONO;
+
+ /* FORMAT 8 BPP COLOR */
+ /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
+
+ if (GFXbpp == 8) {
+ bgcolor &= 0x00FF;
+ bgcolor |= (bgcolor << 8);
+ fgcolor &= 0x00FF;
+ fgcolor |= (fgcolor << 8);
+ }
+
+ /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor);
+ WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor);
+ WRITE_REG32(GP_PAT_DATA_0, data0);
+ WRITE_REG32(GP_PAT_DATA_1, data1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SET_COLOR_PATTERN
+ *
+ * This routine is used to specify a color pattern.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
+ unsigned long data0, unsigned long data1, unsigned long data2,
+ unsigned long data3, unsigned char transparent)
+#else
+void
+gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
+ unsigned long data0, unsigned long data1, unsigned long data2,
+ unsigned long data3, unsigned char transparent)
+#endif
+{
+ /* CLEAR TRANSPARENCY FLAG */
+
+ GFXsourceFlags = 0;
+
+ /* SET PATTERN FLAGS */
+
+ GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
+ RM_PAT_MONO;
+
+ GFXpatternFlags |= RM_PAT_COLOR;
+ /* FORMAT 8 BPP COLOR */
+ /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
+
+ if (GFXbpp == 8) {
+ bgcolor &= 0x00FF;
+ bgcolor |= (bgcolor << 8);
+ fgcolor &= 0x00FF;
+ fgcolor |= (fgcolor << 8);
+ }
+
+ /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor);
+ WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor);
+ WRITE_REG32(GP_PAT_DATA_0, data0);
+ WRITE_REG32(GP_PAT_DATA_1, data1);
+ if (GFXbpp > 8) {
+ WRITE_REG32(GP_PAT_DATA_2, data2);
+ WRITE_REG32(GP_PAT_DATA_3, data3);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_LOAD_COLOR_PATTERN_LINE
+ *
+ * This routine is used to load a single line of a 8x8 color pattern.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8)
+#else
+void
+gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8)
+#endif
+{
+ /* CLEAR TRANSPARENCY FLAG */
+
+ GFXsourceFlags = 0;
+
+ /* SET PATTERN FLAGS */
+
+ GFXpatternFlags = RM_PAT_COLOR;
+
+ y &= 7;
+
+ if (GFXbpp > 8)
+ pattern_8x8 += (y << 2);
+ else
+ pattern_8x8 += (y << 1);
+
+ /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG32(GP_PAT_DATA_0, pattern_8x8[0]);
+ WRITE_REG32(GP_PAT_DATA_1, pattern_8x8[1]);
+ if (GFXbpp > 8) {
+ WRITE_REG32(GP_PAT_DATA_2, pattern_8x8[2]);
+ WRITE_REG32(GP_PAT_DATA_3, pattern_8x8[3]);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SET_RASTER_OPERATION
+ *
+ * This routine loads the specified raster operation. It sets the pattern
+ * flags appropriately.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_set_raster_operation(unsigned char rop)
+#else
+void
+gfx_set_raster_operation(unsigned char rop)
+#endif
+{
+ unsigned short rop16;
+
+ /* GENERATE 16-BIT VERSION OF ROP WITH PATTERN FLAGS */
+
+ rop16 = (unsigned short)rop | GFXpatternFlags;
+ if ((rop & 0x33) ^ ((rop >> 2) & 0x33))
+ rop16 |= GFXsourceFlags;
+
+ /* SAVE ROP FOR LATER COMPARISONS */
+ /* Need to have the pattern flags included */
+
+ GFXsavedRop = rop16;
+
+ /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */
+ /* True if even bits (0:2:4:6) do not equal the correspinding */
+ /* even bits (1:3:5:7). */
+
+ GFXusesDstData = ((rop & 0x55) ^ ((rop >> 1) & 0x55));
+
+ /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
+ /* Only one operation can be pending at a time. */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_RASTER_MODE, rop16);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * GFX_SOLID_FILL
+ *
+ * This routine MUST be used when performing a solid rectangle fill with
+ * the ROPs of PATCOPY (0xF0), BLACKNESS (0x00), WHITENESS (0xFF), or
+ * PATINVERT (0x0F). There is a bug in GXm for these cases that requires a
+ * workaround.
+ *
+ * For BLACKNESS (ROP = 0x00), set the color to 0x0000.
+ * For WHITENESS (ROP = 0xFF), set the color to 0xFFFF.
+ * For PATINVERT (ROP = 0x0F), invert the desired color.
+ *
+ * X screen X position (left)
+ * Y screen Y position (top)
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * COLOR fill color
+ *
+ * THIS ROUTINE SHOULD NOT BE DIRECTLY CALLED FROM THE DRIVER. The driver
+ * should always use GFX_pattern_fill and let that routine call this one
+ * when approipriate. This is to hide quirks specific to MediaGX hardware.
+ *---------------------------------------------------------------------------
+ */
+void
+gu1_solid_fill(unsigned short x, unsigned short y,
+ unsigned short width, unsigned short height, unsigned long color)
+{
+ unsigned short section;
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+ /* Only one operation can be pending at a time. */
+
+ GFX_WAIT_PENDING;
+
+ /* SET REGISTERS TO DRAW RECTANGLE */
+
+ WRITE_REG16(GP_DST_XCOOR, x);
+ WRITE_REG16(GP_DST_YCOOR, y);
+ WRITE_REG16(GP_HEIGHT, height);
+ WRITE_REG16(GP_RASTER_MODE, 0x00F0); /* PATCOPY */
+ WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color);
+
+ /* CHECK WIDTH FOR GX BUG WORKAROUND */
+
+ if (width <= 16) {
+ /* OK TO DRAW SMALL RECTANGLE IN ONE PASS */
+
+ WRITE_REG16(GP_WIDTH, width);
+ WRITE_REG16(GP_BLIT_MODE, 0);
+ } else {
+ /* DRAW FIRST PART OF RECTANGLE */
+ /* Get to a 16 pixel boundary. */
+
+ section = 0x10 - (x & 0x0F);
+ WRITE_REG16(GP_WIDTH, section);
+ WRITE_REG16(GP_BLIT_MODE, 0);
+
+ /* POLL UNTIL ABLE TO LOAD THE SECOND RECTANGLE */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_DST_XCOOR, x + section);
+ WRITE_REG16(GP_DST_YCOOR, y);
+ WRITE_REG16(GP_WIDTH, width - section);
+ WRITE_REG16(GP_BLIT_MODE, 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * GFX_PATTERN_FILL
+ *
+ * This routine is used to fill a rectangular region. The pattern must
+ * be previously loaded using one of GFX_load_*_pattern routines. Also, the
+ * raster operation must be previously specified using the
+ * "GFX_load_raster_operation" routine.
+ *
+ * X screen X position (left)
+ * Y screen Y position (top)
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_pattern_fill(unsigned short x, unsigned short y,
+ unsigned short width, unsigned short height)
+#else
+void
+gfx_pattern_fill(unsigned short x, unsigned short y,
+ unsigned short width, unsigned short height)
+#endif
+{
+ unsigned short section, buffer_width, blit_mode;
+
+ /* CHECK IF OPTIMIZED SOLID CASES */
+ /* Check all 16 bits of the ROP to include solid pattern flags. */
+
+ switch (GFXsavedRop) {
+ /* CHECK FOR SPECIAL CASES WITHOUT DESTINATION DATA */
+ /* Need hardware workaround for fast "burst write" cases. */
+
+ case 0x00F0:
+ gu1_solid_fill(x, y, width, height, (unsigned short)GFXsavedColor);
+ break;
+ case 0x000F:
+ gu1_solid_fill(x, y, width, height, (unsigned short)~GFXsavedColor);
+ break;
+ case 0x0000:
+ gu1_solid_fill(x, y, width, height, 0x0000);
+ break;
+ case 0x00FF:
+ gu1_solid_fill(x, y, width, height, 0xFFFF);
+ break;
+
+ /* REMAINING CASES REQUIRE DESTINATION DATA OR NOT SOLID COLOR */
+
+ default:
+
+ /* DETERMINE BLT MODE VALUE */
+ /* Still here for non-solid patterns without destination data. */
+
+ blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
+
+ /* SET SOURCE EXPANSION MODE */
+ /* If the ROP requires source data, then the source data is all 1's */
+ /* and then expanded into the desired color in GP_SRC_COLOR_1. */
+
+ blit_mode |= BM_SOURCE_EXPAND;
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+ /* Write the registers that do not change for each section. */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, height);
+
+ /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
+ /* Therefore, width available = BLT buffer width * 2. */
+
+ buffer_width = GFXbufferWidthPixels << 1;
+
+ /* REPEAT UNTIL FINISHED WITH RECTANGLE */
+ /* Perform BLT in vertical sections, as wide as the BLT buffer */
+ /* allows. Hardware does not split the operations, so */
+ /* software must do it to avoid large scanlines that would */
+ /* overflow the BLT buffers. */
+
+ while (width > 0) {
+ /* DETERMINE WIDTH OF SECTION */
+
+ if (width > buffer_width)
+ section = buffer_width;
+ else
+ section = width;
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_DST_XCOOR, x);
+ WRITE_REG16(GP_DST_YCOOR, y);
+ WRITE_REG16(GP_WIDTH, section);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+
+ /* ADJUST PARAMETERS FOR NEXT SECTION */
+
+ width -= section;
+ x += section;
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * GFX_COLOR_PATTERN_FILL
+ *
+ * This routine is used to render a rectangle using the current raster
+ * operation and the specified color pattern. It allows an 8x8 color
+ * pattern to be rendered without multiple calls to the gfx_set_color_pattern
+ * and gfx_pattern_fill routines.
+ *
+ * X screen X position (left)
+ * Y screen Y position (top)
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * *PATTERN pointer to 8x8 color pattern data
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_color_pattern_fill(unsigned short x, unsigned short y,
+ unsigned short width, unsigned short height, unsigned long *pattern)
+#else
+void
+gfx_color_pattern_fill(unsigned short x, unsigned short y,
+ unsigned short width, unsigned short height, unsigned long *pattern)
+#endif
+{
+ unsigned short blit_mode, passes, cur_y, pat_y, i;
+ unsigned short buffer_width, line_width;
+ unsigned short bpp_shift, section, cur_x;
+
+ /* SET APPROPRIATE INCREMENT */
+
+ bpp_shift = (GFXbpp > 8) ? 2 : 1;
+
+ /* SET DESTINATION REQUIRED */
+
+ blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
+
+ /* SET SOURCE EXPANSION */
+
+ blit_mode |= BM_SOURCE_EXPAND;
+
+ /* OVERRIDE RASTER MODE TO FORCE A COLOR PATTERN */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_RASTER_MODE,
+ (GFXsavedRop & ~RM_PAT_MASK & ~RM_PAT_TRANSPARENT) | RM_PAT_COLOR);
+
+ /* WRITE THE REGISTERS THAT DO NOT CHANGE */
+ /* If destination data is required, the width and */
+ /* x position will be overwritten. */
+
+ WRITE_REG16(GP_HEIGHT, 1);
+ WRITE_REG16(GP_WIDTH, width);
+ WRITE_REG16(GP_DST_XCOOR, x);
+
+ /* THE ENTIRE PATTERN WILL NOT BE DRAWN IF THE HEIGHT IS LESS THAN 8 */
+
+ passes = (height < 8) ? height : 8;
+
+ /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
+ /* Therefore, width available = BLT buffer width * 2. */
+
+ buffer_width = GFXbufferWidthPixels << 1;
+
+ for (i = 0; i < passes; i++) {
+ pat_y = ((y + i) & 7) << bpp_shift;
+ cur_y = y + i;
+
+ /* WRITE THE PATTERN DATA FOR THE ACTIVE LINE */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG32(GP_PAT_DATA_0, pattern[pat_y]);
+ WRITE_REG32(GP_PAT_DATA_1, pattern[pat_y + 1]);
+
+ if (GFXbpp > 8) {
+ WRITE_REG32(GP_PAT_DATA_2, pattern[pat_y + 2]);
+ WRITE_REG32(GP_PAT_DATA_3, pattern[pat_y + 3]);
+ }
+
+ /* SPLIT BLT LINE INTO SECTIONS IF REQUIRED */
+ /* If no destination data is required, we can ignore */
+ /* the BLT buffers. Otherwise, we must separate the BLT */
+ /* so as not to overflow the buffers */
+
+ if (blit_mode & BM_READ_DST_BB0) {
+ line_width = width;
+ cur_x = x;
+
+ while (line_width) {
+ section =
+ (line_width > buffer_width) ? buffer_width : line_width;
+ cur_y = y + i;
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_DST_XCOOR, cur_x);
+ WRITE_REG16(GP_WIDTH, section);
+
+ while (cur_y < y + height) {
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_DST_YCOOR, cur_y);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ cur_y += 8;
+ }
+
+ cur_x += section;
+ line_width -= section;
+ }
+
+ } else {
+ while (cur_y < y + height) {
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_DST_YCOOR, cur_y);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ cur_y += 8;
+ }
+ }
+
+ }
+
+ /* RESTORE ORIGINAL ROP AND FLAGS */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_RASTER_MODE, GFXsavedRop);
+
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * SCREEN TO SCREEN BLT
+ *
+ * This routine should be used to perform a screen to screen BLT when the
+ * ROP does not require destination data.
+ *
+ * SRCX screen X position to copy from
+ * SRCY screen Y position to copy from
+ * DSTX screen X position to copy to
+ * DSTY screen Y position to copy to
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height)
+#else
+void
+gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height)
+#endif
+{
+ unsigned short section, buffer_width;
+ unsigned short blit_mode;
+
+ /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
+
+ blit_mode = GFXusesDstData ? BM_READ_DST_FB1 | BM_READ_SRC_FB :
+ BM_READ_SRC_FB;
+
+ /* CHECK Y DIRECTION */
+ /* Hardware has support for negative Y direction. */
+
+ if (dsty > srcy) {
+ blit_mode |= BM_REVERSE_Y;
+ srcy += height - 1;
+ dsty += height - 1;
+ }
+
+ /* CHECK X DIRECTION */
+ /* Hardware does not support negative X direction since at the time */
+ /* of development all supported resolutions could fit a scanline of */
+ /* data at once into the BLT buffers (using both BB0 and BB1). This */
+ /* code is more generic to allow for any size BLT buffer. */
+
+ if (dstx > srcx) {
+ srcx += width;
+ dstx += width;
+ }
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+ /* Write the registers that do not change for each section. */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, height);
+
+ /* CHECK AVAILABLE BLT BUFFER SIZE */
+ /* Can use both BLT buffers if no destination data is required. */
+
+ buffer_width = GFXusesDstData ? GFXbufferWidthPixels :
+ GFXbufferWidthPixels << 1;
+
+ /* REPEAT UNTIL FINISHED WITH RECTANGLE */
+ /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
+ /* Hardware does not split the operations, so software must do it to */
+ /* avoid large scanlines that would overflow the BLT buffers. */
+
+ while (width > 0) {
+ /* CHECK WIDTH OF CURRENT SECTION */
+
+ if (width > buffer_width)
+ section = buffer_width;
+ else
+ section = width;
+
+ /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_SRC_YCOOR, srcy);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+ WRITE_REG16(GP_WIDTH, section);
+
+ /* CHECK X DIRECTION */
+
+ if (dstx > srcx) {
+ /* NEGATIVE X DIRECTION */
+ /* Still positive X direction within the section. */
+
+ srcx -= section;
+ dstx -= section;
+ WRITE_REG16(GP_SRC_XCOOR, srcx);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ } else {
+ /* POSITIVE X DIRECTION */
+
+ WRITE_REG16(GP_SRC_XCOOR, srcx);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ dstx += section;
+ srcx += section;
+ }
+ width -= section;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * SCREEN TO SCREEN TRANSPARENT BLT
+ *
+ * This routine should be used to perform a screen to screen BLT when a
+ * specified color should by transparent. The only supported ROP is SRCCOPY.
+ *
+ * SRCX screen X position to copy from
+ * SRCY screen Y position to copy from
+ * DSTX screen X position to copy to
+ * DSTY screen Y position to copy to
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * COLOR transparent color
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned long color)
+#else
+void
+gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned long color)
+#endif
+{
+ unsigned short section, buffer_width;
+ unsigned short blit_mode = BM_READ_SRC_FB;
+
+ /* CHECK Y DIRECTION */
+ /* Hardware has support for negative Y direction. */
+
+ if (dsty > srcy) {
+ blit_mode |= BM_REVERSE_Y;
+ srcy += height - 1;
+ dsty += height - 1;
+ }
+
+ /* CHECK X DIRECTION */
+ /* Hardware does not support negative X direction since at the time */
+ /* of development all supported resolutions could fit a scanline of */
+ /* data at once into the BLT buffers (using both BB0 and BB1). This */
+ /* code is more generic to allow for any size BLT buffer. */
+
+ if (dstx > srcx) {
+ srcx += width;
+ dstx += width;
+ }
+
+ /* CALCULATE BLT BUFFER SIZE */
+ /* Need to use BB1 to store the BLT buffer data. */
+
+ buffer_width = GFXbufferWidthPixels;
+
+ /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
+
+ if (GFXbpp == 8) {
+ color &= 0x00FF;
+ color |= (color << 8);
+ }
+ color = (color & 0x0000FFFF) | (color << 16);
+
+ /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
+ /* Need to make sure any previous BLT using BB1 is complete. */
+ /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
+
+ GFX_WAIT_BUSY;
+ WRITE_SCRATCH32(GFXbb1Base, color);
+
+ /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
+ /* Already know graphics pipeline is idle. */
+ /* Only need to latch data into the holding registers for the current */
+ /* data from BB1. A 1 pixel wide BLT will suffice. */
+
+ WRITE_REG32(GP_DST_XCOOR, 0);
+ WRITE_REG32(GP_SRC_XCOOR, 0);
+ WRITE_REG32(GP_WIDTH, 0x00010001);
+ WRITE_REG16(GP_RASTER_MODE, 0x00CC);
+ WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
+
+ /* WRITE REGISTERS FOR REAL SCREEN TO SCREEN BLT */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, height);
+ WRITE_REG16(GP_RASTER_MODE, 0x10C6);
+ WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
+
+ /* REPEAT UNTIL FINISHED WITH RECTANGLE */
+ /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
+ /* Hardware does not split the operations, so software must do it to */
+ /* avoid large scanlines that would overflow the BLT buffers. */
+
+ while (width > 0) {
+ /* CHECK WIDTH OF CURRENT SECTION */
+
+ if (width > buffer_width)
+ section = buffer_width;
+ else
+ section = width;
+
+ /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_SRC_YCOOR, srcy);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+ WRITE_REG16(GP_WIDTH, section);
+
+ /* CHECK X DIRECTION */
+ /* Again, this must be done in software, and can be removed if the */
+ /* display driver knows that the BLT buffers will always be large */
+ /* enough to contain an entire scanline of a screen to screen BLT. */
+
+ if (dstx > srcx) {
+ /* NEGATIVE X DIRECTION */
+ /* Still positive X direction within the section. */
+
+ srcx -= section;
+ dstx -= section;
+ WRITE_REG16(GP_SRC_XCOOR, srcx);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ } else {
+ /* POSITIVE X DIRECTION */
+
+ WRITE_REG16(GP_SRC_XCOOR, srcx);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ dstx += section;
+ srcx += section;
+ }
+ width -= section;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * COLOR BITMAP TO SCREEN BLT
+ *
+ * This routine transfers color bitmap data to the screen. For most cases,
+ * when the ROP is SRCCOPY, it may be faster to write a separate routine that
+ * copies the data to the frame buffer directly. This routine should be
+ * used when the ROP requires destination data.
+ *
+ * Transparency is handled by another routine.
+ *
+ * SRCX X offset within source bitmap
+ * SRCY Y offset within source bitmap
+ * DSTX screen X position to render data
+ * DSTY screen Y position to render data
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * *DATA pointer to bitmap data
+ * PITCH pitch of bitmap data (bytes between scanlines)
+ *----------------------------------------------------------------------------
+ */
+
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data, long pitch)
+#else
+void
+gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data, long pitch)
+#endif
+{
+ unsigned short section, buffer_width;
+ unsigned short blit_mode = BM_READ_SRC_BB0;
+ unsigned short temp_height;
+ unsigned long dword_bytes_needed, bytes_extra;
+ unsigned long bpp_shift;
+ long array_offset;
+
+ /* CHECK SIZE OF BLT BUFFER */
+
+ buffer_width = GFXbufferWidthPixels;
+
+ /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
+ /* If no destination data, we have twice the room for */
+ /* source data. */
+
+ if (GFXusesDstData)
+ blit_mode |= BM_READ_DST_FB1;
+ else
+ buffer_width <<= 1;
+
+ /* SET THE SCRATCHPAD BASE */
+
+ SET_SCRATCH_BASE(GFXbb0Base);
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+ /* Write the registers that do not change for each section. */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, 1);
+
+ bpp_shift = (GFXbpp + 7) >> 4;
+
+ while (width > 0) {
+ if (width > buffer_width)
+ section = buffer_width;
+ else
+ section = width;
+
+ dword_bytes_needed = (section << bpp_shift) & ~3l;
+ bytes_extra = (section << bpp_shift) & 3l;
+
+ temp_height = height;
+
+ /* WRITE THE REGISTERS FOR EACH SECTION */
+ /* The GX hardware will auto-increment the Y coordinate, meaning */
+ /* that we don't have to. */
+
+ WRITE_REG16(GP_WIDTH, section);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+
+ /* CALCULATE THE BITMAP OFFSET */
+
+ array_offset =
+ (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift);
+
+ while (temp_height--) {
+ GFX_WAIT_PIPELINE;
+
+ /* WRITE ALL DATA TO THE BLT BUFFERS */
+ /* The WRITE_SCRATCH_STRING macro assumes that the data begins
+ * at the scratchpad offset set by the SET_SCRATCH_BASE macro.
+ * */
+
+ WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
+ array_offset);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+
+ array_offset += pitch;
+ }
+
+ width -= section;
+ srcx += section;
+ dstx += section;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * COLOR BITMAP TO SCREEN TRANSPARENT BLT
+ *
+ * This routine transfers color bitmap data to the screen with transparency.
+ * The transparent color is specified. The only supported ROP is SRCCOPY,
+ * meaning that transparency cannot be applied if the ROP requires
+ * destination data (this is a hardware restriction).
+ *
+ * SRCX X offset within source bitmap
+ * SRCY Y offset within source bitmap
+ * DSTX screen X position to render data
+ * DSTY screen Y position to render data
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * *DATA pointer to bitmap data
+ * PITCH pitch of bitmap data (bytes between scanlines)
+ * COLOR transparent color
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data, long pitch,
+ unsigned long color)
+#else
+void
+gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data, long pitch,
+ unsigned long color)
+#endif
+{
+ unsigned short section, buffer_width;
+ unsigned short temp_height;
+ unsigned long dword_bytes_needed, bytes_extra;
+ unsigned long bpp_shift;
+ long array_offset;
+
+ /* CHECK SIZE OF BLT BUFFER */
+
+ buffer_width = GFXbufferWidthPixels;
+
+ /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
+
+ if (GFXbpp == 8) {
+ color &= 0x00FF;
+ color |= (color << 8);
+ }
+ color = (color & 0x0000FFFF) | (color << 16);
+
+ /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
+ /* Need to make sure any previous BLT using BB1 is complete. */
+ /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
+
+ GFX_WAIT_PIPELINE;
+ GFX_WAIT_PENDING;
+ WRITE_SCRATCH32(GFXbb1Base, color);
+
+ /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
+ /* Already know graphics pipeline is idle. */
+ /* Only need to latch data into the holding registers for the current */
+ /* data from BB1. A 1 pixel wide BLT will suffice. */
+
+ WRITE_REG32(GP_DST_XCOOR, 0);
+ WRITE_REG32(GP_SRC_XCOOR, 0);
+ WRITE_REG32(GP_WIDTH, 0x00010001);
+ WRITE_REG16(GP_RASTER_MODE, 0x00CC);
+ WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+ /* Write the registers that do not change for each section. */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, 1);
+ WRITE_REG16(GP_RASTER_MODE, 0x10C6);
+ WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
+
+ bpp_shift = (GFXbpp + 7) >> 4;
+
+ /* SET THE SCRATCHPAD BASE */
+
+ SET_SCRATCH_BASE(GFXbb0Base);
+
+ while (width > 0) {
+ if (width > buffer_width)
+ section = buffer_width;
+ else
+ section = width;
+
+ dword_bytes_needed = (section << bpp_shift) & ~3l;
+ bytes_extra = (section << bpp_shift) & 3l;
+
+ temp_height = height;
+
+ /* WRITE THE REGISTERS FOR EACH SECTION */
+ /* The GX hardware will auto-increment the Y coordinate, meaning */
+ /* that we don't have to. */
+
+ WRITE_REG16(GP_WIDTH, section);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+
+ /* CALCULATE THE BITMAP OFFSET */
+
+ array_offset =
+ (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift);
+
+ while (temp_height--) {
+ GFX_WAIT_PIPELINE;
+
+ /* WRITE ALL DATA TO THE BLT BUFFERS */
+ /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
+ /* scratchpad offset set by the SET_SCRATCH_BASE macro. */
+
+ WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
+ array_offset);
+ WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0);
+
+ array_offset += pitch;
+ }
+
+ width -= section;
+ srcx += section;
+ dstx += section;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * MONOCHROME BITMAP TO SCREEN BLT
+ *
+ * This routine transfers monochrome bitmap data to the screen.
+ *
+ * SRCX X offset within source bitmap
+ * SRCY Y offset within source bitmap
+ * DSTX screen X position to render data
+ * DSTY screen Y position to render data
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * *DATA pointer to bitmap data
+ * PITCH pitch of bitmap data (bytes between scanlines)
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data, short pitch)
+#else
+void
+gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
+ unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data, short pitch)
+#endif
+{
+ unsigned short section, buffer_width;
+ unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND;
+ unsigned short temp_height;
+ unsigned long dword_bytes_needed, bytes_extra;
+ long array_offset;
+
+ /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
+ /* If no destination data, the source data will always fit. */
+ /* So, in that event we will set the buffer width to a */
+ /* fictitiously large value such that the BLT is never split. */
+
+ if (GFXusesDstData) {
+ buffer_width = GFXbufferWidthPixels;
+ blit_mode |= BM_READ_DST_FB1;
+ } else
+ buffer_width = 3200;
+
+ /* CHECK IF DATA ALREADY IN BLIT BUFFER */
+ /* If the pointer is NULL, data for the full BLT is already there */
+ /* WARNING: This could cause problems if destination data is */
+ /* involved and it overflows the BLT buffer. Need to remove */
+ /* this option and change the drivers to use a temporary buffer. */
+
+ if (!data) {
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+ WRITE_REG16(GP_WIDTH, width);
+ WRITE_REG16(GP_HEIGHT, height);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+ return;
+ }
+
+ /* SET THE SCRATCHPAD BASE */
+
+ SET_SCRATCH_BASE(GFXbb0Base);
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+ /* Write the registers that do not change for each section. */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, 1);
+
+ while (width > 0) {
+ if (width > buffer_width)
+ section = buffer_width;
+ else
+ section = width;
+
+ /* CALCULATE BYTES NEEDED */
+ /* Add 1 for possible alignment issues. */
+
+ dword_bytes_needed = ((section + 7 + (srcx & 7)) >> 3) & ~3l;
+ bytes_extra = ((section + 7 + (srcx & 7)) >> 3) & 3l;
+
+ temp_height = height;
+
+ /* WRITE THE REGISTERS FOR EACH SECTION */
+ /* The GX hardware will auto-increment the Y coordinate, meaning */
+ /* that we don't have to. */
+
+ WRITE_REG16(GP_WIDTH, section);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+ WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
+
+ /* CALCULATE THE BITMAP OFFSET */
+
+ array_offset = (unsigned long)srcy *(long)pitch + ((long)srcx >> 3);
+
+ while (temp_height--) {
+ GFX_WAIT_PIPELINE;
+
+ /* WRITE ALL DATA TO THE BLT BUFFERS */
+ /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
+ /* scratchpad offset set by the SET_SCRATCH_BASE macro. */
+
+ WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
+ array_offset);
+ WRITE_REG16(GP_BLIT_MODE, blit_mode);
+
+ array_offset += pitch;
+ }
+
+ width -= section;
+ srcx += section;
+ dstx += section;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * MONOCHROME TEXT BLT
+ *
+ * This routine transfers contiguous monochrome text data to the screen.
+ *
+ * DSTX screen X position to render data
+ * DSTY screen Y position to render data
+ * WIDTH width of rectangle, in pixels
+ * HEIGHT height of rectangle, in scanlines
+ * *DATA pointer to bitmap data
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data)
+#else
+void
+gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
+ unsigned short height, unsigned char *data)
+#endif
+{
+ unsigned long dword_bytes_needed, bytes_extra;
+ long pitch, buffer_bytes, data_bytes;
+
+ /* CALCULATE DATA SIZE */
+
+ pitch = (width + 7) >> 3;
+ data_bytes = (long)height *pitch;
+
+ /* CHECK FOR SIMPLE CASE */
+ /* This routine is designed to render a source copy text glyph. If
+ * destination data is required or the source data will not fit, we will
+ * punt the operation to the more versatile (and slow) mono bitmap routine
+ * */
+
+ if (GFXbpp > 8)
+ buffer_bytes = GFXbufferWidthPixels << 1;
+ else
+ buffer_bytes = GFXbufferWidthPixels;
+
+ if (GFXusesDstData || data_bytes > buffer_bytes) {
+ gfx_mono_bitmap_to_screen_blt(0, 0, dstx, dsty, width, height, data,
+ (short)pitch);
+ return;
+ }
+
+ /* SET THE SCRATCHPAD BASE */
+
+ SET_SCRATCH_BASE(GFXbb0Base);
+
+ /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
+
+ dword_bytes_needed = data_bytes & ~3l;
+ bytes_extra = data_bytes & 3l;
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_HEIGHT, height);
+ WRITE_REG16(GP_WIDTH, width);
+ WRITE_REG16(GP_DST_XCOOR, dstx);
+ WRITE_REG16(GP_DST_YCOOR, dsty);
+ WRITE_REG16(GP_SRC_XCOOR, 0);
+
+ /* WRITE ALL DATA TO THE BLT BUFFERS */
+ /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
+ /* scratchpad offset set by the SET_SCRATCH_BASE macro. */
+
+ GFX_WAIT_PIPELINE;
+
+ WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 0);
+ WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_SOURCE_TEXT);
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * BRESENHAM LINE
+ *
+ * This routine draws a vector using the specified Bresenham parameters.
+ * Currently this file does not support a routine that accepts the two
+ * endpoints of a vector and calculates the Bresenham parameters. If it
+ * ever does, this routine is still required for vectors that have been
+ * clipped.
+ *
+ * X screen X position to start vector
+ * Y screen Y position to start vector
+ * LENGTH length of the vector, in pixels
+ * INITERR Bresenham initial error term
+ * AXIALERR Bresenham axial error term
+ * DIAGERR Bresenham diagonal error term
+ * FLAGS VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC
+ *----------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_bresenham_line(unsigned short x, unsigned short y,
+ unsigned short length, unsigned short initerr,
+ unsigned short axialerr, unsigned short diagerr, unsigned short flags)
+#else
+void
+gfx_bresenham_line(unsigned short x, unsigned short y,
+ unsigned short length, unsigned short initerr,
+ unsigned short axialerr, unsigned short diagerr, unsigned short flags)
+#endif
+{
+ unsigned short vector_mode = flags;
+
+ if (GFXusesDstData)
+ vector_mode |= VM_READ_DST_FB;
+
+ /* CHECK NULL LENGTH */
+
+ if (!length)
+ return;
+
+ /* LOAD THE REGISTERS FOR THE VECTOR */
+
+ GFX_WAIT_PENDING;
+ WRITE_REG16(GP_DST_XCOOR, x);
+ WRITE_REG16(GP_DST_YCOOR, y);
+ WRITE_REG16(GP_VECTOR_LENGTH, length);
+ WRITE_REG16(GP_INIT_ERROR, initerr);
+ WRITE_REG16(GP_AXIAL_ERROR, axialerr);
+ WRITE_REG16(GP_DIAG_ERROR, diagerr);
+ WRITE_REG16(GP_VECTOR_MODE, vector_mode);
+}
+
+/*---------------------------------------------------------------------------
+ * GFX_WAIT_UNTIL_IDLE
+ *
+ * This routine waits until the graphics engine is idle. This is required
+ * before allowing direct access to the frame buffer.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+void
+gu1_wait_until_idle(void)
+#else
+void
+gfx_wait_until_idle(void)
+#endif
+{
+ GFX_WAIT_BUSY;
+}
+
+/*---------------------------------------------------------------------------
+ * GFX_TEST_BLT_PENDING
+ *
+ * This routine returns 1 if a BLT is pending, meaning that a call to
+ * perform a rendering operation would stall. Otherwise it returns 0.
+ * It is used by Darwin during random testing to only start a BLT
+ * operation when it knows the Durango routines won't spin on graphics
+ * (so Darwin can continue to do frame buffer reads and writes).
+ *---------------------------------------------------------------------------
+ */
+#if GFX_2DACCEL_DYNAMIC
+int
+gu1_test_blt_pending(void)
+#else
+int
+gfx_test_blt_pending(void)
+#endif
+{
+ if (READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING)
+ return (1);
+ else
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * BLT BUFFERS!!!!!
+ *---------------------------------------------------------------------------
+ */
+
+/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */
+/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */
+
+#define BB0_BASE_2K 0x800
+#define BB1_BASE_2K 0xB30
+#define BB0_BASE_3K 0x400
+#define BB1_BASE_3K 0x930
+
+/*---------------------------------------------------------------------------
+ * gu1_detect_blt_buffer_base
+ *
+ * This detection is hidden from the driver by being called from the
+ * "gfx_set_bpp" routine.
+ *
+ * This is fairly ugly for the following reasons:
+ *
+ * - It is the boot code that must set the BLT buffer bases to the
+ * appropriate values and load the scratchpad tags.
+ * - The old drivers would also set the base address values to what they
+ * knew they should be for the 2K or 3K scratchpad configuration.
+ * - Unfortunately, to set the base addresses requires the use of the
+ * CPU_WRITE instruction, an instruction specific to GX.
+ * - Using the CPU_WRITE instruction requires the use of assembly to
+ * produce the appropriate op codes.
+ * - Assembly is something that is avoided in Durango because it is not
+ * platform independent. Some compilers do not support inline assembly.
+ * - Therefore Durango cannot use the CPU_WRITE instruction.
+ * - Therefore drivers using Durango must rely on the boot code to set
+ * the appropriate values. Durango uses this routine to check where
+ * the base addresses have been set.
+ * - Unfortunately, it is not as simple as using IO to check for 2K or 3K
+ * scratchpad size. In VSA1, even though the boot code may set it for
+ * 3K, SoftVGA comes along and resets it to 2K for it's use in text
+ * redraws. It used to be that the display driver would set it back
+ * to 3K.
+ * - So, the Durango code was changed to just always use 2K.
+ * - But, the XpressROM code sets it for 3K, and the newer versions of
+ * SoftVGA do not interfere with that, so then Durango needs to use
+ * the 3K values to work properly.
+ * - Therefore, Durango does somewhat of a kludge by writing to directly
+ * to the scratchpad at both the 2K and 3K locations, then performing
+ * a unobtrusive BLT that loads data into BB0 (the graphics engine
+ * always knows the true base). After the BLT, Durango looks to see
+ * which location changed to know where the base address is.
+ * - This is a relatively simple way to allow Durango to work on old
+ * and new platforms without using theCPU_WRITE instructions.
+ *
+ * To summarize, the BLT buffers are one of the most painful aspects of
+ * the GX graphics unit design, and have been removed from future designs
+ * (the graphics unit has its own dedicated RAM). Durango has tried to
+ * hide the BLT buffer use from the drivers.
+ *---------------------------------------------------------------------------
+ */
+void
+gu1_detect_blt_buffer_base(void)
+{
+ /* ASSUME 2K */
+
+ GFXbb0Base = BB0_BASE_2K;
+ GFXbb1Base = BB1_BASE_2K;
+
+ /* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */
+ /* Boot code should still set 3K values for 4K. */
+
+ if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08) {
+ /* WRITE DATA TO 3K LOCATION */
+
+ GFX_WAIT_BUSY;
+ WRITE_SCRATCH32(BB0_BASE_3K, 0xFEEDFACE);
+
+ /* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */
+
+ WRITE_REG32(GP_DST_XCOOR, 0x00000000); /* AT (0,0) */
+ WRITE_REG32(GP_WIDTH, 0x00010004); /* 4x1 BLT */
+ WRITE_REG16(GP_RASTER_MODE, 0x00AA); /* KEEP DST */
+ WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0); /* STORE IN BB0 */
+
+ /* CHECK 3K LOCATION */
+ /* Breaks if data happened to be 0xFEEDFACE - unlikely. */
+
+ GFX_WAIT_BUSY;
+ if (READ_SCRATCH32(BB0_BASE_3K) != 0xFEEDFACE) {
+ GFXbb0Base = BB0_BASE_3K;
+ GFXbb1Base = BB1_BASE_3K;
+ }
+ }
+}
+
+/* END OF FILE */