2 * OS/2 video output driver
4 * Copyright (c) 2007-2009 by KO Myung-Hun (komh@chollian.net)
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 #include "video_out.h"
41 #include "video_out_internal.h"
44 #include "fastmemcpy.h"
46 #include "osdep/keycodes.h"
47 #include "input/input.h"
48 #include "input/mouse.h"
49 #include "subopt-helper.h"
52 #include "cpudetect.h"
53 #include "libswscale/swscale.h"
54 #include "libmpcodecs/vf_scale.h"
56 static const vo_info_t info
= {
57 "SNAP/WarpOverlay!/DIVE video output",
59 "KO Myung-Hun <komh@chollian.net>",
63 const LIBVO_EXTERN(kva
)
65 #define WC_MPLAYER "WC_MPLAYER"
67 #define SRC_WIDTH m_int.kvas.szlSrcSize.cx
68 #define SRC_HEIGHT m_int.kvas.szlSrcSize.cy
70 #define HWNDFROMWINID(wid) ((wid) + 0x80000000UL)
72 static const struct mp_keymap m_vk_map
[] = {
73 {VK_NEWLINE
, KEY_ENTER
}, {VK_TAB
, KEY_TAB
}, {VK_SPACE
, ' '},
76 {VK_CTRL
, KEY_CTRL
}, {VK_BACKSPACE
, KEY_BS
},
77 {VK_DELETE
, KEY_DELETE
}, {VK_INSERT
, KEY_INSERT
},
78 {VK_HOME
, KEY_HOME
}, {VK_END
, KEY_END
},
79 {VK_PAGEUP
, KEY_PAGE_UP
}, {VK_PAGEDOWN
, KEY_PAGE_DOWN
},
83 {VK_RIGHT
, KEY_RIGHT
}, {VK_LEFT
, KEY_LEFT
},
84 {VK_DOWN
, KEY_DOWN
}, {VK_UP
, KEY_UP
},
87 {VK_F1
, KEY_F
+1}, {VK_F2
, KEY_F
+2}, {VK_F3
, KEY_F
+3}, {VK_F4
, KEY_F
+4},
88 {VK_F5
, KEY_F
+5}, {VK_F6
, KEY_F
+6}, {VK_F7
, KEY_F
+7}, {VK_F8
, KEY_F
+8},
89 {VK_F9
, KEY_F
+9}, {VK_F10
, KEY_F
+10}, {VK_F11
, KEY_F
+11}, {VK_F12
, KEY_F
+12},
94 static const struct mp_keymap m_keypad_map
[] = {
96 {0x52, KEY_KP0
}, {0x4F, KEY_KP1
}, {0x50, KEY_KP2
}, {0x51, KEY_KP3
},
97 {0x4B, KEY_KP4
}, {0x4C, KEY_KP5
}, {0x4D, KEY_KP6
}, {0x47, KEY_KP7
},
98 {0x48, KEY_KP8
}, {0x49, KEY_KP9
}, {0x53, KEY_KPDEC
}, {0x5A, KEY_KPENTER
},
103 static const struct mp_keymap m_mouse_map
[] = {
104 {WM_BUTTON1DOWN
, MOUSE_BTN0
},
105 {WM_BUTTON3DOWN
, MOUSE_BTN1
},
106 {WM_BUTTON2DOWN
, MOUSE_BTN2
},
107 {WM_BUTTON1DBLCLK
, MOUSE_BTN0_DBL
},
108 {WM_BUTTON3DBLCLK
, MOUSE_BTN1_DBL
},
109 {WM_BUTTON2DBLCLK
, MOUSE_BTN2_DBL
},
133 uint8_t *planes
[MP_MAX_PLANES
]; // y = 0, u = 1, v = 2
134 int stride
[MP_MAX_PLANES
];
137 struct SwsContext
*sws
;
140 static inline void setAspectRatio(ULONG ulRatio
)
142 m_int
.kvas
.ulRatio
= ulRatio
;
143 kvaSetup(&m_int
.kvas
);
146 static int query_format_info(int format
, PBOOL pfHWAccel
, PFOURCC pfcc
,
147 int *pbpp
, int *pnChromaShift
)
156 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_YV12
;
163 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_YUY2
;
170 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_YVU9
;
177 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR24
;
184 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR16
;
191 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR15
;
202 *pfHWAccel
= fHWAccel
;
211 *pnChromaShift
= nChromaShift
;
216 static void imgCreate(void)
218 int size
= SRC_HEIGHT
* m_int
.lStride
;;
220 switch (m_int
.iImageFormat
) {
230 m_int
.pbImage
= malloc(size
);
232 memset(m_int
.planes
, 0, sizeof(m_int
.planes
));
233 memset(m_int
.stride
, 0, sizeof(m_int
.stride
));
234 m_int
.planes
[0] = m_int
.pbImage
;
235 m_int
.stride
[0] = m_int
.lStride
;
238 if (m_int
.nChromaShift
) {
239 m_int
.planes
[1] = m_int
.planes
[0] + SRC_HEIGHT
* m_int
.stride
[0];
240 m_int
.stride
[1] = m_int
.stride
[0] >> m_int
.nChromaShift
;
242 m_int
.planes
[2] = m_int
.planes
[1] +
243 (SRC_HEIGHT
>> m_int
.nChromaShift
) * m_int
.stride
[1];
244 m_int
.stride
[2] = m_int
.stride
[1];
248 static void imgFree(void)
252 m_int
.pbImage
= NULL
;
255 static void imgDisplay(void)
260 if (!kvaLockBuffer(&pBuffer
, &ulBPL
)) {
261 uint8_t *dst
[MP_MAX_PLANES
] = {NULL
};
262 int dstStride
[MP_MAX_PLANES
] = {0};
266 dstStride
[0] = ulBPL
;
269 if (m_int
.nChromaShift
) {
271 dst
[2] = dst
[0] + SRC_HEIGHT
* dstStride
[0];
272 dstStride
[2] = dstStride
[0] >> m_int
.nChromaShift
;
276 (SRC_HEIGHT
>> m_int
.nChromaShift
) * dstStride
[2];
277 dstStride
[1] = dstStride
[2];
280 if (m_int
.fHWAccel
) {
287 mem2agpcpy_pic(dst
[0], m_int
.planes
[0], w
, h
,
288 dstStride
[0], m_int
.stride
[0]);
291 if (m_int
.nChromaShift
) {
292 w
>>= m_int
.nChromaShift
; h
>>= m_int
.nChromaShift
;
295 mem2agpcpy_pic(dst
[1], m_int
.planes
[1], w
, h
,
296 dstStride
[1], m_int
.stride
[1]);
299 mem2agpcpy_pic(dst
[2], m_int
.planes
[2], w
, h
,
300 dstStride
[2], m_int
.stride
[2]);
303 sws_scale(m_int
.sws
, m_int
.planes
, m_int
.stride
, 0, SRC_HEIGHT
,
311 // Frame window procedure to work around T23 laptop with S3 video card,
312 // which supports upscaling only.
313 static MRESULT EXPENTRY
NewFrameWndProc(HWND hwnd
, ULONG msg
, MPARAM mp1
,
317 case WM_QUERYTRACKINFO
:
319 PTRACKINFO pti
= (PTRACKINFO
)mp2
;
325 m_int
.pfnwpOldFrame(hwnd
, msg
, mp1
, mp2
);
329 rcl
.xRight
= SRC_WIDTH
+ 1;
330 rcl
.yTop
= SRC_HEIGHT
+ 1;
332 WinCalcFrameRect(hwnd
, &rcl
, FALSE
);
334 pti
->ptlMinTrackSize
.x
= rcl
.xRight
- rcl
.xLeft
;
335 pti
->ptlMinTrackSize
.y
= rcl
.yTop
- rcl
.yBottom
;
337 pti
->ptlMaxTrackSize
.x
= vo_screenwidth
;
338 pti
->ptlMaxTrackSize
.y
= vo_screenheight
;
340 return (MRESULT
)TRUE
;
343 case WM_ADJUSTWINDOWPOS
:
345 PSWP pswp
= (PSWP
)mp1
;
351 if (pswp
->fl
& SWP_SIZE
) {
353 rcl
.yBottom
= pswp
->y
;
354 rcl
.xRight
= rcl
.xLeft
+ pswp
->cx
;
355 rcl
.yTop
= rcl
.yBottom
+ pswp
->cy
;
357 WinCalcFrameRect(hwnd
, &rcl
, TRUE
);
359 if (rcl
.xRight
- rcl
.xLeft
<= SRC_WIDTH
)
360 rcl
.xRight
= rcl
.xLeft
+ (SRC_WIDTH
+ 1);
362 if (rcl
.yTop
- rcl
.yBottom
<= SRC_HEIGHT
)
363 rcl
.yTop
= rcl
.yBottom
+ (SRC_HEIGHT
+ 1);
365 WinCalcFrameRect(hwnd
, &rcl
, FALSE
);
367 if (rcl
.xRight
- rcl
.xLeft
> vo_screenwidth
) {
369 rcl
.xRight
= vo_screenwidth
;
372 if (rcl
.yTop
- rcl
.yBottom
> vo_screenheight
) {
374 rcl
.yTop
= vo_screenheight
;
377 pswp
->fl
|= SWP_MOVE
;
379 pswp
->y
= rcl
.yBottom
;
380 pswp
->cx
= rcl
.xRight
- rcl
.xLeft
;
381 pswp
->cy
= rcl
.yTop
- rcl
.yBottom
;
387 return m_int
.pfnwpOldFrame(hwnd
, msg
, mp1
, mp2
);
390 static MRESULT EXPENTRY
WndProc(HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
)
392 // if slave mode, ignore mouse events and deliver them to a parent window
394 ((msg
>= WM_MOUSEFIRST
&& msg
<= WM_MOUSELAST
) ||
395 (msg
>= WM_EXTMOUSEFIRST
&& msg
<= WM_EXTMOUSELAST
))) {
396 WinPostMsg(HWNDFROMWINID(WinID
), msg
, mp1
, mp2
);
398 return (MRESULT
)TRUE
;
403 mplayer_put_key(KEY_CLOSE_WIN
);
409 USHORT fsFlags
= SHORT1FROMMP(mp1
);
410 UCHAR uchScan
= CHAR4FROMMP(mp1
);
411 USHORT usCh
= SHORT1FROMMP(mp2
);
412 USHORT usVk
= SHORT2FROMMP(mp2
);
415 if (fsFlags
& KC_KEYUP
)
418 if (fsFlags
& KC_SCANCODE
) {
419 mpkey
= lookup_keymap_table(m_keypad_map
, uchScan
);
421 // distinguish KEY_KP0 and KEY_KPINS
422 if (mpkey
== KEY_KP0
&& usCh
!= '0')
425 // distinguish KEY_KPDEC and KEY_KPDEL
426 if (mpkey
== KEY_KPDEC
&& usCh
!= '.')
429 mplayer_put_key(mpkey
);
431 return (MRESULT
)TRUE
;
435 if (fsFlags
& KC_VIRTUALKEY
) {
436 mpkey
= lookup_keymap_table(m_vk_map
, usVk
);
438 mplayer_put_key(mpkey
);
440 return (MRESULT
)TRUE
;
444 if ((fsFlags
& KC_CHAR
) && !HIBYTE(usCh
))
445 mplayer_put_key(usCh
);
447 return (MRESULT
)TRUE
;
453 case WM_BUTTON1DBLCLK
:
454 case WM_BUTTON3DBLCLK
:
455 case WM_BUTTON2DBLCLK
:
456 if (WinQueryFocus(HWND_DESKTOP
) != hwnd
)
457 WinSetFocus(HWND_DESKTOP
, hwnd
);
458 else if (!vo_nomouse_input
)
459 mplayer_put_key(lookup_keymap_table(m_mouse_map
, msg
));
461 return (MRESULT
)TRUE
;
471 // get a current movie area
472 kvaAdjustDstRect(&m_int
.kvas
.rclSrcRect
, &rclDst
);
474 // get a current invalidated area
475 hps
= WinBeginPaint(hwnd
, NULLHANDLE
, &rcl
);
477 // create a region for an invalidated area
478 hrgn
= GpiCreateRegion(hps
, 1, &rcl
);
479 // create a region for a movie area
480 hrgnDst
= GpiCreateRegion(hps
, 1, &rclDst
);
482 // exclude a movie area from an invalidated area
483 GpiCombineRegion(hps
, hrgn
, hrgn
, hrgnDst
, CRGN_DIFF
);
485 // get rectangles from the region
487 rgnCtl
.ulDirection
= RECTDIR_LFRT_TOPBOT
;
488 GpiQueryRegionRects(hps
, hrgn
, NULL
, &rgnCtl
, NULL
);
490 if (rgnCtl
.crcReturned
> 0) {
491 rgnCtl
.crc
= rgnCtl
.crcReturned
;
492 prcl
= malloc(sizeof(RECTL
) * rgnCtl
.crcReturned
);
495 // draw black bar if needed
496 if (prcl
&& GpiQueryRegionRects(hps
, hrgn
, NULL
, &rgnCtl
, prcl
)) {
499 for (i
= 0; i
< rgnCtl
.crcReturned
; i
++)
500 WinFillRect(hps
, &prcl
[i
], CLR_BLACK
);
505 GpiDestroyRegion(hps
, hrgnDst
);
506 GpiDestroyRegion(hps
, hrgn
);
514 return WinDefWindowProc(hwnd
, msg
, mp1
, mp2
);
517 // Change process type from VIO to PM to use PM APIs.
518 static void morphToPM(void)
522 DosGetInfoBlocks(NULL
, &pib
);
524 // Change flag from VIO to PM:
525 if (pib
->pib_ultype
== 2)
529 static int preinit(const char *arg
)
540 const opt_t subopts
[] = {
541 {"snap", OPT_ARG_BOOL
, &fUseSnap
, NULL
},
542 {"wo", OPT_ARG_BOOL
, &fUseWO
, NULL
},
543 {"dive", OPT_ARG_BOOL
, &fUseDive
, NULL
},
544 {"t23", OPT_ARG_BOOL
, &fFixT23
, NULL
},
545 {NULL
, 0, NULL
, NULL
}
548 PCSZ pcszVideoModeStr
[3] = {"DIVE", "WarpOverlay!", "SNAP"};
550 if (subopt_parse(arg
, subopts
) != 0)
555 memset(&m_int
, 0, sizeof(m_int
));
557 m_int
.hab
= WinInitialize(0);
558 m_int
.hmq
= WinCreateMsgQueue(m_int
.hab
, 0);
560 WinRegisterClass(m_int
.hab
,
563 CS_SIZEREDRAW
| CS_MOVENOTIFY
,
567 hwndParent
= HWND_DESKTOP
;
568 flFrameFlags
= FCF_SYSMENU
| FCF_TITLEBAR
| FCF_MINMAX
|
569 FCF_SIZEBORDER
| FCF_TASKLIST
;
571 hwndParent
= HWNDFROMWINID(WinID
);
576 WinCreateStdWindow(hwndParent
, // parent window handle
577 WS_VISIBLE
, // frame window style
578 &flFrameFlags
, // window style
579 WC_MPLAYER
, // class name
581 0L, // default client style
582 NULLHANDLE
, // resource in exe file
583 1, // frame window id
584 &m_int
.hwndClient
); // client window handle
586 if (m_int
.hwndFrame
== NULLHANDLE
)
589 m_int
.hwndSysMenu
= WinWindowFromID(m_int
.hwndFrame
, FID_SYSMENU
);
590 m_int
.hwndTitleBar
= WinWindowFromID(m_int
.hwndFrame
, FID_TITLEBAR
);
591 m_int
.hwndMinMax
= WinWindowFromID(m_int
.hwndFrame
, FID_MINMAX
);
593 m_int
.fFixT23
= fFixT23
;
596 m_int
.pfnwpOldFrame
= WinSubclassWindow(m_int
.hwndFrame
,
599 if (!!fUseSnap
+ !!fUseWO
+ !!fUseDive
> 1)
600 mp_msg(MSGT_VO
, MSGL_WARN
,"KVA: Multiple mode specified!!!\n");
611 if (kvaInit(kvaMode
, m_int
.hwndClient
, vo_colorkey
)) {
612 mp_msg(MSGT_VO
, MSGL_ERR
, "KVA: Init failed!!!\n");
617 kvaCaps(&m_int
.kvac
);
619 mp_msg(MSGT_VO
, MSGL_V
, "KVA: Selected video mode = %s\n",
620 pcszVideoModeStr
[m_int
.kvac
.ulMode
- 1]);
622 kvaDisableScreenSaver();
624 // Might cause PM DLLs to be loaded which incorrectly enable SIG_FPE,
625 // so mask off all floating-point exceptions.
626 _control87(MCW_EM
, MCW_EM
);
631 static void uninit(void)
633 kvaEnableScreenSaver();
637 sws_freeContext(m_int
.sws
);
639 if (m_int
.hwndFrame
!= NULLHANDLE
) {
644 WinSubclassWindow(m_int
.hwndFrame
, m_int
.pfnwpOldFrame
);
646 WinDestroyWindow(m_int
.hwndFrame
);
649 WinDestroyMsgQueue(m_int
.hmq
);
650 WinTerminate(m_int
.hab
);
653 static int config(uint32_t width
, uint32_t height
,
654 uint32_t d_width
, uint32_t d_height
,
655 uint32_t flags
, char *title
, uint32_t format
)
659 mp_msg(MSGT_VO
, MSGL_V
,
660 "KVA: Using 0x%X (%s) image format, vo_config_count = %d\n",
661 format
, vo_format_name(format
), vo_config_count
);
665 if (query_format_info(format
, &m_int
.fHWAccel
, &m_int
.fcc
, &m_int
.bpp
,
666 &m_int
.nChromaShift
))
669 m_int
.iImageFormat
= format
;
671 // if there is no hw accel for given format,
672 // try any format supported by hw accel
673 if (!m_int
.fHWAccel
) {
676 sws_freeContext(m_int
.sws
);
678 if (m_int
.kvac
.ulInputFormatFlags
& KVAF_YV12
)
679 dstFormat
= IMGFMT_YV12
;
680 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_YUY2
)
681 dstFormat
= IMGFMT_YUY2
;
682 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_YVU9
)
683 dstFormat
= IMGFMT_YVU9
;
684 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR24
)
685 dstFormat
= IMGFMT_BGR24
;
686 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR16
)
687 dstFormat
= IMGFMT_BGR16
;
688 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR15
)
689 dstFormat
= IMGFMT_BGR15
;
691 if (query_format_info(dstFormat
, NULL
, &m_int
.fcc
, NULL
, NULL
))
694 m_int
.sws
= sws_getContextFromCmdLine(width
, height
, format
,
695 width
, height
, dstFormat
);
698 mp_msg(MSGT_VO
, MSGL_V
, "KVA: Selected FOURCC = %.4s\n", (char *)&m_int
.fcc
);
700 m_int
.kvas
.ulLength
= sizeof(KVASETUP
);
701 m_int
.kvas
.szlSrcSize
.cx
= width
;
702 m_int
.kvas
.szlSrcSize
.cy
= height
;
703 m_int
.kvas
.rclSrcRect
.xLeft
= 0;
704 m_int
.kvas
.rclSrcRect
.yTop
= 0;
705 m_int
.kvas
.rclSrcRect
.xRight
= width
;
706 m_int
.kvas
.rclSrcRect
.yBottom
= height
;
707 m_int
.kvas
.ulRatio
= vo_keepaspect
? KVAR_FORCEANY
: KVAR_NONE
;
708 m_int
.kvas
.ulAspectWidth
= d_width
;
709 m_int
.kvas
.ulAspectHeight
= d_height
;
710 m_int
.kvas
.fccSrcColor
= m_int
.fcc
;
711 m_int
.kvas
.fDither
= TRUE
;
713 if (kvaSetup(&m_int
.kvas
)) {
714 mp_msg(MSGT_VO
, MSGL_ERR
, "KVA: Setup failed!!!\n");
719 m_int
.lStride
= width
* m_int
.bpp
;
724 WinSetWindowText(m_int
.hwndFrame
, title
);
726 // initialize 'vo_fs' only once at first config() call
727 if (vo_config_count
== 0)
728 vo_fs
= flags
& VOFLAG_FULLSCREEN
;
730 // workaround for T23 laptop with S3 Video by Franz Bakan
731 if (!vo_fs
&& m_int
.fFixT23
) {
736 m_int
.rclDst
.xLeft
= ((LONG
)vo_screenwidth
- (LONG
)d_width
) / 2;
737 m_int
.rclDst
.yBottom
= ((LONG
)vo_screenheight
- (LONG
)d_height
) / 2;
738 m_int
.rclDst
.xRight
= m_int
.rclDst
.xLeft
+ d_width
;
739 m_int
.rclDst
.yTop
= m_int
.rclDst
.yBottom
+ d_height
;
742 d_width
= vo_screenwidth
;
743 d_height
= vo_screenheight
;
745 // when -fs option is used without this, title bar is not highlighted
746 WinSetActiveWindow(HWND_DESKTOP
, m_int
.hwndFrame
);
748 WinSetParent(m_int
.hwndSysMenu
, HWND_OBJECT
, FALSE
);
749 WinSetParent(m_int
.hwndTitleBar
, HWND_OBJECT
, FALSE
);
750 WinSetParent(m_int
.hwndMinMax
, HWND_OBJECT
, FALSE
);
752 setAspectRatio(KVAR_FORCEANY
);
755 rcl
.xLeft
= ((LONG
)vo_screenwidth
- (LONG
)d_width
) / 2;
756 rcl
.yBottom
= ((LONG
)vo_screenheight
- (LONG
)d_height
) /2 ;
757 rcl
.xRight
= rcl
.xLeft
+ d_width
;
758 rcl
.yTop
= rcl
.yBottom
+ d_height
;
762 WinQueryWindowRect(HWNDFROMWINID(WinID
), &m_int
.rclDst
);
766 WinCalcFrameRect(m_int
.hwndFrame
, &rcl
, FALSE
);
768 WinSetWindowPos(m_int
.hwndFrame
, HWND_TOP
,
769 rcl
.xLeft
, rcl
.yBottom
,
770 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
771 SWP_SIZE
| SWP_MOVE
| SWP_ZORDER
| SWP_SHOW
|
772 (WinID
== -1 ? SWP_ACTIVATE
: 0));
774 WinInvalidateRect(m_int
.hwndFrame
, NULL
, TRUE
);
779 static uint32_t get_image(mp_image_t
*mpi
)
781 if (m_int
.iImageFormat
!= mpi
->imgfmt
)
784 if (mpi
->type
== MP_IMGTYPE_STATIC
|| mpi
->type
== MP_IMGTYPE_TEMP
) {
785 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
786 mpi
->planes
[1] = m_int
.planes
[1];
787 mpi
->planes
[2] = m_int
.planes
[2];
789 mpi
->stride
[1] = m_int
.stride
[1];
790 mpi
->stride
[2] = m_int
.stride
[2];
793 mpi
->planes
[0] = m_int
.planes
[0];
794 mpi
->stride
[0] = m_int
.stride
[0];
795 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
803 static uint32_t draw_image(mp_image_t
*mpi
)
805 // if -dr or -slices then do nothing:
806 if (mpi
->flags
& (MP_IMGFLAG_DIRECT
| MP_IMGFLAG_DRAW_CALLBACK
))
809 draw_slice(mpi
->planes
, mpi
->stride
, mpi
->w
, mpi
->h
, mpi
->x
, mpi
->y
);
814 static int query_format(uint32_t format
)
819 if (query_format_info(format
, &fHWAccel
, NULL
, NULL
, NULL
))
822 res
= VFCAP_CSP_SUPPORTED
| VFCAP_OSD
;
824 res
|= VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP
;
827 res
|= VFCAP_HWSCALE_DOWN
;
833 static int fs_toggle(void)
842 WinQueryWindowPos(m_int
.hwndFrame
, &swp
);
843 m_int
.rclDst
.xLeft
= swp
.x
;
844 m_int
.rclDst
.yBottom
= swp
.y
;
845 m_int
.rclDst
.xRight
= m_int
.rclDst
.xLeft
+ swp
.cx
;
846 m_int
.rclDst
.yTop
= m_int
.rclDst
.yBottom
+ swp
.cy
;
847 WinCalcFrameRect(m_int
.hwndFrame
, &m_int
.rclDst
, TRUE
);
850 WinSetParent(m_int
.hwndFrame
, HWND_DESKTOP
, FALSE
);
852 WinSetParent(m_int
.hwndSysMenu
, HWND_OBJECT
, FALSE
);
853 WinSetParent(m_int
.hwndTitleBar
, HWND_OBJECT
, FALSE
);
854 WinSetParent(m_int
.hwndMinMax
, HWND_OBJECT
, FALSE
);
858 rcl
.xRight
= vo_screenwidth
;
859 rcl
.yTop
= vo_screenheight
;
861 setAspectRatio(KVAR_FORCEANY
);
864 WinSetParent(m_int
.hwndFrame
, HWNDFROMWINID(WinID
), TRUE
);
866 WinSetParent(m_int
.hwndSysMenu
, m_int
.hwndFrame
, FALSE
);
867 WinSetParent(m_int
.hwndTitleBar
, m_int
.hwndFrame
, FALSE
);
868 WinSetParent(m_int
.hwndMinMax
, m_int
.hwndFrame
, FALSE
);
872 setAspectRatio(vo_keepaspect
? KVAR_FORCEANY
: KVAR_NONE
);
875 WinCalcFrameRect(m_int
.hwndFrame
, &rcl
, FALSE
);
877 WinSetWindowPos(m_int
.hwndFrame
, HWND_TOP
,
878 rcl
.xLeft
, rcl
.yBottom
,
879 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
880 SWP_SIZE
| SWP_MOVE
| SWP_ZORDER
| SWP_SHOW
|
881 (WinID
== -1 ? SWP_ACTIVATE
: 0));
886 static int color_ctrl_set(char *what
, int value
)
891 if (!strcmp(what
, "brightness"))
892 ulAttr
= KVAA_BRIGHTNESS
;
893 else if (!strcmp(what
, "contrast"))
894 ulAttr
= KVAA_CONTRAST
;
895 else if (!strcmp(what
, "hue"))
897 else if (!strcmp(what
, "saturation"))
898 ulAttr
= KVAA_SATURATION
;
902 ulValue
= (value
+ 100) * 255 / 200;
904 if (kvaSetAttr(ulAttr
, &ulValue
))
910 static int color_ctrl_get(char *what
, int *value
)
915 if (!strcmp(what
, "brightness"))
916 ulAttr
= KVAA_BRIGHTNESS
;
917 else if (!strcmp(what
, "contrast"))
918 ulAttr
= KVAA_CONTRAST
;
919 else if (!strcmp(what
, "hue"))
921 else if (!strcmp(what
, "saturation"))
922 ulAttr
= KVAA_SATURATION
;
926 if (kvaQueryAttr(ulAttr
, &ulValue
))
929 // add 1 to adjust range
930 *value
= ((ulValue
+ 1) * 200 / 255) - 100;
935 static int control(uint32_t request
, void *data
)
938 case VOCTRL_GET_IMAGE
:
939 return get_image(data
);
941 case VOCTRL_DRAW_IMAGE
:
942 return draw_image(data
);
944 case VOCTRL_QUERY_FORMAT
:
945 return query_format(*(uint32_t *)data
);
947 case VOCTRL_FULLSCREEN
:
950 case VOCTRL_SET_EQUALIZER
:
952 struct voctrl_set_equalizer_args
*args
= data
;
953 color_ctrl_set(args
->name
, args
->value
);
956 case VOCTRL_GET_EQUALIZER
:
958 struct voctrl_get_equalizer_args
*args
= data
;
959 return color_ctrl_get(args
->name
, args
->valueptr
);
962 case VOCTRL_UPDATE_SCREENINFO
:
963 vo_screenwidth
= m_int
.kvac
.cxScreen
;
964 vo_screenheight
= m_int
.kvac
.cyScreen
;
966 aspect_save_screenres(vo_screenwidth
, vo_screenheight
);
974 static int draw_frame(uint8_t *src
[])
979 static int draw_slice(uint8_t *src
[], int stride
[], int w
, int h
, int x
, int y
)
985 d
= m_int
.planes
[0] + m_int
.stride
[0] * y
+ x
;
987 mem2agpcpy_pic(d
, s
, w
* m_int
.bpp
, h
, m_int
.stride
[0], stride
[0]);
990 if (m_int
.nChromaShift
) {
991 w
>>= m_int
.nChromaShift
; h
>>= m_int
.nChromaShift
;
992 x
>>= m_int
.nChromaShift
; y
>>= m_int
.nChromaShift
;
995 d
= m_int
.planes
[1] + m_int
.stride
[1] * y
+ x
;
997 mem2agpcpy_pic(d
, s
, w
, h
, m_int
.stride
[1], stride
[1]);
1000 d
= m_int
.planes
[2] + m_int
.stride
[2] * y
+ x
;
1002 mem2agpcpy_pic(d
, s
, w
, h
, m_int
.stride
[2], stride
[2]);
1008 #define vo_draw_alpha(imgfmt) \
1009 vo_draw_alpha_##imgfmt(w, h, src, srca, stride, \
1010 m_int.planes[0] + m_int.stride[0] * y0 + m_int.bpp * x0, \
1013 static void draw_alpha(int x0
, int y0
, int w
, int h
,
1014 unsigned char *src
, unsigned char *srca
, int stride
)
1016 switch (m_int
.iImageFormat
) {
1019 vo_draw_alpha(yv12
);
1023 vo_draw_alpha(yuy2
);
1027 vo_draw_alpha(rgb24
);
1031 vo_draw_alpha(rgb16
);
1035 vo_draw_alpha(rgb15
);
1040 static void draw_osd(void)
1042 vo_draw_text(SRC_WIDTH
, SRC_HEIGHT
, draw_alpha
);
1045 static void flip_page(void)
1050 static void check_events(void)
1054 // On slave mode, we need to change our window size according to a
1055 // parent window size
1059 WinQueryWindowRect(HWNDFROMWINID(WinID
), &rcl
);
1061 if (rcl
.xLeft
!= m_int
.rclParent
.xLeft
||
1062 rcl
.yBottom
!= m_int
.rclParent
.yBottom
||
1063 rcl
.xRight
!= m_int
.rclParent
.xRight
||
1064 rcl
.yTop
!= m_int
.rclParent
.yTop
) {
1065 WinSetWindowPos(m_int
.hwndFrame
, NULLHANDLE
,
1066 rcl
.xLeft
, rcl
.yBottom
,
1067 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
1068 SWP_SIZE
| SWP_MOVE
);
1070 m_int
.rclParent
= rcl
;
1074 while (WinPeekMsg(m_int
.hab
, &qm
, NULLHANDLE
, 0, 0, PM_REMOVE
))
1075 WinDispatchMsg(m_int
.hab
, &qm
);