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.
41 #include "video_out.h"
42 #include "video_out_internal.h"
45 #include "fastmemcpy.h"
47 #include "osdep/keycodes.h"
48 #include "input/input.h"
49 #include "input/mouse.h"
50 #include "subopt-helper.h"
53 #include "cpudetect.h"
54 #include "libswscale/swscale.h"
55 #include "libmpcodecs/vf_scale.h"
57 static const vo_info_t info
= {
58 "SNAP/WarpOverlay!/DIVE video output",
60 "KO Myung-Hun <komh@chollian.net>",
66 #define WC_MPLAYER "WC_MPLAYER"
68 #define SRC_WIDTH m_int.kvas.szlSrcSize.cx
69 #define SRC_HEIGHT m_int.kvas.szlSrcSize.cy
71 #define HWNDFROMWINID(wid) ((wid) + 0x80000000UL)
73 static const struct keymap m_vk_map
[] = {
74 {VK_NEWLINE
, KEY_ENTER
}, {VK_TAB
, KEY_TAB
}, {VK_SPACE
, ' '},
77 {VK_CTRL
, KEY_CTRL
}, {VK_BACKSPACE
, KEY_BS
},
78 {VK_DELETE
, KEY_DELETE
}, {VK_INSERT
, KEY_INSERT
},
79 {VK_HOME
, KEY_HOME
}, {VK_END
, KEY_END
},
80 {VK_PAGEUP
, KEY_PAGE_UP
}, {VK_PAGEDOWN
, KEY_PAGE_DOWN
},
84 {VK_RIGHT
, KEY_RIGHT
}, {VK_LEFT
, KEY_LEFT
},
85 {VK_DOWN
, KEY_DOWN
}, {VK_UP
, KEY_UP
},
88 {VK_F1
, KEY_F
+1}, {VK_F2
, KEY_F
+2}, {VK_F3
, KEY_F
+3}, {VK_F4
, KEY_F
+4},
89 {VK_F5
, KEY_F
+5}, {VK_F6
, KEY_F
+6}, {VK_F7
, KEY_F
+7}, {VK_F8
, KEY_F
+8},
90 {VK_F9
, KEY_F
+9}, {VK_F10
, KEY_F
+10}, {VK_F11
, KEY_F
+11}, {VK_F12
, KEY_F
+12},
95 static const struct keymap m_keypad_map
[] = {
97 {0x52, KEY_KP0
}, {0x4F, KEY_KP1
}, {0x50, KEY_KP2
}, {0x51, KEY_KP3
},
98 {0x4B, KEY_KP4
}, {0x4C, KEY_KP5
}, {0x4D, KEY_KP6
}, {0x47, KEY_KP7
},
99 {0x48, KEY_KP8
}, {0x49, KEY_KP9
}, {0x53, KEY_KPDEC
}, {0x5A, KEY_KPENTER
},
104 static const struct keymap m_mouse_map
[] = {
105 {WM_BUTTON1DOWN
, MOUSE_BTN0
},
106 {WM_BUTTON3DOWN
, MOUSE_BTN1
},
107 {WM_BUTTON2DOWN
, MOUSE_BTN2
},
108 {WM_BUTTON1DBLCLK
, MOUSE_BTN0_DBL
},
109 {WM_BUTTON3DBLCLK
, MOUSE_BTN1_DBL
},
110 {WM_BUTTON2DBLCLK
, MOUSE_BTN2_DBL
},
134 uint8_t *planes
[MP_MAX_PLANES
]; // y = 0, u = 1, v = 2
135 int stride
[MP_MAX_PLANES
];
138 struct SwsContext
*sws
;
141 static inline void setAspectRatio(ULONG ulRatio
)
143 m_int
.kvas
.ulRatio
= ulRatio
;
144 kvaSetup(&m_int
.kvas
);
147 static int query_format_info(int format
, PBOOL pfHWAccel
, PFOURCC pfcc
,
148 int *pbpp
, int *pnChromaShift
)
157 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_YV12
;
164 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_YUY2
;
171 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_YVU9
;
178 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR24
;
185 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR16
;
192 fHWAccel
= m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR15
;
203 *pfHWAccel
= fHWAccel
;
212 *pnChromaShift
= nChromaShift
;
217 static void imgCreate(void)
219 int size
= SRC_HEIGHT
* m_int
.lStride
;;
221 switch (m_int
.iImageFormat
) {
231 m_int
.pbImage
= malloc(size
);
233 memset(m_int
.planes
, 0, sizeof(m_int
.planes
));
234 memset(m_int
.stride
, 0, sizeof(m_int
.stride
));
235 m_int
.planes
[0] = m_int
.pbImage
;
236 m_int
.stride
[0] = m_int
.lStride
;
239 if (m_int
.nChromaShift
) {
240 m_int
.planes
[1] = m_int
.planes
[0] + SRC_HEIGHT
* m_int
.stride
[0];
241 m_int
.stride
[1] = m_int
.stride
[0] >> m_int
.nChromaShift
;
243 m_int
.planes
[2] = m_int
.planes
[1] +
244 (SRC_HEIGHT
>> m_int
.nChromaShift
) * m_int
.stride
[1];
245 m_int
.stride
[2] = m_int
.stride
[1];
249 static void imgFree(void)
253 m_int
.pbImage
= NULL
;
256 static void imgDisplay(void)
261 if (!kvaLockBuffer(&pBuffer
, &ulBPL
)) {
262 uint8_t *dst
[MP_MAX_PLANES
] = {NULL
};
263 int dstStride
[MP_MAX_PLANES
] = {0};
267 dstStride
[0] = ulBPL
;
270 if (m_int
.nChromaShift
) {
272 dst
[2] = dst
[0] + SRC_HEIGHT
* dstStride
[0];
273 dstStride
[2] = dstStride
[0] >> m_int
.nChromaShift
;
277 (SRC_HEIGHT
>> m_int
.nChromaShift
) * dstStride
[2];
278 dstStride
[1] = dstStride
[2];
281 if (m_int
.fHWAccel
) {
288 mem2agpcpy_pic(dst
[0], m_int
.planes
[0], w
, h
,
289 dstStride
[0], m_int
.stride
[0]);
292 if (m_int
.nChromaShift
) {
293 w
>>= m_int
.nChromaShift
; h
>>= m_int
.nChromaShift
;
296 mem2agpcpy_pic(dst
[1], m_int
.planes
[1], w
, h
,
297 dstStride
[1], m_int
.stride
[1]);
300 mem2agpcpy_pic(dst
[2], m_int
.planes
[2], w
, h
,
301 dstStride
[2], m_int
.stride
[2]);
304 sws_scale(m_int
.sws
, m_int
.planes
, m_int
.stride
, 0, SRC_HEIGHT
,
312 // Frame window procedure to work around T23 laptop with S3 video card,
313 // which supports upscaling only.
314 static MRESULT EXPENTRY
NewFrameWndProc(HWND hwnd
, ULONG msg
, MPARAM mp1
,
318 case WM_QUERYTRACKINFO
:
320 PTRACKINFO pti
= (PTRACKINFO
)mp2
;
326 m_int
.pfnwpOldFrame(hwnd
, msg
, mp1
, mp2
);
330 rcl
.xRight
= SRC_WIDTH
+ 1;
331 rcl
.yTop
= SRC_HEIGHT
+ 1;
333 WinCalcFrameRect(hwnd
, &rcl
, FALSE
);
335 pti
->ptlMinTrackSize
.x
= rcl
.xRight
- rcl
.xLeft
;
336 pti
->ptlMinTrackSize
.y
= rcl
.yTop
- rcl
.yBottom
;
338 pti
->ptlMaxTrackSize
.x
= vo_screenwidth
;
339 pti
->ptlMaxTrackSize
.y
= vo_screenheight
;
341 return (MRESULT
)TRUE
;
344 case WM_ADJUSTWINDOWPOS
:
346 PSWP pswp
= (PSWP
)mp1
;
352 if (pswp
->fl
& SWP_SIZE
) {
354 rcl
.yBottom
= pswp
->y
;
355 rcl
.xRight
= rcl
.xLeft
+ pswp
->cx
;
356 rcl
.yTop
= rcl
.yBottom
+ pswp
->cy
;
358 WinCalcFrameRect(hwnd
, &rcl
, TRUE
);
360 if (rcl
.xRight
- rcl
.xLeft
<= SRC_WIDTH
)
361 rcl
.xRight
= rcl
.xLeft
+ (SRC_WIDTH
+ 1);
363 if (rcl
.yTop
- rcl
.yBottom
<= SRC_HEIGHT
)
364 rcl
.yTop
= rcl
.yBottom
+ (SRC_HEIGHT
+ 1);
366 WinCalcFrameRect(hwnd
, &rcl
, FALSE
);
368 if (rcl
.xRight
- rcl
.xLeft
> vo_screenwidth
) {
370 rcl
.xRight
= vo_screenwidth
;
373 if (rcl
.yTop
- rcl
.yBottom
> vo_screenheight
) {
375 rcl
.yTop
= vo_screenheight
;
378 pswp
->fl
|= SWP_MOVE
;
380 pswp
->y
= rcl
.yBottom
;
381 pswp
->cx
= rcl
.xRight
- rcl
.xLeft
;
382 pswp
->cy
= rcl
.yTop
- rcl
.yBottom
;
388 return m_int
.pfnwpOldFrame(hwnd
, msg
, mp1
, mp2
);
391 static MRESULT EXPENTRY
WndProc(HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
)
393 // if slave mode, ignore mouse events and deliver them to a parent window
395 ((msg
>= WM_MOUSEFIRST
&& msg
<= WM_MOUSELAST
) ||
396 (msg
>= WM_EXTMOUSEFIRST
&& msg
<= WM_EXTMOUSELAST
))) {
397 WinPostMsg(HWNDFROMWINID(WinID
), msg
, mp1
, mp2
);
399 return (MRESULT
)TRUE
;
404 mplayer_put_key(KEY_CLOSE_WIN
);
410 USHORT fsFlags
= SHORT1FROMMP(mp1
);
411 UCHAR uchScan
= CHAR4FROMMP(mp1
);
412 USHORT usCh
= SHORT1FROMMP(mp2
);
413 USHORT usVk
= SHORT2FROMMP(mp2
);
416 if (fsFlags
& KC_KEYUP
)
419 if (fsFlags
& KC_SCANCODE
) {
420 mpkey
= lookup_keymap_table(m_keypad_map
, uchScan
);
422 // distinguish KEY_KP0 and KEY_KPINS
423 if (mpkey
== KEY_KP0
&& usCh
!= '0')
426 // distinguish KEY_KPDEC and KEY_KPDEL
427 if (mpkey
== KEY_KPDEC
&& usCh
!= '.')
430 mplayer_put_key(mpkey
);
432 return (MRESULT
)TRUE
;
436 if (fsFlags
& KC_VIRTUALKEY
) {
437 mpkey
= lookup_keymap_table(m_vk_map
, usVk
);
439 mplayer_put_key(mpkey
);
441 return (MRESULT
)TRUE
;
445 if ((fsFlags
& KC_CHAR
) && !HIBYTE(usCh
))
446 mplayer_put_key(usCh
);
448 return (MRESULT
)TRUE
;
454 case WM_BUTTON1DBLCLK
:
455 case WM_BUTTON3DBLCLK
:
456 case WM_BUTTON2DBLCLK
:
457 if (WinQueryFocus(HWND_DESKTOP
) != hwnd
)
458 WinSetFocus(HWND_DESKTOP
, hwnd
);
459 else if (!vo_nomouse_input
)
460 mplayer_put_key(lookup_keymap_table(m_mouse_map
, msg
));
462 return (MRESULT
)TRUE
;
472 // get a current movie area
473 kvaAdjustDstRect(&m_int
.kvas
.rclSrcRect
, &rclDst
);
475 // get a current invalidated area
476 hps
= WinBeginPaint(hwnd
, NULLHANDLE
, &rcl
);
478 // create a region for an invalidated area
479 hrgn
= GpiCreateRegion(hps
, 1, &rcl
);
480 // create a region for a movie area
481 hrgnDst
= GpiCreateRegion(hps
, 1, &rclDst
);
483 // exclude a movie area from an invalidated area
484 GpiCombineRegion(hps
, hrgn
, hrgn
, hrgnDst
, CRGN_DIFF
);
486 // get rectangles from the region
488 rgnCtl
.ulDirection
= RECTDIR_LFRT_TOPBOT
;
489 GpiQueryRegionRects(hps
, hrgn
, NULL
, &rgnCtl
, NULL
);
491 if (rgnCtl
.crcReturned
> 0) {
492 rgnCtl
.crc
= rgnCtl
.crcReturned
;
493 prcl
= malloc(sizeof(RECTL
) * rgnCtl
.crcReturned
);
496 // draw black bar if needed
497 if (prcl
&& GpiQueryRegionRects(hps
, hrgn
, NULL
, &rgnCtl
, prcl
)) {
500 for (i
= 0; i
< rgnCtl
.crcReturned
; i
++)
501 WinFillRect(hps
, &prcl
[i
], CLR_BLACK
);
506 GpiDestroyRegion(hps
, hrgnDst
);
507 GpiDestroyRegion(hps
, hrgn
);
515 return WinDefWindowProc(hwnd
, msg
, mp1
, mp2
);
518 // Change process type from VIO to PM to use PM APIs.
519 static void morphToPM(void)
523 DosGetInfoBlocks(NULL
, &pib
);
525 // Change flag from VIO to PM:
526 if (pib
->pib_ultype
== 2)
530 static int preinit(const char *arg
)
541 const opt_t subopts
[] = {
542 {"snap", OPT_ARG_BOOL
, &fUseSnap
, NULL
},
543 {"wo", OPT_ARG_BOOL
, &fUseWO
, NULL
},
544 {"dive", OPT_ARG_BOOL
, &fUseDive
, NULL
},
545 {"t23", OPT_ARG_BOOL
, &fFixT23
, NULL
},
546 {NULL
, 0, NULL
, NULL
}
549 PCSZ pcszVideoModeStr
[3] = {"DIVE", "WarpOverlay!", "SNAP"};
551 if (subopt_parse(arg
, subopts
) != 0)
556 memset(&m_int
, 0, sizeof(m_int
));
558 m_int
.hab
= WinInitialize(0);
559 m_int
.hmq
= WinCreateMsgQueue(m_int
.hab
, 0);
561 WinRegisterClass(m_int
.hab
,
564 CS_SIZEREDRAW
| CS_MOVENOTIFY
,
568 hwndParent
= HWND_DESKTOP
;
569 flFrameFlags
= FCF_SYSMENU
| FCF_TITLEBAR
| FCF_MINMAX
|
570 FCF_SIZEBORDER
| FCF_TASKLIST
;
572 hwndParent
= HWNDFROMWINID(WinID
);
577 WinCreateStdWindow(hwndParent
, // parent window handle
578 WS_VISIBLE
, // frame window style
579 &flFrameFlags
, // window style
580 WC_MPLAYER
, // class name
582 0L, // default client style
583 NULLHANDLE
, // resource in exe file
584 1, // frame window id
585 &m_int
.hwndClient
); // client window handle
587 if (m_int
.hwndFrame
== NULLHANDLE
)
590 m_int
.hwndSysMenu
= WinWindowFromID(m_int
.hwndFrame
, FID_SYSMENU
);
591 m_int
.hwndTitleBar
= WinWindowFromID(m_int
.hwndFrame
, FID_TITLEBAR
);
592 m_int
.hwndMinMax
= WinWindowFromID(m_int
.hwndFrame
, FID_MINMAX
);
594 m_int
.fFixT23
= fFixT23
;
597 m_int
.pfnwpOldFrame
= WinSubclassWindow(m_int
.hwndFrame
,
600 if (!!fUseSnap
+ !!fUseWO
+ !!fUseDive
> 1)
601 mp_msg(MSGT_VO
, MSGL_WARN
,"KVA: Multiple mode specified!!!\n");
612 if (kvaInit(kvaMode
, m_int
.hwndClient
, vo_colorkey
)) {
613 mp_msg(MSGT_VO
, MSGL_ERR
, "KVA: Init failed!!!\n");
618 kvaCaps(&m_int
.kvac
);
620 mp_msg(MSGT_VO
, MSGL_V
, "KVA: Selected video mode = %s\n",
621 pcszVideoModeStr
[m_int
.kvac
.ulMode
- 1]);
623 kvaDisableScreenSaver();
625 // Might cause PM DLLs to be loaded which incorrectly enable SIG_FPE,
626 // so mask off all floating-point exceptions.
627 _control87(MCW_EM
, MCW_EM
);
632 static void uninit(void)
634 kvaEnableScreenSaver();
638 sws_freeContext(m_int
.sws
);
640 if (m_int
.hwndFrame
!= NULLHANDLE
) {
645 WinSubclassWindow(m_int
.hwndFrame
, m_int
.pfnwpOldFrame
);
647 WinDestroyWindow(m_int
.hwndFrame
);
650 WinDestroyMsgQueue(m_int
.hmq
);
651 WinTerminate(m_int
.hab
);
654 static int config(uint32_t width
, uint32_t height
,
655 uint32_t d_width
, uint32_t d_height
,
656 uint32_t flags
, char *title
, uint32_t format
)
660 mp_msg(MSGT_VO
, MSGL_V
,
661 "KVA: Using 0x%X (%s) image format, vo_config_count = %d\n",
662 format
, vo_format_name(format
), vo_config_count
);
666 if (query_format_info(format
, &m_int
.fHWAccel
, &m_int
.fcc
, &m_int
.bpp
,
667 &m_int
.nChromaShift
))
670 m_int
.iImageFormat
= format
;
672 // if there is no hw accel for given format,
673 // try any format supported by hw accel
674 if (!m_int
.fHWAccel
) {
677 sws_freeContext(m_int
.sws
);
679 if (m_int
.kvac
.ulInputFormatFlags
& KVAF_YV12
)
680 dstFormat
= IMGFMT_YV12
;
681 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_YUY2
)
682 dstFormat
= IMGFMT_YUY2
;
683 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_YVU9
)
684 dstFormat
= IMGFMT_YVU9
;
685 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR24
)
686 dstFormat
= IMGFMT_BGR24
;
687 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR16
)
688 dstFormat
= IMGFMT_BGR16
;
689 else if (m_int
.kvac
.ulInputFormatFlags
& KVAF_BGR15
)
690 dstFormat
= IMGFMT_BGR15
;
692 if (query_format_info(dstFormat
, NULL
, &m_int
.fcc
, NULL
, NULL
))
695 m_int
.sws
= sws_getContextFromCmdLine(width
, height
, format
,
696 width
, height
, dstFormat
);
699 mp_msg(MSGT_VO
, MSGL_V
, "KVA: Selected FOURCC = %.4s\n", (char *)&m_int
.fcc
);
701 m_int
.kvas
.ulLength
= sizeof(KVASETUP
);
702 m_int
.kvas
.szlSrcSize
.cx
= width
;
703 m_int
.kvas
.szlSrcSize
.cy
= height
;
704 m_int
.kvas
.rclSrcRect
.xLeft
= 0;
705 m_int
.kvas
.rclSrcRect
.yTop
= 0;
706 m_int
.kvas
.rclSrcRect
.xRight
= width
;
707 m_int
.kvas
.rclSrcRect
.yBottom
= height
;
708 m_int
.kvas
.ulRatio
= vo_keepaspect
? KVAR_FORCEANY
: KVAR_NONE
;
709 m_int
.kvas
.ulAspectWidth
= d_width
;
710 m_int
.kvas
.ulAspectHeight
= d_height
;
711 m_int
.kvas
.fccSrcColor
= m_int
.fcc
;
712 m_int
.kvas
.fDither
= TRUE
;
714 if (kvaSetup(&m_int
.kvas
)) {
715 mp_msg(MSGT_VO
, MSGL_ERR
, "KVA: Setup failed!!!\n");
720 m_int
.lStride
= width
* m_int
.bpp
;
725 WinSetWindowText(m_int
.hwndFrame
, title
);
727 // initialize 'vo_fs' only once at first config() call
728 if (vo_config_count
== 0)
729 vo_fs
= flags
& VOFLAG_FULLSCREEN
;
731 // workaround for T23 laptop with S3 Video by Franz Bakan
732 if (!vo_fs
&& m_int
.fFixT23
) {
737 m_int
.rclDst
.xLeft
= ((LONG
)vo_screenwidth
- (LONG
)d_width
) / 2;
738 m_int
.rclDst
.yBottom
= ((LONG
)vo_screenheight
- (LONG
)d_height
) / 2;
739 m_int
.rclDst
.xRight
= m_int
.rclDst
.xLeft
+ d_width
;
740 m_int
.rclDst
.yTop
= m_int
.rclDst
.yBottom
+ d_height
;
743 d_width
= vo_screenwidth
;
744 d_height
= vo_screenheight
;
746 // when -fs option is used without this, title bar is not highlighted
747 WinSetActiveWindow(HWND_DESKTOP
, m_int
.hwndFrame
);
749 WinSetParent(m_int
.hwndSysMenu
, HWND_OBJECT
, FALSE
);
750 WinSetParent(m_int
.hwndTitleBar
, HWND_OBJECT
, FALSE
);
751 WinSetParent(m_int
.hwndMinMax
, HWND_OBJECT
, FALSE
);
753 setAspectRatio(KVAR_FORCEANY
);
756 rcl
.xLeft
= ((LONG
)vo_screenwidth
- (LONG
)d_width
) / 2;
757 rcl
.yBottom
= ((LONG
)vo_screenheight
- (LONG
)d_height
) /2 ;
758 rcl
.xRight
= rcl
.xLeft
+ d_width
;
759 rcl
.yTop
= rcl
.yBottom
+ d_height
;
763 WinQueryWindowRect(HWNDFROMWINID(WinID
), &m_int
.rclDst
);
767 WinCalcFrameRect(m_int
.hwndFrame
, &rcl
, FALSE
);
769 WinSetWindowPos(m_int
.hwndFrame
, HWND_TOP
,
770 rcl
.xLeft
, rcl
.yBottom
,
771 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
772 SWP_SIZE
| SWP_MOVE
| SWP_ZORDER
| SWP_SHOW
|
773 (WinID
== -1 ? SWP_ACTIVATE
: 0));
775 WinInvalidateRect(m_int
.hwndFrame
, NULL
, TRUE
);
780 static uint32_t get_image(mp_image_t
*mpi
)
782 if (m_int
.iImageFormat
!= mpi
->imgfmt
)
785 if (mpi
->type
== MP_IMGTYPE_STATIC
|| mpi
->type
== MP_IMGTYPE_TEMP
) {
786 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
787 mpi
->planes
[1] = m_int
.planes
[1];
788 mpi
->planes
[2] = m_int
.planes
[2];
790 mpi
->stride
[1] = m_int
.stride
[1];
791 mpi
->stride
[2] = m_int
.stride
[2];
794 mpi
->planes
[0] = m_int
.planes
[0];
795 mpi
->stride
[0] = m_int
.stride
[0];
796 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
804 static uint32_t draw_image(mp_image_t
*mpi
)
806 // if -dr or -slices then do nothing:
807 if (mpi
->flags
& (MP_IMGFLAG_DIRECT
| MP_IMGFLAG_DRAW_CALLBACK
))
810 draw_slice(mpi
->planes
, mpi
->stride
, mpi
->w
, mpi
->h
, mpi
->x
, mpi
->y
);
815 static int query_format(uint32_t format
)
820 if (query_format_info(format
, &fHWAccel
, NULL
, NULL
, NULL
))
823 res
= VFCAP_CSP_SUPPORTED
| VFCAP_OSD
;
825 res
|= VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP
;
828 res
|= VFCAP_HWSCALE_DOWN
;
834 static int fs_toggle(void)
843 WinQueryWindowPos(m_int
.hwndFrame
, &swp
);
844 m_int
.rclDst
.xLeft
= swp
.x
;
845 m_int
.rclDst
.yBottom
= swp
.y
;
846 m_int
.rclDst
.xRight
= m_int
.rclDst
.xLeft
+ swp
.cx
;
847 m_int
.rclDst
.yTop
= m_int
.rclDst
.yBottom
+ swp
.cy
;
848 WinCalcFrameRect(m_int
.hwndFrame
, &m_int
.rclDst
, TRUE
);
851 WinSetParent(m_int
.hwndFrame
, HWND_DESKTOP
, FALSE
);
853 WinSetParent(m_int
.hwndSysMenu
, HWND_OBJECT
, FALSE
);
854 WinSetParent(m_int
.hwndTitleBar
, HWND_OBJECT
, FALSE
);
855 WinSetParent(m_int
.hwndMinMax
, HWND_OBJECT
, FALSE
);
859 rcl
.xRight
= vo_screenwidth
;
860 rcl
.yTop
= vo_screenheight
;
862 setAspectRatio(KVAR_FORCEANY
);
865 WinSetParent(m_int
.hwndFrame
, HWNDFROMWINID(WinID
), TRUE
);
867 WinSetParent(m_int
.hwndSysMenu
, m_int
.hwndFrame
, FALSE
);
868 WinSetParent(m_int
.hwndTitleBar
, m_int
.hwndFrame
, FALSE
);
869 WinSetParent(m_int
.hwndMinMax
, m_int
.hwndFrame
, FALSE
);
873 setAspectRatio(vo_keepaspect
? KVAR_FORCEANY
: KVAR_NONE
);
876 WinCalcFrameRect(m_int
.hwndFrame
, &rcl
, FALSE
);
878 WinSetWindowPos(m_int
.hwndFrame
, HWND_TOP
,
879 rcl
.xLeft
, rcl
.yBottom
,
880 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
881 SWP_SIZE
| SWP_MOVE
| SWP_ZORDER
| SWP_SHOW
|
882 (WinID
== -1 ? SWP_ACTIVATE
: 0));
887 static int color_ctrl_set(char *what
, int value
)
892 if (!strcmp(what
, "brightness"))
893 ulAttr
= KVAA_BRIGHTNESS
;
894 else if (!strcmp(what
, "contrast"))
895 ulAttr
= KVAA_CONTRAST
;
896 else if (!strcmp(what
, "hue"))
898 else if (!strcmp(what
, "saturation"))
899 ulAttr
= KVAA_SATURATION
;
903 ulValue
= (value
+ 100) * 255 / 200;
905 if (kvaSetAttr(ulAttr
, &ulValue
))
911 static int color_ctrl_get(char *what
, int *value
)
916 if (!strcmp(what
, "brightness"))
917 ulAttr
= KVAA_BRIGHTNESS
;
918 else if (!strcmp(what
, "contrast"))
919 ulAttr
= KVAA_CONTRAST
;
920 else if (!strcmp(what
, "hue"))
922 else if (!strcmp(what
, "saturation"))
923 ulAttr
= KVAA_SATURATION
;
927 if (kvaQueryAttr(ulAttr
, &ulValue
))
930 // add 1 to adjust range
931 *value
= ((ulValue
+ 1) * 200 / 255) - 100;
936 static int control(uint32_t request
, void *data
)
939 case VOCTRL_GET_IMAGE
:
940 return get_image(data
);
942 case VOCTRL_DRAW_IMAGE
:
943 return draw_image(data
);
945 case VOCTRL_QUERY_FORMAT
:
946 return query_format(*(uint32_t *)data
);
948 case VOCTRL_FULLSCREEN
:
951 case VOCTRL_SET_EQUALIZER
:
953 struct voctrl_set_equalizer_args
*args
= data
;
954 color_ctrl_set(args
->name
, args
->value
);
957 case VOCTRL_GET_EQUALIZER
:
959 struct voctrl_get_equalizer_args
*args
= data
;
960 return color_ctrl_get(args
->name
, args
->valueptr
);
963 case VOCTRL_UPDATE_SCREENINFO
:
964 vo_screenwidth
= m_int
.kvac
.cxScreen
;
965 vo_screenheight
= m_int
.kvac
.cyScreen
;
967 aspect_save_screenres(vo_screenwidth
, vo_screenheight
);
975 static int draw_frame(uint8_t *src
[])
980 static int draw_slice(uint8_t *src
[], int stride
[], int w
, int h
, int x
, int y
)
986 d
= m_int
.planes
[0] + m_int
.stride
[0] * y
+ x
;
988 mem2agpcpy_pic(d
, s
, w
* m_int
.bpp
, h
, m_int
.stride
[0], stride
[0]);
991 if (m_int
.nChromaShift
) {
992 w
>>= m_int
.nChromaShift
; h
>>= m_int
.nChromaShift
;
993 x
>>= m_int
.nChromaShift
; y
>>= m_int
.nChromaShift
;
996 d
= m_int
.planes
[1] + m_int
.stride
[1] * y
+ x
;
998 mem2agpcpy_pic(d
, s
, w
, h
, m_int
.stride
[1], stride
[1]);
1001 d
= m_int
.planes
[2] + m_int
.stride
[2] * y
+ x
;
1003 mem2agpcpy_pic(d
, s
, w
, h
, m_int
.stride
[2], stride
[2]);
1009 #define vo_draw_alpha(imgfmt) \
1010 vo_draw_alpha_##imgfmt(w, h, src, srca, stride, \
1011 m_int.planes[0] + m_int.stride[0] * y0 + m_int.bpp * x0, \
1014 static void draw_alpha(int x0
, int y0
, int w
, int h
,
1015 unsigned char *src
, unsigned char *srca
, int stride
)
1017 switch (m_int
.iImageFormat
) {
1020 vo_draw_alpha(yv12
);
1024 vo_draw_alpha(yuy2
);
1028 vo_draw_alpha(rgb24
);
1032 vo_draw_alpha(rgb16
);
1036 vo_draw_alpha(rgb15
);
1041 static void draw_osd(void)
1043 vo_draw_text(SRC_WIDTH
, SRC_HEIGHT
, draw_alpha
);
1046 static void flip_page(void)
1051 static void check_events(void)
1055 // On slave mode, we need to change our window size according to a
1056 // parent window size
1060 WinQueryWindowRect(HWNDFROMWINID(WinID
), &rcl
);
1062 if (rcl
.xLeft
!= m_int
.rclParent
.xLeft
||
1063 rcl
.yBottom
!= m_int
.rclParent
.yBottom
||
1064 rcl
.xRight
!= m_int
.rclParent
.xRight
||
1065 rcl
.yTop
!= m_int
.rclParent
.yTop
) {
1066 WinSetWindowPos(m_int
.hwndFrame
, NULLHANDLE
,
1067 rcl
.xLeft
, rcl
.yBottom
,
1068 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
1069 SWP_SIZE
| SWP_MOVE
);
1071 m_int
.rclParent
= rcl
;
1075 while (WinPeekMsg(m_int
.hab
, &qm
, NULLHANDLE
, 0, 0, PM_REMOVE
))
1076 WinDispatchMsg(m_int
.hab
, &qm
);