Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2006 Joseph Garvin
      3  * Copyright 2012 Connor Behan
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Joseph Garvin <joseph.h.garvin (at) gmail.com>
     27  *    Connor Behan <connor.behan (at) gmail.com>
     28  *
     29  */
     30 
     31 #ifdef HAVE_CONFIG_H
     32 #include "config.h"
     33 #endif
     34 
     35 #include "r128.h"
     36 #include "exa.h"
     37 
     38 #include "r128_reg.h"
     39 #include "r128_rop.h"
     40 
     41 #include "xf86.h"
     42 
     43 /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
     44  * require src and dest datatypes to be equal.
     45  */
     46 Bool R128GetDatatypeBpp(int bpp, uint32_t *type)
     47 {
     48     switch (bpp) {
     49     case 8:
     50         *type = R128_DATATYPE_CI8;
     51         return TRUE;
     52     case 16:
     53         *type = R128_DATATYPE_RGB565;
     54         return TRUE;
     55     case 24:
     56         *type = R128_DATATYPE_RGB888;
     57         return TRUE;
     58     case 32:
     59         *type = R128_DATATYPE_ARGB8888;
     60         return TRUE;
     61     default:
     62         return FALSE;
     63     }
     64 }
     65 
     66 static Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
     67 				 unsigned int offset, unsigned int pitch)
     68 {
     69     ScreenPtr     pScreen   = pPix->drawable.pScreen;
     70     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
     71     R128InfoPtr   info      = R128PTR(pScrn);
     72 
     73     if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) {
     74         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
     75                             "Bad pitch 0x%08x\n", pitch));
     76 	return FALSE;
     77     }
     78 
     79     if (offset % info->ExaDriver->pixmapOffsetAlign != 0) {
     80         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
     81                             "Bad offset 0x%08x\n", offset));
     82 	return FALSE;
     83     }
     84 
     85     *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
     86 
     87     return TRUE;
     88 }
     89 
     90 Bool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
     91 {
     92     uint32_t pitch, offset;
     93     int bpp;
     94 
     95     bpp = pPix->drawable.bitsPerPixel;
     96     if (bpp == 24)
     97         bpp = 8;
     98 
     99     offset = exaGetPixmapOffset(pPix);
    100     pitch = exaGetPixmapPitch(pPix);
    101 
    102     return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
    103 }
    104 
    105 static void Emit2DState(ScrnInfoPtr pScrn)
    106 {
    107     R128InfoPtr   info      = R128PTR(pScrn);
    108     int has_src		    = info->state_2d.src_pitch_offset;
    109     unsigned char *R128MMIO = info->MMIO;
    110 
    111     R128WaitForFifo(pScrn, (has_src ? 10 : 9));
    112 
    113     OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
    114     OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
    115     OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
    116     OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
    117     OUTREG(R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
    118     OUTREG(R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
    119     OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask);
    120     OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl);
    121 
    122     OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
    123     if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
    124 }
    125 
    126 #ifdef R128DRI
    127 void EmitCCE2DState(ScrnInfoPtr pScrn)
    128 {
    129     R128InfoPtr   info      = R128PTR(pScrn);
    130     int has_src		    = info->state_2d.src_pitch_offset;
    131     RING_LOCALS;
    132 
    133     R128CCE_REFRESH( pScrn, info );
    134 
    135     BEGIN_RING( (has_src ? 20 : 18) );
    136 
    137     OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right );
    138     OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl );
    139     OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr );
    140     OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr );
    141     OUT_RING_REG( R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr );
    142     OUT_RING_REG( R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr );
    143     OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask );
    144     OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl );
    145 
    146     OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset );
    147     if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset );
    148 
    149     ADVANCE_RING();
    150 }
    151 #endif
    152 
    153 /* EXA Callbacks */
    154 
    155 static Bool
    156 R128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
    157 {
    158     ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
    159     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    160     R128InfoPtr   info      = R128PTR(pScrn);
    161 
    162     int bpp = pPixmap->drawable.bitsPerPixel;
    163     uint32_t datatype, dst_pitch_offset;
    164 
    165     if (!R128GetDatatypeBpp(bpp, &datatype)) {
    166         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    167                             "R128GetDatatypeBpp failed\n"));
    168 	return FALSE;
    169     }
    170     if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) {
    171         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    172                             "R128GetPixmapOffsetPitch failed\n"));
    173 	return FALSE;
    174     }
    175     if (info->state_2d.in_use) return FALSE;
    176 
    177     info->state_2d.in_use = TRUE;
    178     info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
    179     info->state_2d.dp_brush_bkgd_clr = 0x00000000;
    180     info->state_2d.dp_src_frgd_clr = 0xffffffff;
    181     info->state_2d.dp_src_bkgd_clr = 0x00000000;
    182     info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
    183 					  R128_GMC_BRUSH_SOLID_COLOR |
    184 					  (datatype >> 8) |
    185 					  R128_GMC_SRC_DATATYPE_COLOR |
    186 					  R128_ROP[alu].pattern |
    187 					  R128_GMC_CLR_CMP_CNTL_DIS);
    188     info->state_2d.dp_brush_frgd_clr = fg;
    189     info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
    190     info->state_2d.dp_write_mask = planemask;
    191     info->state_2d.dst_pitch_offset = dst_pitch_offset;
    192     info->state_2d.src_pitch_offset = 0;
    193 
    194 #ifdef R128DRI
    195     if (info->directRenderingEnabled) {
    196         EmitCCE2DState(pScrn);
    197     } else
    198 #endif
    199     {
    200         Emit2DState(pScrn);
    201     }
    202     return TRUE;
    203 }
    204 
    205 static void
    206 R128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
    207 {
    208     ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
    209     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    210     R128InfoPtr   info      = R128PTR(pScrn);
    211     unsigned char *R128MMIO = info->MMIO;
    212 
    213     R128WaitForFifo(pScrn, 2);
    214     OUTREG(R128_DST_Y_X,          (y1 << 16) | x1);
    215     OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1));
    216     exaMarkSync(pScreen);
    217 }
    218 
    219 #define R128DoneSolid R128Done
    220 
    221 void
    222 R128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
    223 			uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask)
    224 {
    225     R128InfoPtr   info      = R128PTR(pScrn);
    226 
    227     info->state_2d.in_use = TRUE;
    228     info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
    229 					  R128_GMC_SRC_PITCH_OFFSET_CNTL |
    230 					  R128_GMC_BRUSH_NONE |
    231 					  (datatype >> 8) |
    232 					  R128_GMC_SRC_DATATYPE_COLOR |
    233 					  R128_ROP[alu].rop |
    234 					  R128_DP_SRC_SOURCE_MEMORY |
    235 					  R128_GMC_CLR_CMP_CNTL_DIS);
    236     info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
    237 			       (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0));
    238     info->state_2d.dp_brush_frgd_clr = 0xffffffff;
    239     info->state_2d.dp_brush_bkgd_clr = 0x00000000;
    240     info->state_2d.dp_src_frgd_clr = 0xffffffff;
    241     info->state_2d.dp_src_bkgd_clr = 0x00000000;
    242     info->state_2d.dp_write_mask = planemask;
    243     info->state_2d.dst_pitch_offset = dst_pitch_offset;
    244     info->state_2d.src_pitch_offset = src_pitch_offset;
    245     info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
    246 
    247 #ifdef R128DRI
    248     if (info->directRenderingEnabled) {
    249         EmitCCE2DState(pScrn);
    250     } else
    251 #endif
    252     {
    253         Emit2DState(pScrn);
    254     }
    255 }
    256 
    257 static Bool
    258 R128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask)
    259 {
    260     ScreenPtr     pScreen   = pSrcPixmap->drawable.pScreen;
    261     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    262     R128InfoPtr   info      = R128PTR(pScrn);
    263 
    264     int bpp = pDstPixmap->drawable.bitsPerPixel;
    265     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
    266 
    267     if (!R128GetDatatypeBpp(bpp, &datatype)) {
    268         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    269                             "R128GetDatatypeBpp failed\n"));
    270 	return FALSE;
    271     }
    272     if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) {
    273         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    274                             "R128GetPixmapOffsetPitch source "
    275                             "failed\n"));
    276 	return FALSE;
    277     }
    278     if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) {
    279         DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    280                             "R128GetPixmapOffsetPitch dest failed\n"));
    281 	return FALSE;
    282     }
    283     if (info->state_2d.in_use) return FALSE;
    284 
    285     info->xdir = xdir;
    286     info->ydir = ydir;
    287 
    288     R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask);
    289 
    290     return TRUE;
    291 }
    292 
    293 static void
    294 R128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
    295 {
    296     ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
    297     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    298     R128InfoPtr   info      = R128PTR(pScrn);
    299     unsigned char *R128MMIO = info->MMIO;
    300 
    301     if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
    302     if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
    303 
    304     R128WaitForFifo(pScrn, 3);
    305     OUTREG(R128_SRC_Y_X,          (srcY << 16) | srcX);
    306     OUTREG(R128_DST_Y_X,          (dstY << 16) | dstX);
    307     OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width);
    308     exaMarkSync(pScreen);
    309 }
    310 
    311 #define R128DoneCopy R128Done
    312 
    313 static void
    314 R128Sync(ScreenPtr pScreen, int marker)
    315 {
    316     R128WaitForIdle(xf86ScreenToScrn(pScreen));
    317 }
    318 
    319 void
    320 R128Done(PixmapPtr pPixmap)
    321 {
    322     ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
    323     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    324     R128InfoPtr   info      = R128PTR(pScrn);
    325 
    326     info->state_2d.in_use = FALSE;
    327 #if defined(R128DRI) && defined(RENDER)
    328     if (info->state_2d.src_pix) {
    329         pScreen->DestroyPixmap(info->state_2d.src_pix);
    330 	info->state_2d.src_pix = NULL;
    331     }
    332     if (info->state_2d.msk_pix) {
    333         pScreen->DestroyPixmap(info->state_2d.msk_pix);
    334 	info->state_2d.msk_pix = NULL;
    335     }
    336 #endif
    337 }
    338 
    339 #ifdef R128DRI
    340 
    341 #define R128CCEPrepareSolid R128PrepareSolid
    342 
    343 static void
    344 R128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
    345 {
    346     ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
    347     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    348     R128InfoPtr   info      = R128PTR(pScrn);
    349     RING_LOCALS;
    350 
    351     R128CCE_REFRESH( pScrn, info );
    352 
    353     BEGIN_RING( 4 );
    354 
    355     OUT_RING_REG( R128_DST_Y_X,          (y1 << 16) | x1 );
    356     OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) );
    357 
    358     ADVANCE_RING();
    359 }
    360 
    361 #define R128CCEDoneSolid R128Done
    362 
    363 #define R128CCEPrepareCopy R128PrepareCopy
    364 
    365 static void
    366 R128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
    367 	 int width, int height)
    368 {
    369     ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
    370     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    371     R128InfoPtr   info      = R128PTR(pScrn);
    372     RING_LOCALS;
    373 
    374     R128CCE_REFRESH( pScrn, info );
    375 
    376     if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
    377     if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
    378 
    379     BEGIN_RING( 6 );
    380 
    381     OUT_RING_REG( R128_SRC_Y_X,          (srcY << 16) | srcX );
    382     OUT_RING_REG( R128_DST_Y_X,          (dstY << 16) | dstX );
    383     OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width );
    384 
    385     ADVANCE_RING();
    386 }
    387 
    388 #define R128CCEDoneCopy R128Done
    389 
    390 static void
    391 R128CCESync(ScreenPtr pScreen, int marker)
    392 {
    393     R128CCEWaitForIdle(xf86ScreenToScrn(pScreen));
    394 }
    395 
    396 #endif
    397 
    398 /*
    399  * Memcpy-based UTS.
    400  */
    401 static Bool
    402 R128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
    403     char *src, int src_pitch)
    404 {
    405     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
    406     R128InfoPtr	info      = R128PTR(pScrn);
    407     char	*dst        = info->FB + exaGetPixmapOffset(pDst);
    408     int		dst_pitch  = exaGetPixmapPitch(pDst);
    409     int		bpp    = pDst->drawable.bitsPerPixel;
    410     int		cpp    = (bpp + 7) >> 3;
    411     int		wBytes = w * cpp;
    412 
    413     dst += (x * cpp) + (y * dst_pitch);
    414 
    415     R128WaitForIdle(pScrn);
    416 
    417     while (h--) {
    418 	memcpy(dst, src, wBytes);
    419 	src += src_pitch;
    420 	dst += dst_pitch;
    421     }
    422 
    423     return TRUE;
    424 }
    425 
    426 /*
    427  * Hostblit-based UTS.
    428  * this assumes 32bit pixels
    429  */
    430 static Bool
    431 R128UploadToScreenHW(PixmapPtr pDst, int x, int y, int w, int h,
    432     char *src, int src_pitch)
    433 {
    434     ScrnInfoPtr	pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
    435     R128InfoPtr	info      = R128PTR(pScrn);
    436     uint32_t	dst_pitch_offset, datatype;
    437     int		cnt, line, px;
    438     unsigned char *R128MMIO = info->MMIO;
    439     int		bpp = pDst->drawable.bitsPerPixel;
    440     uint32_t	*s;
    441 
    442     if (!R128GetDatatypeBpp(bpp, &datatype)) {
    443 	return FALSE;
    444     }
    445 
    446     if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) {
    447 	return FALSE;
    448     }
    449 
    450     info->state_2d.in_use = TRUE;
    451     info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
    452 					  R128_GMC_BRUSH_NONE |
    453 					  (datatype >> 8) |
    454 					  R128_GMC_SRC_DATATYPE_COLOR |
    455 					  R128_ROP3_S |
    456 					  R128_DP_SRC_SOURCE_HOST_DATA |
    457 					  R128_GMC_CLR_CMP_CNTL_DIS);
    458     info->state_2d.dp_cntl = R128_DST_X_LEFT_TO_RIGHT |
    459                              R128_DST_Y_TOP_TO_BOTTOM;
    460     info->state_2d.dp_write_mask = 0xffffffff;
    461     info->state_2d.dst_pitch_offset = dst_pitch_offset;
    462     info->state_2d.default_sc_bottom_right = R128_DEFAULT_SC_RIGHT_MAX |
    463                                              R128_DEFAULT_SC_BOTTOM_MAX;
    464     Emit2DState(pScrn);
    465 
    466     R128WaitForFifo(pScrn, 3);
    467     OUTREG(R128_SRC_Y_X, 0);
    468     OUTREG(R128_DST_Y_X, (y << 16) | x);
    469     OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
    470 
    471     R128WaitForFifo(pScrn, 32);
    472     cnt = 0;
    473 
    474     for (line = 0; line < h; line++) {
    475     	s = (void *)src;
    476     	for (px = 0; px < w; px++) {
    477     	    OUTREG(R128_HOST_DATA0, cpu_to_le32(*s));
    478     	    s++;
    479     	    cnt++;
    480     	    if (cnt > 31) {
    481 		R128WaitForFifo(pScrn, 32);
    482 		cnt = 0;
    483 	    }
    484 	}
    485 	src += src_pitch;
    486     }
    487     info->state_2d.in_use = FALSE;
    488     exaMarkSync(pDst->drawable.pScreen);
    489     return TRUE;
    490 }
    491 
    492 /*
    493  * Memcpy-based DFS.
    494  */
    495 static Bool
    496 R128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
    497     char *dst, int dst_pitch)
    498 {
    499     ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
    500     R128InfoPtr   info      = R128PTR(pScrn);
    501     char  *src        = info->FB + exaGetPixmapOffset(pSrc);
    502     int    src_pitch  = exaGetPixmapPitch(pSrc);
    503 
    504     int bpp    = pSrc->drawable.bitsPerPixel;
    505     int cpp    = (bpp + 7) >> 3;
    506     int wBytes = w * cpp;
    507 
    508     src += (x * cpp) + (y * src_pitch);
    509 
    510     R128WaitForIdle(pScrn);
    511 
    512     while (h--) {
    513 	memcpy(dst, src, wBytes);
    514 	src += src_pitch;
    515 	dst += dst_pitch;
    516     }
    517 
    518     return TRUE;
    519 }
    520 
    521 Bool
    522 R128EXAInit(ScreenPtr pScreen, int total)
    523 {
    524     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    525     R128InfoPtr info  = R128PTR(pScrn);
    526 
    527     info->ExaDriver = exaDriverAlloc();
    528     if (!info->ExaDriver) {
    529         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    530                     "Could not allocate EXA driver...\n");
    531         return FALSE;
    532     }
    533 
    534     info->ExaDriver->exa_major = EXA_VERSION_MAJOR;
    535     info->ExaDriver->exa_minor = EXA_VERSION_MINOR;
    536 
    537     info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset;
    538     info->ExaDriver->offScreenBase = pScrn->virtualY *
    539                                         (pScrn->displayWidth *
    540                                         info->CurrentLayout.pixel_bytes);
    541     info->ExaDriver->memorySize = total;
    542     info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS;
    543 
    544 #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
    545     info->ExaDriver->maxPitchBytes = 16320;
    546 #endif
    547     /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */
    548     info->ExaDriver->pixmapPitchAlign = 32;
    549     info->ExaDriver->pixmapOffsetAlign = 32;
    550     info->ExaDriver->maxX = 2048;
    551     info->ExaDriver->maxY = 2048;
    552 
    553     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    554 	       "Setting up EXA callbacks\n");
    555 
    556 #ifdef R128DRI
    557     if (info->directRenderingEnabled) {
    558 	info->ExaDriver->PrepareSolid = R128CCEPrepareSolid;
    559 	info->ExaDriver->Solid = R128CCESolid;
    560 	info->ExaDriver->DoneSolid = R128CCEDoneSolid;
    561 
    562 	info->ExaDriver->PrepareCopy = R128CCEPrepareCopy;
    563 	info->ExaDriver->Copy = R128CCECopy;
    564 	info->ExaDriver->DoneCopy = R128CCEDoneCopy;
    565 
    566 #ifdef RENDER
    567 	if (info->RenderAccel) {
    568 	    info->ExaDriver->flags |= EXA_OFFSCREEN_ALIGN_POT;
    569 	    info->ExaDriver->CheckComposite = R128CCECheckComposite;
    570 	    info->ExaDriver->PrepareComposite = R128CCEPrepareComposite;
    571 	    info->ExaDriver->Composite = R128CCEComposite;
    572 	    info->ExaDriver->DoneComposite = R128CCEDoneComposite;
    573 	}
    574 #endif
    575 
    576 	info->ExaDriver->WaitMarker = R128CCESync;
    577     } else
    578 #endif
    579     {
    580 	info->ExaDriver->PrepareSolid = R128PrepareSolid;
    581 	info->ExaDriver->Solid = R128Solid;
    582 	info->ExaDriver->DoneSolid = R128DoneSolid;
    583 
    584 	info->ExaDriver->PrepareCopy = R128PrepareCopy;
    585 	info->ExaDriver->Copy = R128Copy;
    586 	info->ExaDriver->DoneCopy = R128DoneCopy;
    587 
    588 	if (pScrn->bitsPerPixel < 24) {
    589 	    info->ExaDriver->UploadToScreen = R128UploadToScreen;
    590 	} else {
    591 	    info->ExaDriver->UploadToScreen = R128UploadToScreenHW;
    592 	}
    593 	info->ExaDriver->DownloadFromScreen = R128DownloadFromScreen;
    594 
    595 	/* The registers used for r128 compositing are CCE specific, just like the
    596 	 * registers used for radeon compositing are CP specific. The radeon driver
    597 	 * falls back to different registers when there is no DRI. The equivalent
    598 	 * registers on the r128 (if they even exist) are not listed in the register
    599 	 * file so I can't implement compositing without DRI.
    600 	 */
    601 
    602 	info->ExaDriver->WaitMarker = R128Sync;
    603     }
    604 
    605     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    606 	       "Initializing 2D acceleration engine...\n");
    607 
    608     R128EngineInit(pScrn);
    609 
    610     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    611 	       "Initializing EXA driver...\n");
    612 
    613     if (!exaDriverInit(pScreen, info->ExaDriver)) {
    614         free(info->ExaDriver);
    615 	return FALSE;
    616     }
    617 
    618     info->state_2d.composite_setup = FALSE;
    619     return TRUE;
    620 }
    621