1/*
2Copyright (C) 2006 Dennis De Winter  All Rights Reserved.
3Copyright (C) 2007 Alex Deucher  All Rights Reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9of the Software, and to permit persons to whom the Software is furnished to do
10so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22*/
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include "smi.h"
29
30#if SMI501_CLI_DEBUG
31# include "smi_501.h"
32# undef WRITE_DPR
33# define WRITE_DPR(pSmi, dpr, data)					\
34    do {								\
35	if (pSmi->batch_active)						\
36	    BATCH_LOAD_REG((pSmi->DPRBase - pSmi->MapBase) +		\
37			   dpr, data);					\
38	else								\
39	    MMIO_OUT32(pSmi->DPRBase, dpr, data);			\
40	DEBUG("DPR%02X = %08X\n", dpr, data);				\
41    } while (0)
42#endif
43
44static void
45SMI_EXASync(ScreenPtr pScreen, int marker);
46
47static Bool
48SMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
49		int xdir, int ydir, int alu, Pixel planemask);
50
51static void
52SMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height);
53
54static void
55SMI_DoneCopy(PixmapPtr pDstPixmap);
56
57static Bool
58SMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg);
59
60static void
61SMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
62
63static void
64SMI_DoneSolid(PixmapPtr pPixmap);
65
66Bool
67SMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch);
68
69Bool
70SMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch);
71
72static Bool
73SMI_CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture);
74static Bool
75SMI_PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture,
76                     PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
77static void
78SMI_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
79              int dstX, int dstY, int width, int height);
80static void
81SMI730_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
82              int dstX, int dstY, int width, int height);
83static void
84SMI_DoneComposite(PixmapPtr pDst);
85
86
87#define PIXMAP_FORMAT(pixmap) SMI_DEDataFormat(pixmap->drawable.bitsPerPixel)
88#define PIXMAP_OFFSET(pixmap)	IS_MSOC(pSmi) ?				\
89    exaGetPixmapOffset(pixmap) : exaGetPixmapOffset(pixmap) >> 3
90
91Bool
92SMI_EXAInit(ScreenPtr pScreen)
93{
94    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
95    SMIPtr pSmi = SMIPTR(pScrn);
96
97    ENTER();
98
99    if (!(pSmi->EXADriverPtr = exaDriverAlloc())) {
100	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate EXADriverRec.\n");
101	LEAVE(FALSE);
102    }
103
104    /* Require 2.1 semantics:
105       Don't uninitialize the memory manager when swapping out */
106    pSmi->EXADriverPtr->exa_major = 2;
107    pSmi->EXADriverPtr->exa_minor = 1;
108
109    SMI_EngineReset(pScrn);
110
111    /* Memory Manager */
112    pSmi->EXADriverPtr->memoryBase = pSmi->FBBase;
113    pSmi->EXADriverPtr->memorySize = pSmi->FBReserved;
114
115    /* The framebuffer is allocated as an offscreen area with the
116       memory manager (It makes easier further resizing) */
117    pSmi->EXADriverPtr->offScreenBase = 0;
118
119    /* Flags */
120    pSmi->EXADriverPtr->flags = EXA_TWO_BITBLT_DIRECTIONS;
121    if (pSmi->EXADriverPtr->memorySize > pSmi->EXADriverPtr->offScreenBase) {
122	/* Offscreen Pixmaps */
123	pSmi->EXADriverPtr->flags |= EXA_OFFSCREEN_PIXMAPS;
124	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
125		   "EXA offscreen memory manager enabled.\n");
126    }
127    else
128	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
129		   "Not enough video RAM for EXA offscreen memory manager.\n");
130
131    /* 12 bit coordinates */
132    pSmi->EXADriverPtr->maxX = 4096;
133    pSmi->EXADriverPtr->maxY = 4096;
134
135    if (pScrn->bitsPerPixel == 24) {
136	pSmi->EXADriverPtr->maxX = 4096 / 3;
137
138	if (pSmi->Chipset == SMI_LYNX) {
139	    pSmi->EXADriverPtr->maxY = 4096 / 3;
140	}
141    }
142
143    pSmi->EXADriverPtr->pixmapPitchAlign  = 16;
144    pSmi->EXADriverPtr->pixmapOffsetAlign = 8;
145
146    /* Sync */
147    pSmi->EXADriverPtr->WaitMarker = SMI_EXASync;
148
149    /* Copy */
150    pSmi->EXADriverPtr->PrepareCopy = SMI_PrepareCopy;
151    pSmi->EXADriverPtr->Copy = SMI_Copy;
152    pSmi->EXADriverPtr->DoneCopy = SMI_DoneCopy;
153
154    /* Solid */
155    pSmi->EXADriverPtr->PrepareSolid = SMI_PrepareSolid;
156    pSmi->EXADriverPtr->Solid = SMI_Solid;
157    pSmi->EXADriverPtr->DoneSolid = SMI_DoneSolid;
158
159#if 0
160    /* DFS & UTS */
161    pSmi->EXADriverPtr->UploadToScreen = SMI_UploadToScreen;
162    pSmi->EXADriverPtr->DownloadFromScreen = SMI_DownloadFromScreen;
163#endif
164
165    /* Composite */
166    pSmi->EXADriverPtr->CheckComposite = SMI_CheckComposite;
167    pSmi->EXADriverPtr->PrepareComposite = SMI_PrepareComposite;
168
169    if (IS_MSOC(pSmi) || pSmi->Chipset == SMI_COUGAR3DR)
170	pSmi->EXADriverPtr->Composite = SMI730_Composite;
171    else
172	pSmi->EXADriverPtr->Composite = SMI_Composite;
173
174    pSmi->EXADriverPtr->DoneComposite = SMI_DoneComposite;
175
176    if(!exaDriverInit(pScreen, pSmi->EXADriverPtr)) {
177	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "exaDriverInit failed.\n");
178	LEAVE(FALSE);
179    }
180
181
182    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled.\n");
183
184    LEAVE(TRUE);
185}
186
187static void
188SMI_EXASync(ScreenPtr pScreen, int marker)
189{
190    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
191
192    ENTER();
193
194    SMI_AccelSync(pScrn);
195
196    LEAVE();
197}
198
199/* ----------------------------------------------------- EXA Copy ---------------------------------------------- */
200
201CARD8 SMI_BltRop[16] =	/* table stolen from KAA */
202{
203    /* GXclear      */      0x00,         /* 0 */
204    /* GXand        */      0x88,         /* src AND dst */
205    /* GXandReverse */      0x44,         /* src AND NOT dst */
206    /* GXcopy       */      0xCC,         /* src */
207    /* GXandInverted*/      0x22,         /* NOT src AND dst */
208    /* GXnoop       */      0xAA,         /* dst */
209    /* GXxor        */      0x66,         /* src XOR dst */
210    /* GXor         */      0xEE,         /* src OR dst */
211    /* GXnor        */      0x11,         /* NOT src AND NOT dst */
212    /* GXequiv      */      0x99,         /* NOT src XOR dst */
213    /* GXinvert     */      0x55,         /* NOT dst */
214    /* GXorReverse  */      0xDD,         /* src OR NOT dst */
215    /* GXcopyInverted*/     0x33,         /* NOT src */
216    /* GXorInverted */      0xBB,         /* NOT src OR dst */
217    /* GXnand       */      0x77,         /* NOT src OR NOT dst */
218    /* GXset        */      0xFF,         /* 1 */
219};
220
221static Bool
222SMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
223		int alu, Pixel planemask)
224{
225    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
226    SMIPtr pSmi = SMIPTR(pScrn);
227    int src_pitch, dst_pitch;
228    unsigned long src_offset, dst_offset;
229
230    ENTER();
231    DEBUG("xdir=%d ydir=%d alu=%02X", xdir, ydir, alu);
232
233    /* Bit Mask not supported > 16 bpp */
234    if ((pSrcPixmap->drawable.bitsPerPixel > 16) &&
235	(!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask)))
236	LEAVE(FALSE);
237
238    /* calculate pitch in pixel unit */
239    src_pitch  = exaGetPixmapPitch(pSrcPixmap) / (pSrcPixmap->drawable.bitsPerPixel >> 3);
240    dst_pitch  = exaGetPixmapPitch(pDstPixmap) / (pDstPixmap->drawable.bitsPerPixel >> 3);
241    /* calculate offset in 8 byte (64 bit) unit */
242    src_offset = PIXMAP_OFFSET(pSrcPixmap);
243    dst_offset = PIXMAP_OFFSET(pDstPixmap);
244
245    pSmi->AccelCmd = SMI_BltRop[alu]
246		   | SMI_BITBLT
247		   | SMI_QUICK_START;
248
249    if (xdir < 0 || (ydir < 0)) {
250	pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT;
251    }
252
253    if (pDstPixmap->drawable.bitsPerPixel == 24) {
254	src_pitch *= 3;
255	dst_pitch *= 3;
256    }
257
258#if SMI501_CLI_DEBUG
259    BATCH_BEGIN(7);
260#else
261    WaitQueue();
262#endif
263    /* Destination and Source Window Widths */
264    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF));
265    /* Destination and Source Row Pitch */
266    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF));
267
268    /* Bit Mask (planemask) - 16 bit only */
269    if (pSrcPixmap->drawable.bitsPerPixel == 16) {
270	WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000);
271    } else {
272	WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
273    }
274    /* Drawing engine data format */
275    WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pDstPixmap));
276    /* Destination and Source Base Address (offset) */
277    WRITE_DPR(pSmi, 0x40, src_offset);
278    WRITE_DPR(pSmi, 0x44, dst_offset);
279
280    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
281#if SMI501_CLI_DEBUG
282    BATCH_END();
283#endif
284
285    LEAVE(TRUE);
286}
287
288static void
289SMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX,
290	 int dstY, int width, int height)
291{
292    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
293    SMIPtr pSmi = SMIPTR(pScrn);
294
295    ENTER();
296    DEBUG("srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n",
297	  srcX, srcY, dstX, dstY, width, height);
298
299    if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
300	srcX += width  - 1;
301	srcY += height - 1;
302	dstX += width  - 1;
303	dstY += height - 1;
304    }
305
306    if (pDstPixmap->drawable.bitsPerPixel == 24) {
307	srcX  *= 3;
308	dstX  *= 3;
309	width *= 3;
310
311    	if (pSmi->Chipset == SMI_LYNX) {
312	    srcY *= 3;
313	    dstY *= 3;
314        }
315
316	if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
317	    srcX += 2;
318	    dstX += 2;
319	}
320    }
321
322#if SMI501_CLI_DEBUG
323    BATCH_BEGIN(3);
324#else
325    WaitQueue();
326#endif
327    WRITE_DPR(pSmi, 0x00, (srcX  << 16) + (srcY & 0xFFFF));
328    WRITE_DPR(pSmi, 0x04, (dstX  << 16) + (dstY & 0xFFFF));
329    WRITE_DPR(pSmi, 0x08, (width << 16) + (height & 0xFFFF));
330#if SMI501_CLI_DEBUG
331    BATCH_END();
332#endif
333
334    LEAVE();
335}
336
337static void
338SMI_DoneCopy(PixmapPtr pDstPixmap)
339{
340    ENTER();
341
342    LEAVE();
343}
344
345/* ----------------------------------------------------- EXA Solid --------------------------------------------- */
346
347CARD8 SMI_SolidRop[16] =	/* table stolen from KAA */
348{
349    /* GXclear      */      0x00,         /* 0 */
350    /* GXand        */      0xA0,         /* src AND dst */
351    /* GXandReverse */      0x50,         /* src AND NOT dst */
352    /* GXcopy       */      0xF0,         /* src */
353    /* GXandInverted*/      0x0A,         /* NOT src AND dst */
354    /* GXnoop       */      0xAA,         /* dst */
355    /* GXxor        */      0x5A,         /* src XOR dst */
356    /* GXor         */      0xFA,         /* src OR dst */
357    /* GXnor        */      0x05,         /* NOT src AND NOT dst */
358    /* GXequiv      */      0xA5,         /* NOT src XOR dst */
359    /* GXinvert     */      0x55,         /* NOT dst */
360    /* GXorReverse  */      0xF5,         /* src OR NOT dst */
361    /* GXcopyInverted*/     0x0F,         /* NOT src */
362    /* GXorInverted */      0xAF,         /* NOT src OR dst */
363    /* GXnand       */      0x5F,         /* NOT src OR NOT dst */
364    /* GXset        */      0xFF,         /* 1 */
365};
366
367static Bool
368SMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
369{
370    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
371    SMIPtr pSmi = SMIPTR(pScrn);
372    int dst_pitch;
373    unsigned long dst_offset;
374
375    ENTER();
376    DEBUG("alu=%02X\n", alu);
377
378    /* HW ignores alpha */
379    if (pPixmap->drawable.bitsPerPixel == 32)
380	LEAVE(FALSE);
381
382    /* Bit Mask not supported > 16 bpp */
383    if ((pPixmap->drawable.bitsPerPixel > 16) &&
384	(!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask)))
385	LEAVE(FALSE);
386
387    /* calculate pitch in pixel unit */
388    dst_pitch  = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel >> 3);
389    /* calculate offset in 8 byte (64 bit) unit */
390    dst_offset = PIXMAP_OFFSET(pPixmap);
391
392    pSmi->AccelCmd = SMI_SolidRop[alu]
393		   | SMI_BITBLT
394		   | SMI_QUICK_START;
395
396    if (pPixmap->drawable.bitsPerPixel == 24) {
397	dst_pitch *= 3;
398    }
399
400#if SMI501_CLI_DEBUG
401    BATCH_BEGIN(10);
402#else
403    WaitQueue();
404#endif
405
406    /* Destination Window Width */
407    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (dst_pitch & 0xFFFF));
408    /* Destination Row Pitch */
409    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (dst_pitch & 0xFFFF));
410
411    /* Bit Mask (planemask) - 16 bit only */
412    if (pPixmap->drawable.bitsPerPixel == 16) {
413	WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000);
414    } else {
415	WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
416    }
417
418    /* Drawing engine data format */
419    WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pPixmap));
420    /* Source and Destination Base Address (offset) */
421    WRITE_DPR(pSmi, 0x40, dst_offset);
422    WRITE_DPR(pSmi, 0x44, dst_offset);
423    /* Foreground Color */
424    WRITE_DPR(pSmi, 0x14, fg);
425    /* Mono Pattern High and Low */
426    WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF);
427    WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF);
428
429    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
430#if SMI501_CLI_DEBUG
431    BATCH_END();
432#endif
433
434    LEAVE(TRUE);
435}
436
437static void
438SMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
439{
440    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
441    SMIPtr pSmi = SMIPTR(pScrn);
442    int w, h;
443
444    ENTER();
445    DEBUG("x1=%d y1=%d x2=%d y2=%d\n", x1, y1, x2, y2);
446
447    w = (x2 - x1);
448    h = (y2 - y1);
449
450    if (pPixmap->drawable.bitsPerPixel == 24) {
451	x1 *= 3;
452	w  *= 3;
453
454	if (pSmi->Chipset == SMI_LYNX) {
455	    y1 *= 3;
456	}
457    }
458
459#if SMI501_CLI_DEBUG
460    BATCH_BEGIN(2);
461#else
462    WaitQueue();
463#endif
464    WRITE_DPR(pSmi, 0x04, (x1 << 16) | (y1 & 0xFFFF));
465    WRITE_DPR(pSmi, 0x08, (w  << 16) | (h  & 0xFFFF));
466#if SMI501_CLI_DEBUG
467    BATCH_END();
468#endif
469
470    LEAVE();
471}
472
473static void
474SMI_DoneSolid(PixmapPtr pPixmap)
475{
476    ENTER();
477
478    LEAVE();
479}
480
481/* --------------------------------------- EXA DFS & UTS ---------------------------------------- */
482
483Bool
484SMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
485		       char *dst, int dst_pitch)
486{
487    unsigned char *src = pSrc->devPrivate.ptr;
488    int src_pitch = exaGetPixmapPitch(pSrc);
489
490    ENTER();
491    DEBUG("x=%d y=%d w=%d h=%d dst=%d dst_pitch=%d\n",
492	  x, y, w, h, dst, dst_pitch);
493
494    exaWaitSync(pSrc->drawable.pScreen);
495
496    src += (y * src_pitch) + (x * pSrc->drawable.bitsPerPixel/8);
497    w   *= pSrc->drawable.bitsPerPixel/8;
498
499    while (h--) {
500	memcpy(dst, src, w);
501	src += src_pitch;
502	dst += dst_pitch;
503    }
504
505    LEAVE(TRUE);
506}
507
508Bool
509SMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
510		   char *src, int src_pitch)
511{
512    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
513    SMIPtr pSmi = SMIPTR(pScrn);
514    int dst_pixelpitch, src_pixelpitch, align, aligned_pitch;
515    unsigned long dst_offset;
516
517    ENTER();
518    DEBUG("x=%d y=%d w=%d h=%d src=%d src_pitch=%d\n",
519	  x, y, w, h, src, src_pitch);
520
521    if (pDst->drawable.bitsPerPixel == 24) {
522	align = 16;
523    } else {
524	align = 128 / pDst->drawable.bitsPerPixel;
525    }
526
527    aligned_pitch = ((w*pDst->drawable.bitsPerPixel >> 3) + align - 1) & ~(align - 1);
528
529    /* calculate pitch in pixel unit */
530    dst_pixelpitch  = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3);
531    src_pixelpitch = src_pitch / (pDst->drawable.bitsPerPixel >> 3);
532    /* calculate offset in 8 byte (64 bit) unit */
533    dst_offset = PIXMAP_OFFSET(pDst);
534
535    pSmi->AccelCmd = 0xCC /* GXcopy */
536		   | SMI_HOSTBLT_WRITE
537		   | SMI_QUICK_START;
538
539    /* set clipping */
540    SMI_SetClippingRectangle(pScrn, x, y, x+w, y+h);
541
542#if SMI501_CLI_DEBUG
543    BATCH_BEGIN(9);
544#else
545    WaitQueue();
546#endif
547    /* Destination and Source Window Widths */
548    WRITE_DPR(pSmi, 0x3C, (dst_pixelpitch << 16) | (src_pixelpitch & 0xFFFF));
549
550    if (pDst->drawable.bitsPerPixel == 24) {
551	x *= 3;
552	w *= 3;
553	dst_pixelpitch *= 3;
554	if (pSmi->Chipset == SMI_LYNX) {
555	    y *= 3;
556	}
557    }
558
559    /* Source and Destination Row Pitch */
560    WRITE_DPR(pSmi, 0x10, (dst_pixelpitch << 16) | (src_pixelpitch & 0xFFFF));
561    /* Drawing engine data format */
562    WRITE_DPR(pSmi, 0x1C,PIXMAP_FORMAT(pDst));
563    /* Source and Destination Base Address (offset) */
564    WRITE_DPR(pSmi, 0x40, 0);
565    WRITE_DPR(pSmi, 0x44, dst_offset);
566
567    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
568    WRITE_DPR(pSmi, 0x00, 0);
569    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
570    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
571#if SMI501_CLI_DEBUG
572    BATCH_END();
573#endif
574
575    while (h--) {
576	memcpy(pSmi->DataPortBase, src, aligned_pitch);
577	src += src_pitch;
578    }
579
580    /* disable clipping */
581    SMI_DisableClipping(pScrn);
582
583    exaWaitSync(pDst->drawable.pScreen);
584
585    LEAVE(TRUE);
586}
587
588/* --------------------------------------- EXA Composite ---------------------------------------- */
589/* This is a very incomplete Composite implementation that only
590   accelerates PictOpSrc with source coordinates transformation by
591   using 2D Engine rotate-BITBLTs */
592
593#define SMI_ISROTATION_90(t)                                    \
594    (t->matrix[0][0] == 0 && t->matrix[0][1] == xFixed1 &&      \
595     t->matrix[1][0] == -xFixed1 && t->matrix[1][1] == 0)
596
597#define SMI_ISROTATION_270(t)                                   \
598    (t->matrix[0][0] == 0 && t->matrix[0][1] == -xFixed1 &&     \
599     t->matrix[1][0] == xFixed1 && t->matrix[1][1] == 0)
600
601static Bool
602SMI_CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture)
603{
604    ENTER();
605
606    if(op!=PictOpSrc || pMaskPicture ||
607       pSrcPicture->repeatType || !pSrcPicture->transform)
608	LEAVE(FALSE);
609
610    if(!SMI_ISROTATION_90(pSrcPicture->transform) &&
611       !SMI_ISROTATION_270(pSrcPicture->transform))
612        LEAVE(FALSE);
613
614    if(PICT_FORMAT_BPP(pSrcPicture->format) == 24)
615	LEAVE(FALSE);
616
617    LEAVE(TRUE);
618}
619
620static Bool
621SMI_PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture,
622		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
623{
624    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
625    SMIPtr pSmi = SMIPTR(pScrn);
626
627    if (!pSrc) return FALSE;
628    if (!pSrcPicture->pDrawable) return FALSE;
629
630    int src_pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel >> 3);
631    int dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3);
632
633    ENTER();
634
635#if SMI501_CLI_DEBUG
636    BATCH_BEGIN(7);
637#else
638    WaitQueue();
639#endif
640
641    /* Destination and Source Window Widths */
642    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF));
643
644    /* Destination and Source Row Pitch */
645    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF));
646
647    /* Drawing engine data format */
648    WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pDst));
649
650    /* DE Bit Mask */
651    WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
652
653    /* Destination and Source Base Address (offset) */
654    WRITE_DPR(pSmi, 0x40, PIXMAP_OFFSET(pSrc));
655    WRITE_DPR(pSmi, 0x44, PIXMAP_OFFSET(pDst));
656
657    /* DE command*/
658    if(SMI_ISROTATION_90(pSrcPicture->transform))
659        WRITE_DPR(pSmi, 0x0C, 0xCC /*GXCopy*/ | SMI_ROTATE_BLT |
660		    SMI_ROTATE_CW | SMI_QUICK_START);
661    else
662        WRITE_DPR(pSmi, 0x0C, 0xCC /*GXCopy*/ | SMI_ROTATE_BLT |
663		    SMI_ROTATE_CCW | SMI_QUICK_START);
664
665#if SMI501_CLI_DEBUG
666    BATCH_END();
667#endif
668
669    pSmi->renderTransform = pSrcPicture->transform;
670
671    LEAVE(TRUE);
672}
673
674static void
675SMI_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
676		int dstX, int dstY, int width, int height)
677{
678    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
679    SMIPtr pSmi = SMIPTR(pScrn);
680    PictTransformPtr t = pSmi->renderTransform;
681    PictVector v;
682
683    ENTER();
684
685    if(SMI_ISROTATION_90(t)){
686        srcX=srcX+width;
687        dstX=dstX+width-1;
688    }else{
689        srcY=srcY+height;
690        dstY=dstY+height-1;
691    }
692
693    v.vector[0] = IntToxFixed(srcX);
694    v.vector[1] = IntToxFixed(srcY);
695    v.vector[2] = xFixed1;
696    PictureTransformPoint(t, &v);
697
698#if SMI501_CLI_DEBUG
699    BATCH_BEGIN(3);
700#else
701    WaitQueue();
702#endif
703
704    WRITE_DPR(pSmi, 0x00, (xFixedToInt(v.vector[0]) << 16) + (xFixedToInt(v.vector[1]) & 0xFFFF));
705    WRITE_DPR(pSmi, 0x04, (dstX << 16) + (dstY & 0xFFFF));
706    WRITE_DPR(pSmi, 0x08, (height << 16) + (width & 0xFFFF));
707#if SMI501_CLI_DEBUG
708    BATCH_END();
709#endif
710
711    LEAVE();
712}
713
714static void
715SMI730_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
716		int dstX, int dstY, int width, int height)
717{
718    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
719    SMIPtr pSmi = SMIPTR(pScrn);
720    int maxPixels;
721
722    ENTER();
723
724    /* Both SM501 and SM731 cannot rotate-blt more than a certain
725       number of pixels. */
726    if(IS_MSOC(pSmi))
727        maxPixels = 128 / pDst->drawable.bitsPerPixel;
728    else
729        maxPixels = 1280 / pDst->drawable.bitsPerPixel;
730
731    while(height>0){
732	SMI_Composite(pDst, srcX, srcY, maskX, maskY, dstX, dstY, width, min(height, maxPixels));
733
734	srcY += maxPixels;
735	dstY += maxPixels;
736	height -= maxPixels;
737    }
738
739    LEAVE();
740}
741
742static void
743SMI_DoneComposite(PixmapPtr pDst)
744{
745    ENTER();
746    LEAVE();
747}
748