Fix flickering resized video frame.
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / crtcconfig / sec_plane.c
1 /**************************************************************************
2
3 xserver-xorg-video-exynos
4
5 Copyright 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 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <sys/ioctl.h>
36 #include <stdint.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <poll.h>
43
44 #include <xorgVersion.h>
45 #include <tbm_bufmgr.h>
46 #include <xf86Crtc.h>
47 #include <xf86DDC.h>
48 #include <xf86cmap.h>
49 #include <list.h>
50 #include <X11/Xatom.h>
51 #include <X11/extensions/dpmsconst.h>
52 #include <sec.h>
53 #include "common.h"
54
55 #include "sec_crtc.h"
56 #include "sec_output.h"
57 #include "sec_util.h"
58 #include "sec_video_fourcc.h"
59 #include "sec_plane.h"
60 #include "fimg2d.h"
61
62 /* HW restriction */
63 #define MIN_WIDTH   32
64 #define MIN_HEIGHT   4
65
66 enum
67 {
68     PLANE_FB_TYPE_NONE,
69     PLANE_FB_TYPE_DEFAULT,
70     PLANE_FB_TYPE_BO,
71     PLANE_FB_TYPE_MAX
72 };
73
74 typedef struct _SECPlaneAccess
75 {
76     unsigned int fb_id;
77
78     tbm_bo bo;
79
80     int width;
81     int height;
82
83     xRectangle src;
84     xRectangle dst;
85 } SECPlaneAccess;
86
87 /* This is structure to manage a added buffer. */
88 typedef struct _SECPlaneFb
89 {
90     unsigned int id;
91
92     int type;
93     union
94     {
95         /* for framebuffer */
96         tbm_bo       bo;
97         SECVideoBuf *vbuf;
98     } buffer;
99
100     int width;
101     int height;
102
103     Bool buffer_gone;
104
105     struct xorg_list link;
106 } SECPlaneFb;
107
108 typedef struct _SECPlaneTable
109 {
110     SECPlanePrivPtr pPlanePriv;
111     int plane_id;
112
113     /* buffers which this plane has */
114     struct xorg_list  fbs;
115     SECPlaneFb  *cur_fb;
116
117     /* visibilitiy information */
118     Bool visible;
119     int  crtc_id;
120     int  zpos;
121     xRectangle src;
122     xRectangle dst;
123     int  conn_type;
124
125     Bool onoff;
126     Bool in_use;
127     Bool freeze_update;
128
129     /* accessibility */
130     SECPlaneAccess *access;
131 } SECPlaneTable;
132
133 /* table of planes which system has entirely */
134 static SECPlaneTable *plane_table;
135 static int plane_table_size;
136
137 static SECPlaneTable* _secPlaneTableFind (int plane_id);
138 static SECPlaneFb* _secPlaneTableFindBuffer (SECPlaneTable *table, int fb_id,
139                                              tbm_bo bo, SECVideoBuf *vbuf);
140 static Bool _secPlaneHideInternal (SECPlaneTable *table);
141
142 static void
143 _secPlaneFreeVbuf (SECVideoBuf *vbuf, void *data)
144 {
145     int plane_id = (int)data;
146     SECPlaneTable *table;
147     SECPlaneFb *fb;
148
149     table = _secPlaneTableFind (plane_id);
150     XDBG_RETURN_IF_FAIL (table != NULL);
151
152     fb = _secPlaneTableFindBuffer (table, vbuf->fb_id, NULL, NULL);
153     XDBG_RETURN_IF_FAIL (fb != NULL);
154
155     fb->buffer_gone = TRUE;
156     secPlaneRemoveBuffer (plane_id, vbuf->fb_id);
157 }
158
159 static SECPlaneTable*
160 _secPlaneTableFindPos (int crtc_id, int zpos)
161 {
162     int i;
163
164     XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, NULL);
165
166     for (i = 0; i < plane_table_size; i++)
167         if (plane_table[i].crtc_id == crtc_id && plane_table[i].zpos == zpos)
168             return &plane_table[i];
169
170     return NULL;
171 }
172
173 static SECPlaneTable*
174 _secPlaneTableFind (int plane_id)
175 {
176     int i;
177
178     XDBG_RETURN_VAL_IF_FAIL (plane_id > 0, NULL);
179
180     for (i = 0; i < plane_table_size; i++)
181         if (plane_table[i].plane_id == plane_id)
182             return &plane_table[i];
183
184     XDBG_TRACE (MPLN, "plane(%d) not found. \n", plane_id);
185
186     return NULL;
187 }
188
189 static SECPlaneTable*
190 _secPlaneTableFindEmpty (void)
191 {
192     int i;
193
194     for (i = 0; i < plane_table_size; i++)
195         if (!plane_table[i].in_use)
196             return &plane_table[i];
197
198     return NULL;
199 }
200
201 static SECPlaneFb*
202 _secPlaneTableFindBuffer (SECPlaneTable *table,
203                           int fb_id,
204                           tbm_bo bo,
205                           SECVideoBuf *vbuf)
206 {
207     SECPlaneFb *fb = NULL, *fb_next = NULL;
208
209     xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link)
210     {
211         if (fb_id > 0)
212         {
213             if (fb->id == fb_id)
214                 return fb;
215         }
216         else if (bo)
217         {
218             if (fb->type == PLANE_FB_TYPE_BO && fb->buffer.bo == bo)
219                 return fb;
220         }
221         else if (vbuf)
222         {
223             XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), NULL);
224
225             if (fb->type == PLANE_FB_TYPE_DEFAULT)
226                 if (fb->buffer.vbuf == vbuf && fb->buffer.vbuf->stamp == vbuf->stamp)
227                     return fb;
228         }
229     }
230
231     return NULL;
232 }
233
234 static void
235 _secPlaneTableFreeBuffer (SECPlaneTable *table, SECPlaneFb *fb)
236 {
237     if (table->cur_fb == fb)
238         return;
239
240     if (fb->type == PLANE_FB_TYPE_BO)
241     {
242         if (fb->buffer.bo)
243             tbm_bo_unref (fb->buffer.bo);
244     }
245     else
246     {
247         if (!fb->buffer_gone && fb->buffer.vbuf)
248             secUtilRemoveFreeVideoBufferFunc (fb->buffer.vbuf, _secPlaneFreeVbuf,
249                                               (void*)table->plane_id);
250     }
251
252     xorg_list_del (&fb->link);
253
254     free (fb);
255 }
256
257 static Bool
258 _secPlaneTableEnsure (ScrnInfoPtr pScrn, int count_planes)
259 {
260     int i;
261
262     XDBG_RETURN_VAL_IF_FAIL (count_planes > 0, FALSE);
263
264     if (plane_table)
265     {
266         if (plane_table_size != count_planes)
267             XDBG_WARNING (MPLN, "%d != %d, need to re-create! \n",
268                           plane_table_size, count_planes);
269         return TRUE;
270     }
271
272     plane_table = calloc (sizeof (SECPlaneTable), count_planes);
273     XDBG_RETURN_VAL_IF_FAIL (plane_table != NULL, FALSE);
274
275     plane_table_size = count_planes;
276
277     for (i = 0; i < plane_table_size; i++)
278     {
279         SECPlaneTable *table = &plane_table[i];
280         table->plane_id = -1;
281         table->onoff = TRUE;
282     }
283
284     return TRUE;
285 }
286
287 static void
288 _secPlaneExecAccessibility (tbm_bo src_bo, int sw, int sh, xRectangle *sr,
289                             tbm_bo dst_bo, int dw, int dh, xRectangle *dr,
290                             Bool bNegative)
291 {
292     G2dImage *srcImg = NULL, *dstImg = NULL;
293     tbm_bo_handle src_bo_handle = {0,};
294     tbm_bo_handle dst_bo_handle = {0,};
295     G2dColorKeyMode mode;
296
297     mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
298     src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
299     XDBG_GOTO_IF_FAIL (src_bo_handle.s32 > 0, access_done);
300
301     dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE);
302     XDBG_GOTO_IF_FAIL (dst_bo_handle.s32 > 0, access_done);
303
304     srcImg = g2d_image_create_bo (mode, sw, sh, src_bo_handle.s32, sw * 4);
305     XDBG_GOTO_IF_FAIL (srcImg != NULL, access_done);
306
307     dstImg = g2d_image_create_bo (mode, dw, dh, dst_bo_handle.s32, dw * 4);
308     XDBG_GOTO_IF_FAIL (dstImg != NULL, access_done);
309
310     util_g2d_copy_with_scale (srcImg, dstImg,
311                               (int)sr->x, (int)sr->y, sr->width, sr->height,
312                               (int)dr->x, (int)dr->y, dr->width, dr->height,
313                               (int)bNegative);
314     g2d_exec ();
315
316 access_done:
317     if (src_bo_handle.s32)
318         tbm_bo_unmap (src_bo);
319     if (dst_bo_handle.s32)
320         tbm_bo_unmap (dst_bo);
321     if (srcImg)
322         g2d_image_free (srcImg);
323     if (dstImg)
324         g2d_image_free (dstImg);
325 }
326
327 static Bool
328 _check_hw_restriction (ScrnInfoPtr pScrn, int crtc_id, int buf_w, int buf_h,
329                        xRectanglePtr src, xRectanglePtr dst,
330                        xRectanglePtr aligned_src, xRectanglePtr aligned_dst)
331 {
332     /* Kernel manage CRTC status based out output config */
333     xf86CrtcPtr pCrtc = secCrtcGetByID(pScrn, crtc_id);
334     if (pCrtc == NULL)
335     {
336         XDBG_ERROR(MPLN, "Can't found crtc_id(%d)\n", crtc_id);
337         return FALSE;
338     }
339     if (!pCrtc->enabled && !pCrtc->active)
340     {
341         XDBG_ERROR(MPLN, "Current crtc_id(%d) not active\n", crtc_id);
342         return FALSE;
343     }
344
345     int max_w = pCrtc->mode.CrtcHDisplay;
346     int max_h = pCrtc->mode.CrtcVDisplay;
347     if (max_w == 0 || max_h == 0)
348     {
349         max_w = pScrn->virtualX;
350         max_h = pScrn->virtualY;
351     }
352     if (buf_w < MIN_WIDTH || buf_w % 2)
353     {
354         XDBG_TRACE (MPLN, "hide: buf_w(%d) not 2's multiple or less than %d\n",
355                     buf_w, MIN_WIDTH);
356         return FALSE;
357     }
358
359     if (buf_h < MIN_HEIGHT)
360     {
361         XDBG_TRACE (MPLN, "hide: buf_h(%d) less than %d\n",
362                     buf_h, MIN_HEIGHT);
363         return FALSE;
364     }
365 #if 0
366     if (src_x > dst_x || ((dst_x - src_x) + buf_w) > max_w)
367         virtual_screen = TRUE;
368     else
369         virtual_screen = FALSE;
370 #endif
371     aligned_dst->x = (dst->x < 0) ? 0 : dst->x;
372     aligned_dst->y = (dst->y < 0) ? 0 : dst->y;
373     aligned_dst->width = ((aligned_dst->x + dst->width) > max_w) ? max_w : (aligned_dst->x + dst->width);
374     aligned_dst->height = ((aligned_dst->y + dst->height) > max_h) ? max_h : (aligned_dst->y + dst->height);
375
376     /* check window minimum width / height */
377     if (((aligned_dst->width - aligned_dst->x) < MIN_WIDTH) || ((aligned_dst->height - aligned_dst->y) < MIN_HEIGHT))
378     {
379         XDBG_TRACE (MPLN, "hide: %d, %d: buf_w(%d) buf_h(%d)\n",
380                     aligned_dst->width - aligned_dst->x,
381                     aligned_dst->height - aligned_dst->y,
382                     buf_w, buf_h);
383         XDBG_TRACE (MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d)\n",
384                     src->x, src->y, src->width, src->height,
385                     dst->x, dst->y, dst->width, dst->height);
386         XDBG_TRACE (MPLN,"start(x%d,y%d) end(w%d,h%d)\n",
387                     aligned_dst->x, aligned_dst->y,
388                     aligned_dst->width, aligned_dst->height);
389         return FALSE;
390     }
391
392     aligned_dst->width = (aligned_dst->width - aligned_dst->x) & (~0x1);
393     aligned_dst->height = (aligned_dst->height - aligned_dst->y);
394
395     aligned_src->x = (src->x < 0) ? 0 : src->x;
396     aligned_src->y = (src->y < 0) ? 0 : src->y;
397     aligned_src->width = ((aligned_src->x + src->width) > buf_w) ? buf_w : (aligned_src->x + src->width);
398     aligned_src->height = ((aligned_src->y + src->height) > buf_h) ? buf_h : (aligned_src->y + src->height);
399
400     if (((aligned_src->width - aligned_src->x) < MIN_WIDTH) || ((aligned_src->height - aligned_src->y) < MIN_HEIGHT))
401     {
402         XDBG_TRACE (MPLN, "hide: %d, %d: buf_w(%d) buf_h(%d)\n",
403                     aligned_src->width - aligned_src->x,
404                     aligned_src->height - aligned_src->y,
405                     buf_w, buf_h);
406         XDBG_TRACE (MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d)\n",
407                     src->x, src->y, src->width, src->height,
408                     dst->x, dst->y, dst->width, dst->height);
409         XDBG_TRACE (MPLN,"start(x%d,y%d) end(w%d,h%d)\n",
410                     aligned_src->x, aligned_src->y,
411                     aligned_src->width, aligned_src->height);
412         return FALSE;
413     }
414
415     aligned_src->width = (aligned_src->width - aligned_src->x) & (~0x1);
416     aligned_src->height = (aligned_src->height - aligned_src->y);
417 #if 0
418     if (!virtual_screen)
419     {
420         /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
421         if ((end_dst - start_dst) % 2)
422             end_dst--;
423     }
424     else
425     {
426         /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
427         if (end_dst % 2)
428             end_dst--;
429     }
430
431     *new_dst_x = start_dst;
432     *new_dst_w = end_dst - start_dst;
433     *new_src_w = end_src - start_src;
434 //    diff = start_dst - dst_x;
435     *new_src_x = start_src;
436
437     XDBG_RETURN_VAL_IF_FAIL (*new_src_w > 0, FALSE);
438     XDBG_RETURN_VAL_IF_FAIL (*new_dst_w > 0, FALSE);
439     if (src_x != *new_src_x || src_w != *new_src_w ||
440         dst_x != *new_dst_x || dst_w != *new_dst_w)
441         XDBG_TRACE (MPLN, " => buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n",
442                     buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start_dst, end_dst);
443 #endif
444     XDBG_TRACE (MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d) ratio_x %f ratio_y %f\n",
445                 src->x, src->y, src->width, src->height,
446                 dst->x, dst->y, dst->width, dst->height,
447                 (double) src->width/dst->width, (double) src->height/dst->height);
448     if (!memcmp(aligned_src, src, sizeof(xRectangle))
449         || !memcmp(aligned_dst, dst, sizeof(xRectangle)))
450     {
451         XDBG_TRACE(MPLN, "===> src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d) ratio_x %f ratio_y %f\n",
452                    aligned_src->x, aligned_src->y,
453                    aligned_src->width, aligned_src->height,
454                    aligned_dst->x, aligned_dst->y,
455                    aligned_dst->width, aligned_dst->height,
456                    (double) aligned_src->width / aligned_dst->width,
457                    (double) aligned_src->height / aligned_dst->height);
458     }
459     return TRUE;
460 }
461
462 static Bool
463 _secPlaneShowInternal (SECPlaneTable *table,
464                        SECPlaneFb *old_fb, SECPlaneFb *new_fb,
465                        xRectangle *new_src, xRectangle *new_dst, int new_zpos,
466                        Bool need_set_plane)
467 {
468     SECPtr pSec;
469     SECModePtr pSecMode;
470     xRectangle old_src = table->src;
471     xRectangle old_dst = table->dst;
472     int old_zpos = table->zpos;
473     Bool change_zpos = FALSE;
474     tbm_bo_handle bo_handle;
475
476     pSec = SECPTR (table->pPlanePriv->pScrn);
477     pSecMode = table->pPlanePriv->pSecMode;
478
479     if (pSec->isLcdOff)
480     {
481         XDBG_TRACE (MPLN, "lcd off, can't show : plane(%d) crtc(%d) pos(%d). \n",
482                     table->plane_id, table->crtc_id, new_zpos);
483         return FALSE;
484     }
485
486     if (!table->onoff)
487     {
488         XDBG_TRACE (MPLN, "plane off, can't show : plane(%d) crtc(%d) pos(%d). \n",
489                     table->plane_id, table->crtc_id, new_zpos);
490         return FALSE;
491     }
492
493     /* should set zpos before doing drmModeSetPlane */
494     if (new_zpos != old_zpos)
495     {
496         if (!secUtilSetDrmProperty (pSecMode, table->plane_id, DRM_MODE_OBJECT_PLANE,
497                                     "zpos", new_zpos))
498             return FALSE;
499
500         table->zpos = new_zpos;
501         change_zpos = TRUE;
502
503         XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) zpos(%d)\n",
504                     table->plane_id, table->crtc_id, table->zpos);
505     }
506
507     if (!table->visible || need_set_plane ||
508         change_zpos ||
509         (!old_fb || (old_fb != new_fb)) ||
510         (memcmp (&old_src, new_src, sizeof (xRectangle))) ||
511         (memcmp (&old_dst, new_dst, sizeof (xRectangle))))
512     {
513         xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (table->pPlanePriv->pScrn);
514         SECCrtcPrivPtr pCrtcPriv = NULL;
515         int c;
516
517         for (c = 0; c < pCrtcConfig->num_crtc; c++)
518         {
519             xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
520             SECCrtcPrivPtr pTemp =  pCrtc->driver_private;
521             if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == table->crtc_id)
522             {
523                 pCrtcPriv = pTemp;
524                 break;
525             }
526         }
527
528         XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
529
530         XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) fb(%d) (%d,%d %dx%d) => (%d,%d %dx%d) [%d,%d,%c%c%c%c]\n",
531                     table->plane_id, table->crtc_id, new_fb->id,
532                     new_src->x, new_src->y, new_src->width, new_src->height,
533                     new_dst->x, new_dst->y, new_dst->width, new_dst->height,
534                     pCrtcPriv->bAccessibility, new_fb->type,
535                     FOURCC_STR (new_fb->buffer.vbuf->id));
536
537         if (!pCrtcPriv->bAccessibility ||
538             (new_fb->type == PLANE_FB_TYPE_DEFAULT && new_fb->buffer.vbuf->id != FOURCC_RGB32))
539         {
540 #if 0
541             int aligned_src_x = new_src->x;
542             int aligned_src_w = new_src->width;
543             int aligned_dst_x = new_dst->x;
544             int aligned_dst_w = new_dst->width;
545 #endif
546             xRectangle aligned_src;
547             xRectangle aligned_dst;
548             if (!_check_hw_restriction (table->pPlanePriv->pScrn, table->crtc_id,
549                                         table->cur_fb->width, table->cur_fb->height,
550                                         new_src, new_dst,
551                                         &aligned_src, &aligned_dst))
552             {
553                 XDBG_TRACE (MPLN, "out of range: plane(%d) crtc(%d) pos(%d) crtc(x%d,y%d w%d-h%d)\n",
554                             table->plane_id, table->crtc_id, new_zpos,
555                             new_dst->x, new_dst->y, new_dst->width, new_dst->height);
556                 XDBG_TRACE (MPLN, "src(x%d,y%d w%d-h%d)\n",
557                             new_src->x, new_src->y, new_src->width, new_src->height);
558
559                 _secPlaneHideInternal (table);
560
561                 return TRUE;
562             }
563
564             /* Source values are 16.16 fixed point */
565
566             uint32_t fixed_x = ((unsigned int)aligned_src.x) << 16;
567             uint32_t fixed_y = ((unsigned int)aligned_src.y) << 16;
568             uint32_t fixed_w = ((unsigned int)aligned_src.width) << 16;
569             uint32_t fixed_h = ((unsigned int)aligned_src.height) << 16;
570
571             if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id,
572                                  new_fb->id, 0,
573                                  aligned_dst.x, aligned_dst.y,
574                                  aligned_dst.width, aligned_dst.height,
575                                  fixed_x, fixed_y,
576                                  fixed_w, fixed_h))
577             {
578                 XDBG_ERRNO (MPLN, "drmModeSetPlane failed. plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
579                             table->plane_id, table->crtc_id, table->zpos,
580                             new_fb->id, FOURCC_STR (new_fb->buffer.vbuf->id),
581                             new_fb->buffer.vbuf->width, new_fb->buffer.vbuf->height,
582                             aligned_src.x, aligned_src.y, aligned_src.width, aligned_src.height,
583                             aligned_dst.x, aligned_dst.y, aligned_dst.width, aligned_dst.height);
584
585                 return FALSE;
586             }
587
588             if (!table->visible)
589             {
590                 XDBG_SECURE (MPLN, "plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
591                              table->plane_id, table->crtc_id, table->zpos,
592                              new_fb->id, FOURCC_STR (new_fb->buffer.vbuf->id),
593                              new_fb->buffer.vbuf->width, new_fb->buffer.vbuf->height,
594                              aligned_src.x, aligned_src.y, aligned_src.width, aligned_src.height,
595                              aligned_dst.x, aligned_dst.y, aligned_dst.width, aligned_dst.height);
596                 table->visible = TRUE;
597             }
598         }
599         else
600         {
601             SECPlaneAccess *access;
602             xRectangle fb_src = {0,};
603             tbm_bo src_bo;
604             int old_w = 0, old_h = 0;
605
606             if (!table->access)
607             {
608                 table->access = calloc (1, sizeof (SECPlaneAccess));
609                 XDBG_RETURN_VAL_IF_FAIL (table->access != NULL, FALSE);
610             }
611             else
612             {
613                 old_w = table->access->width;
614                 old_h = table->access->height;
615             }
616
617             access = table->access;
618
619             if (pCrtcPriv->bScale)
620             {
621                 float h_ratio = 0.0, v_ratio = 0.0;
622                 xRectangle crop;
623
624                 h_ratio = (float)pCrtcPriv->kmode.hdisplay / pCrtcPriv->sw;
625                 v_ratio = (float)pCrtcPriv->kmode.vdisplay / pCrtcPriv->sh;
626
627                 fb_src.x = new_src->x;
628                 fb_src.y = new_src->y;
629                 fb_src.width = new_src->width;
630                 fb_src.height = new_src->height;
631
632                 CLEAR (crop);
633                 crop.x = pCrtcPriv->sx;
634                 crop.y = pCrtcPriv->sy;
635                 crop.width = pCrtcPriv->sw;
636                 crop.height = pCrtcPriv->sh;
637
638                 crop.x -= new_dst->x;
639                 crop.y -= new_dst->y;
640                 crop.x += new_src->x;
641                 crop.y += new_src->y;
642                 secUtilRectIntersect (&fb_src, &fb_src, &crop);
643
644                 access->dst = *new_dst;
645
646                 access->dst.x = new_dst->x;
647                 access->dst.y = new_dst->y;
648                 access->dst.width = new_dst->width;
649                 access->dst.height = new_dst->height;
650
651                 CLEAR (crop);
652                 crop.x = pCrtcPriv->sx;
653                 crop.y = pCrtcPriv->sy;
654                 crop.width = pCrtcPriv->sw;
655                 crop.height = pCrtcPriv->sh;
656                 secUtilRectIntersect (&access->dst, &access->dst, &crop);
657
658                 access->dst.x -= pCrtcPriv->sx;
659                 access->dst.y -= pCrtcPriv->sy;
660
661                 access->dst.x *= h_ratio;
662                 access->dst.y *= v_ratio;
663                 access->dst.width *= h_ratio;
664                 access->dst.height *= v_ratio;
665
666                 access->width = pCrtcPriv->kmode.hdisplay;
667                 access->height = pCrtcPriv->kmode.vdisplay;
668
669                 access->src.x = 0;
670                 access->src.y = 0;
671                 access->src.width = access->dst.width;
672                 access->src.height = access->dst.height;
673             }
674             else
675             {
676                 fb_src.x = new_src->x;
677                 fb_src.y = new_src->y;
678                 fb_src.width = new_src->width;
679                 fb_src.height = new_src->height;
680
681                 /* hw restriction: 8 bytes */
682                 new_dst->width &= ~1;
683
684                 access->dst.x = new_dst->x;
685                 access->dst.y = new_dst->y;
686                 access->dst.width = new_dst->width;
687                 access->dst.height = new_dst->height;
688
689                 access->width = access->dst.width;
690                 access->height = access->dst.height;
691
692                 access->src.x = 0;
693                 access->src.y = 0;
694                 access->src.width = access->dst.width;
695                 access->src.height = access->dst.height;
696             }
697
698             XDBG_DEBUG (MPLN, "access : accessibility_status(%d) scale(%d) bo(%p) fb(%d) (%d,%d %dx%d) (%dx%d) (%d,%d %dx%d) (%d,%d %dx%d).\n",
699                         pCrtcPriv->accessibility_status, pCrtcPriv->bScale,
700                         access->bo, access->fb_id,
701                         fb_src.x, fb_src.y, fb_src.width, fb_src.height,
702                         access->width, access->height,
703                         access->src.x, access->src.y, access->src.width, access->src.height,
704                         access->dst.x, access->dst.y, access->dst.width, access->dst.height);
705
706             if (!fb_src.width || !fb_src.height ||
707                 !access->width || !access->height ||
708                 !access->dst.width || !access->dst.height)
709             {
710                 _secPlaneHideInternal (table);
711
712                 return TRUE;
713             }
714
715             if (access->bo)
716             {
717                 if (old_w != access->width || old_h != access->height)
718                 {
719                     if (table->access->fb_id)
720                     {
721                         drmModeRmFB (pSecMode->fd, table->access->fb_id);
722                         table->access->fb_id = 0;
723                     }
724
725                     tbm_bo_unref (table->access->bo);
726                     table->access->bo = NULL;
727                 }
728             }
729
730             if (!access->bo)
731             {
732                 access->bo = tbm_bo_alloc (pSec->tbm_bufmgr,
733                                                access->width * access->height * 4,
734                                                TBM_BO_NONCACHABLE);
735                 XDBG_RETURN_VAL_IF_FAIL (access->bo != NULL, FALSE);
736
737                 bo_handle = tbm_bo_get_handle (access->bo, TBM_DEVICE_DEFAULT);
738                 if (drmModeAddFB (pSecMode->fd, access->width, access->height,
739                                   table->pPlanePriv->pScrn->depth,
740                                   table->pPlanePriv->pScrn->bitsPerPixel,
741                                   access->width * 4,
742                                   bo_handle.u32,
743                                   &access->fb_id))
744                 {
745                     XDBG_ERRNO (MPLN, "drmModeAddFB failed. plane(%d)\n", table->plane_id);
746                     return FALSE;
747                 }
748
749                 XDBG_RETURN_VAL_IF_FAIL (access->fb_id > 0, FALSE);
750             }
751
752             if (new_fb->type == PLANE_FB_TYPE_DEFAULT)
753                 src_bo = new_fb->buffer.vbuf->bo[0];
754             else
755                 src_bo = new_fb->buffer.bo;
756             XDBG_RETURN_VAL_IF_FAIL (src_bo != NULL, FALSE);
757
758             _secPlaneExecAccessibility (src_bo, new_fb->width, new_fb->height, &fb_src,
759                                         access->bo, access->width, access->height, &access->src,
760                                         pCrtcPriv->accessibility_status);
761             xRectangle aligned_src;
762             xRectangle aligned_dst;
763             if (!_check_hw_restriction (table->pPlanePriv->pScrn, table->crtc_id,
764                                         access->width, access->height,
765                                         &access->src, &access->dst,
766                                         &aligned_src, &aligned_dst))
767             {
768                 XDBG_TRACE (MPLN, "access : out of range: plane(%d) crtc(%d) pos(%d) crtc(x%d,y%d w%d-h%d)\n",
769                             table->plane_id, table->crtc_id, new_zpos,
770                             access->dst.x, access->dst.y, access->dst.width, access->dst.height);
771                 XDBG_TRACE (MPLN, "access : src(x%d,y%d w%d-h%d)\n",
772                             access->src.x, access->src.y, access->src.width, access->src.height);
773
774                 _secPlaneHideInternal (table);
775
776                 return TRUE;
777             }
778
779             /* Source values are 16.16 fixed point */
780             uint32_t fixed_x = ((unsigned int)aligned_src.x) << 16;
781             uint32_t fixed_y = ((unsigned int)aligned_src.y) << 16;
782             uint32_t fixed_w = ((unsigned int)aligned_src.width) << 16;
783             uint32_t fixed_h = ((unsigned int)aligned_src.height) << 16;
784
785             XDBG_DEBUG(MPLN, "Access plane: fixed:(x%d,y%d w%d-h%d), dst:(x%d,y%d w%d-h%d)\n",
786                        aligned_src.x, aligned_src.y, aligned_src.width, aligned_src.height,
787                        aligned_dst.x, aligned_dst.y, aligned_dst.width, aligned_dst.height);
788
789             if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id,
790                                  access->fb_id, 0,
791                                  aligned_dst.x, aligned_dst.y,
792                                  aligned_dst.width, aligned_dst.height,
793                                  fixed_x, fixed_y,
794                                  fixed_w, fixed_h))
795             {
796                 XDBG_ERRNO (MPLN, "drmModeSetPlane failed. \n");
797
798                 return FALSE;
799             }
800             if (!table->visible)
801             {
802                 XDBG_SECURE (MPLN, "plane(%d) crtc(%d) pos(%d) on: access_fb(%d,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
803                              table->plane_id, table->crtc_id, table->zpos,
804                              access->fb_id, access->width, access->height,
805                              aligned_src.x, aligned_src.y, aligned_src.width, aligned_src.height,
806                              aligned_dst.x, aligned_dst.y, aligned_dst.width, aligned_dst.height);
807                 table->visible = TRUE;
808             }
809         }
810
811         memcpy (&table->src, new_src, sizeof (xRectangle));
812         memcpy (&table->dst, new_dst, sizeof (xRectangle));
813     }
814
815     return TRUE;
816 }
817
818 static Bool
819 _secPlaneHideInternal (SECPlaneTable *table)
820 {
821     SECPtr pSec;
822     SECModePtr pSecMode;
823
824     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
825
826     if (!table->visible)
827         return TRUE;
828
829     XDBG_RETURN_VAL_IF_FAIL (table->crtc_id > 0, FALSE);
830
831     pSec = SECPTR (table->pPlanePriv->pScrn);
832     pSecMode = table->pPlanePriv->pSecMode;
833
834     if (!pSec->isLcdOff && table->onoff)
835     {
836         if (drmModeSetPlane (pSecMode->fd,
837                              table->plane_id,
838                              table->crtc_id,
839                              0, 0,
840                              0, 0, 0, 0, 0, 0, 0, 0))
841         {
842             XDBG_ERRNO (MPLN, "drmModeSetPlane failed. plane(%d) crtc(%d) zpos(%d) fb(%d)\n",
843                         table->plane_id, table->crtc_id, table->zpos, table->cur_fb->id);
844
845             return FALSE;
846         }
847     }
848
849     if (table->visible)
850     {
851         XDBG_SECURE (MPLN, "plane(%d) crtc(%d) zpos(%d) off. lcd(%s) onoff(%d)\n",
852                      table->plane_id, table->crtc_id, table->zpos,
853                      (pSec->isLcdOff)?"off":"on", table->onoff);
854         table->visible = FALSE;
855     }
856
857     XDBG_TRACE (MPLN, "plane(%d) fb(%d) removed from crtc(%d) zpos(%d). LCD(%s) ONOFF(%s).\n",
858                 table->plane_id, table->cur_fb->id, table->crtc_id, table->zpos,
859                 (pSec->isLcdOff)?"OFF":"ON", (table->onoff)?"ON":"OFF");
860
861     return TRUE;
862
863 }
864
865 void
866 secPlaneInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num)
867 {
868     SECPlanePrivPtr pPlanePriv;
869
870     XDBG_RETURN_IF_FAIL (pScrn != NULL);
871     XDBG_RETURN_IF_FAIL (pSecMode != NULL);
872     XDBG_RETURN_IF_FAIL (pSecMode->plane_res != NULL);
873     XDBG_RETURN_IF_FAIL (pSecMode->plane_res->count_planes > 0);
874
875     if (!_secPlaneTableEnsure (pScrn, pSecMode->plane_res->count_planes))
876         return;
877
878     pPlanePriv = calloc (sizeof (SECPlanePrivRec), 1);
879     XDBG_RETURN_IF_FAIL (pPlanePriv != NULL);
880
881     pPlanePriv->mode_plane = drmModeGetPlane (pSecMode->fd,
882                              pSecMode->plane_res->planes[num]);
883     if (!pPlanePriv->mode_plane)
884     {
885         XDBG_ERRNO (MPLN, "drmModeGetPlane failed. plane(%d)\n",
886                     pSecMode->plane_res->planes[num]);
887
888         free (pPlanePriv);
889         return;
890     }
891
892     pPlanePriv->pScrn = pScrn;
893     pPlanePriv->pSecMode = pSecMode;
894     pPlanePriv->plane_id = pPlanePriv->mode_plane->plane_id;
895
896     plane_table[num].plane_id = pPlanePriv->plane_id;
897     plane_table[num].pPlanePriv = pPlanePriv;
898     xorg_list_init (&plane_table[num].fbs);
899
900     xorg_list_add(&pPlanePriv->link, &pSecMode->planes);
901 }
902
903 void
904 secPlaneDeinit (ScrnInfoPtr pScrn, SECPlanePrivPtr pPlanePriv)
905 {
906     int i;
907
908     XDBG_RETURN_IF_FAIL (pScrn != NULL);
909     XDBG_RETURN_IF_FAIL (pPlanePriv != NULL);
910
911     secPlaneFreeId (pPlanePriv->plane_id);
912     drmModeFreePlane (pPlanePriv->mode_plane);
913     xorg_list_del (&pPlanePriv->link);
914
915     for (i = 0; i < plane_table_size; i++)
916         if (plane_table[i].plane_id == pPlanePriv->plane_id)
917         {
918             plane_table[i].plane_id = -1;
919             break;
920         }
921
922     free (pPlanePriv);
923
924     if (plane_table)
925     {
926         for (i = 0; i < plane_table_size; i++)
927             if (plane_table[i].plane_id != -1)
928                 return;
929
930         free (plane_table);
931         plane_table = NULL;
932         plane_table_size = 0;
933         XDBG_TRACE (MPLN, "plane_table destroyed. %d\n", plane_table_size);
934     }
935 }
936
937 void
938 secPlaneShowAll (int crtc_id)
939 {
940     int i;
941
942     XDBG_TRACE (MPLN, "crtc(%d) \n", crtc_id);
943
944     for (i = 0; i < plane_table_size; i++)
945     {
946         SECPlaneTable *table = &plane_table[i];
947
948         if (!table || !table->in_use || !table->visible || !table->onoff)
949             continue;
950
951         if (table->crtc_id != crtc_id)
952             continue;
953
954         if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
955                                     &table->src, &table->dst, table->zpos, TRUE))
956
957         {
958             XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n");
959         }
960
961         XDBG_TRACE (MPLN, "plane(%d) crtc(%d) zpos(%d) on.\n",
962                     table->plane_id, table->crtc_id, table->zpos);
963     }
964 }
965
966 int
967 secPlaneGetID (void)
968 {
969     SECPlaneTable *table = _secPlaneTableFindEmpty ();
970
971     if (!table)
972     {
973         XDBG_ERROR (MPLN, "No avaliable plane ID. %d\n", -1);
974         return -1;
975     }
976
977     table->in_use = TRUE;
978     table->onoff = TRUE;
979
980     XDBG_TRACE (MPLN, "plane(%d). \n", table->plane_id);
981
982     return table->plane_id;
983 }
984
985 void
986 secPlaneFreeId (int plane_id)
987 {
988     SECPlaneTable *table = _secPlaneTableFind (plane_id);
989     SECPlaneFb *fb = NULL, *fb_next = NULL;
990
991     XDBG_RETURN_IF_FAIL (table != NULL);
992
993     secPlaneHide (table->plane_id);
994
995     table->visible = FALSE;
996     table->crtc_id = 0;
997
998     table->zpos = 0;
999     memset (&table->src, 0x00, sizeof (xRectangle));
1000     memset (&table->dst, 0x00, sizeof (xRectangle));
1001
1002     table->cur_fb = NULL;
1003     xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link)
1004     {
1005         _secPlaneTableFreeBuffer (table, fb);
1006     }
1007
1008     if (table->access)
1009     {
1010         if (table->access->fb_id)
1011         {
1012             SECModePtr pSecMode = table->pPlanePriv->pSecMode;
1013             if (pSecMode)
1014                 drmModeRmFB (pSecMode->fd, table->access->fb_id);
1015         }
1016
1017         if (table->access->bo)
1018             tbm_bo_unref (table->access->bo);
1019
1020         free (table->access);
1021         table->access = NULL;
1022     }
1023
1024     table->in_use = FALSE;
1025     table->onoff = TRUE;
1026
1027     XDBG_TRACE (MPLN, "plane(%d).\n", table->plane_id);
1028 }
1029
1030 Bool
1031 secPlaneTrun (int plane_id, Bool onoff, Bool user)
1032 {
1033     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1034     SECPtr pSec;
1035
1036     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1037
1038     pSec = SECPTR (table->pPlanePriv->pScrn);
1039
1040     if (pSec->isLcdOff)
1041         return TRUE;
1042
1043     onoff = (onoff > 0) ? TRUE : FALSE;
1044
1045     if (table->onoff == onoff)
1046         return TRUE;
1047
1048     if (onoff)
1049     {
1050         table->onoff = onoff;
1051
1052         if (!table->visible)
1053         {
1054             if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
1055                                         &table->src, &table->dst, table->zpos, TRUE))
1056
1057             {
1058                 XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n");
1059             }
1060
1061             XDBG_DEBUG (MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", (user)?"user":"Xorg",
1062                         plane_id, table->crtc_id, table->zpos, (onoff)?"ON":"OFF");
1063         }
1064     }
1065     else
1066     {
1067         if (table->visible)
1068         {
1069             if (!_secPlaneHideInternal (table))
1070
1071             {
1072                 XDBG_WARNING (MPLN, "_secPlaneHideInternal failed. \n");
1073             }
1074
1075             XDBG_DEBUG (MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", (user)?"user":"Xorg",
1076                         plane_id, table->crtc_id, table->zpos, (onoff)?"ON":"OFF");
1077         }
1078
1079         table->onoff = onoff;
1080     }
1081
1082     return TRUE;
1083 }
1084
1085 Bool
1086 secPlaneTrunStatus (int plane_id)
1087 {
1088     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1089
1090     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1091
1092     return table->onoff;
1093 }
1094
1095 void
1096 secPlaneFreezeUpdate (int plane_id, Bool enable)
1097 {
1098     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1099
1100     XDBG_RETURN_IF_FAIL (table != NULL);
1101
1102     table->freeze_update = enable;
1103 }
1104
1105 Bool
1106 secPlaneRemoveBuffer (int plane_id, int fb_id)
1107 {
1108     SECPlaneTable *table;
1109     SECPlaneFb *fb;
1110
1111     XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE);
1112
1113     table = _secPlaneTableFind (plane_id);
1114     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1115
1116     fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
1117     XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE);
1118
1119     _secPlaneTableFreeBuffer (table, fb);
1120
1121     XDBG_TRACE (MPLN, "plane(%d) fb(%d). \n", plane_id, fb_id);
1122
1123     return TRUE;
1124 }
1125
1126 int
1127 secPlaneAddBo (int plane_id, tbm_bo bo)
1128 {
1129     SECPlaneTable *table;
1130     SECPlaneFb *fb;
1131     int fb_id = 0;
1132     SECFbBoDataPtr bo_data = NULL;
1133     int width, height;
1134
1135     XDBG_RETURN_VAL_IF_FAIL (bo != NULL, 0);
1136
1137     table = _secPlaneTableFind (plane_id);
1138     XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
1139
1140     fb = _secPlaneTableFindBuffer (table, 0, bo, NULL);
1141     XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0);
1142
1143     tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void**)&bo_data);
1144     XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, 0);
1145
1146     fb_id = bo_data->fb_id;
1147     width = bo_data->pos.x2 - bo_data->pos.x1;
1148     height = bo_data->pos.y2 - bo_data->pos.y1;
1149
1150     XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, 0);
1151     XDBG_RETURN_VAL_IF_FAIL (width > 0, 0);
1152     XDBG_RETURN_VAL_IF_FAIL (height > 0, 0);
1153
1154     fb = calloc (1, sizeof (SECPlaneFb));
1155     XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0);
1156
1157     xorg_list_add(&fb->link, &table->fbs);
1158
1159     fb->type = PLANE_FB_TYPE_BO;
1160     fb->id = fb_id;
1161     fb->width = width;
1162     fb->height = height;
1163
1164     fb->buffer.bo = tbm_bo_ref (bo);
1165
1166     XDBG_TRACE (MPLN, "plane(%d) bo(%d,%dx%d)\n", plane_id,
1167                 fb_id, fb->width, fb->height);
1168
1169     return fb->id;
1170 }
1171
1172 int
1173 secPlaneAddBuffer (int plane_id, SECVideoBuf *vbuf)
1174 {
1175     SECPlaneTable *table;
1176     SECPlaneFb *fb;
1177
1178     XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0);
1179     XDBG_RETURN_VAL_IF_FAIL (vbuf->fb_id > 0, 0);
1180     XDBG_RETURN_VAL_IF_FAIL (vbuf->width > 0, 0);
1181     XDBG_RETURN_VAL_IF_FAIL (vbuf->height > 0, 0);
1182
1183     table = _secPlaneTableFind (plane_id);
1184     XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
1185
1186     fb = _secPlaneTableFindBuffer (table, 0, NULL, vbuf);
1187     XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0);
1188
1189     fb = calloc (1, sizeof (SECPlaneFb));
1190     XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0);
1191
1192     xorg_list_add(&fb->link, &table->fbs);
1193
1194     fb->type = PLANE_FB_TYPE_DEFAULT;
1195     fb->id = vbuf->fb_id;
1196     fb->width = vbuf->width;
1197     fb->height = vbuf->height;
1198
1199     fb->buffer.vbuf = vbuf;
1200
1201     secUtilAddFreeVideoBufferFunc (vbuf, _secPlaneFreeVbuf, (void*)plane_id);
1202
1203     XDBG_TRACE (MPLN, "plane(%d) vbuf(%ld,%d,%dx%d)\n", plane_id,
1204                 vbuf->stamp, vbuf->fb_id, vbuf->width, vbuf->height);
1205
1206     return fb->id;
1207 }
1208
1209 int
1210 secPlaneGetBuffer (int plane_id, tbm_bo bo, SECVideoBuf *vbuf)
1211 {
1212     SECPlaneTable *table;
1213     SECPlaneFb *fb;
1214
1215     table = _secPlaneTableFind (plane_id);
1216     XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
1217
1218     fb = _secPlaneTableFindBuffer (table, 0, bo, vbuf);
1219     if (!fb)
1220         return 0;
1221
1222     return fb->id;
1223 }
1224
1225 void
1226 secPlaneGetBufferSize (int plane_id, int fb_id, int *width, int *height)
1227 {
1228     SECPlaneTable *table;
1229     SECPlaneFb *fb;
1230
1231     table = _secPlaneTableFind (plane_id);
1232     XDBG_RETURN_IF_FAIL (table != NULL);
1233
1234     fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
1235     XDBG_RETURN_IF_FAIL (fb != NULL);
1236
1237     if (width)
1238         *width = fb->width;
1239
1240     if (height)
1241         *height = fb->height;
1242 }
1243
1244 Bool
1245 secPlaneAttach (int plane_id, int fb_id)
1246 {
1247     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1248     SECPlaneFb *fb;
1249
1250     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1251     XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE);
1252
1253     fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
1254     XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE);
1255
1256     table->cur_fb = fb;
1257
1258     XDBG_DEBUG (MPLN, "plane(%d) fb(%d)\n", plane_id, fb_id);
1259
1260     return TRUE;
1261 }
1262
1263 Bool
1264 secPlaneIsVisible (int plane_id)
1265 {
1266     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1267
1268     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1269
1270     return table->visible;
1271 }
1272
1273 Bool
1274 secPlaneShow (int plane_id, int crtc_id,
1275               int src_x, int src_y, int src_w, int src_h,
1276               int dst_x, int dst_y, int dst_w, int dst_h,
1277               int zpos, Bool need_update)
1278 {
1279     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1280     SECPlaneTable *temp;
1281     xRectangle src = {src_x, src_y, src_w, src_h};
1282     xRectangle dst = {dst_x, dst_y, dst_w, dst_h};
1283
1284     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1285     XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE);
1286     XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, FALSE);
1287     XDBG_RETURN_VAL_IF_FAIL (zpos >= 0, FALSE);
1288
1289     temp = _secPlaneTableFindPos (crtc_id, zpos);
1290
1291     if (temp && temp->plane_id != plane_id)
1292     {
1293         XDBG_ERROR (MPLN, "can't change zpos. plane(%d) is at zpos(%d) crtc(%d) \n",
1294                     temp->plane_id, temp->zpos, crtc_id);
1295         return FALSE;
1296     }
1297
1298     if (!table->visible)
1299         table->crtc_id = crtc_id;
1300     else if (table->crtc_id != crtc_id)
1301     {
1302         XDBG_ERROR (MPLN, "can't change crtc. plane(%d) is on crtc(%d) \n",
1303                     table->plane_id, table->zpos);
1304         return FALSE;
1305     }
1306
1307     if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
1308                                 &src, &dst, zpos, need_update))
1309     {
1310         return FALSE;
1311     }
1312
1313     return TRUE;
1314 }
1315
1316 Bool
1317 secPlaneHide (int plane_id)
1318 {
1319     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1320
1321     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1322
1323     if (!table->visible)
1324         return TRUE;
1325
1326     XDBG_TRACE (MPLN, "plane(%d) crtc(%d)\n", table->plane_id, table->crtc_id);
1327
1328     _secPlaneHideInternal (table);
1329
1330     return TRUE;
1331 }
1332
1333 Bool
1334 secPlaneMove (int plane_id, int x, int y)
1335 {
1336     SECPlaneTable *table = _secPlaneTableFind (plane_id);
1337     xRectangle dst;
1338
1339     XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1340     XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE);
1341
1342     dst.x = x;
1343     dst.y = y;
1344     dst.width = table->dst.width;
1345     dst.height = table->dst.height;
1346
1347     if (table->visible && !table->freeze_update)
1348         if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
1349                                     &table->src, &dst, table->zpos, FALSE))
1350         {
1351             return FALSE;
1352         }
1353
1354     XDBG_TRACE (MPLN, "plane(%d) moved to (%d,%d)\n", table->plane_id, x, y);
1355
1356     return TRUE;
1357 }
1358
1359 char*
1360 secPlaneDump (char *reply, int *len)
1361 {
1362     Bool in_use = FALSE;
1363     int i;
1364
1365     for (i = 0; i < plane_table_size; i++)
1366         if (plane_table[i].in_use)
1367         {
1368             in_use = TRUE;
1369             break;
1370         }
1371
1372     if (!in_use)
1373         return reply;
1374
1375     XDBG_REPLY ("=================================================\n");
1376     XDBG_REPLY ("plane\tcrtc\tpos\tvisible\tonoff\tfb(w,h)\tsrc\t\tdst\n");
1377
1378     for (i = 0; i < plane_table_size; i++)
1379     {
1380         if (plane_table[i].in_use)
1381             XDBG_REPLY ("%d\t%d\t%d\t%d\t%d\t%d(%dx%d)\t%d,%d %dx%d\t%d,%d %dx%d\n",
1382                         plane_table[i].plane_id,
1383                         plane_table[i].crtc_id, plane_table[i].zpos,
1384                         plane_table[i].visible,
1385                         plane_table[i].onoff,
1386                         (plane_table[i].cur_fb)?plane_table[i].cur_fb->id:0,
1387                         (plane_table[i].cur_fb)?plane_table[i].cur_fb->width:0,
1388                         (plane_table[i].cur_fb)?plane_table[i].cur_fb->height:0,
1389                         plane_table[i].src.x, plane_table[i].src.y,
1390                         plane_table[i].src.width, plane_table[i].src.height,
1391                         plane_table[i].dst.x, plane_table[i].dst.y,
1392                         plane_table[i].dst.width, plane_table[i].dst.height);
1393     }
1394
1395     XDBG_REPLY ("=================================================\n");
1396
1397     return reply;
1398 }