59d0a87cbeb80056b8f207bf99d317afc97e9ca6
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / accel / sec_exa_sw.c
1 /**************************************************************************
2
3 xserver-xorg-video-exynos
4
5 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #include "sec.h"
32 #include "sec_accel.h"
33 #include "sec_util.h"
34 #include "sec_layer.h"
35 #include "exa.h"
36 #include "fbpict.h"
37 #include "neonmem.h"
38
39 typedef struct
40 {
41     BoxRec  pos;
42     PixmapPtr pixmap;
43     tbm_bo bo;
44     void* addr;
45 } ExaOpBuf;
46
47 typedef struct
48 {
49     int refcnt;
50     int opt;
51     int num;
52     int isSame;
53
54     ExaOpBuf buf[5];
55 } ExaOpInfo;
56
57 typedef struct
58 {
59     BoxRec box;
60     int state;            /*state of region*/
61
62     struct xorg_list link;
63
64     ExaOpBuf *pSrc;
65     ExaOpBuf *pMask;
66     ExaOpBuf *pDst;
67 } ExaBox;
68
69 typedef struct
70 {
71     Bool bDo;
72
73     int alu;
74     Pixel planemask;
75     Pixel fg;
76     PixmapPtr pixmap;
77
78     int x,y,w,h;
79     GCPtr pGC;
80     ExaOpInfo* pOpDst;
81     struct xorg_list opBox;
82 } OpSolid;
83
84 typedef struct
85 {
86     Bool bDo;
87     Pixel pm;
88     int alu;
89     int reverse;
90     int upsidedown;
91     PixmapPtr pSrcPix;
92     PixmapPtr pDstPix;
93
94     /*copy param*/
95     int srcX;
96     int srcY;
97     int dstX;
98     int dstY;
99     int width, height;
100
101     ExaOpInfo* pOpDst;
102     ExaOpInfo* pOpSrc;
103     struct xorg_list opBox;
104 } OpCopy;
105
106 typedef struct
107 {
108     Bool bDo;
109     int op;
110
111     PicturePtr pSrcPicture;
112     PicturePtr pMaskPicture;
113     PicturePtr pDstPicture;
114     PixmapPtr pSrcPixmap;
115     PixmapPtr pMaskPixmap;
116     PixmapPtr pDstPixmap;
117
118     /*copy param*/
119     int srcX, srcY;
120     int maskX, maskY;
121     int dstX, dstY;
122     int width, height;
123
124     ExaOpInfo* pOpSrc;
125     ExaOpInfo* pOpMask;
126     ExaOpInfo* pOpDst;
127     struct xorg_list opBox;
128 } OpComposite;
129
130 typedef struct
131 {
132     Bool bDo;
133
134     PixmapPtr pDst;
135     int x,y,w,h;
136     char* src;
137     int src_pitch;
138
139     ExaOpInfo* pOpDst;
140     struct xorg_list opBox;
141 } OpUTS;
142
143 typedef struct
144 {
145     Bool bDo;
146
147     PixmapPtr pSrc;
148     int x,y,w,h;
149     char* dst;
150     int dst_pitch;
151
152     ExaOpInfo* pOpSrc;
153     struct xorg_list opBox;
154 } OpDFS;
155
156 typedef void (* DoDrawProcPtr) (PixmapPtr pPix, Bool isPart,
157                                 int x, int y,
158                                 int clip_x, int clip_y,
159                                 int w, int h, void* data);
160
161 typedef void (* DoDrawProcPtrEx) (ExaBox* box, void* data);
162
163 static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES];
164 static OpSolid gOpSolid;
165 static OpCopy gOpCopy;
166 static OpComposite gOpComposite;
167 static OpUTS gOpUTS;
168 static OpDFS gOpDFS;
169
170 ExaBox* _swBoxAdd (struct xorg_list *l, BoxPtr b1, BoxPtr b2)
171 {
172     ExaBox* rgn = NULL;
173
174     rgn = calloc (1, sizeof (ExaBox));
175     rgn->state = secUtilBoxIntersect (&rgn->box, b1, b2);
176     if (rgnOUT == rgn->state)
177     {
178         free (rgn);
179         return NULL;
180     }
181
182     xorg_list_add (&rgn->link, l);
183     return rgn;
184 }
185
186 void _swBoxMerge (struct xorg_list *l, struct xorg_list* b, struct xorg_list* t)
187 {
188     ExaBox *b1 = NULL, *b2 = NULL;
189     ExaBox* r=NULL;
190
191     xorg_list_for_each_entry (b1, b, link)
192     {
193         xorg_list_for_each_entry (b2, t, link)
194         {
195             r = _swBoxAdd (l, &b1->box, &b2->box);
196             if (r)
197             {
198                 r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc;
199                 r->pMask= b1->pMask ? b1->pMask : b2->pMask;
200                 r->pDst = b1->pDst ? b1->pDst : b2->pDst;
201             }
202         }
203     }
204 }
205
206 void _swBoxMove (struct xorg_list* l, int tx, int ty)
207 {
208     ExaBox *b = NULL;
209
210     xorg_list_for_each_entry (b, l, link)
211     {
212         secUtilBoxMove (&b->box, tx, ty);
213     }
214 }
215
216 void _swBoxRemoveAll (struct xorg_list* l)
217 {
218     ExaBox *ref = NULL, *next = NULL;
219
220     xorg_list_for_each_entry_safe (ref, next, l, link)
221     {
222         xorg_list_del (&ref->link);
223         free (ref);
224     }
225 }
226
227 int _swBoxIsOne (struct xorg_list* l)
228 {
229     if (l->next != l)
230     {
231         if (l->next == l->prev)
232             return 1;
233         else
234             return -1;
235     }
236
237     return 0;
238 }
239
240 void _swBoxPrint (ExaBox* sb1, const char* name)
241 {
242     ExaBox *b = NULL;
243
244     xorg_list_for_each_entry (b, &sb1->link, link)
245     {
246         XDBG_DEBUG (MEXA, "[%s] %d,%d - %d,%d\n", name,
247                 b->box.x1, b->box.y1, b->box.x2, b->box.y2);
248     }
249 }
250
251 static ExaOpInfo* _swPrepareAccess (PixmapPtr pPix, int index)
252 {
253     ScreenPtr pScreen = pPix->drawable.pScreen;
254     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
255     SECPtr pSec = SECPTR (pScrn);
256     SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
257     ExaOpInfo* op = &OpInfo[index];
258     int opt = TBM_OPTION_READ;
259     int i;
260     tbm_bo *bos;
261     tbm_bo_handle bo_handle;
262     SECFbBoDataPtr bo_data;
263     int num_bo = 0;
264     int ret;
265
266     XDBG_RETURN_VAL_IF_FAIL ((privPixmap != NULL), NULL);
267
268     if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST)
269         opt |= TBM_OPTION_WRITE;
270
271     /* Check mapped */
272     if (privPixmap->exaOpInfo)
273     {
274         op = (ExaOpInfo*)privPixmap->exaOpInfo;
275         op->refcnt++;
276         XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
277                     pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
278         return op;
279     }
280
281     /*Set buffer info*/
282     memset (op, 0x00, sizeof (ExaOpInfo));
283     op->refcnt = 1;
284     op->opt = opt;
285     op->isSame = 0;
286
287     if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB)
288     {
289         ret = secFbFindBo (pSec->pFb,
290                            pPix->drawable.x, pPix->drawable.y,
291                            pPix->drawable.width, pPix->drawable.height,
292                            &num_bo, &bos);
293         XDBG_TRACE (MEXAS,"FB  ret:%d num_pix:%d, %dx%d+%d+%d\n",
294                     ret, num_bo,
295                     pPix->drawable.width, pPix->drawable.height,
296                     pPix->drawable.x, pPix->drawable.y);
297
298         if (ret == rgnSAME && num_bo == 1)
299         {
300             op->num = 1;
301             op->isSame = 1;
302
303             op->buf[0].pixmap = pPix;
304             op->buf[0].bo = bos[0];
305             bo_handle = tbm_bo_map (op->buf[0].bo, TBM_DEVICE_CPU, op->opt);
306             op->buf[0].addr = bo_handle.ptr;
307             op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr;
308             op->buf[0].pos.x1 = 0;
309             op->buf[0].pos.y1 = 0;
310             op->buf[0].pos.x2 = pPix->drawable.width;
311             op->buf[0].pos.y2 = pPix->drawable.height;
312         }
313         else
314         {
315
316 #ifdef NO_CRTC_MODE
317             if (num_bo == 0)
318             {
319                 num_bo = 1;
320                 bos = (tbm_bo *)calloc(1, sizeof(tbm_bo));
321                 bos[0] = pSec->pFb->default_bo;
322             }
323 #endif //NO_CRTC_MODE
324
325             op->num = num_bo;
326             op->isSame = 0;
327
328             for (i = 0; i < num_bo; i++)
329             {
330                 tbm_bo_get_user_data (bos[i], TBM_BO_DATA_FB, (void**)&bo_data);
331                 op->buf[i].pixmap = secRenderBoGetPixmap (pSec->pFb, bos[i]);
332                 op->buf[i].bo = bos[i];
333                 bo_handle = tbm_bo_map (bos[i], TBM_DEVICE_CPU, op->opt);
334                 op->buf[i].addr = bo_handle.ptr;
335                 op->buf[i].pixmap->devPrivate.ptr = op->buf[i].addr;
336                 op->buf[i].pos = bo_data->pos;
337             }
338         }
339
340         if (bos)
341         {
342             free (bos);
343             bos=NULL;
344         }
345     }
346     else
347     {
348         op->num = 1;
349         op->isSame = 1;
350
351         op->buf[0].pixmap = pPix;
352         if (privPixmap->bo)
353         {
354             op->buf[0].bo = privPixmap->bo;
355             bo_handle = tbm_bo_map (op->buf[0].bo, TBM_DEVICE_CPU, op->opt);
356             op->buf[0].addr = bo_handle.ptr;
357         }
358         else
359         {
360             op->buf[0].bo = privPixmap->bo;
361             op->buf[0].addr = privPixmap->pPixData;
362         }
363         op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr;
364         op->buf[0].pos.x1 = 0;
365         op->buf[0].pos.y1 = 0;
366         op->buf[0].pos.x2 = pPix->drawable.width;
367         op->buf[0].pos.y2 = pPix->drawable.height;
368     }
369
370     privPixmap->exaOpInfo = op;
371
372     XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
373                 pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
374     return op;
375 }
376
377 static void _swFinishAccess (PixmapPtr pPix, int index)
378 {
379     XDBG_RETURN_IF_FAIL (pPix!=NULL);
380
381     SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
382     ExaOpInfo* op;
383     int i;
384
385     XDBG_RETURN_IF_FAIL (privPixmap!=NULL);
386     XDBG_RETURN_IF_FAIL (privPixmap->exaOpInfo!=NULL);
387
388     op = (ExaOpInfo*)privPixmap->exaOpInfo;
389     op->refcnt --;
390
391     if (op->refcnt == 0)
392     {
393         for (i=0; i < op->num; i++)
394         {
395             if (op->buf[i].bo)
396             {
397                 tbm_bo_unmap (op->buf[i].bo);
398
399                 if( index == EXA_PREPARE_DEST && pPix->usage_hint == CREATE_PIXMAP_USAGE_FB )
400                 {
401                     // In this case, DEST is framebuffer. It is updated by CPU.
402                     // After that LCD will use this buffer.
403                     // So we should call cache op!!
404                     tbm_bo_map(op->buf[i].bo, TBM_DEVICE_3D, TBM_OPTION_READ);
405                     tbm_bo_unmap(op->buf[i].bo);
406
407                     ScreenPtr pScreen;
408                     pScreen = pPix->drawable.pScreen;
409
410                     if( pScreen != NULL )
411                     {
412                         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
413                         SECPtr pSec = SECPTR(pScrn);
414
415                         pSec->is_fb_touched = TRUE;
416                     }
417                 }
418                 op->buf[i].bo = NULL;
419             }
420
421             if (op->buf[i].pixmap)
422             {
423                 op->buf[i].pixmap->devPrivate.ptr = NULL;
424                 op->buf[i].pixmap = NULL;
425             }
426             op->buf[i].addr = NULL;
427         }
428
429         privPixmap->exaOpInfo = NULL;
430     }
431
432     if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY)
433         secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER));
434
435     XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
436                 pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
437 }
438
439 void
440 _swDoDraw (struct xorg_list *l, DoDrawProcPtrEx do_draw, void* data)
441 {
442     ExaBox *box = NULL;
443     xorg_list_for_each_entry (box, l, link)
444     {
445         do_draw (box, data);
446     }
447 }
448
449 static void
450 _swDoSolid (ExaBox* box, void* data)
451 {
452     XDBG_TRACE (MEXAS, "(%d,%d), (%d,%d) off(%d,%d)\n",
453                 box->box.x1,
454                 box->box.y1,
455                 box->box.x2,
456                 box->box.y2,
457                 gOpSolid.x,
458                 gOpSolid.y);
459
460     fbFill (&box->pDst->pixmap->drawable,
461             gOpSolid.pGC,
462             box->box.x1 + gOpSolid.x - box->pDst->pos.x1,
463             box->box.y1 + gOpSolid.y - box->pDst->pos.y1,
464             box->box.x2- box->box.x1,
465             box->box.y2- box->box.y1);
466 }
467
468 static void
469 _swDoCopy (ExaBox* box, void* data)
470 {
471     CARD8 alu = gOpCopy.alu;
472     FbBits pm = gOpCopy.pm;
473     FbBits *src;
474     FbStride srcStride;
475     int srcBpp;
476     FbBits *dst;
477     FbStride dstStride;
478     int dstBpp;
479     _X_UNUSED int       srcXoff, srcYoff;
480     _X_UNUSED int       dstXoff, dstYoff;
481     int srcX, srcY, dstX, dstY, width, height;
482
483     XDBG_TRACE (MEXAS, "box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n",
484                 box->box.x1,
485                 box->box.y1,
486                 box->box.x2,
487                 box->box.y2,
488                 gOpCopy.srcX,
489                 gOpCopy.srcY,
490                 gOpCopy.dstX,
491                 gOpCopy.dstY);
492
493     srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1;
494     srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1;
495     dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1;
496     dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1;
497     width = box->box.x2 - box->box.x1;
498     height = box->box.y2 - box->box.y1;
499
500     fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
501     fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
502     /* temp fix : do right things later */
503     if (!src || !dst)
504     {
505         return;
506     }
507
508     if (pm != FB_ALLONES ||
509             alu != GXcopy ||
510             gOpCopy.reverse ||
511             gOpCopy.upsidedown ||
512             !pixman_blt ((uint32_t *)src, (uint32_t *)dst,
513                          srcStride,
514                          dstStride,
515                          srcBpp, dstBpp,
516                          srcX, srcY, dstX, dstY, width, height))
517     {
518         fbBlt (src + srcY * srcStride,
519                srcStride,
520                srcX * srcBpp,
521
522                dst + dstY * dstStride,
523                dstStride,
524                dstX * dstBpp,
525
526                width * dstBpp,
527                height,
528
529                alu,
530                pm,
531                dstBpp,
532
533                gOpCopy.reverse,
534                gOpCopy.upsidedown);
535     }
536 }
537
538 static void
539 _swDoComposite (ExaBox* box, void* data)
540 {
541     PicturePtr  pDstPicture;
542     pixman_image_t *src, *mask, *dest;
543     int src_xoff, src_yoff, msk_xoff, msk_yoff;
544     FbBits *bits;
545     FbStride stride;
546     int bpp;
547
548     if (box->state == rgnPART)
549     {
550         XDBG_RETURN_IF_FAIL (gOpComposite.pSrcPicture->transform == NULL);
551         XDBG_RETURN_IF_FAIL (gOpComposite.pMaskPicture &&
552                              gOpComposite.pMaskPicture->transform == NULL);
553     }
554
555     pDstPicture = gOpComposite.pDstPicture;
556
557     src = image_from_pict (gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff);
558     mask = image_from_pict (gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff);
559
560     fbGetPixmapBitsData (box->pDst->pixmap, bits, stride, bpp);
561     dest = pixman_image_create_bits (pDstPicture->format,
562                                      box->pDst->pixmap->drawable.width,
563                                      box->pDst->pixmap->drawable.height,
564                                      (uint32_t *)bits, stride * sizeof (FbStride));
565
566     pixman_image_composite (gOpComposite.op,
567                             src, mask, dest,
568                             gOpComposite.srcX + box->box.x1,
569                             gOpComposite.srcY + box->box.y1,
570                             gOpComposite.maskX + box->box.x1,
571                             gOpComposite.maskY + box->box.y1,
572                             gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1,
573                             gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1,
574                             box->box.x2 - box->box.x1,
575                             box->box.y2 - box->box.y1);
576
577     free_pixman_pict (gOpComposite.pSrcPicture, src);
578     free_pixman_pict (gOpComposite.pMaskPicture, mask);
579     pixman_image_unref (dest);
580 }
581
582 static void
583 _swDoUploadToScreen (ExaBox* box, void* data)
584 {
585     FbBits      *dst;
586     FbStride    dstStride;
587     int         dstBpp;
588     _X_UNUSED int               dstXoff, dstYoff;
589     int              srcStride;
590     int             dstX, dstY;
591     int             width, height;
592
593     fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
594
595     srcStride = gOpUTS.src_pitch/sizeof (uint32_t);
596     dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1;
597     dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1;
598     width = box->box.x2 - box->box.x1;
599     height = box->box.y2 - box->box.y1;
600
601     XDBG_TRACE (MEXAS, "src(%p, %d) %d,%d,%d,%d\n",
602                 gOpUTS.src, srcStride, dstX, dstY, width, height);
603
604     if(dstBpp < 8)
605     {
606         XDBG_WARNING(MEXAS, "dstBpp:%d\n", dstBpp);
607         return;
608     }
609
610     if (!pixman_blt ((uint32_t *)gOpUTS.src,
611                      (uint32_t *)dst,
612                      srcStride,
613                      dstStride,
614                      dstBpp, dstBpp,
615                      box->box.x1, box->box.y1,
616                      dstX, dstY,
617                      width, height))
618     {
619         unsigned char *pDst, *pSrc;
620         int dst_pitch, src_pitch, cpp;
621
622         pDst = (unsigned char*)dst;
623         pSrc = (unsigned char*)gOpUTS.src;
624         cpp = dstBpp / 8;
625         src_pitch = gOpUTS.src_pitch;
626         dst_pitch = box->pDst->pixmap->devKind;
627
628         pSrc += box->box.y1 * src_pitch + box->box.x1 * cpp;
629         pDst += dstY * dst_pitch + dstX * cpp;
630
631         for (; height > 0; height--) {
632             memcpy(pDst, pSrc, width * cpp);
633             pDst += dst_pitch;
634             pSrc += src_pitch;
635         }
636     }
637 }
638
639 static void
640 _swDoDownladFromScreen (ExaBox* box, void* data)
641 {
642     FbBits      *src;
643     FbStride    srcStride;
644     int         srcBpp;
645     _X_UNUSED int               srcXoff, srcYoff;
646     int              dstStride;
647     int             srcX, srcY;
648     int             width, height;
649
650     fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
651
652     dstStride = gOpDFS.dst_pitch/sizeof (uint32_t);
653     srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1;
654     srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1;
655     width = box->box.x2 - box->box.x1;
656     height = box->box.y2 - box->box.y1;
657
658     XDBG_TRACE (MEXAS, "dst(%p, %d) %d,%d,%d,%d\n",
659                 gOpDFS.dst, dstStride, srcX, srcY, width, height);
660
661     if(srcBpp < 8)
662     {
663         XDBG_WARNING(MEXAS, "srcBpp:%d\n", srcBpp);
664         return;
665     }
666
667     if (!pixman_blt ((uint32_t *)src,
668                      (uint32_t *)gOpDFS.dst,
669                      srcStride,
670                      dstStride,
671                      srcBpp, srcBpp,
672                      srcX, srcY,
673                      box->box.x1, box->box.y1,
674                      width, height))
675     {
676         unsigned char *pDst, *pSrc;
677         int dst_pitch, src_pitch, cpp;
678
679         pDst = (unsigned char*)gOpDFS.dst;
680         pSrc = (unsigned char*)src;
681         cpp = srcBpp / 8;
682         src_pitch = box->pSrc->pixmap->devKind;
683         dst_pitch = gOpDFS.dst_pitch;
684
685         pSrc += srcY * src_pitch + srcX * cpp;
686         pDst += box->box.y1 * dst_pitch + box->box.x1 * cpp;
687
688         for (; height > 0; height--) {
689             memcpy(pDst, pSrc, width * cpp);
690             pDst += dst_pitch;
691             pSrc += src_pitch;
692         }
693     }
694 }
695
696 static Bool
697 SECExaSwPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
698 {
699     ScreenPtr pScreen = pPixmap->drawable.pScreen;
700     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
701     ChangeGCVal tmpval[3];
702
703     XDBG_TRACE (MEXAS, "\n");
704     memset (&gOpSolid, 0x00, sizeof (gOpSolid));
705
706     /* Put ff at the alpha bits when transparency is set to xv */
707     if (pPixmap->drawable.depth == 24)
708         fg = fg | (~ (pScrn->mask.red|pScrn->mask.green|pScrn->mask.blue));
709     gOpSolid.alu = alu;
710     gOpSolid.fg = fg;
711     gOpSolid.planemask = planemask;
712     gOpSolid.pixmap = pPixmap;
713
714     gOpSolid.pOpDst = _swPrepareAccess (pPixmap, EXA_PREPARE_DEST);
715     XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail);
716     gOpSolid.pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
717
718     tmpval[0].val = alu;
719     tmpval[1].val = planemask;
720     tmpval[2].val = fg;
721     ChangeGC (NullClient, gOpSolid.pGC, GCFunction|GCPlaneMask|GCForeground, tmpval);
722     ValidateGC (&pPixmap->drawable, gOpSolid.pGC);
723
724     gOpSolid.bDo = TRUE;
725
726     return TRUE;
727
728 bail:
729     XDBG_TRACE (MEXAS, "FAIL: pix:%p hint:%d, num_pix:%d\n",
730                 pPixmap, pPixmap->usage_hint, gOpSolid.pOpDst->num);
731     gOpSolid.bDo = FALSE;
732     gOpSolid.pGC = NULL;
733
734     return TRUE;
735 }
736
737
738 static void
739 SECExaSwSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
740 {
741     XDBG_TRACE (MEXAS, " (%d,%d), (%d,%d)\n", x1,y1,x2,y2);
742     if (gOpSolid.bDo == FALSE) return;
743
744     gOpSolid.x = x1;
745     gOpSolid.y = y1;
746     gOpSolid.w = x2-x1;
747     gOpSolid.h = y2-y1;
748
749     if (gOpSolid.pOpDst->isSame)
750     {
751         ExaBox box;
752
753         box.state = rgnIN;
754         box.box.x1 = 0;
755         box.box.y1 = 0;
756         box.box.x2 = x2-x1;
757         box.box.y2 = y2-y1;
758         box.pDst = &gOpSolid.pOpDst->buf[0];
759         _swDoSolid (&box, NULL);
760     }
761     else
762     {
763         int i;
764         ExaBox *box;
765         BoxRec b;
766
767         /*Init box list*/
768         xorg_list_init (&gOpSolid.opBox);
769
770         b.x1 = x1;
771         b.y1 = y1;
772         b.x2 = x2;
773         b.y2 = y2;
774
775         for (i=0; i<gOpSolid.pOpDst->num; i++)
776         {
777             box = _swBoxAdd (&gOpSolid.opBox,
778                              &gOpSolid.pOpDst->buf[i].pos,
779                              &b);
780             if (box)
781             {
782                 box->pDst = &gOpSolid.pOpDst->buf[i];
783             }
784         }
785         _swBoxMove (&gOpSolid.opBox, -x1, -y1);
786
787         /* Call solid function */
788         _swDoDraw (&gOpSolid.opBox,
789                    _swDoSolid, NULL);
790
791         /*Remove box list*/
792         _swBoxRemoveAll (&gOpSolid.opBox);
793     }
794 }
795
796 static void
797 SECExaSwDoneSolid (PixmapPtr pPixmap)
798 {
799     XDBG_TRACE (MEXAS, "\n");
800     if (gOpSolid.pGC)
801     {
802         FreeScratchGC (gOpSolid.pGC);
803         gOpSolid.pGC = NULL;
804     }
805
806     if (gOpSolid.pixmap)
807         _swFinishAccess (gOpSolid.pixmap, EXA_PREPARE_DEST);
808 }
809
810 static Bool
811 SECExaSwPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
812                      int dx, int dy, int alu, Pixel planemask)
813 {
814     int num_dst_pix = -1;
815     int num_src_pix = -1;
816
817     XDBG_TRACE (MEXAS, "\n");
818     memset (&gOpCopy, 0x00, sizeof (gOpCopy));
819
820     gOpCopy.alu = alu;
821     gOpCopy.pm = planemask;
822     gOpCopy.reverse = (dx == 1)?0:1;
823     gOpCopy.upsidedown = (dy == 1)?0:1;
824     gOpCopy.pDstPix = pDstPixmap;
825     gOpCopy.pSrcPix = pSrcPixmap;
826
827     gOpCopy.pOpDst = _swPrepareAccess (pDstPixmap, EXA_PREPARE_DEST);
828     XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
829     gOpCopy.pOpSrc = _swPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC);
830     XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
831
832     gOpCopy.bDo = TRUE;
833
834     return TRUE;
835
836 bail:
837     XDBG_TRACE (MEXAS, "FAIL\n");
838     XDBG_TRACE (MEXAS, "   SRC pix:%p, hint:%d, num_pix:%d\n",
839                 pSrcPixmap, pSrcPixmap->usage_hint, num_src_pix);
840     XDBG_TRACE (MEXAS, "   DST pix:%p, hint:%d, num_pix:%d\n",
841                 pDstPixmap, pDstPixmap->usage_hint, num_dst_pix);
842     gOpCopy.bDo = FALSE;
843
844     return TRUE;
845 }
846
847
848 static void
849 SECExaSwCopy (PixmapPtr pDstPixmap, int srcX, int srcY,
850               int dstX, int dstY, int width, int height)
851 {
852     XDBG_TRACE (MEXAS, "src(%d,%d) dst(%d,%d) %dx%d\n",
853                 srcX, srcY, dstX, dstY, width, height);
854
855     if (gOpSolid.bDo == FALSE) return;
856
857     gOpCopy.srcX = srcX;
858     gOpCopy.srcY = srcY;
859     gOpCopy.dstX = dstX;
860     gOpCopy.dstY = dstY;
861     gOpCopy.width = width;
862     gOpCopy.height = height;
863
864     if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame)
865     {
866         ExaBox box;
867
868         box.state = rgnIN;
869         box.box.x1 = 0;
870         box.box.y1 = 0;
871         box.box.x2 = width;
872         box.box.y2 = height;
873         box.pDst = &gOpCopy.pOpDst->buf[0];
874         box.pSrc = &gOpCopy.pOpSrc->buf[0];
875         _swDoCopy (&box, NULL);
876     }
877     else
878     {
879         int i;
880         struct xorg_list lSrc, lDst;
881         ExaBox *box;
882         BoxRec b;
883
884         //Set Dest
885         b.x1 = dstX;
886         b.y1 = dstY;
887         b.x2 = dstX + width;
888         b.y2 = dstY + height;
889         xorg_list_init (&lDst);
890         for (i=0; i<gOpCopy.pOpDst->num; i++)
891         {
892             box = _swBoxAdd (&lDst,
893                              &gOpCopy.pOpDst->buf[i].pos,
894                              &b);
895             if (box)
896             {
897                 box->pDst = &gOpCopy.pOpDst->buf[i];
898             }
899         }
900         _swBoxMove (&lDst, -dstX, -dstY);
901
902         //Set Src
903         b.x1 = srcX;
904         b.y1 = srcY;
905         b.x2 = srcX + width;
906         b.y2 = srcY + height;
907
908         xorg_list_init (&lSrc);
909         for (i=0; i<gOpCopy.pOpSrc->num; i++)
910         {
911             box = _swBoxAdd (&lSrc,
912                              &gOpCopy.pOpSrc->buf[i].pos,
913                              &b);
914             if (box)
915             {
916                 box->pSrc = &gOpCopy.pOpSrc->buf[i];
917             }
918         }
919         _swBoxMove (&lSrc, -srcX, -srcY);
920
921         //Merge and call copy
922         xorg_list_init (&gOpCopy.opBox);
923         _swBoxMerge (&gOpCopy.opBox, &lSrc, &lDst);
924         _swDoDraw (&gOpCopy.opBox,
925                    _swDoCopy, NULL);
926
927         //Remove box list
928         _swBoxRemoveAll (&lSrc);
929         _swBoxRemoveAll (&lDst);
930         _swBoxRemoveAll (&gOpCopy.opBox);
931     }
932 }
933
934 static void
935 SECExaSwDoneCopy (PixmapPtr pDstPixmap)
936 {
937     XDBG_TRACE (MEXAS, "\n");
938
939     if (gOpCopy.pDstPix)
940         _swFinishAccess (gOpCopy.pDstPix, EXA_PREPARE_DEST);
941     if (gOpCopy.pSrcPix)
942         _swFinishAccess (gOpCopy.pSrcPix, EXA_PREPARE_SRC);
943 }
944
945 static Bool
946 SECExaSwCheckComposite (int op, PicturePtr pSrcPicture,
947                         PicturePtr pMaskPicture, PicturePtr pDstPicture)
948 {
949     return TRUE;
950 }
951
952 static Bool
953 SECExaSwPrepareComposite (int op, PicturePtr pSrcPicture,
954                           PicturePtr pMaskPicture, PicturePtr pDstPicture,
955                           PixmapPtr pSrcPixmap,
956                           PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap)
957 {
958     XDBG_TRACE (MEXAS, "\n");
959     memset (&gOpComposite, 0x00, sizeof (gOpComposite));
960     XDBG_GOTO_IF_FAIL (pDstPixmap != NULL, bail);
961
962     gOpComposite.op = op;
963     gOpComposite.pDstPicture = pDstPicture;
964     gOpComposite.pSrcPicture = pSrcPicture;
965     gOpComposite.pMaskPicture = pMaskPicture;
966     gOpComposite.pSrcPixmap = pSrcPixmap;
967     gOpComposite.pMaskPixmap = pMaskPixmap;
968     gOpComposite.pDstPixmap = pDstPixmap;
969
970     gOpComposite.pOpDst = _swPrepareAccess (pDstPixmap, EXA_PREPARE_DEST);
971
972     if (pSrcPixmap)
973     {
974         gOpComposite.pOpSrc = _swPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC);
975         XDBG_GOTO_IF_FAIL (gOpComposite.pOpSrc->num == 1, bail);
976     }
977
978     if (pMaskPixmap)
979     {
980         gOpComposite.pOpMask = _swPrepareAccess (pMaskPixmap, EXA_PREPARE_MASK);
981         XDBG_GOTO_IF_FAIL (gOpComposite.pOpMask->num == 1, bail);
982     }
983
984     gOpComposite.bDo = TRUE;
985
986     return TRUE;
987
988 bail:
989     XDBG_TRACE (MEXAS, "FAIL: op%d\n", op);
990     XDBG_TRACE (MEXAS, "   SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap);
991     XDBG_TRACE (MEXAS, "   MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap);
992     XDBG_TRACE (MEXAS, "   DST picture:%p pix:%p\n", pDstPicture, pDstPixmap);
993
994     gOpComposite.bDo = FALSE;
995
996     return TRUE;
997 }
998
999 static void
1000 SECExaSwComposite (PixmapPtr pDstPixmap, int srcX, int srcY,
1001                    int maskX, int maskY, int dstX, int dstY,
1002                    int width, int height)
1003 {
1004     XDBG_TRACE (MEXAS, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n",
1005                 srcX, srcY,
1006                 maskX, maskY,
1007                 dstX, dstY,
1008                 width, height);
1009     if (!gOpComposite.bDo) return;
1010
1011     gOpComposite.srcX = srcX;
1012     gOpComposite.srcY = srcY;
1013     gOpComposite.maskX = maskX;
1014     gOpComposite.maskY = maskY;
1015     gOpComposite.dstX = dstX;
1016     gOpComposite.dstY = dstY;
1017     gOpComposite.width = width;
1018     gOpComposite.height = height;
1019
1020     if (gOpComposite.pOpDst->isSame)
1021     {
1022         ExaBox box;
1023
1024         box.state = rgnIN;
1025         box.box.x1 = 0;
1026         box.box.y1 = 0;
1027         box.box.x2 = width;
1028         box.box.y2 = height;
1029         box.pDst = &gOpComposite.pOpDst->buf[0];
1030         box.pSrc = (gOpComposite.pOpSrc)? (&gOpComposite.pOpSrc->buf[0]):NULL;
1031         box.pSrc = (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
1032
1033         _swDoComposite (&box, NULL);
1034     }
1035     else
1036     {
1037         int i;
1038         ExaBox *box;
1039         BoxRec b;
1040
1041         /*Init box list*/
1042         xorg_list_init (&gOpComposite.opBox);
1043
1044         b.x1 = dstX;
1045         b.y1 = dstY;
1046         b.x2 = dstX+width;
1047         b.y2 = dstY+height;
1048
1049         for (i=0; i<gOpComposite.pOpDst->num; i++)
1050         {
1051             box = _swBoxAdd (&gOpComposite.opBox,
1052                              &gOpComposite.pOpDst->buf[i].pos,
1053                              &b);
1054             if (box)
1055             {
1056                 box->pDst = &gOpComposite.pOpDst->buf[i];
1057                 box->pSrc = (gOpComposite.pOpSrc)? (&gOpComposite.pOpSrc->buf[0]):NULL;
1058                 box->pMask= (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
1059             }
1060         }
1061         _swBoxMove (&gOpComposite.opBox, -dstX, -dstY);
1062
1063         /* Call solid function */
1064         _swDoDraw (&gOpComposite.opBox,
1065                    _swDoComposite, NULL);
1066
1067         /*Remove box list*/
1068         _swBoxRemoveAll (&gOpComposite.opBox);
1069     }
1070 }
1071
1072 /* done composite : sw done composite, not using pvr2d */
1073 static void
1074 SECExaSwDoneComposite (PixmapPtr pDst)
1075 {
1076     XDBG_TRACE (MEXAS, "\n");
1077     if (gOpComposite.pDstPixmap != NULL)
1078         _swFinishAccess (gOpComposite.pDstPixmap, EXA_PREPARE_DEST);
1079     if (gOpComposite.pSrcPixmap != NULL)
1080         _swFinishAccess (gOpComposite.pSrcPixmap, EXA_PREPARE_SRC);
1081     if (gOpComposite.pMaskPixmap != NULL)
1082         _swFinishAccess (gOpComposite.pMaskPixmap, EXA_PREPARE_MASK);
1083 }
1084
1085 static Bool
1086 SECExaSwUploadToScreen (PixmapPtr pDst, int x, int y, int w, int h,
1087                         char *src, int src_pitch)
1088 {
1089     XDBG_RETURN_VAL_IF_FAIL (src!=NULL, TRUE);
1090     XDBG_TRACE (MEXAS, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x,y,w,h);
1091     XDBG_TRACE (MEXAS, "\tdst depth:%d, bpp:%d, pitch:%d, %dx%d\n",
1092                 pDst->drawable.depth, pDst->drawable.bitsPerPixel, pDst->devKind,
1093                 pDst->drawable.width, pDst->drawable.height);
1094
1095     gOpUTS.pDst = pDst;
1096     gOpUTS.x = x;
1097     gOpUTS.y = y;
1098     gOpUTS.w = w;
1099     gOpUTS.h = h;
1100     gOpUTS.src = src;
1101     gOpUTS.src_pitch = src_pitch;
1102     gOpUTS.pOpDst = _swPrepareAccess (pDst, EXA_PREPARE_DEST);
1103
1104     if (gOpUTS.pOpDst->isSame)
1105     {
1106         ExaBox box;
1107
1108         box.box.x1 = 0;
1109         box.box.y1 = 0;
1110         box.box.x2 = w;
1111         box.box.y2 = h;
1112         box.state = rgnIN;
1113         box.pDst = &gOpUTS.pOpDst->buf[0];
1114         _swDoUploadToScreen (&box, NULL);
1115     }
1116     else
1117     {
1118         int i;
1119         ExaBox *box;
1120         BoxRec b;
1121
1122         /*Init box list*/
1123         xorg_list_init (&gOpUTS.opBox);
1124
1125         b.x1 = x;
1126         b.y1 = y;
1127         b.x2 = x+w;
1128         b.y2 = y+h;
1129
1130         for (i=0; i<gOpUTS.pOpDst->num; i++)
1131         {
1132             box = _swBoxAdd (&gOpUTS.opBox,
1133                              &gOpUTS.pOpDst->buf[i].pos,
1134                              &b);
1135             if (box)
1136             {
1137                 box->pDst = &gOpUTS.pOpDst->buf[i];
1138             }
1139         }
1140         _swBoxMove (&gOpUTS.opBox, -x, -y);
1141
1142         /* Call solid function */
1143         _swDoDraw (&gOpUTS.opBox,
1144                    _swDoUploadToScreen, NULL);
1145
1146         /*Remove box list*/
1147         _swBoxRemoveAll (&gOpUTS.opBox);
1148     }
1149
1150     _swFinishAccess (pDst, EXA_PREPARE_DEST);
1151     return TRUE;
1152 }
1153
1154
1155
1156 static Bool
1157 SECExaSwDownloadFromScreen (PixmapPtr pSrc, int x, int y, int w, int h,
1158                             char *dst, int dst_pitch)
1159 {
1160     XDBG_RETURN_VAL_IF_FAIL (dst!=NULL, TRUE);
1161     XDBG_TRACE (MEXAS, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x,y,w,h);
1162
1163     gOpDFS.pSrc = pSrc;
1164     gOpDFS.x = x;
1165     gOpDFS.y = y;
1166     gOpDFS.w = w;
1167     gOpDFS.h = h;
1168     gOpDFS.dst = dst;
1169     gOpDFS.dst_pitch = dst_pitch;
1170     gOpDFS.pOpSrc = _swPrepareAccess (pSrc, EXA_PREPARE_SRC);
1171
1172     if (gOpDFS.pOpSrc->isSame)
1173     {
1174         ExaBox box;
1175
1176         box.box.x1 = 0;
1177         box.box.y1 = 0;
1178         box.box.x2 = w;
1179         box.box.y2 = h;
1180         box.state = rgnIN;
1181         box.pSrc = &gOpDFS.pOpSrc->buf[0];
1182         _swDoDownladFromScreen (&box, NULL);
1183     }
1184     else
1185     {
1186         int i;
1187         ExaBox *box;
1188         BoxRec b;
1189
1190         /*Init box list*/
1191         xorg_list_init (&gOpDFS.opBox);
1192
1193         b.x1 = x;
1194         b.y1 = y;
1195         b.x2 = x+w;
1196         b.y2 = y+h;
1197
1198         for (i=0; i<gOpDFS.pOpSrc->num; i++)
1199         {
1200             box = _swBoxAdd (&gOpDFS.opBox,
1201                              &gOpDFS.pOpSrc->buf[i].pos,
1202                              &b);
1203             if (box)
1204             {
1205                 box->pSrc = &gOpDFS.pOpSrc->buf[i];
1206             }
1207         }
1208         _swBoxMove (&gOpDFS.opBox, -x, -y);
1209
1210         /* Call solid function */
1211         _swDoDraw (&gOpDFS.opBox,
1212                    _swDoDownladFromScreen, NULL);
1213
1214         /*Remove box list*/
1215         _swBoxRemoveAll (&gOpDFS.opBox);
1216     }
1217
1218     _swFinishAccess (pSrc, EXA_PREPARE_SRC);
1219     return TRUE;
1220 }
1221
1222 int SECExaMarkSync(ScreenPtr pScreen)
1223 {
1224     XDBG_RETURN_VAL_IF_FAIL (pScreen != NULL, TRUE);
1225     int ret=0;
1226
1227     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1228     SECPtr pSec = SECPTR(pScrn);
1229
1230     if( pSec && pSec->is_fb_touched == TRUE )
1231     {
1232         XDBG_TRACE(MEXAS, "UpdateRequest to the display!\n");
1233
1234         ret = secDisplayUpdateRequest(pScrn);
1235         pSec->is_fb_touched = FALSE;
1236     }
1237
1238     return ret;
1239 }
1240
1241 Bool secExaSwInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver)
1242 {
1243     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1244
1245     pExaDriver->PrepareSolid = SECExaSwPrepareSolid;
1246     pExaDriver->Solid = SECExaSwSolid;
1247     pExaDriver->DoneSolid = SECExaSwDoneSolid;
1248
1249     pExaDriver->PrepareCopy = SECExaSwPrepareCopy;
1250     pExaDriver->Copy = SECExaSwCopy;
1251     pExaDriver->DoneCopy = SECExaSwDoneCopy;
1252
1253     pExaDriver->CheckComposite = SECExaSwCheckComposite;
1254     pExaDriver->PrepareComposite = SECExaSwPrepareComposite;
1255     pExaDriver->Composite = SECExaSwComposite;
1256     pExaDriver->DoneComposite = SECExaSwDoneComposite;
1257
1258     pExaDriver->UploadToScreen = SECExaSwUploadToScreen;
1259     pExaDriver->DownloadFromScreen = SECExaSwDownloadFromScreen;
1260
1261     pExaDriver->MarkSync = SECExaMarkSync;
1262
1263     xf86DrvMsg (pScrn->scrnIndex, X_INFO
1264                 , "Succeed to Initialize SW EXA\n");
1265
1266     return TRUE;
1267 }
1268
1269 void secExaSwDeinit (ScreenPtr pScreen)
1270 {
1271     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1272
1273     xf86DrvMsg (pScrn->scrnIndex, X_INFO
1274                 , "Succeed to finish SW EXA\n");
1275 }