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