diff options
author | Eric Anholt <eric@anholt.net> | 2007-03-02 13:44:57 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2007-03-02 13:44:57 -0800 |
commit | fd52d635603b7093c5a2b7fa9c987cf59f9be27c (patch) | |
tree | fa25a303689b73a88b6798e7fe7e9c3bf46fa5a4 | |
parent | ca0fa875e8bb5cb778d4db7d8053ec0a5ae34ef4 (diff) |
Add a WIP UploadToScreen implementation. This almost displays right.
-rw-r--r-- | src/common.h | 37 | ||||
-rw-r--r-- | src/i810_reg.h | 2 | ||||
-rw-r--r-- | src/i830_exa.c | 91 |
3 files changed, 130 insertions, 0 deletions
diff --git a/src/common.h b/src/common.h index 8f42bde8..6e8ddbda 100644 --- a/src/common.h +++ b/src/common.h @@ -131,6 +131,43 @@ extern void I830DPRINTF_stub(const char *filename, int line, 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 6a9c11e4..d63be025 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -1906,6 +1906,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #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 37fd2842..bef8faef 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -297,6 +297,93 @@ i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform, } } +/** + * 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"); |