disable neon things
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / accel / sec_exa_g2d.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 "g2d/fimg2d.h"
38
39 #define DO(x)   ((x.bDo==DO_DRAW_NONE)?"SKIP": \
40                             ((x.bDo==DO_DRAW_SW)?"SW":"HW"))
41
42 #define PIXINFO(pPixmap)       if(pPixmap) { \
43                                                     XDBG_TRACE(MEXAH, "%s:%p(0x%x) %dx%d depth:%d(%d) pitch:%d\n", \
44                                                                 #pPixmap,    \
45                                                                 pPixmap, ID(pPixmap), \
46                                                                 pPixmap->drawable.width, pPixmap->drawable.height, \
47                                                                 pPixmap->drawable.depth, \
48                                                                 pPixmap->drawable.bitsPerPixel, \
49                                                                 pPixmap->devKind); \
50                                                 }
51
52 #define PICINFO(pPic)       if(pPic) { \
53                                                     XDBG_TRACE(MEXAH, "%s, draw:%p, repeat:%d(%d), ca:%d, srcPict:%p\n", \
54                                                                 #pPic,    \
55                                                                 pPic->pDrawable,  \
56                                                                 pPic->repeat, pPic->repeatType, \
57                                                                 pPic->componentAlpha, \
58                                                                 pPic->pSourcePict); \
59                                                     if(pPic->transform) { \
60                                                         XDBG_TRACE("EXA2D", "\t0x%08x  0x%08x 0x%08x\n", \
61                                                                     pPic->transform->matrix[0][0], \
62                                                                     pPic->transform->matrix[0][1], \
63                                                                     pPic->transform->matrix[0][2]); \
64                                                         XDBG_TRACE("EXA2D", "\t0x%08x  0x%08x 0x%08x\n", \
65                                                                     pPic->transform->matrix[1][0], \
66                                                                     pPic->transform->matrix[1][1], \
67                                                                     pPic->transform->matrix[1][2]); \
68                                                         XDBG_TRACE("EXA2D", "\t0x%08x  0x%08x 0x%08x\n", \
69                                                                     pPic->transform->matrix[1][0], \
70                                                                     pPic->transform->matrix[1][1], \
71                                                                     pPic->transform->matrix[1][2]); \
72                                                     }\
73                                                 }
74
75 typedef struct
76 {
77     BoxRec  pos;
78     PixmapPtr pixmap;
79     tbm_bo bo;
80
81     unsigned int access_device; /*TBM_DEVICE_XXX*/
82     unsigned int access_data;   /*pointer or gem*/
83     G2dImage* imgG2d;
84 } ExaOpBuf;
85
86 typedef struct
87 {
88     int refcnt;
89     int opt;
90     int num;
91     int isSame;
92
93     ExaOpBuf buf[5];
94 } ExaOpInfo;
95
96 typedef struct
97 {
98     BoxRec box;
99     int state;            /*state of region*/
100
101     struct xorg_list link;
102
103     ExaOpBuf *pSrc;
104     ExaOpBuf *pMask;
105     ExaOpBuf *pDst;
106 } ExaBox;
107
108 enum{
109     DO_DRAW_NONE,
110     DO_DRAW_SW,
111     DO_DRAW_HW
112 };
113
114 typedef struct
115 {
116     char bDo;
117
118     int alu;
119     Pixel planemask;
120     Pixel fg;
121     PixmapPtr pixmap;
122
123     int x,y,w,h;
124     GCPtr pGC;
125     ExaOpInfo* pOpDst;
126     struct xorg_list opBox;
127 } OpSolid;
128
129 typedef struct
130 {
131     char bDo;
132
133     Pixel pm;
134     int alu;
135     int reverse;
136     int upsidedown;
137     PixmapPtr pSrcPix;
138     PixmapPtr pDstPix;
139
140     /*copy param*/
141     int srcX;
142     int srcY;
143     int dstX;
144     int dstY;
145     int width, height;
146
147     ExaOpInfo* pOpDst;
148     ExaOpInfo* pOpSrc;
149     struct xorg_list opBox;
150 } OpCopy;
151
152 typedef struct
153 {
154     char bDo;
155
156     int op;
157     PicturePtr pSrcPicture;
158     PicturePtr pMaskPicture;
159     PicturePtr pDstPicture;
160     PixmapPtr pSrcPixmap;
161     PixmapPtr pMaskPixmap;
162     PixmapPtr pDstPixmap;
163
164     /*copy param*/
165     int srcX, srcY;
166     int maskX, maskY;
167     int dstX, dstY;
168     int width, height;
169
170     char srcRepeat;
171     char srcRotate;
172     double srcScaleX;
173     double srcScaleY;
174
175     char maskRepeat;
176     char maskRotate;
177     double maskScaleX;
178     double maskScaleY;
179
180     ExaOpInfo* pOpSrc;
181     ExaOpInfo* pOpMask;
182     ExaOpInfo* pOpDst;
183     struct xorg_list opBox;
184 } OpComposite;
185
186 typedef struct
187 {
188     char bDo;
189
190     PixmapPtr pDst;
191     int x,y,w,h;
192     char* src;
193     int src_pitch;
194
195     G2dImage* imgSrc;
196     ExaOpInfo* pOpDst;
197     struct xorg_list opBox;
198 } OpUTS;
199
200 typedef struct
201 {
202     char bDo;
203
204     PixmapPtr pSrc;
205     int x,y,w,h;
206     char* dst;
207     int dst_pitch;
208
209     G2dImage* imgDst;
210     ExaOpInfo* pOpSrc;
211     struct xorg_list opBox;
212 } OpDFS;
213
214 typedef void (* DoDrawProcPtr) (PixmapPtr pPix, Bool isPart,
215                                 int x, int y,
216                                 int clip_x, int clip_y,
217                                 int w, int h, void* data);
218
219 typedef void (* DoDrawProcPtrEx) (ExaBox* box, void* data);
220
221 static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES];
222 static OpSolid gOpSolid;
223 static OpCopy gOpCopy;
224 static OpComposite gOpComposite;
225 static OpUTS gOpUTS;
226 static OpDFS gOpDFS;
227
228 ExaBox* _g2dBoxAdd (struct xorg_list *l, BoxPtr b1, BoxPtr b2)
229 {
230     ExaBox* rgn;
231
232     rgn = calloc (1, sizeof (ExaBox));
233     rgn->state = secUtilBoxIntersect (&rgn->box, b1, b2);
234     if (rgnOUT == rgn->state)
235     {
236         free (rgn);
237         return NULL;
238     }
239
240     xorg_list_add (&rgn->link, l);
241     return rgn;
242 }
243
244 void _g2dBoxMerge (struct xorg_list *l, struct xorg_list* b, struct xorg_list* t)
245 {
246     ExaBox *b1 = NULL, *b2 = NULL;
247     ExaBox* r = NULL;
248
249     xorg_list_for_each_entry (b1, b, link)
250     {
251         xorg_list_for_each_entry (b2, t, link)
252         {
253             r = _g2dBoxAdd (l, &b1->box, &b2->box);
254             if (r)
255             {
256                 r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc;
257                 r->pMask= b1->pMask ? b1->pMask : b2->pMask;
258                 r->pDst = b1->pDst ? b1->pDst : b2->pDst;
259             }
260         }
261     }
262 }
263
264 void _g2dBoxMove (struct xorg_list* l, int tx, int ty)
265 {
266     ExaBox *b = NULL;
267
268     xorg_list_for_each_entry (b, l, link)
269     {
270         secUtilBoxMove (&b->box, tx, ty);
271     }
272 }
273
274 void _g2dBoxRemoveAll (struct xorg_list* l)
275 {
276     ExaBox *ref = NULL, *next = NULL;
277
278     xorg_list_for_each_entry_safe (ref, next, l, link)
279     {
280         xorg_list_del (&ref->link);
281         free (ref);
282     }
283 }
284
285 int _g2dBoxIsOne (struct xorg_list* l)
286 {
287     if (l->next != l)
288     {
289         if (l->next == l->prev)
290             return 1;
291         else
292             return -1;
293     }
294
295     return 0;
296 }
297
298 void _g2dBoxPrint (ExaBox* sb1, const char* name)
299 {
300     ExaBox *b = NULL;
301
302     xorg_list_for_each_entry (b, &sb1->link, link)
303     {
304         XDBG_DEBUG (MEXAS, "[%s] %d,%d - %d,%d\n", name,
305                 b->box.x1, b->box.y1, b->box.x2, b->box.y2);
306     }
307 }
308
309 static pixman_bool_t
310 _g2d_check_within_epsilon (pixman_fixed_t a,
311                 pixman_fixed_t b,
312                 pixman_fixed_t epsilon)
313 {
314     pixman_fixed_t t = a - b;
315
316     if (t < 0)
317         t = -t;
318
319     return t <= epsilon;
320 }
321
322 static Bool
323 _g2d_check_picture(PicturePtr pPicture, char *rot90, double *scaleX, double *scaleY, char* repeat)
324 {
325     struct pixman_transform* t;
326
327 #define EPSILON (pixman_fixed_t) (2)
328
329 #define IS_SAME(a, b) (_g2d_check_within_epsilon (a, b, EPSILON))
330 #define IS_ZERO(a)    (_g2d_check_within_epsilon (a, 0, EPSILON))
331 #define IS_ONE(a)     (_g2d_check_within_epsilon (a, F (1), EPSILON))
332 #define IS_UNIT(a)                          \
333                                     (_g2d_check_within_epsilon (a, F (1), EPSILON) ||  \
334                                     _g2d_check_within_epsilon (a, F (-1), EPSILON) || \
335                                     IS_ZERO (a))
336 #define IS_INT(a)    (IS_ZERO (pixman_fixed_frac (a)))
337
338 /*RepeatNormal*/
339
340     if(pPicture == NULL)
341     {
342         return TRUE;
343     }
344
345     if(pPicture->repeat)
346     {
347         switch(pPicture->repeatType)
348         {
349         case RepeatNormal:
350             *repeat = G2D_REPEAT_MODE_REPEAT;
351             break;
352         case RepeatPad:
353             *repeat = G2D_REPEAT_MODE_PAD;
354             break;
355         case RepeatReflect:
356             *repeat = G2D_REPEAT_MODE_REFLECT;
357             break;
358         default:
359             *repeat = G2D_REPEAT_MODE_NONE;
360             break;
361         }
362     }
363     else
364     {
365         *repeat = G2D_REPEAT_MODE_NONE;
366     }
367
368     if(pPicture->transform == NULL)
369     {
370         *rot90 = 0;
371         *scaleX = 1.0;
372         *scaleY = 1.0;
373         return TRUE;
374     }
375
376     t= pPicture->transform;
377
378     if(!IS_ZERO(t->matrix[0][0]) && IS_ZERO(t->matrix[0][1]) && IS_ZERO(t->matrix[1][0]) && !IS_ZERO(t->matrix[1][1]))
379     {
380         *rot90 = FALSE;
381         *scaleX = pixman_fixed_to_double(t->matrix[0][0]);
382         *scaleY = pixman_fixed_to_double(t->matrix[1][1]);
383     }
384     else if(IS_ZERO(t->matrix[0][0]) && !IS_ZERO(t->matrix[0][1]) && !IS_ZERO(t->matrix[1][0]) && IS_ZERO(t->matrix[1][1]))
385     {
386         /* FIMG2D 90 => PIXMAN 270 */
387         *rot90 = TRUE;
388         *scaleX = pixman_fixed_to_double(t->matrix[0][1]);
389         *scaleY = pixman_fixed_to_double(t->matrix[1][0]*-1);
390     }
391     else
392     {
393         return FALSE;
394     }
395
396     return TRUE;
397 }
398
399 static Bool
400 _g2dIsSupport(PixmapPtr pPix, Bool forMask)
401 {
402     SECPixmapPriv *privPixmap;
403
404     if(!pPix) return TRUE;
405
406     if(!forMask && pPix->drawable.depth < 8)
407         return FALSE;
408
409     privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
410     if(!privPixmap->isFrameBuffer && !privPixmap->bo)
411         return FALSE;
412
413     return TRUE;
414 }
415
416 static G2dImage*
417 _g2dGetImageFromPixmap(PixmapPtr pPix, unsigned int gem)
418 {
419     G2dImage* img;
420     G2dColorKeyMode mode;
421
422     if(gem == 0)
423     {
424         gem = (unsigned int)pPix->devPrivate.ptr;
425     }
426
427     XDBG_RETURN_VAL_IF_FAIL((pPix != NULL && gem != 0), NULL);
428
429     switch(pPix->drawable.depth)
430     {
431     case 32:
432         mode = G2D_COLOR_FMT_ARGB8888|G2D_ORDER_AXRGB;
433         break;
434     case 24:
435         mode = G2D_COLOR_FMT_XRGB8888|G2D_ORDER_AXRGB;
436         break;
437     case 16:
438         mode = G2D_COLOR_FMT_RGB565|G2D_ORDER_AXRGB;
439         break;
440     case 8:
441         mode = G2D_COLOR_FMT_A8|G2D_ORDER_AXRGB;
442         break;
443     case 1:
444         mode = G2D_COLOR_FMT_A1|G2D_ORDER_AXRGB;
445         break;
446     default:
447         XDBG_ERROR(MEXA, "Unsupport format depth:%d(%d),pitch:%d \n",
448                    pPix->drawable.depth, pPix->drawable.bitsPerPixel, pPix->devKind);
449         return NULL;
450     }
451
452     img = g2d_image_create_bo(mode,
453                                             pPix->drawable.width,
454                                             pPix->drawable.height,
455                                             gem,
456                                             pPix->devKind);
457
458     return img;
459 }
460
461 static ExaOpInfo* _g2dPrepareAccess (PixmapPtr pPix, int index, unsigned int device)
462 {
463     ScreenPtr pScreen = pPix->drawable.pScreen;
464     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
465     SECPtr pSec = SECPTR (pScrn);
466     SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
467     ExaOpInfo* op = &OpInfo[index];
468     int opt = TBM_OPTION_READ;
469     int i;
470     tbm_bo *bos;
471     tbm_bo_handle bo_handle;
472     SECFbBoDataPtr bo_data;
473     int num_bo;
474     int ret;
475
476     XDBG_RETURN_VAL_IF_FAIL ((privPixmap != NULL), NULL);
477
478     if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST)
479         opt |= TBM_OPTION_WRITE;
480
481     /* Check mapped */
482     if (privPixmap->exaOpInfo)
483     {
484         op = (ExaOpInfo*)privPixmap->exaOpInfo;
485         op->refcnt++;
486         XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
487                     pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
488         return op;
489     }
490
491     /*Set buffer info*/
492     memset (op, 0x00, sizeof (ExaOpInfo));
493     op->refcnt = 1;
494     op->opt = opt;
495     op->isSame = 0;
496
497     if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB)
498     {
499         ret = secFbFindBo (pSec->pFb,
500                            pPix->drawable.x, pPix->drawable.y,
501                            pPix->drawable.width, pPix->drawable.height,
502                            &num_bo, &bos);
503         XDBG_TRACE (MEXAH,"FB  ret:%d num_pix:%d, %dx%d+%d+%d\n",
504                     ret, num_bo,
505                     pPix->drawable.width, pPix->drawable.height,
506                     pPix->drawable.x, pPix->drawable.y);
507
508         if (ret == rgnSAME && num_bo == 1)
509         {
510             op->num = 1;
511             op->isSame = 1;
512
513             op->buf[0].pixmap = pPix;
514             op->buf[0].bo = bos[0];
515             op->buf[0].pos.x1 = 0;
516             op->buf[0].pos.y1 = 0;
517             op->buf[0].pos.x2 = pPix->drawable.width;
518             op->buf[0].pos.y2 = pPix->drawable.height;
519
520             op->buf[0].access_device = device;
521             bo_handle = tbm_bo_map (op->buf[0].bo, device, op->opt);
522             op->buf[0].access_data = bo_handle.u32;
523             op->buf[0].pixmap->devPrivate.ptr = (pointer)op->buf[0].access_data;
524             if(device == TBM_DEVICE_2D)
525             {
526                 op->buf[0].imgG2d = _g2dGetImageFromPixmap(op->buf[0].pixmap,
527                                                                                             op->buf[0].access_data);
528             }
529         }
530         else
531         {
532             op->num = num_bo;
533             op->isSame = 0;
534
535             for (i = 0; i < num_bo; i++)
536             {
537                 tbm_bo_get_user_data (bos[i], TBM_BO_DATA_FB, (void**)&bo_data);
538                 op->buf[i].pixmap = secRenderBoGetPixmap (pSec->pFb, bos[i]);
539                 op->buf[i].bo = bos[i];
540                 op->buf[i].pos = bo_data->pos;
541
542                 op->buf[i].access_device = device;
543                 bo_handle = tbm_bo_map (op->buf[i].bo, device, op->opt);
544                 op->buf[i].access_data = bo_handle.u32;
545                 op->buf[i].pixmap->devPrivate.ptr = (pointer)op->buf[i].access_data;
546                 if(device == TBM_DEVICE_2D)
547                 {
548                     op->buf[i].imgG2d = _g2dGetImageFromPixmap(op->buf[i].pixmap,
549                                                                                                 op->buf[i].access_data);
550                 }
551             }
552
553             if (bos)
554                 free (bos);
555         }
556     }
557     else
558     {
559         op->num = 1;
560         op->isSame = 1;
561
562         op->buf[0].pixmap = pPix;
563         op->buf[0].bo = privPixmap->bo;
564         op->buf[0].pos.x1 = 0;
565         op->buf[0].pos.y1 = 0;
566         op->buf[0].pos.x2 = pPix->drawable.width;
567         op->buf[0].pos.y2 = pPix->drawable.height;
568
569         op->buf[0].access_device = device;
570         if (privPixmap->bo)
571         {
572             bo_handle = tbm_bo_map (op->buf[0].bo, device, op->opt);
573             op->buf[0].access_data =  bo_handle.u32;
574             if(device == TBM_DEVICE_2D)
575             {
576                 op->buf[0].imgG2d = _g2dGetImageFromPixmap(op->buf[0].pixmap, op->buf[0].access_data);
577             }
578         }
579         else
580         {
581             op->buf[0].access_data = (unsigned int)privPixmap->pPixData;
582             op->buf[0].imgG2d = NULL;
583         }
584         op->buf[0].pixmap->devPrivate.ptr = (pointer)op->buf[0].access_data;
585     }
586
587     privPixmap->exaOpInfo = op;
588
589     XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
590                 pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
591     return op;
592 }
593
594 static void _g2dFinishAccess (PixmapPtr pPix, int index)
595 {
596     XDBG_RETURN_IF_FAIL (pPix!=NULL);
597
598     SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
599     ExaOpInfo* op;
600     int i;
601
602     XDBG_RETURN_IF_FAIL (privPixmap!=NULL);
603     XDBG_RETURN_IF_FAIL (privPixmap->exaOpInfo!=NULL);
604
605     op = (ExaOpInfo*)privPixmap->exaOpInfo;
606     op->refcnt --;
607
608     if (op->refcnt == 0)
609     {
610         for (i=0; i<op->num; i++)
611         {
612             if(op->buf[i].bo)
613             {
614                 tbm_bo_unmap(op->buf[i].bo);
615                 op->buf[i].bo = NULL;
616             }
617
618             if(op->buf[i].pixmap)
619             {
620                 op->buf[i].pixmap->devPrivate.ptr = NULL;
621                 op->buf[i].pixmap = NULL;
622             }
623
624             if(op->buf[i].imgG2d)
625             {
626                 g2d_image_free(op->buf[i].imgG2d);
627                 op->buf[i].imgG2d = NULL;
628             }
629
630             op->buf[i].access_data = (unsigned int)NULL;
631         }
632
633         privPixmap->exaOpInfo = NULL;
634     }
635
636     if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY)
637         secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER));
638
639     XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
640                 pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
641 }
642
643 void
644 _g2dDoDraw (struct xorg_list *l, DoDrawProcPtrEx do_draw, void* data)
645 {
646     ExaBox *box = NULL;
647     xorg_list_for_each_entry (box, l, link)
648     {
649         do_draw (box, data);
650     }
651 }
652
653 static void
654 _g2dDoSolid (ExaBox* box, void* data)
655 {
656     XDBG_TRACE (MEXAH, "[%s] (%d,%d), (%d,%d) off(%d,%d)\n",
657                 DO(gOpSolid),
658                 box->box.x1,
659                 box->box.y1,
660                 box->box.x2,
661                 box->box.y2,
662                 gOpSolid.x,
663                 gOpSolid.y);
664
665     if(gOpSolid.bDo == DO_DRAW_SW)
666     {
667         fbFill (&box->pDst->pixmap->drawable,
668                 gOpSolid.pGC,
669                 box->box.x1 + gOpSolid.x - box->pDst->pos.x1,
670                 box->box.y1 + gOpSolid.y - box->pDst->pos.y1,
671                 box->box.x2- box->box.x1,
672                 box->box.y2- box->box.y1);
673     }
674     else
675     {
676         util_g2d_fill_alu(box->pDst->imgG2d,
677                 box->box.x1 + gOpSolid.x - box->pDst->pos.x1,
678                 box->box.y1 + gOpSolid.y - box->pDst->pos.y1,
679                 box->box.x2- box->box.x1,
680                 box->box.y2- box->box.y1,
681                 gOpSolid.fg,
682                 (G2dAlu)gOpSolid.alu);
683     }
684 }
685
686 static void
687 _g2dDoCopy (ExaBox* box, void* data)
688 {
689     CARD8 alu = gOpCopy.alu;
690     FbBits pm = gOpCopy.pm;
691     FbBits *src;
692     FbStride srcStride;
693     int srcBpp;
694     FbBits *dst;
695     FbStride dstStride;
696     int dstBpp;
697     _X_UNUSED int       srcXoff, srcYoff;
698     _X_UNUSED int       dstXoff, dstYoff;
699     int srcX, srcY, dstX, dstY, width, height;
700
701     XDBG_TRACE (MEXAH, "[%s] box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n",
702                 DO(gOpCopy),
703                 box->box.x1,
704                 box->box.y1,
705                 box->box.x2,
706                 box->box.y2,
707                 gOpCopy.srcX,
708                 gOpCopy.srcY,
709                 gOpCopy.dstX,
710                 gOpCopy.dstY);
711
712     srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1;
713     srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1;
714     dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1;
715     dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1;
716     width = box->box.x2 - box->box.x1;
717     height = box->box.y2 - box->box.y1;
718
719     if(gOpCopy.bDo == DO_DRAW_SW)
720     {
721         fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
722         fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
723         /* temp fix : do right things later */
724         if (!src || !dst)
725         {
726             return;
727         }
728
729         if (pm != FB_ALLONES ||
730                 alu != GXcopy ||
731                 gOpCopy.reverse ||
732                 gOpCopy.upsidedown ||
733                 !pixman_blt ((uint32_t *)src, (uint32_t *)dst,
734                              srcStride,
735                              dstStride,
736                              srcBpp, dstBpp,
737                              srcX, srcY, dstX, dstY, width, height))
738         {
739             fbBlt (src + srcY * srcStride,
740                    srcStride,
741                    srcX * srcBpp,
742
743                    dst + dstY * dstStride,
744                    dstStride,
745                    dstX * dstBpp,
746
747                    width * dstBpp,
748                    height,
749
750                    alu,
751                    pm,
752                    dstBpp,
753
754                    gOpCopy.reverse,
755                    gOpCopy.upsidedown);
756         }
757     }
758     else
759     {
760         util_g2d_copy_alu(box->pSrc->imgG2d,
761                                         box->pDst->imgG2d,
762                                         srcX, srcY,
763                                         dstX, dstY,
764                                         width, height,
765                                         gOpCopy.alu);
766     }
767 }
768
769 static void
770 _g2dDoComposite (ExaBox* box, void* data)
771 {
772
773     if (box->state == rgnPART)
774     {
775         XDBG_RETURN_IF_FAIL (gOpComposite.pSrcPicture->transform == NULL);
776         XDBG_RETURN_IF_FAIL (gOpComposite.pMaskPicture &&
777                              gOpComposite.pMaskPicture->transform == NULL);
778     }
779
780     if (gOpComposite.bDo == DO_DRAW_SW)
781     {
782         PicturePtr      pDstPicture;
783         pixman_image_t *src, *mask, *dest;
784         int src_xoff, src_yoff, msk_xoff, msk_yoff;
785         FbBits *bits;
786         FbStride stride;
787         int bpp;
788
789         pDstPicture = gOpComposite.pDstPicture;
790
791         src = image_from_pict (gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff);
792         mask = image_from_pict (gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff);
793
794         fbGetPixmapBitsData (box->pDst->pixmap, bits, stride, bpp);
795         dest = pixman_image_create_bits (pDstPicture->format,
796                                          box->pDst->pixmap->drawable.width,
797                                          box->pDst->pixmap->drawable.height,
798                                          (uint32_t *)bits, stride * sizeof (FbStride));
799
800         pixman_image_composite (gOpComposite.op,
801                                 src, mask, dest,
802                                 gOpComposite.srcX + box->box.x1,
803                                 gOpComposite.srcY + box->box.y1,
804                                 gOpComposite.maskX + box->box.x1,
805                                 gOpComposite.maskY + box->box.y1,
806                                 gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1,
807                                 gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1,
808                                 box->box.x2 - box->box.x1,
809                                 box->box.y2 - box->box.y1);
810
811         free_pixman_pict (gOpComposite.pSrcPicture, src);
812         free_pixman_pict (gOpComposite.pMaskPicture, mask);
813         pixman_image_unref (dest);
814     }
815     else
816     {
817         util_g2d_composite (gOpComposite.op,
818                                     box->pSrc->imgG2d,
819                                     box->pMask ? box->pMask->imgG2d:NULL,
820                                     box->pDst->imgG2d,
821                                     gOpComposite.srcX + box->box.x1,
822                                     gOpComposite.srcY + box->box.y1,
823                                     gOpComposite.maskX + box->box.x1,
824                                     gOpComposite.maskY + box->box.y1,
825                                     gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1,
826                                     gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1,
827                                     box->box.x2 - box->box.x1,
828                                     box->box.y2 - box->box.y1);
829     }
830 }
831
832 static void
833 _g2dDoUploadToScreen (ExaBox* box, void* data)
834 {
835     int             dstX, dstY;
836     int             width, height;
837
838     dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1;
839     dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1;
840     width = box->box.x2 - box->box.x1;
841     height = box->box.y2 - box->box.y1;
842
843     if(gOpUTS.bDo == DO_DRAW_SW)
844     {
845         FbBits  *dst;
846         FbStride        dstStride;
847         int             dstBpp;
848         _X_UNUSED int           dstXoff, dstYoff;
849         int              srcStride;
850
851         fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
852
853         srcStride = gOpUTS.src_pitch/sizeof (uint32_t);
854
855         XDBG_TRACE (MEXAH, "src(%p, %d) %d,%d,%d,%d\n",
856                     gOpUTS.src, srcStride, dstX, dstY, width, height);
857
858         if (!pixman_blt ((uint32_t *)gOpUTS.src,
859                          (uint32_t *)dst,
860                          srcStride,
861                          dstStride,
862                          dstBpp, dstBpp,
863                          box->box.x1, box->box.y1,
864                          dstX, dstY,
865                          width, height))
866         {
867             fbBlt ((FbBits*) ((FbBits*)gOpUTS.src),
868                    srcStride,
869                    box->box.x1,
870
871                    dst + dstY * dstStride,
872                    dstStride,
873                    dstX,
874
875                    width,
876                    height,
877
878                    GXcopy,
879                    ~0,
880                    dstBpp,
881
882                    0,
883                    0);
884         }
885     }
886     else
887     {
888         util_g2d_copy(gOpUTS.imgSrc,
889                             box->pDst->imgG2d,
890                             box->box.x1, box->box.y1,
891                             dstX, dstY,
892                             width, height);
893     }
894 }
895
896 static void
897 _g2dDoDownladFromScreen (ExaBox* box, void* data)
898 {
899     int             srcX, srcY;
900     int             width, height;
901     int             dstStride;
902
903     dstStride = gOpDFS.dst_pitch/sizeof (uint32_t);
904     srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1;
905     srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1;
906     width = box->box.x2 - box->box.x1;
907     height = box->box.y2 - box->box.y1;
908
909     XDBG_TRACE (MEXAH, "dst(%p, %d) %d,%d,%d,%d\n",
910                 gOpDFS.dst, dstStride, srcX, srcY, width, height);
911
912     if(gOpDFS.bDo == DO_DRAW_SW)
913     {
914         FbBits  *src;
915         FbStride        srcStride;
916         int             srcBpp;
917         _X_UNUSED int           srcXoff, srcYoff;
918
919         fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
920
921         if (!pixman_blt ((uint32_t *)src,
922                          (uint32_t *)gOpDFS.dst,
923                          srcStride,
924                          dstStride,
925                          srcBpp, srcBpp,
926                          srcX, srcY,
927                          box->box.x1, box->box.y1,
928                          width, height))
929         {
930             fbBlt (src + srcY * srcStride,
931                    srcStride,
932                    srcX,
933
934                    (FbBits*) ((FbBits*)gOpDFS.dst),
935                    dstStride,
936                    box->box.x1,
937
938                    width,
939                    height,
940
941                    GXcopy,
942                    ~0,
943                    srcBpp,
944
945                    0,
946                    0);
947         }
948     }
949     else
950     {
951         util_g2d_copy (box->pSrc->imgG2d,
952                                 gOpDFS.imgDst,
953                                 srcX, srcY,
954                                 box->box.x1, box->box.y1,
955                                 width, height);
956     }
957 }
958
959 static Bool
960 SECExaG2dPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
961 {
962     ScreenPtr pScreen = pPixmap->drawable.pScreen;
963     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
964     ChangeGCVal tmpval[3];
965
966     XDBG_TRACE (MEXAH, "\n");
967     memset (&gOpSolid, 0x00, sizeof (gOpSolid));
968
969     /* Put ff at the alpha bits when transparency is set to xv */
970     if (pPixmap->drawable.depth == 24)
971         fg = fg | (~ (pScrn->mask.red|pScrn->mask.green|pScrn->mask.blue));
972
973     gOpSolid.alu = alu;
974     gOpSolid.fg = fg;
975     gOpSolid.planemask = planemask;
976     gOpSolid.pixmap = pPixmap;
977
978     if (!_g2dIsSupport(pPixmap, 0))
979     {
980         gOpSolid.pOpDst = _g2dPrepareAccess (pPixmap,
981                                                                         EXA_PREPARE_DEST,
982                                                                         TBM_DEVICE_CPU);
983         XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail);
984
985         gOpSolid.pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
986         tmpval[0].val = alu;
987         tmpval[1].val = planemask;
988         tmpval[2].val = fg;
989         ChangeGC (NullClient, gOpSolid.pGC, GCFunction|GCPlaneMask|GCForeground, tmpval);
990         ValidateGC (&pPixmap->drawable, gOpSolid.pGC);
991
992         gOpSolid.bDo = DO_DRAW_SW;
993     }
994     else
995     {
996         gOpSolid.pOpDst = _g2dPrepareAccess (pPixmap,
997                                                                         EXA_PREPARE_DEST,
998                                                                         TBM_DEVICE_2D);
999         XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail);
1000         gOpSolid.bDo = DO_DRAW_HW;
1001     }
1002
1003     return TRUE;
1004
1005 bail:
1006     XDBG_TRACE (MEXAH, "FAIL: pix:%p hint:%d, num_pix:%d\n",
1007                 pPixmap, pPixmap->usage_hint, gOpSolid.pOpDst->num);
1008     gOpSolid.bDo = DO_DRAW_NONE;
1009     gOpSolid.pGC = NULL;
1010
1011     return TRUE;
1012 }
1013
1014
1015 static void
1016 SECExaG2dSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
1017 {
1018     XDBG_TRACE (MEXAH, " (%d,%d), (%d,%d)\n", x1,y1,x2,y2);
1019     XDBG_TRACE (MEXAH, "%s\n", DO(gOpSolid));
1020     if (gOpSolid.bDo == DO_DRAW_NONE) return;
1021
1022     gOpSolid.x = x1;
1023     gOpSolid.y = y1;
1024     gOpSolid.w = x2-x1;
1025     gOpSolid.h = y2-y1;
1026
1027     if (gOpSolid.pOpDst->isSame)
1028     {
1029         ExaBox box;
1030
1031         box.state = rgnIN;
1032         box.box.x1 = 0;
1033         box.box.y1 = 0;
1034         box.box.x2 = x2-x1;
1035         box.box.y2 = y2-y1;
1036         box.pDst = &gOpSolid.pOpDst->buf[0];
1037         _g2dDoSolid (&box, NULL);
1038     }
1039     else
1040     {
1041         int i;
1042         ExaBox *box;
1043         BoxRec b;
1044
1045         /*Init box list*/
1046         xorg_list_init (&gOpSolid.opBox);
1047
1048         b.x1 = x1;
1049         b.y1 = y1;
1050         b.x2 = x2;
1051         b.y2 = y2;
1052
1053         for (i=0; i<gOpSolid.pOpDst->num; i++)
1054         {
1055             box = _g2dBoxAdd (&gOpSolid.opBox,
1056                              &gOpSolid.pOpDst->buf[i].pos,
1057                              &b);
1058             if (box)
1059             {
1060                 box->pDst = &gOpSolid.pOpDst->buf[i];
1061             }
1062         }
1063         _g2dBoxMove (&gOpSolid.opBox, -x1, -y1);
1064
1065         /* Call solid function */
1066         _g2dDoDraw (&gOpSolid.opBox,
1067                    _g2dDoSolid, NULL);
1068
1069         /*Remove box list*/
1070         _g2dBoxRemoveAll (&gOpSolid.opBox);
1071     }
1072 }
1073
1074 static void
1075 SECExaG2dDoneSolid (PixmapPtr pPixmap)
1076 {
1077     XDBG_TRACE (MEXAH, "\n");
1078
1079     if (gOpSolid.bDo)
1080         g2d_exec();
1081
1082     if (gOpSolid.pGC)
1083     {
1084         FreeScratchGC (gOpSolid.pGC);
1085         gOpSolid.pGC = NULL;
1086     }
1087
1088     if (gOpSolid.pixmap)
1089         _g2dFinishAccess (gOpSolid.pixmap, EXA_PREPARE_DEST);
1090 }
1091
1092 static Bool
1093 SECExaG2dPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
1094                      int dx, int dy, int alu, Pixel planemask)
1095 {
1096     int num_dst_pix = -1;
1097     int num_src_pix = -1;
1098     unsigned int draw_type = DO_DRAW_HW;
1099     unsigned int access_device = TBM_DEVICE_2D;
1100
1101     XDBG_TRACE (MEXAH, "\n");
1102     memset (&gOpCopy, 0x00, sizeof (gOpCopy));
1103
1104     gOpCopy.alu = alu;
1105     gOpCopy.pm = planemask;
1106     gOpCopy.reverse = (dx == 1)?0:1;
1107     gOpCopy.upsidedown = (dy == 1)?0:1;
1108     gOpCopy.pDstPix = pDstPixmap;
1109     gOpCopy.pSrcPix = pSrcPixmap;
1110
1111     /* Check capability */
1112     if(!_g2dIsSupport(pSrcPixmap, 0) ||
1113         !_g2dIsSupport(pDstPixmap, 0) ||
1114         gOpCopy.reverse ||
1115         gOpCopy.upsidedown)
1116     {
1117         draw_type = DO_DRAW_SW;
1118         access_device = TBM_DEVICE_CPU;
1119     }
1120
1121     gOpCopy.pOpDst = _g2dPrepareAccess (pDstPixmap, EXA_PREPARE_DEST, access_device);
1122     XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
1123     gOpCopy.pOpSrc = _g2dPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC, access_device);
1124     XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
1125
1126     gOpCopy.bDo = draw_type;
1127
1128     return TRUE;
1129
1130 bail:
1131     XDBG_TRACE (MEXAH, "FAIL\n");
1132     XDBG_TRACE (MEXAH, "   SRC pix:%p, hint:%d, num_pix:%d\n",
1133                 pSrcPixmap, pSrcPixmap->usage_hint, num_src_pix);
1134     XDBG_TRACE (MEXAH, "   DST pix:%p, hint:%d, num_pix:%d\n",
1135                 pDstPixmap, pDstPixmap->usage_hint, num_dst_pix);
1136     gOpCopy.bDo = DO_DRAW_NONE;
1137
1138     return TRUE;
1139 }
1140
1141
1142 static void
1143 SECExaG2dCopy (PixmapPtr pDstPixmap, int srcX, int srcY,
1144               int dstX, int dstY, int width, int height)
1145 {
1146     XDBG_TRACE (MEXAH, "%s\n", DO(gOpCopy));
1147     XDBG_TRACE (MEXAH, "src(%d,%d) dst(%d,%d) %dx%d\n",
1148                 srcX, srcY, dstX, dstY, width, height);
1149
1150     if (gOpSolid.bDo == FALSE) return;
1151
1152     gOpCopy.srcX = srcX;
1153     gOpCopy.srcY = srcY;
1154     gOpCopy.dstX = dstX;
1155     gOpCopy.dstY = dstY;
1156     gOpCopy.width = width;
1157     gOpCopy.height = height;
1158
1159     if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame)
1160     {
1161         ExaBox box;
1162
1163         box.state = rgnIN;
1164         box.box.x1 = 0;
1165         box.box.y1 = 0;
1166         box.box.x2 = width;
1167         box.box.y2 = height;
1168         box.pDst = &gOpCopy.pOpDst->buf[0];
1169         box.pSrc = &gOpCopy.pOpSrc->buf[0];
1170         _g2dDoCopy (&box, NULL);
1171     }
1172     else
1173     {
1174         int i;
1175         struct xorg_list lSrc, lDst;
1176         ExaBox *box;
1177         BoxRec b;
1178
1179         //Set Dest
1180         b.x1 = dstX;
1181         b.y1 = dstY;
1182         b.x2 = dstX + width;
1183         b.y2 = dstY + height;
1184         xorg_list_init (&lDst);
1185         for (i=0; i<gOpCopy.pOpDst->num; i++)
1186         {
1187             box = _g2dBoxAdd (&lDst,
1188                              &gOpCopy.pOpDst->buf[i].pos,
1189                              &b);
1190             if (box)
1191             {
1192                 box->pDst = &gOpCopy.pOpDst->buf[i];
1193             }
1194         }
1195         _g2dBoxMove (&lDst, -dstX, -dstY);
1196
1197         //Set Src
1198         b.x1 = srcX;
1199         b.y1 = srcY;
1200         b.x2 = srcX + width;
1201         b.y2 = srcY + height;
1202
1203         xorg_list_init (&lSrc);
1204         for (i=0; i<gOpCopy.pOpSrc->num; i++)
1205         {
1206             box = _g2dBoxAdd (&lSrc,
1207                              &gOpCopy.pOpSrc->buf[i].pos,
1208                              &b);
1209             if (box)
1210             {
1211                 box->pSrc = &gOpCopy.pOpSrc->buf[i];
1212             }
1213         }
1214         _g2dBoxMove (&lSrc, -srcX, -srcY);
1215
1216         //Merge and call copy
1217         xorg_list_init (&gOpCopy.opBox);
1218         _g2dBoxMerge (&gOpCopy.opBox, &lSrc, &lDst);
1219         _g2dDoDraw (&gOpCopy.opBox,
1220                    _g2dDoCopy, NULL);
1221
1222         //Remove box list
1223         _g2dBoxRemoveAll (&lSrc);
1224         _g2dBoxRemoveAll (&lDst);
1225         _g2dBoxRemoveAll (&gOpCopy.opBox);
1226     }
1227 }
1228
1229 static void
1230 SECExaG2dDoneCopy (PixmapPtr pDstPixmap)
1231 {
1232     XDBG_TRACE (MEXAH, "\n");
1233     if (gOpCopy.bDo == DO_DRAW_HW)
1234         g2d_exec();
1235
1236     if (gOpCopy.pDstPix)
1237         _g2dFinishAccess (gOpCopy.pDstPix, EXA_PREPARE_DEST);
1238     if (gOpCopy.pSrcPix)
1239         _g2dFinishAccess (gOpCopy.pSrcPix, EXA_PREPARE_SRC);
1240 }
1241
1242 static Bool
1243 SECExaG2dCheckComposite (int op, PicturePtr pSrcPicture,
1244                         PicturePtr pMaskPicture, PicturePtr pDstPicture)
1245 {
1246     return TRUE;
1247 }
1248
1249 static Bool
1250 SECExaG2dPrepareComposite (int op, PicturePtr pSrcPicture,
1251                           PicturePtr pMaskPicture, PicturePtr pDstPicture,
1252                           PixmapPtr pSrcPixmap,
1253                           PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap)
1254 {
1255     XDBG_GOTO_IF_FAIL (pDstPixmap, bail);
1256     XDBG_GOTO_IF_FAIL (pSrcPicture && pDstPicture, bail);
1257
1258     unsigned int draw_type = DO_DRAW_HW;
1259     unsigned int access_device = TBM_DEVICE_2D;
1260
1261     XDBG_TRACE (MEXAH, "\n");
1262     memset (&gOpComposite, 0x00, sizeof (gOpComposite));
1263
1264     gOpComposite.op = op;
1265     gOpComposite.pDstPicture = pDstPicture;
1266     gOpComposite.pSrcPicture = pSrcPicture;
1267     gOpComposite.pMaskPicture = pMaskPicture;
1268     gOpComposite.pSrcPixmap = pSrcPixmap;
1269     gOpComposite.pMaskPixmap = pMaskPixmap;
1270     gOpComposite.pDstPixmap = pDstPixmap;
1271
1272     if (!_g2dIsSupport(pSrcPixmap, 0) ||
1273         !_g2dIsSupport(pDstPixmap, 0) ||
1274         !_g2dIsSupport(pMaskPixmap, 1))
1275     {
1276         draw_type = DO_DRAW_SW;
1277     }
1278
1279     if (!_g2d_check_picture(pSrcPicture,
1280                                     &gOpComposite.srcRotate,
1281                                     &gOpComposite.srcScaleX,
1282                                     &gOpComposite.srcScaleY,
1283                                     &gOpComposite.srcRepeat) ||
1284          !_g2d_check_picture(pMaskPicture,
1285                                     &gOpComposite.maskRotate,
1286                                     &gOpComposite.maskScaleX,
1287                                     &gOpComposite.maskScaleY,
1288                                     &gOpComposite.maskRepeat))
1289     {
1290         draw_type = DO_DRAW_SW;
1291     }
1292
1293     if(draw_type == DO_DRAW_SW)
1294     {
1295         access_device = TBM_DEVICE_CPU;
1296     }
1297
1298     gOpComposite.pOpDst = _g2dPrepareAccess (pDstPixmap,
1299                                                                             EXA_PREPARE_DEST,
1300                                                                             access_device);
1301
1302     if (pSrcPixmap)
1303     {
1304         gOpComposite.pOpSrc = _g2dPrepareAccess (pSrcPixmap,
1305                                                                                 EXA_PREPARE_SRC,
1306                                                                                 access_device);
1307         XDBG_GOTO_IF_FAIL (gOpComposite.pOpSrc->num == 1, bail);
1308     }
1309
1310     if (pMaskPixmap)
1311     {
1312         gOpComposite.pOpMask = _g2dPrepareAccess (pMaskPixmap,
1313                                                                                     EXA_PREPARE_MASK,
1314                                                                                     access_device);
1315         XDBG_GOTO_IF_FAIL (gOpComposite.pOpMask->num == 1, bail);
1316     }
1317
1318     if(draw_type == DO_DRAW_HW)
1319     {
1320         G2dImage *imgSrc = NULL, *imgMask = NULL;
1321
1322         if(pSrcPicture)
1323         {
1324             if(gOpComposite.pOpSrc == NULL)
1325             {
1326                 gOpComposite.pOpSrc = &OpInfo[EXA_PREPARE_SRC];
1327                 gOpComposite.pOpSrc->buf[0].imgG2d =
1328                             g2d_image_create_solid((unsigned int)gOpComposite.pSrcPicture->pSourcePict->solidFill.color);
1329             }
1330
1331             imgSrc = gOpComposite.pOpSrc->buf[0].imgG2d;
1332         }
1333
1334
1335         if(pMaskPicture)
1336         {
1337             if(gOpComposite.pOpMask == NULL)
1338             {
1339                 gOpComposite.pOpMask = &OpInfo[EXA_PREPARE_MASK];
1340                 gOpComposite.pOpMask->buf[0].imgG2d =
1341                             g2d_image_create_solid((unsigned int)gOpComposite.pSrcPicture->pSourcePict->solidFill.color);
1342             }
1343
1344             imgMask = gOpComposite.pOpMask->buf[0].imgG2d;
1345         }
1346
1347         /*Set Repeat*/
1348         imgSrc->repeat_mode = gOpComposite.srcRepeat;
1349
1350         /*Set Rotate */
1351         imgSrc->rotate_90 = gOpComposite.srcRotate;
1352         imgSrc->xDir = (gOpComposite.srcScaleX < 0.0);
1353         imgSrc->yDir = (gOpComposite.srcScaleY < 0.0);
1354
1355         /*Set Scale*/
1356         if(((gOpComposite.srcScaleX != 1.0 && gOpComposite.srcScaleX != -1.0) ||
1357             (gOpComposite.srcScaleY != 1.0 && gOpComposite.srcScaleY != -1.0)))
1358         {
1359             imgSrc->xscale = G2D_DOUBLE_TO_FIXED(gOpComposite.srcScaleX);
1360             imgSrc->yscale = G2D_DOUBLE_TO_FIXED(gOpComposite.srcScaleY);
1361             imgSrc->scale_mode = G2D_SCALE_MODE_BILINEAR;
1362         }
1363
1364         if(imgMask)
1365         {
1366             /*Set Repeat*/
1367             imgMask->repeat_mode = gOpComposite.maskRepeat;
1368
1369             /*Set Rotate */
1370             imgMask->rotate_90 = gOpComposite.maskRotate;
1371             imgMask->xDir = (gOpComposite.maskScaleX < 0.0);
1372             imgMask->yDir = (gOpComposite.maskScaleY < 0.0);
1373
1374             /*Set Scale*/
1375             if(((gOpComposite.maskScaleX != 1.0 && gOpComposite.maskScaleX != -1.0) ||
1376                 (gOpComposite.maskScaleY != 1.0 && gOpComposite.maskScaleY != -1.0)))
1377             {
1378                 imgMask->xscale = G2D_DOUBLE_TO_FIXED(gOpComposite.maskScaleX);
1379                 imgMask->yscale = G2D_DOUBLE_TO_FIXED(gOpComposite.maskScaleY);
1380                 imgMask->scale_mode = G2D_SCALE_MODE_BILINEAR;
1381             }
1382         }
1383     }
1384
1385     gOpComposite.bDo = draw_type;
1386
1387     return TRUE;
1388
1389 bail:
1390     XDBG_TRACE (MEXAH, "FAIL: op%d\n", op);
1391     XDBG_TRACE (MEXAH, "   SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap);
1392     XDBG_TRACE (MEXAH, "   MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap);
1393     XDBG_TRACE (MEXAH, "   DST picture:%p pix:%p\n", pDstPicture, pDstPixmap);
1394
1395     gOpComposite.bDo = DO_DRAW_NONE;
1396
1397     return TRUE;
1398 }
1399
1400 static void
1401 SECExaG2dComposite (PixmapPtr pDstPixmap, int srcX, int srcY,
1402                    int maskX, int maskY, int dstX, int dstY,
1403                    int width, int height)
1404 {
1405     XDBG_TRACE (MEXAH, "%s\n", DO(gOpComposite));
1406     XDBG_TRACE (MEXAH, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n",
1407                 srcX, srcY,
1408                 maskX, maskY,
1409                 dstX, dstY,
1410                 width, height);
1411     if (gOpComposite.bDo == DO_DRAW_NONE) return;
1412
1413     gOpComposite.srcX = srcX;
1414     gOpComposite.srcY = srcY;
1415     gOpComposite.maskX = maskX;
1416     gOpComposite.maskY = maskY;
1417     gOpComposite.dstX = dstX;
1418     gOpComposite.dstY = dstY;
1419     gOpComposite.width = width;
1420     gOpComposite.height = height;
1421
1422     if (gOpComposite.pOpDst->isSame)
1423     {
1424         ExaBox box;
1425
1426         box.state = rgnIN;
1427         box.box.x1 = 0;
1428         box.box.y1 = 0;
1429         box.box.x2 = width;
1430         box.box.y2 = height;
1431         box.pDst = &gOpComposite.pOpDst->buf[0];
1432         box.pSrc = &gOpComposite.pOpSrc->buf[0];
1433         box.pMask = (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
1434
1435         _g2dDoComposite (&box, NULL);
1436     }
1437     else
1438     {
1439         int i;
1440         ExaBox *box;
1441         BoxRec b;
1442
1443         /*Init box list*/
1444         xorg_list_init (&gOpComposite.opBox);
1445
1446         b.x1 = dstX;
1447         b.y1 = dstY;
1448         b.x2 = dstX+width;
1449         b.y2 = dstY+height;
1450
1451         for (i=0; i<gOpComposite.pOpDst->num; i++)
1452         {
1453             box = _g2dBoxAdd (&gOpComposite.opBox,
1454                              &gOpComposite.pOpDst->buf[i].pos,
1455                              &b);
1456             if (box)
1457             {
1458                 box->pDst = &gOpComposite.pOpDst->buf[i];
1459                 box->pSrc = &gOpComposite.pOpSrc->buf[0];
1460                 box->pMask= (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
1461             }
1462         }
1463         _g2dBoxMove (&gOpComposite.opBox, -dstX, -dstY);
1464
1465         /* Call solid function */
1466         _g2dDoDraw (&gOpComposite.opBox,
1467                    _g2dDoComposite, NULL);
1468
1469         /*Remove box list*/
1470         _g2dBoxRemoveAll (&gOpComposite.opBox);
1471     }
1472 }
1473
1474 /* done composite : sw done composite, not using pvr2d */
1475 static void
1476 SECExaG2dDoneComposite (PixmapPtr pDst)
1477 {
1478     XDBG_TRACE (MEXAH, "\n");
1479
1480     if(gOpComposite.bDo == DO_DRAW_HW)
1481         g2d_exec();
1482
1483     if (gOpComposite.pDstPixmap != NULL)
1484         _g2dFinishAccess (gOpComposite.pDstPixmap, EXA_PREPARE_DEST);
1485
1486     if (gOpComposite.pSrcPixmap != NULL)
1487         _g2dFinishAccess (gOpComposite.pSrcPixmap, EXA_PREPARE_SRC);
1488     else if (gOpComposite.pOpSrc)
1489     {
1490         g2d_image_free (gOpComposite.pOpSrc->buf[0].imgG2d);
1491         gOpComposite.pOpSrc->buf[0].imgG2d = NULL;
1492     }
1493
1494     if (gOpComposite.pMaskPixmap != NULL)
1495         _g2dFinishAccess (gOpComposite.pMaskPixmap, EXA_PREPARE_MASK);
1496     else if (gOpComposite.pOpMask != NULL)
1497     {
1498         g2d_image_free (gOpComposite.pOpMask->buf[0].imgG2d);
1499         gOpComposite.pOpMask->buf[0].imgG2d = NULL;
1500     }
1501 }
1502
1503 static Bool
1504 SECExaG2dUploadToScreen (PixmapPtr pDst, int x, int y, int w, int h,
1505                         char *src, int src_pitch)
1506 {
1507     XDBG_RETURN_VAL_IF_FAIL (src!=NULL, TRUE);
1508     XDBG_TRACE (MEXAH, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x,y,w,h);
1509
1510     gOpUTS.pDst = pDst;
1511     gOpUTS.x = x;
1512     gOpUTS.y = y;
1513     gOpUTS.w = w;
1514     gOpUTS.h = h;
1515     gOpUTS.src = src;
1516     gOpUTS.src_pitch = src_pitch;
1517
1518     if(_g2dIsSupport(pDst, FALSE))
1519     {
1520         gOpUTS.pOpDst = _g2dPrepareAccess (pDst,
1521                                                                     EXA_PREPARE_DEST,
1522                                                                     TBM_DEVICE_2D);
1523         gOpUTS.imgSrc = g2d_image_create_data (gOpUTS.pOpDst->buf[0].imgG2d->color_mode,
1524                                                                     w, h, (void*)src, src_pitch);
1525         gOpUTS.bDo = DO_DRAW_HW;
1526     }
1527     else
1528     {
1529         gOpUTS.pOpDst = _g2dPrepareAccess (pDst,
1530                                                                     EXA_PREPARE_DEST,
1531                                                                     TBM_DEVICE_CPU);
1532         gOpUTS.imgSrc = NULL;
1533         gOpUTS.bDo = DO_DRAW_SW;
1534     }
1535
1536     XDBG_TRACE (MEXAH, "%s\n", DO(gOpUTS));
1537     if (gOpUTS.pOpDst->isSame)
1538     {
1539         ExaBox box;
1540
1541         box.box.x1 = 0;
1542         box.box.y1 = 0;
1543         box.box.x2 = w;
1544         box.box.y2 = h;
1545         box.state = rgnIN;
1546         box.pDst = &gOpUTS.pOpDst->buf[0];
1547         _g2dDoUploadToScreen (&box, NULL);
1548     }
1549     else
1550     {
1551         int i;
1552         ExaBox *box;
1553         BoxRec b;
1554
1555         /*Init box list*/
1556         xorg_list_init (&gOpUTS.opBox);
1557
1558         b.x1 = x;
1559         b.y1 = y;
1560         b.x2 = x+w;
1561         b.y2 = y+h;
1562
1563         for (i=0; i<gOpUTS.pOpDst->num; i++)
1564         {
1565             box = _g2dBoxAdd (&gOpUTS.opBox,
1566                              &gOpUTS.pOpDst->buf[i].pos,
1567                              &b);
1568             if (box)
1569             {
1570                 box->pDst = &gOpUTS.pOpDst->buf[i];
1571             }
1572         }
1573         _g2dBoxMove (&gOpUTS.opBox, -x, -y);
1574
1575         /* Call solid function */
1576         _g2dDoDraw (&gOpUTS.opBox,
1577                    _g2dDoUploadToScreen, NULL);
1578
1579         /*Remove box list*/
1580         _g2dBoxRemoveAll (&gOpUTS.opBox);
1581     }
1582
1583     if(gOpUTS.bDo == DO_DRAW_HW)
1584         g2d_exec();
1585
1586     _g2dFinishAccess (pDst, EXA_PREPARE_DEST);
1587     if(gOpUTS.imgSrc)
1588     {
1589         g2d_image_free(gOpUTS.imgSrc);
1590     }
1591     return TRUE;
1592 }
1593
1594
1595
1596 static Bool
1597 SECExaG2dDownloadFromScreen (PixmapPtr pSrc, int x, int y, int w, int h,
1598                             char *dst, int dst_pitch)
1599 {
1600     XDBG_RETURN_VAL_IF_FAIL (dst!=NULL, TRUE);
1601     XDBG_TRACE (MEXAH, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x,y,w,h);
1602
1603     gOpDFS.pSrc = pSrc;
1604     gOpDFS.x = x;
1605     gOpDFS.y = y;
1606     gOpDFS.w = w;
1607     gOpDFS.h = h;
1608     gOpDFS.dst = dst;
1609     gOpDFS.dst_pitch = dst_pitch;
1610
1611     if(_g2dIsSupport(pSrc, FALSE))
1612     {
1613         gOpDFS.pOpSrc = _g2dPrepareAccess (pSrc,
1614                                                                     EXA_PREPARE_DEST,
1615                                                                     TBM_DEVICE_2D);
1616         gOpDFS.imgDst = g2d_image_create_data (gOpDFS.pOpSrc->buf[0].imgG2d->color_mode,
1617                                                                     w, h, (void*)dst, dst_pitch);
1618         gOpDFS.bDo = DO_DRAW_HW;
1619     }
1620     else
1621     {
1622         gOpDFS.pOpSrc = _g2dPrepareAccess (pSrc,
1623                                                                     EXA_PREPARE_DEST,
1624                                                                     TBM_DEVICE_CPU);
1625         gOpDFS.imgDst = NULL;
1626         gOpDFS.bDo = DO_DRAW_SW;
1627     }
1628
1629     XDBG_TRACE (MEXAH, "%s\n", DO(gOpDFS));
1630     if (gOpDFS.pOpSrc->isSame)
1631     {
1632         ExaBox box;
1633
1634         box.box.x1 = 0;
1635         box.box.y1 = 0;
1636         box.box.x2 = w;
1637         box.box.y2 = h;
1638         box.state = rgnIN;
1639         box.pSrc = &gOpDFS.pOpSrc->buf[0];
1640         _g2dDoDownladFromScreen (&box, NULL);
1641     }
1642     else
1643     {
1644         int i;
1645         ExaBox *box;
1646         BoxRec b;
1647
1648         /*Init box list*/
1649         xorg_list_init (&gOpDFS.opBox);
1650
1651         b.x1 = x;
1652         b.y1 = y;
1653         b.x2 = x+w;
1654         b.y2 = y+h;
1655
1656         for (i=0; i<gOpDFS.pOpSrc->num; i++)
1657         {
1658             box = _g2dBoxAdd (&gOpDFS.opBox,
1659                              &gOpDFS.pOpSrc->buf[i].pos,
1660                              &b);
1661             if (box)
1662             {
1663                 box->pSrc = &gOpDFS.pOpSrc->buf[i];
1664             }
1665         }
1666         _g2dBoxMove (&gOpDFS.opBox, -x, -y);
1667
1668         /* Call solid function */
1669         _g2dDoDraw (&gOpDFS.opBox,
1670                    _g2dDoDownladFromScreen, NULL);
1671
1672         /*Remove box list*/
1673         _g2dBoxRemoveAll (&gOpDFS.opBox);
1674     }
1675
1676     if(gOpDFS.bDo == DO_DRAW_HW)
1677         g2d_exec();
1678
1679     _g2dFinishAccess (pSrc, EXA_PREPARE_SRC);
1680     if(gOpDFS.imgDst)
1681     {
1682         g2d_image_free(gOpDFS.imgDst);
1683     }
1684     return TRUE;
1685 }
1686
1687 Bool secExaG2dInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver)
1688 {
1689     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1690     SECPtr pSec = SECPTR (pScrn);
1691
1692     if(!g2d_init (pSec->drm_fd))
1693     {
1694         XDBG_WARNING (MEXA, "[EXAG2D] fail to g2d_init(%d)\n", pSec->drm_fd);
1695     }
1696
1697     pExaDriver->PrepareSolid = SECExaG2dPrepareSolid;
1698     pExaDriver->Solid = SECExaG2dSolid;
1699     pExaDriver->DoneSolid = SECExaG2dDoneSolid;
1700
1701     pExaDriver->PrepareCopy = SECExaG2dPrepareCopy;
1702     pExaDriver->Copy = SECExaG2dCopy;
1703     pExaDriver->DoneCopy = SECExaG2dDoneCopy;
1704
1705     pExaDriver->CheckComposite = SECExaG2dCheckComposite;
1706     pExaDriver->PrepareComposite = SECExaG2dPrepareComposite;
1707     pExaDriver->Composite = SECExaG2dComposite;
1708     pExaDriver->DoneComposite = SECExaG2dDoneComposite;
1709
1710     pExaDriver->UploadToScreen = SECExaG2dUploadToScreen;
1711     pExaDriver->DownloadFromScreen = SECExaG2dDownloadFromScreen;
1712
1713     xf86DrvMsg (pScrn->scrnIndex, X_INFO
1714                 , "Succeed to Initialize G2D EXA\n");
1715
1716     return TRUE;
1717 }
1718
1719 void secExaG2dDeinit (ScreenPtr pScreen)
1720 {
1721     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1722
1723     xf86DrvMsg (pScrn->scrnIndex, X_INFO
1724                 , "Succeed to finish SW EXA\n");
1725 }