1 /**************************************************************************
3 xserver-xorg-video-exynos
5 Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>
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:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
35 #include <sys/ioctl.h>
37 #include <sys/types.h>
44 #include <xorgVersion.h>
45 #include <tbm_bufmgr.h>
50 #include <X11/Xatom.h>
51 #include <X11/extensions/dpmsconst.h>
56 #include "sec_output.h"
58 #include "sec_video_fourcc.h"
59 #include "sec_plane.h"
69 PLANE_FB_TYPE_DEFAULT,
74 typedef struct _SECPlaneAccess
87 /* This is structure to manage a added buffer. */
88 typedef struct _SECPlaneFb
105 struct xorg_list link;
108 typedef struct _SECPlaneTable
110 SECPlanePrivPtr pPlanePriv;
113 /* buffers which this plane has */
114 struct xorg_list fbs;
117 /* visibilitiy information */
130 SECPlaneAccess *access;
133 /* table of planes which system has entirely */
134 static SECPlaneTable *plane_table;
135 static int plane_table_size;
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);
143 _secPlaneFreeVbuf (SECVideoBuf *vbuf, void *data)
145 int plane_id = (int)data;
146 SECPlaneTable *table;
149 table = _secPlaneTableFind (plane_id);
150 XDBG_RETURN_IF_FAIL (table != NULL);
152 fb = _secPlaneTableFindBuffer (table, vbuf->fb_id, NULL, NULL);
153 XDBG_RETURN_IF_FAIL (fb != NULL);
155 fb->buffer_gone = TRUE;
156 secPlaneRemoveBuffer (plane_id, vbuf->fb_id);
159 static SECPlaneTable*
160 _secPlaneTableFindPos (int crtc_id, int zpos)
164 XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, NULL);
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];
173 static SECPlaneTable*
174 _secPlaneTableFind (int plane_id)
178 XDBG_RETURN_VAL_IF_FAIL (plane_id > 0, NULL);
180 for (i = 0; i < plane_table_size; i++)
181 if (plane_table[i].plane_id == plane_id)
182 return &plane_table[i];
184 XDBG_TRACE (MPLN, "plane(%d) not found. \n", plane_id);
189 static SECPlaneTable*
190 _secPlaneTableFindEmpty (void)
194 for (i = 0; i < plane_table_size; i++)
195 if (!plane_table[i].in_use)
196 return &plane_table[i];
202 _secPlaneTableFindBuffer (SECPlaneTable *table,
207 SECPlaneFb *fb = NULL, *fb_next = NULL;
209 xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link)
218 if (fb->type == PLANE_FB_TYPE_BO && fb->buffer.bo == bo)
223 XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), NULL);
225 if (fb->type == PLANE_FB_TYPE_DEFAULT)
226 if (fb->buffer.vbuf == vbuf && fb->buffer.vbuf->stamp == vbuf->stamp)
235 _secPlaneTableFreeBuffer (SECPlaneTable *table, SECPlaneFb *fb)
237 if (table->cur_fb == fb)
240 if (fb->type == PLANE_FB_TYPE_BO)
243 tbm_bo_unref (fb->buffer.bo);
247 if (!fb->buffer_gone && fb->buffer.vbuf)
248 secUtilRemoveFreeVideoBufferFunc (fb->buffer.vbuf, _secPlaneFreeVbuf,
249 (void*)table->plane_id);
252 xorg_list_del (&fb->link);
258 _secPlaneTableEnsure (ScrnInfoPtr pScrn, int count_planes)
262 XDBG_RETURN_VAL_IF_FAIL (count_planes > 0, FALSE);
266 if (plane_table_size != count_planes)
267 XDBG_WARNING (MPLN, "%d != %d, need to re-create! \n",
268 plane_table_size, count_planes);
272 plane_table = calloc (sizeof (SECPlaneTable), count_planes);
273 XDBG_RETURN_VAL_IF_FAIL (plane_table != NULL, FALSE);
275 plane_table_size = count_planes;
277 for (i = 0; i < plane_table_size; i++)
279 SECPlaneTable *table = &plane_table[i];
280 table->plane_id = -1;
288 _secPlaneExecAccessibility (tbm_bo src_bo, int sw, int sh, xRectangle *sr,
289 tbm_bo dst_bo, int dw, int dh, xRectangle *dr,
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;
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);
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);
304 srcImg = g2d_image_create_bo (mode, sw, sh, src_bo_handle.s32, sw * 4);
305 XDBG_GOTO_IF_FAIL (srcImg != NULL, access_done);
307 dstImg = g2d_image_create_bo (mode, dw, dh, dst_bo_handle.s32, dw * 4);
308 XDBG_GOTO_IF_FAIL (dstImg != NULL, access_done);
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,
317 if (src_bo_handle.s32)
318 tbm_bo_unmap (src_bo);
319 if (dst_bo_handle.s32)
320 tbm_bo_unmap (dst_bo);
322 g2d_image_free (srcImg);
324 g2d_image_free (dstImg);
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)
332 /* Kernel manage CRTC status based out output config */
333 xf86CrtcPtr pCrtc = secCrtcGetByID(pScrn, crtc_id);
336 XDBG_ERROR(MPLN, "Can't found crtc_id(%d)\n", crtc_id);
339 if (!pCrtc->enabled && !pCrtc->active)
341 XDBG_ERROR(MPLN, "Current crtc_id(%d) not active\n", crtc_id);
345 int max_w = pCrtc->mode.CrtcHDisplay;
346 int max_h = pCrtc->mode.CrtcVDisplay;
347 if (max_w == 0 || max_h == 0)
349 max_w = pScrn->virtualX;
350 max_h = pScrn->virtualY;
352 if (buf_w < MIN_WIDTH || buf_w % 2)
354 XDBG_TRACE (MPLN, "hide: buf_w(%d) not 2's multiple or less than %d\n",
359 if (buf_h < MIN_HEIGHT)
361 XDBG_TRACE (MPLN, "hide: buf_h(%d) less than %d\n",
366 if (src_x > dst_x || ((dst_x - src_x) + buf_w) > max_w)
367 virtual_screen = TRUE;
369 virtual_screen = FALSE;
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);
376 /* check window minimum width / height */
377 if (((aligned_dst->width - aligned_dst->x) < MIN_WIDTH) || ((aligned_dst->height - aligned_dst->y) < MIN_HEIGHT))
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,
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);
392 aligned_dst->width = (aligned_dst->width - aligned_dst->x) & (~0x1);
393 aligned_dst->height = (aligned_dst->height - aligned_dst->y);
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);
400 if (((aligned_src->width - aligned_src->x) < MIN_WIDTH) || ((aligned_src->height - aligned_src->y) < MIN_HEIGHT))
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,
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);
415 aligned_src->width = (aligned_src->width - aligned_src->x) & (~0x1);
416 aligned_src->height = (aligned_src->height - aligned_src->y);
420 /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
421 if ((end_dst - start_dst) % 2)
426 /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
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;
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);
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)))
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);
463 _secPlaneShowInternal (SECPlaneTable *table,
464 SECPlaneFb *old_fb, SECPlaneFb *new_fb,
465 xRectangle *new_src, xRectangle *new_dst, int new_zpos,
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;
476 pSec = SECPTR (table->pPlanePriv->pScrn);
477 pSecMode = table->pPlanePriv->pSecMode;
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);
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);
493 /* should set zpos before doing drmModeSetPlane */
494 if (new_zpos != old_zpos)
496 if (!secUtilSetDrmProperty (pSecMode, table->plane_id, DRM_MODE_OBJECT_PLANE,
500 table->zpos = new_zpos;
503 XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) zpos(%d)\n",
504 table->plane_id, table->crtc_id, table->zpos);
507 if (!table->visible || need_set_plane ||
509 (!old_fb || (old_fb != new_fb)) ||
510 (memcmp (&old_src, new_src, sizeof (xRectangle))) ||
511 (memcmp (&old_dst, new_dst, sizeof (xRectangle))))
513 xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (table->pPlanePriv->pScrn);
514 SECCrtcPrivPtr pCrtcPriv = NULL;
517 for (c = 0; c < pCrtcConfig->num_crtc; c++)
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)
528 XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
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));
537 if (!pCrtcPriv->bAccessibility ||
538 (new_fb->type == PLANE_FB_TYPE_DEFAULT && new_fb->buffer.vbuf->id != FOURCC_RGB32))
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;
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,
551 &aligned_src, &aligned_dst))
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);
559 _secPlaneHideInternal (table);
564 /* Source values are 16.16 fixed point */
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;
571 if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id,
573 aligned_dst.x, aligned_dst.y,
574 aligned_dst.width, aligned_dst.height,
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);
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;
601 SECPlaneAccess *access;
602 xRectangle fb_src = {0,};
604 int old_w = 0, old_h = 0;
608 table->access = calloc (1, sizeof (SECPlaneAccess));
609 XDBG_RETURN_VAL_IF_FAIL (table->access != NULL, FALSE);
613 old_w = table->access->width;
614 old_h = table->access->height;
617 access = table->access;
619 if (pCrtcPriv->bScale)
621 float h_ratio = 0.0, v_ratio = 0.0;
624 h_ratio = (float)pCrtcPriv->kmode.hdisplay / pCrtcPriv->sw;
625 v_ratio = (float)pCrtcPriv->kmode.vdisplay / pCrtcPriv->sh;
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;
633 crop.x = pCrtcPriv->sx;
634 crop.y = pCrtcPriv->sy;
635 crop.width = pCrtcPriv->sw;
636 crop.height = pCrtcPriv->sh;
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);
644 access->dst = *new_dst;
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;
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);
658 access->dst.x -= pCrtcPriv->sx;
659 access->dst.y -= pCrtcPriv->sy;
661 access->dst.x *= h_ratio;
662 access->dst.y *= v_ratio;
663 access->dst.width *= h_ratio;
664 access->dst.height *= v_ratio;
666 access->width = pCrtcPriv->kmode.hdisplay;
667 access->height = pCrtcPriv->kmode.vdisplay;
671 access->src.width = access->dst.width;
672 access->src.height = access->dst.height;
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;
681 /* hw restriction: 8 bytes */
682 new_dst->width &= ~1;
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;
689 access->width = access->dst.width;
690 access->height = access->dst.height;
694 access->src.width = access->dst.width;
695 access->src.height = access->dst.height;
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);
706 if (!fb_src.width || !fb_src.height ||
707 !access->width || !access->height ||
708 !access->dst.width || !access->dst.height)
710 _secPlaneHideInternal (table);
717 if (old_w != access->width || old_h != access->height)
719 if (table->access->fb_id)
721 drmModeRmFB (pSecMode->fd, table->access->fb_id);
722 table->access->fb_id = 0;
725 tbm_bo_unref (table->access->bo);
726 table->access->bo = NULL;
732 access->bo = tbm_bo_alloc (pSec->tbm_bufmgr,
733 access->width * access->height * 4,
735 XDBG_RETURN_VAL_IF_FAIL (access->bo != NULL, FALSE);
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,
745 XDBG_ERRNO (MPLN, "drmModeAddFB failed. plane(%d)\n", table->plane_id);
749 XDBG_RETURN_VAL_IF_FAIL (access->fb_id > 0, FALSE);
752 if (new_fb->type == PLANE_FB_TYPE_DEFAULT)
753 src_bo = new_fb->buffer.vbuf->bo[0];
755 src_bo = new_fb->buffer.bo;
756 XDBG_RETURN_VAL_IF_FAIL (src_bo != NULL, FALSE);
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))
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);
774 _secPlaneHideInternal (table);
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;
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);
789 if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id,
791 aligned_dst.x, aligned_dst.y,
792 aligned_dst.width, aligned_dst.height,
796 XDBG_ERRNO (MPLN, "drmModeSetPlane failed. \n");
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;
811 memcpy (&table->src, new_src, sizeof (xRectangle));
812 memcpy (&table->dst, new_dst, sizeof (xRectangle));
819 _secPlaneHideInternal (SECPlaneTable *table)
824 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
829 XDBG_RETURN_VAL_IF_FAIL (table->crtc_id > 0, FALSE);
831 pSec = SECPTR (table->pPlanePriv->pScrn);
832 pSecMode = table->pPlanePriv->pSecMode;
834 if (!pSec->isLcdOff && table->onoff)
836 if (drmModeSetPlane (pSecMode->fd,
840 0, 0, 0, 0, 0, 0, 0, 0))
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);
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;
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");
866 secPlaneInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num)
868 SECPlanePrivPtr pPlanePriv;
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);
875 if (!_secPlaneTableEnsure (pScrn, pSecMode->plane_res->count_planes))
878 pPlanePriv = calloc (sizeof (SECPlanePrivRec), 1);
879 XDBG_RETURN_IF_FAIL (pPlanePriv != NULL);
881 pPlanePriv->mode_plane = drmModeGetPlane (pSecMode->fd,
882 pSecMode->plane_res->planes[num]);
883 if (!pPlanePriv->mode_plane)
885 XDBG_ERRNO (MPLN, "drmModeGetPlane failed. plane(%d)\n",
886 pSecMode->plane_res->planes[num]);
892 pPlanePriv->pScrn = pScrn;
893 pPlanePriv->pSecMode = pSecMode;
894 pPlanePriv->plane_id = pPlanePriv->mode_plane->plane_id;
896 plane_table[num].plane_id = pPlanePriv->plane_id;
897 plane_table[num].pPlanePriv = pPlanePriv;
898 xorg_list_init (&plane_table[num].fbs);
900 xorg_list_add(&pPlanePriv->link, &pSecMode->planes);
904 secPlaneDeinit (ScrnInfoPtr pScrn, SECPlanePrivPtr pPlanePriv)
908 XDBG_RETURN_IF_FAIL (pScrn != NULL);
909 XDBG_RETURN_IF_FAIL (pPlanePriv != NULL);
911 secPlaneFreeId (pPlanePriv->plane_id);
912 drmModeFreePlane (pPlanePriv->mode_plane);
913 xorg_list_del (&pPlanePriv->link);
915 for (i = 0; i < plane_table_size; i++)
916 if (plane_table[i].plane_id == pPlanePriv->plane_id)
918 plane_table[i].plane_id = -1;
926 for (i = 0; i < plane_table_size; i++)
927 if (plane_table[i].plane_id != -1)
932 plane_table_size = 0;
933 XDBG_TRACE (MPLN, "plane_table destroyed. %d\n", plane_table_size);
938 secPlaneShowAll (int crtc_id)
942 XDBG_TRACE (MPLN, "crtc(%d) \n", crtc_id);
944 for (i = 0; i < plane_table_size; i++)
946 SECPlaneTable *table = &plane_table[i];
948 if (!table || !table->in_use || !table->visible || !table->onoff)
951 if (table->crtc_id != crtc_id)
954 if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
955 &table->src, &table->dst, table->zpos, TRUE))
958 XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n");
961 XDBG_TRACE (MPLN, "plane(%d) crtc(%d) zpos(%d) on.\n",
962 table->plane_id, table->crtc_id, table->zpos);
969 SECPlaneTable *table = _secPlaneTableFindEmpty ();
973 XDBG_ERROR (MPLN, "No avaliable plane ID. %d\n", -1);
977 table->in_use = TRUE;
980 XDBG_TRACE (MPLN, "plane(%d). \n", table->plane_id);
982 return table->plane_id;
986 secPlaneFreeId (int plane_id)
988 SECPlaneTable *table = _secPlaneTableFind (plane_id);
989 SECPlaneFb *fb = NULL, *fb_next = NULL;
991 XDBG_RETURN_IF_FAIL (table != NULL);
993 secPlaneHide (table->plane_id);
995 table->visible = FALSE;
999 memset (&table->src, 0x00, sizeof (xRectangle));
1000 memset (&table->dst, 0x00, sizeof (xRectangle));
1002 table->cur_fb = NULL;
1003 xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link)
1005 _secPlaneTableFreeBuffer (table, fb);
1010 if (table->access->fb_id)
1012 SECModePtr pSecMode = table->pPlanePriv->pSecMode;
1014 drmModeRmFB (pSecMode->fd, table->access->fb_id);
1017 if (table->access->bo)
1018 tbm_bo_unref (table->access->bo);
1020 free (table->access);
1021 table->access = NULL;
1024 table->in_use = FALSE;
1025 table->onoff = TRUE;
1027 XDBG_TRACE (MPLN, "plane(%d).\n", table->plane_id);
1031 secPlaneTrun (int plane_id, Bool onoff, Bool user)
1033 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1036 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1038 pSec = SECPTR (table->pPlanePriv->pScrn);
1043 onoff = (onoff > 0) ? TRUE : FALSE;
1045 if (table->onoff == onoff)
1050 table->onoff = onoff;
1052 if (!table->visible)
1054 if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
1055 &table->src, &table->dst, table->zpos, TRUE))
1058 XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n");
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");
1069 if (!_secPlaneHideInternal (table))
1072 XDBG_WARNING (MPLN, "_secPlaneHideInternal failed. \n");
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");
1079 table->onoff = onoff;
1086 secPlaneTrunStatus (int plane_id)
1088 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1090 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1092 return table->onoff;
1096 secPlaneFreezeUpdate (int plane_id, Bool enable)
1098 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1100 XDBG_RETURN_IF_FAIL (table != NULL);
1102 table->freeze_update = enable;
1106 secPlaneRemoveBuffer (int plane_id, int fb_id)
1108 SECPlaneTable *table;
1111 XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE);
1113 table = _secPlaneTableFind (plane_id);
1114 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1116 fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
1117 XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE);
1119 _secPlaneTableFreeBuffer (table, fb);
1121 XDBG_TRACE (MPLN, "plane(%d) fb(%d). \n", plane_id, fb_id);
1127 secPlaneAddBo (int plane_id, tbm_bo bo)
1129 SECPlaneTable *table;
1132 SECFbBoDataPtr bo_data = NULL;
1135 XDBG_RETURN_VAL_IF_FAIL (bo != NULL, 0);
1137 table = _secPlaneTableFind (plane_id);
1138 XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
1140 fb = _secPlaneTableFindBuffer (table, 0, bo, NULL);
1141 XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0);
1143 tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void**)&bo_data);
1144 XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, 0);
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;
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);
1154 fb = calloc (1, sizeof (SECPlaneFb));
1155 XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0);
1157 xorg_list_add(&fb->link, &table->fbs);
1159 fb->type = PLANE_FB_TYPE_BO;
1162 fb->height = height;
1164 fb->buffer.bo = tbm_bo_ref (bo);
1166 XDBG_TRACE (MPLN, "plane(%d) bo(%d,%dx%d)\n", plane_id,
1167 fb_id, fb->width, fb->height);
1173 secPlaneAddBuffer (int plane_id, SECVideoBuf *vbuf)
1175 SECPlaneTable *table;
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);
1183 table = _secPlaneTableFind (plane_id);
1184 XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
1186 fb = _secPlaneTableFindBuffer (table, 0, NULL, vbuf);
1187 XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0);
1189 fb = calloc (1, sizeof (SECPlaneFb));
1190 XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0);
1192 xorg_list_add(&fb->link, &table->fbs);
1194 fb->type = PLANE_FB_TYPE_DEFAULT;
1195 fb->id = vbuf->fb_id;
1196 fb->width = vbuf->width;
1197 fb->height = vbuf->height;
1199 fb->buffer.vbuf = vbuf;
1201 secUtilAddFreeVideoBufferFunc (vbuf, _secPlaneFreeVbuf, (void*)plane_id);
1203 XDBG_TRACE (MPLN, "plane(%d) vbuf(%ld,%d,%dx%d)\n", plane_id,
1204 vbuf->stamp, vbuf->fb_id, vbuf->width, vbuf->height);
1210 secPlaneGetBuffer (int plane_id, tbm_bo bo, SECVideoBuf *vbuf)
1212 SECPlaneTable *table;
1215 table = _secPlaneTableFind (plane_id);
1216 XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
1218 fb = _secPlaneTableFindBuffer (table, 0, bo, vbuf);
1226 secPlaneGetBufferSize (int plane_id, int fb_id, int *width, int *height)
1228 SECPlaneTable *table;
1231 table = _secPlaneTableFind (plane_id);
1232 XDBG_RETURN_IF_FAIL (table != NULL);
1234 fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
1235 XDBG_RETURN_IF_FAIL (fb != NULL);
1241 *height = fb->height;
1245 secPlaneAttach (int plane_id, int fb_id)
1247 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1250 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1251 XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE);
1253 fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
1254 XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE);
1258 XDBG_DEBUG (MPLN, "plane(%d) fb(%d)\n", plane_id, fb_id);
1264 secPlaneIsVisible (int plane_id)
1266 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1268 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1270 return table->visible;
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)
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};
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);
1289 temp = _secPlaneTableFindPos (crtc_id, zpos);
1291 if (temp && temp->plane_id != plane_id)
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);
1298 if (!table->visible)
1299 table->crtc_id = crtc_id;
1300 else if (table->crtc_id != crtc_id)
1302 XDBG_ERROR (MPLN, "can't change crtc. plane(%d) is on crtc(%d) \n",
1303 table->plane_id, table->zpos);
1307 if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
1308 &src, &dst, zpos, need_update))
1317 secPlaneHide (int plane_id)
1319 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1321 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1323 if (!table->visible)
1326 XDBG_TRACE (MPLN, "plane(%d) crtc(%d)\n", table->plane_id, table->crtc_id);
1328 _secPlaneHideInternal (table);
1334 secPlaneMove (int plane_id, int x, int y)
1336 SECPlaneTable *table = _secPlaneTableFind (plane_id);
1339 XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
1340 XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE);
1344 dst.width = table->dst.width;
1345 dst.height = table->dst.height;
1347 if (table->visible && !table->freeze_update)
1348 if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
1349 &table->src, &dst, table->zpos, FALSE))
1354 XDBG_TRACE (MPLN, "plane(%d) moved to (%d,%d)\n", table->plane_id, x, y);
1360 secPlaneDump (char *reply, int *len)
1362 Bool in_use = FALSE;
1365 for (i = 0; i < plane_table_size; i++)
1366 if (plane_table[i].in_use)
1375 XDBG_REPLY ("=================================================\n");
1376 XDBG_REPLY ("plane\tcrtc\tpos\tvisible\tonoff\tfb(w,h)\tsrc\t\tdst\n");
1378 for (i = 0; i < plane_table_size; i++)
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);
1395 XDBG_REPLY ("=================================================\n");