xf86-video-intel: Branch 'modesetting' - src/common.h src/i810_reg.h src/i830_exa.c

Eric Anholt anholt at kemper.freedesktop.org
Fri Mar 2 23:45:18 EET 2007


 src/common.h   |   37 +++++++++++++++++++++++
 src/i810_reg.h |    2 +
 src/i830_exa.c |   91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+)

New commits:
diff-tree fd52d635603b7093c5a2b7fa9c987cf59f9be27c (from ca0fa875e8bb5cb778d4db7d8053ec0a5ae34ef4)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 2 13:44:57 2007 -0800

    Add a WIP UploadToScreen implementation.  This almost displays right.

diff --git a/src/common.h b/src/common.h
index 8f42bde..6e8ddbd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -131,6 +131,43 @@ extern void I830DPRINTF_stub(const char 
    outring &= ringmask;							\
 } while (0)
 
+static inline void memset_volatile(volatile void *b, int c, size_t len)
+{
+    int i;
+    
+    for (i = 0; i < len; i++)
+	((volatile char *)b)[i] = c;
+}
+
+static inline void memcpy_volatile(volatile void *dst, const void *src,
+				   size_t len)
+{
+    int i;
+    
+    for (i = 0; i < len; i++)
+	((volatile char *)dst)[i] = ((volatile char *)src)[i];
+}
+
+/** Copies a given number of bytes to the ring */
+#define OUT_RING_COPY(n, ptr) do {					\
+    if (I810_DEBUG & DEBUG_VERBOSE_RING)				\
+	ErrorF("OUT_RING_DATA %d bytes\n", n);				\
+    memcpy_volatile(virt + outring, ptr, n);				\
+    outring += n;							\
+    ringused += n;							\
+    outring &= ringmask;						\
+} while (0)
+
+/** Pads the ring with a given number of zero bytes */
+#define OUT_RING_PAD(n) do {						\
+    if (I810_DEBUG & DEBUG_VERBOSE_RING)				\
+	ErrorF("OUT_RING_PAD %d bytes\n", n);				\
+    memset_volatile(virt + outring, 0, n);				\
+    outring += n;							\
+    ringused += n;							\
+    outring &= ringmask;						\
+} while (0)
+
 union intfloat {
 	float f;
 	unsigned int ui;
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 6a9c11e..d63be02 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1906,6 +1906,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
 #define SRC_COPY_BLT_WRITE_RGB		(1<<20)
 
+#define XY_PAT_BLT_IMMEDIATE		((2<<29)|(0x72<<22))
+
 #define XY_MONO_PAT_BLT_CMD		((0x2<<29)|(0x52<<22)|0x7)
 #define XY_MONO_PAT_VERT_SEED		((1<<10)|(1<<9)|(1<<8))
 #define XY_MONO_PAT_HORT_SEED		((1<<14)|(1<<13)|(1<<12))
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 37fd284..bef8fae 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -297,6 +297,93 @@ i830_get_transformed_coordinates(int x, 
     }
 }
 
+/**
+ * Uploads data from system memory to the framebuffer using a series of
+ * 8x8 pattern blits.
+ */
+static Bool
+i830_upload_to_screen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
+		      int src_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    const int uts_width_max = 16, uts_height_max = 16;
+    int cpp = pDst->drawable.bitsPerPixel / 8;
+    int sub_x, sub_y;
+    CARD32 br13;
+    CARD32 offset;
+
+    if (w > uts_width_max || h > uts_height_max)
+	I830FALLBACK("too large for upload to screen (%d,%d)", w, h);
+
+    offset = exaGetPixmapOffset(pDst);
+
+    br13 = exaGetPixmapPitch(pDst);
+    br13 |= ((I830PatternROP[GXcopy] & 0xff) << 16);
+    switch (pDst->drawable.bitsPerPixel) {
+    case 16:
+	br13 |= 1 << 24;
+	break;
+    case 32:
+	br13 |= 3 << 24;
+	break;
+    }
+
+    for (sub_y = 0; sub_y < uts_height_max && sub_y < h; sub_y += 8) {
+	int sub_height;
+
+	if (sub_y + 8 > h)
+	    sub_height = h - sub_y;
+	else
+	    sub_height = 8;
+
+	for (sub_x = 0; sub_x < uts_width_max && sub_x < w; sub_x += 8) {
+	    int sub_width, line;
+	    char *src_line = src + sub_y * src_pitch + sub_x * cpp;
+
+	    if (sub_x + 8 > w)
+		sub_width = w - sub_x;
+	    else
+		sub_width = 8;
+
+	    BEGIN_LP_RING(6 + (cpp * 8 * 8 / 4));
+
+	    /* XXX We may need a pattern offset here for {x,y} % 8 != 0*/
+	    OUT_RING(XY_PAT_BLT_IMMEDIATE |
+		     XY_SRC_COPY_BLT_WRITE_ALPHA |
+		     XY_SRC_COPY_BLT_WRITE_RGB |
+		     (3 + cpp * 8 * 8 / 4));
+	    OUT_RING(br13);
+	    OUT_RING(((y + sub_y) << 16) | (x + sub_x));
+	    OUT_RING(((y + sub_y + sub_height) << 16) |
+		     (x + sub_x + sub_width));
+	    OUT_RING(offset);
+
+	    /* Write out the lines with valid data, followed by any needed
+	     * padding
+	     */
+	    for (line = 0; line < sub_height; line++) {
+		OUT_RING_COPY(sub_width * cpp, src_line);
+		src_line += src_pitch;
+		if (sub_width != 8)
+		    OUT_RING_PAD((8 - sub_width) * cpp);
+	    }
+	    /* Write out any full padding lines to follow */
+	    if (sub_height != 8)
+		OUT_RING_PAD(8 * cpp * (8 - sub_height));
+
+	    OUT_RING(MI_NOOP);
+	    ADVANCE_LP_RING();
+	}
+    }
+
+    exaMarkSync(pDst->drawable.pScreen);
+    /* exaWaitSync(pDst->drawable.pScreen); */
+
+    return TRUE;
+}
+
+
 /*
  * TODO:
  *   - Dual head?
@@ -421,6 +508,10 @@ I830EXAInit(ScreenPtr pScreen)
  	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
     }
 
+    /* UploadToScreen/DownloadFromScreen */
+    if (0)
+	pI830->EXADriverPtr->UploadToScreen = i830_upload_to_screen;
+
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "EXA initialization failed; trying older version\n");



More information about the xorg-commit mailing list