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