Mercurial > mplayer.hg
comparison libvo/vo_direct3d.c @ 27921:327a98d2b55d
Direct3D based video_out module.
Patch by Georgi Petrov (gogothebee gmail com)
Panscan handling is still disabled and needs to be fixed for negative
-panscan.
author | reimar |
---|---|
date | Tue, 18 Nov 2008 12:23:42 +0000 |
parents | |
children | 17b82082ac4a |
comparison
equal
deleted
inserted
replaced
27920:81571689eba3 | 27921:327a98d2b55d |
---|---|
1 /* | |
2 * Copyright (c) 2008 Georgi Petrov (gogothebee) <gogothebee@gmail.com> | |
3 * | |
4 * This file is part of MPlayer. | |
5 * | |
6 * MPlayer is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * MPlayer is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 */ | |
20 | |
21 #include <windows.h> | |
22 #include <errno.h> | |
23 #include <stdio.h> | |
24 #include <d3d9.h> | |
25 #include "config.h" | |
26 #include "video_out.h" | |
27 #include "video_out_internal.h" | |
28 #include "fastmemcpy.h" | |
29 #include "mp_msg.h" | |
30 #include "aspect.h" | |
31 #include "w32_common.h" | |
32 | |
33 static const vo_info_t info = | |
34 { | |
35 "Direct3D 9 Renderer", | |
36 "direct3d", | |
37 "Georgi Petrov (gogothebee) <gogothebee@gmail.com>", | |
38 "" | |
39 }; | |
40 | |
41 /* | |
42 * Link essential libvo functions: preinit, config, control, draw_frame, | |
43 * draw_slice, draw_osd, flip_page, check_events, uninit and | |
44 * the structure info. | |
45 */ | |
46 const LIBVO_EXTERN(direct3d) | |
47 | |
48 | |
49 /* Global variables. Each one starts with "g". Pointers include "p". | |
50 * I try to keep their count low. | |
51 */ | |
52 | |
53 int gIsPaused; /**< 1 = Movie is paused, | |
54 0 = Movie is not paused */ | |
55 int gIsD3DConfigFinished; /**< Synchronization "semaphore". 1 when | |
56 instance of D3DConfigure is finished */ | |
57 int gIsPanscan; /**< 1= Panscan enabled, 0 = Panscan disabled */ | |
58 RECT gFullScrMovieRect; /**< Rect (upscaled) of the movie when displayed | |
59 in fullscreen */ | |
60 RECT gPanScanSrcRect; /**< PanScan source surface cropping in | |
61 fullscreen */ | |
62 int gSrcWidth; /**< Source (movie) width */ | |
63 int gSrcHeight; /**< Source (movie) heigth */ | |
64 LPDIRECT3D9 gpD3DHandle; /**< Direct3D Handle */ | |
65 LPDIRECT3DDEVICE9 gpD3DDevice; /**< The Direct3D Adapter */ | |
66 IDirect3DSurface9 *gpD3DSurface; /**< Offscreen Direct3D Surface. MPlayer | |
67 renders inside it. Uses colorspace | |
68 MovieSrcFmt */ | |
69 IDirect3DSurface9 *gpD3DBackBuf; /**< Video card's back buffer (used to | |
70 display next frame) */ | |
71 D3DFORMAT gMovieSrcFmt; /**< Movie colorspace format (depends on | |
72 the movie's codec) */ | |
73 D3DFORMAT gDesktopFmt; /**< Desktop (screen) colorspace format. | |
74 Usually XRGB */ | |
75 typedef struct | |
76 { | |
77 const unsigned int MPlayerFormat; /**< Given by MPlayer */ | |
78 const D3DFORMAT FourCC; /**< Required by D3D's test function */ | |
79 } DisplayFormatTable; | |
80 | |
81 /* Map table from reported MPlayer format to the required | |
82 FourCC. This is needed to perform the format query. */ | |
83 | |
84 static const DisplayFormatTable gDisplayFormatTable[] = | |
85 { | |
86 {IMGFMT_YV12, MAKEFOURCC('Y','V','1','2')}, | |
87 {IMGFMT_I420, MAKEFOURCC('I','4','2','0')}, | |
88 {IMGFMT_IYUV, MAKEFOURCC('I','Y','U','V')}, | |
89 {IMGFMT_YVU9, MAKEFOURCC('Y','V','U','9')}, | |
90 {IMGFMT_YUY2, MAKEFOURCC('Y','U','Y','2')}, | |
91 {IMGFMT_UYVY, MAKEFOURCC('U','Y','V','Y')} | |
92 }; | |
93 | |
94 #define DISPLAY_FORMAT_TABLE_ENTRIES \ | |
95 (sizeof(gDisplayFormatTable) / sizeof(gDisplayFormatTable[0])) | |
96 | |
97 /**************************************************************************** | |
98 * * | |
99 * * | |
100 * * | |
101 * Direct3D specific implementation functions * | |
102 * * | |
103 * * | |
104 * * | |
105 ****************************************************************************/ | |
106 | |
107 /** @brief Calculate panscan source RECT in fullscreen. | |
108 */ | |
109 void CalculatePanscanRect (void) | |
110 { | |
111 int scaledHeight = 0; | |
112 int scaledWidth = 0; | |
113 int srcPanx; | |
114 int srcPany; | |
115 | |
116 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>CalculatePanscanRect called\r\n"); | |
117 | |
118 aspect(&scaledWidth, &scaledHeight, A_ZOOM); | |
119 panscan_calc(); | |
120 | |
121 if (vo_panscan_x != 0 || vo_panscan_y != 0) | |
122 { | |
123 gIsPanscan = 1; | |
124 mp_msg(MSGT_VO,MSGL_V, | |
125 "<vo_direct3d>Panscan destination correction: x: %d, y: %d\r\n", | |
126 vo_panscan_x, vo_panscan_y); | |
127 | |
128 mp_msg(MSGT_VO,MSGL_V, | |
129 "<vo_direct3d>vo_panscan_x %d, scaledWidth %d, vo_screenwidth %d\r\n", | |
130 vo_panscan_x, scaledWidth, vo_screenwidth); | |
131 | |
132 mp_msg(MSGT_VO,MSGL_V, | |
133 "<vo_direct3d>vo_panscan_y %d, scaledHeight %d, vo_screenheight %d\r\n", | |
134 vo_panscan_y, scaledHeight, vo_screenheight); | |
135 | |
136 srcPanx = vo_panscan_x / (vo_screenwidth / scaledWidth); | |
137 srcPany = vo_panscan_y / (vo_screenheight / scaledHeight); | |
138 | |
139 mp_msg(MSGT_VO,MSGL_V, | |
140 "<vo_direct3d>Panscan source (needed) correction: x: %d, y: %d\r\n", | |
141 srcPanx, srcPany); | |
142 | |
143 gPanScanSrcRect.left = srcPanx / 2; | |
144 if (gPanScanSrcRect.left % 2 != 0) gPanScanSrcRect.left++; | |
145 gPanScanSrcRect.right = gSrcWidth - (srcPanx / 2); | |
146 if (gPanScanSrcRect.right % 2 != 0) gPanScanSrcRect.right--; | |
147 gPanScanSrcRect.top = srcPany / 2; | |
148 if (gPanScanSrcRect.top % 2 != 0) gPanScanSrcRect.top++; | |
149 gPanScanSrcRect.bottom = gSrcHeight - (srcPany / 2); | |
150 if (gPanScanSrcRect.bottom % 2 != 0) gPanScanSrcRect.bottom--; | |
151 | |
152 mp_msg(MSGT_VO,MSGL_V, | |
153 "<vo_direct3d>Panscan Source Rect: t: %ld, l: %ld, r: %ld, b:%ld\r\n", | |
154 gPanScanSrcRect.top, gPanScanSrcRect.left, | |
155 gPanScanSrcRect.right, gPanScanSrcRect.bottom); | |
156 } | |
157 else | |
158 gIsPanscan = 0; | |
159 } | |
160 | |
161 /** @brief Calculate scaled fullscreen movie rectangle with | |
162 * preserved aspect ratio. | |
163 */ | |
164 void CalculateFullscreenRect (void) | |
165 { | |
166 int scaledHeight = 0; | |
167 int scaledWidth = 0; | |
168 /* If we've created fullscreen context, we should calculate stretched | |
169 * movie RECT, otherwise it will fill the whole fullscreen with | |
170 * wrong aspect ratio */ | |
171 | |
172 aspect(&scaledWidth, &scaledHeight, A_ZOOM); | |
173 | |
174 gFullScrMovieRect.left = (vo_screenwidth - scaledWidth) / 2; | |
175 gFullScrMovieRect.right = gFullScrMovieRect.left + scaledWidth; | |
176 gFullScrMovieRect.top = (vo_screenheight - scaledHeight) / 2; | |
177 gFullScrMovieRect.bottom = gFullScrMovieRect.top + scaledHeight; | |
178 | |
179 mp_msg(MSGT_VO,MSGL_V, | |
180 "<vo_direct3d>Fullscreen Movie Rect: t: %ld, l: %ld, r: %ld, b:%ld\r\n", | |
181 gFullScrMovieRect.top, gFullScrMovieRect.left, | |
182 gFullScrMovieRect.right, gFullScrMovieRect.bottom); | |
183 | |
184 /*CalculatePanscanRect();*/ | |
185 } | |
186 | |
187 /** @brief Destroy D3D Context related to the current window. | |
188 */ | |
189 void D3DDestroyContext (void) | |
190 { | |
191 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>D3DDestroyContext called\r\n"); | |
192 /* Let's destroy the old (if any) D3D Content */ | |
193 | |
194 if (gpD3DSurface != NULL) | |
195 { | |
196 IDirect3DSurface9_Release (gpD3DSurface); | |
197 gpD3DSurface = NULL; | |
198 } | |
199 | |
200 if (gpD3DDevice != NULL) | |
201 { | |
202 IDirect3DDevice9_Release (gpD3DDevice); | |
203 gpD3DDevice = NULL; | |
204 } | |
205 | |
206 /* The following is not a memory leak. pD3DBackBuf is not malloc'ed | |
207 * but just holds a pointer to the back buffer. Nobody gets hurt from | |
208 * setting it to NULL. | |
209 */ | |
210 gpD3DBackBuf = NULL; | |
211 } | |
212 | |
213 | |
214 /** @brief (Re)Initialize Direct3D. Kill and recreate context. | |
215 * The first function called to initialize D3D context. | |
216 * @return 1 on success, 0 on failure | |
217 */ | |
218 int D3DConfigure (void) | |
219 { | |
220 D3DPRESENT_PARAMETERS PresentParams; | |
221 D3DDISPLAYMODE DisplayMode; | |
222 | |
223 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d><INFO>D3DConfigure CALLED\n"); | |
224 | |
225 D3DDestroyContext(); | |
226 | |
227 /* Get the current desktop display mode, so we can set up a back buffer | |
228 * of the same format. */ | |
229 if (FAILED (IDirect3D9_GetAdapterDisplayMode (gpD3DHandle, | |
230 D3DADAPTER_DEFAULT, | |
231 &DisplayMode))) | |
232 { | |
233 mp_msg(MSGT_VO,MSGL_ERR, | |
234 "<vo_direct3d><INFO>Could not read adapter display mode.\n"); | |
235 return 0; | |
236 } | |
237 | |
238 /* Write current Desktop's colorspace format in the global storage. */ | |
239 gDesktopFmt = DisplayMode.Format; | |
240 | |
241 /* Prepare Direct3D initialization parameters. */ | |
242 memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS)); | |
243 PresentParams.Windowed = TRUE; | |
244 PresentParams.SwapEffect = D3DSWAPEFFECT_COPY; | |
245 PresentParams.Flags = D3DPRESENTFLAG_VIDEO; | |
246 PresentParams.hDeviceWindow = vo_w32_window; /* w32_common var */ | |
247 PresentParams.BackBufferWidth = 0; /* Fill up window Width */ | |
248 PresentParams.BackBufferHeight = 0; /* Fill up window Height */ | |
249 PresentParams.MultiSampleType = D3DMULTISAMPLE_NONE; | |
250 /* D3DPRESENT_INTERVAL_ONE = vsync */ | |
251 PresentParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; | |
252 PresentParams.BackBufferFormat = gDesktopFmt; | |
253 PresentParams.BackBufferCount = 1; | |
254 PresentParams.EnableAutoDepthStencil = FALSE; | |
255 | |
256 /* vo_w32_window is w32_common variable. It's a handle to the window. */ | |
257 if (FAILED (IDirect3D9_CreateDevice(gpD3DHandle, | |
258 D3DADAPTER_DEFAULT, | |
259 D3DDEVTYPE_HAL, vo_w32_window, | |
260 D3DCREATE_SOFTWARE_VERTEXPROCESSING, | |
261 &PresentParams, &gpD3DDevice))) | |
262 { | |
263 mp_msg(MSGT_VO,MSGL_ERR, | |
264 "<vo_direct3d><INFO>Could not create the D3D device\n"); | |
265 return 0; | |
266 } | |
267 | |
268 mp_msg(MSGT_VO,MSGL_V, | |
269 "New BackBuffer: Width: %d, Height:%d. VO Dest Width:%d, Height: %d\n", | |
270 PresentParams.BackBufferWidth, PresentParams.BackBufferHeight, | |
271 vo_dwidth, vo_dheight); | |
272 | |
273 if (FAILED (IDirect3DDevice9_CreateOffscreenPlainSurface( | |
274 gpD3DDevice, gSrcWidth, gSrcHeight, | |
275 gMovieSrcFmt, D3DPOOL_DEFAULT, &gpD3DSurface, NULL))) | |
276 { | |
277 mp_msg(MSGT_VO,MSGL_ERR, | |
278 "<vo_direct3d><INFO>IDirect3D9_CreateOffscreenPlainSurface Failed.\n"); | |
279 return 0; | |
280 } | |
281 | |
282 if (FAILED (IDirect3DDevice9_GetBackBuffer (gpD3DDevice, 0, 0, | |
283 D3DBACKBUFFER_TYPE_MONO, | |
284 &(gpD3DBackBuf)))) | |
285 { | |
286 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>Back Buffer address get failed\n"); | |
287 return 0; | |
288 } | |
289 | |
290 /* Fill the Surface with black color. */ | |
291 IDirect3DDevice9_ColorFill(gpD3DDevice, gpD3DSurface, NULL, | |
292 D3DCOLOR_ARGB(0xFF, 0, 0, 0) ); | |
293 | |
294 if (vo_fs == 1) | |
295 CalculateFullscreenRect (); | |
296 | |
297 return 1; | |
298 } | |
299 | |
300 /** @brief Uninitialize Direct3D and close the window. | |
301 */ | |
302 void D3DUninit(void) | |
303 { | |
304 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>D3DUninit called\r\n"); | |
305 | |
306 /* Block further calls to D3DConfigure(). */ | |
307 gIsD3DConfigFinished = 0; | |
308 | |
309 /* Destroy D3D Context inside the window. */ | |
310 D3DDestroyContext(); | |
311 | |
312 /* Stop the whole D3D. */ | |
313 if (NULL != gpD3DHandle) | |
314 { | |
315 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Calling IDirect3D9_Release\r\n"); | |
316 IDirect3D9_Release (gpD3DHandle); | |
317 } | |
318 } | |
319 | |
320 /** @brief Render a frame on the screen. | |
321 * @param mpi mpi structure with the decoded frame inside | |
322 * @return VO_TRUE on success, VO_ERROR on failure | |
323 */ | |
324 static uint32_t D3DRenderFrame (mp_image_t *mpi) | |
325 { | |
326 D3DLOCKED_RECT stLockedRect; /**< Offscreen surface we lock in order | |
327 to copy MPlayer's frame inside it.*/ | |
328 | |
329 /* Uncomment when direct rendering is implemented. | |
330 * if (mpi->flags & MP_IMGFLAG_DIRECT) ... | |
331 */ | |
332 | |
333 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) | |
334 return VO_TRUE; | |
335 | |
336 if (mpi->flags & MP_IMGFLAG_PLANAR) | |
337 { /* Copy a planar frame. */ | |
338 draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,0,0); | |
339 return VO_TRUE; | |
340 } | |
341 | |
342 /* If the previous if failed, we should draw a packed frame */ | |
343 if (FAILED (IDirect3DDevice9_BeginScene(gpD3DDevice))) | |
344 { | |
345 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed\n"); | |
346 return VO_ERROR; | |
347 } | |
348 | |
349 if (FAILED (IDirect3DSurface9_LockRect(gpD3DSurface, | |
350 &stLockedRect, NULL, 0))) | |
351 { | |
352 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>Surface lock failure\n"); | |
353 return VO_ERROR; | |
354 } | |
355 | |
356 memcpy_pic(stLockedRect.pBits, mpi->planes[0], mpi->stride[0], | |
357 mpi->height, stLockedRect.Pitch, mpi->stride[0]); | |
358 | |
359 if (FAILED (IDirect3DSurface9_UnlockRect(gpD3DSurface))) | |
360 { | |
361 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Surface unlock failure\n"); | |
362 return VO_ERROR; | |
363 } | |
364 | |
365 if (FAILED (IDirect3DDevice9_StretchRect (gpD3DDevice, | |
366 gpD3DSurface, | |
367 gIsPanscan == 1 ? | |
368 &gPanScanSrcRect : NULL, | |
369 gpD3DBackBuf, | |
370 vo_fs == 1 ? | |
371 &gFullScrMovieRect : NULL, | |
372 D3DTEXF_LINEAR))) | |
373 { | |
374 mp_msg(MSGT_VO,MSGL_ERR, | |
375 "<vo_direct3d>Unable to copy the frame to the back buffer\n"); | |
376 return VO_ERROR; | |
377 } | |
378 | |
379 if (FAILED (IDirect3DDevice9_EndScene(gpD3DDevice))) | |
380 { | |
381 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>EndScene failed\n"); | |
382 return VO_ERROR; | |
383 } | |
384 | |
385 return VO_TRUE; | |
386 } | |
387 | |
388 | |
389 /** @brief Query if movie colorspace is supported by the HW. | |
390 * @return 0 on failure, device capabilities (not probed | |
391 * currently) on success. | |
392 */ | |
393 static int query_format (uint32_t MovieFormat) | |
394 { | |
395 int i; | |
396 for (i=0; i < DISPLAY_FORMAT_TABLE_ENTRIES; i++) | |
397 { | |
398 if (gDisplayFormatTable[i].MPlayerFormat == MovieFormat) | |
399 { | |
400 /* Test conversion from Movie colorspace to | |
401 * display's target colorspace. */ | |
402 if (FAILED (IDirect3D9_CheckDeviceFormatConversion( | |
403 gpD3DHandle, | |
404 D3DADAPTER_DEFAULT, | |
405 D3DDEVTYPE_HAL, | |
406 gDisplayFormatTable[i].FourCC, | |
407 gDesktopFmt))) | |
408 return 0; | |
409 | |
410 gMovieSrcFmt = gDisplayFormatTable[i].FourCC; | |
411 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Accepted Colorspace %s\n", | |
412 vo_format_name(gDisplayFormatTable[i].MPlayerFormat)); | |
413 return (VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | |
414 /*| VFCAP_OSD*/ | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN); | |
415 | |
416 } | |
417 } | |
418 | |
419 return 0; | |
420 } | |
421 | |
422 /**************************************************************************** | |
423 * * | |
424 * * | |
425 * * | |
426 * libvo Control / Callback functions * | |
427 * * | |
428 * * | |
429 * * | |
430 ****************************************************************************/ | |
431 | |
432 | |
433 | |
434 | |
435 /** @brief libvo Callback: Preinitialize the video card. | |
436 * Preinit the hardware just enough to be queried about | |
437 * supported formats. | |
438 * | |
439 * @return 0 on success, -1 on failure | |
440 */ | |
441 static int preinit(const char *arg) | |
442 { | |
443 D3DDISPLAYMODE DisplayMode; | |
444 /* Set to zero all global variables. */ | |
445 gIsPaused = 0; | |
446 gIsD3DConfigFinished = 0; | |
447 gIsPanscan = 0; | |
448 gpD3DHandle = NULL; | |
449 gpD3DDevice = NULL; | |
450 gpD3DSurface = NULL; | |
451 gpD3DBackBuf = NULL; | |
452 | |
453 /* FIXME | |
454 > Please use subopt-helper.h for this, see vo_gl.c:preinit for | |
455 > an example of how to use it. | |
456 */ | |
457 | |
458 if ((gpD3DHandle = Direct3DCreate9 (D3D_SDK_VERSION)) == NULL) | |
459 { | |
460 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>Unable to initialize Direct3D\n"); | |
461 return -1; | |
462 } | |
463 | |
464 if (FAILED (IDirect3D9_GetAdapterDisplayMode (gpD3DHandle, | |
465 D3DADAPTER_DEFAULT, | |
466 &DisplayMode))) | |
467 { | |
468 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>Could not read display mode\n"); | |
469 return -1; | |
470 } | |
471 | |
472 /* Store in gDesktopFmt the user desktop's colorspace. Usually XRGB. */ | |
473 gDesktopFmt = DisplayMode.Format; | |
474 | |
475 mp_msg(MSGT_VO,MSGL_V,"DisplayMode.Width %d, DisplayMode.Height %d\n", | |
476 DisplayMode.Width, DisplayMode.Height); | |
477 | |
478 /* w32_common framework call. Configures window on the screen, gets | |
479 * fullscreen dimensions and does other useful stuff. | |
480 */ | |
481 if (vo_w32_init() == 0) | |
482 { | |
483 mp_msg(MSGT_VO,MSGL_V,"Unable to configure onscreen window\r\n"); | |
484 return -1; | |
485 } | |
486 | |
487 /* Allow the first call to D3DConfigure. */ | |
488 gIsD3DConfigFinished = 1; | |
489 | |
490 return 0; | |
491 } | |
492 | |
493 | |
494 | |
495 /** @brief libvo Callback: Handle control requests. | |
496 * @return VO_TRUE on success, VO_NOTIMPL when not implemented | |
497 */ | |
498 static int control(uint32_t request, void *data, ...) | |
499 { | |
500 switch (request) | |
501 { | |
502 case VOCTRL_QUERY_FORMAT: | |
503 return query_format (*(uint32_t*) data); | |
504 case VOCTRL_GET_IMAGE: /* Direct Rendering. Not implemented yet. */ | |
505 mp_msg(MSGT_VO,MSGL_V, | |
506 "<vo_direct3d>Direct Rendering request. Not implemented yet\n"); | |
507 return VO_NOTIMPL; | |
508 case VOCTRL_DRAW_IMAGE: | |
509 return D3DRenderFrame (data); | |
510 case VOCTRL_FULLSCREEN: | |
511 vo_w32_fullscreen(); | |
512 D3DConfigure(); | |
513 return VO_TRUE; | |
514 case VOCTRL_RESET: | |
515 return VO_NOTIMPL; | |
516 case VOCTRL_PAUSE: | |
517 gIsPaused = 1; | |
518 return VO_TRUE; | |
519 case VOCTRL_RESUME: | |
520 gIsPaused = 0; | |
521 return VO_TRUE; | |
522 case VOCTRL_GUISUPPORT: | |
523 return VO_NOTIMPL; | |
524 case VOCTRL_SET_EQUALIZER: | |
525 return VO_NOTIMPL; | |
526 case VOCTRL_GET_EQUALIZER: | |
527 return VO_NOTIMPL; | |
528 case VOCTRL_ONTOP: | |
529 vo_w32_ontop(); | |
530 return VO_TRUE; | |
531 case VOCTRL_BORDER: | |
532 vo_w32_border(); | |
533 D3DConfigure(); | |
534 return VO_TRUE; | |
535 case VOCTRL_UPDATE_SCREENINFO: | |
536 w32_update_xinerama_info(); | |
537 return VO_TRUE; | |
538 /* | |
539 case VOCTRL_SET_PANSCAN: | |
540 CalculatePanscanRect (); | |
541 return VO_TRUE; | |
542 case VOCTRL_GET_PANSCAN: | |
543 return VO_TRUE; | |
544 */ | |
545 } | |
546 return VO_FALSE; | |
547 } | |
548 | |
549 /** @brief libvo Callback: Configre the Direct3D adapter. | |
550 * @param width Movie source width | |
551 * @param height Movie source height | |
552 * @param d_width Screen (destination) width | |
553 * @param d_height Screen (destination) height | |
554 * @param options Options bitmap | |
555 * @param title Window title | |
556 * @param format Movie colorspace format (using MPlayer's | |
557 * defines, e.g. IMGFMT_YUY2) | |
558 * @return 0 on success, VO_ERROR on failure | |
559 */ | |
560 static int config(uint32_t width, uint32_t height, uint32_t d_width, | |
561 uint32_t d_height, uint32_t options, char *title, | |
562 uint32_t format) | |
563 { | |
564 gSrcWidth = width; | |
565 gSrcHeight = height; | |
566 | |
567 /* w32_common framework call. Creates window on the screen with | |
568 * the given coordinates. | |
569 */ | |
570 if (vo_w32_config(d_width, d_height, options) == 0) | |
571 { | |
572 mp_msg(MSGT_VO,MSGL_V,"Unable to create onscreen window\r\n"); | |
573 return VO_ERROR; | |
574 } | |
575 | |
576 if (gIsD3DConfigFinished == 1) | |
577 { | |
578 gIsD3DConfigFinished = 0; | |
579 if (D3DConfigure () == 0) | |
580 { | |
581 gIsD3DConfigFinished = 1; | |
582 return VO_ERROR; | |
583 } | |
584 gIsD3DConfigFinished = 1; | |
585 } | |
586 return 0; /* Success */ | |
587 } | |
588 | |
589 /** @brief libvo Callback: Flip next already drawn frame on the | |
590 * screen. | |
591 * @return N/A | |
592 */ | |
593 static void flip_page(void) | |
594 { | |
595 if (FAILED (IDirect3DDevice9_Present (gpD3DDevice, 0, 0, 0, 0))) | |
596 { | |
597 mp_msg(MSGT_VO,MSGL_V, | |
598 "<vo_direct3d>Video adapter became uncooperative.\n"); | |
599 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>Trying to reinitialize it...\n"); | |
600 if (D3DConfigure() == 0) | |
601 { | |
602 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Reinitialization Failed.\n"); | |
603 return; | |
604 } | |
605 if (FAILED (IDirect3DDevice9_Present (gpD3DDevice, 0, 0, 0, 0))) | |
606 { | |
607 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Reinitialization Failed.\n"); | |
608 return; | |
609 } | |
610 else | |
611 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Video adapter reinitialized.\n"); | |
612 | |
613 } | |
614 /*IDirect3DDevice9_Clear (gpD3DDevice, 0, NULL, D3DCLEAR_TARGET, 0, 0, 0);*/ | |
615 } | |
616 | |
617 /** @brief libvo Callback: Draw OSD/Subtitles, | |
618 * @return N/A | |
619 */ | |
620 static void draw_osd(void) | |
621 { | |
622 } | |
623 | |
624 /** @brief libvo Callback: Uninitializes all pointers and closes | |
625 * all D3D related stuff, | |
626 * @return N/A | |
627 */ | |
628 static void uninit(void) | |
629 { | |
630 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Uninitialization\r\n"); | |
631 | |
632 D3DUninit(); | |
633 vo_w32_uninit(); /* w32_common framework call */ | |
634 } | |
635 | |
636 /** @brief libvo Callback: Handles video window events. | |
637 * @return N/A | |
638 */ | |
639 static void check_events(void) | |
640 { | |
641 int flags; | |
642 /* w32_common framework call. Handles video window events. | |
643 * Updates global libvo's vo_dwidth/vo_dheight upon resize | |
644 * with the new window width/height. | |
645 */ | |
646 flags = vo_w32_check_events(); | |
647 if (flags & VO_EVENT_RESIZE) | |
648 D3DConfigure(); | |
649 | |
650 if ((flags & VO_EVENT_EXPOSE) && gIsPaused == TRUE) | |
651 flip_page(); | |
652 } | |
653 | |
654 /** @brief libvo Callback: Draw slice | |
655 * @return 0 on success | |
656 */ | |
657 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y ) | |
658 { | |
659 D3DLOCKED_RECT stLockedRect; /**< Offscreen surface we lock in order | |
660 to copy MPlayer's frame inside it.*/ | |
661 char *Src; /**< Pointer to the source image */ | |
662 char *Dst; /**< Pointer to the destination image */ | |
663 int UVstride; /**< Stride of the U/V planes */ | |
664 | |
665 if (FAILED (IDirect3DDevice9_BeginScene(gpD3DDevice))) | |
666 { | |
667 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed\n"); | |
668 return VO_ERROR; | |
669 } | |
670 | |
671 if (FAILED (IDirect3DSurface9_LockRect(gpD3DSurface, | |
672 &stLockedRect, NULL, 0))) | |
673 { | |
674 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Surface lock failure\n"); | |
675 return VO_FALSE; | |
676 } | |
677 | |
678 UVstride = stLockedRect.Pitch / 2; | |
679 | |
680 /* Copy Y */ | |
681 Dst = stLockedRect.pBits; | |
682 Dst = Dst + stLockedRect.Pitch * y + x; | |
683 Src=src[0]; | |
684 memcpy_pic(Dst, Src, w, h, stLockedRect.Pitch, stride[0]); | |
685 | |
686 w/=2;h/=2;x/=2;y/=2; | |
687 | |
688 /* Copy U */ | |
689 Dst = stLockedRect.pBits; | |
690 Dst = Dst + stLockedRect.Pitch * gSrcHeight | |
691 + UVstride * y + x; | |
692 if (gMovieSrcFmt == MAKEFOURCC('Y','V','1','2')) | |
693 Src=src[2]; | |
694 else | |
695 Src=src[1]; | |
696 | |
697 memcpy_pic(Dst, Src, w, h, UVstride, stride[1]); | |
698 | |
699 /* Copy V */ | |
700 Dst = stLockedRect.pBits; | |
701 Dst = Dst + stLockedRect.Pitch * gSrcHeight | |
702 + UVstride * (gSrcHeight / 2) + UVstride * y + x; | |
703 if (gMovieSrcFmt == MAKEFOURCC('Y','V','1','2')) | |
704 Src=src[1]; | |
705 else | |
706 Src=src[2]; | |
707 | |
708 memcpy_pic(Dst, Src, w, h, UVstride, stride[2]); | |
709 | |
710 if (FAILED (IDirect3DSurface9_UnlockRect(gpD3DSurface))) | |
711 { | |
712 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>Surface unlock failure\n"); | |
713 return VO_ERROR; | |
714 } | |
715 | |
716 if (FAILED (IDirect3DDevice9_StretchRect (gpD3DDevice, | |
717 gpD3DSurface, | |
718 gIsPanscan == 1 ? | |
719 &gPanScanSrcRect : NULL, | |
720 gpD3DBackBuf, | |
721 vo_fs == 1 ? | |
722 &gFullScrMovieRect : NULL, | |
723 D3DTEXF_LINEAR))) | |
724 { | |
725 mp_msg(MSGT_VO,MSGL_V, | |
726 "<vo_direct3d>Unable to copy the frame to the back buffer\n"); | |
727 return VO_ERROR; | |
728 } | |
729 | |
730 if (FAILED (IDirect3DDevice9_EndScene(gpD3DDevice))) | |
731 { | |
732 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>EndScene failed\n"); | |
733 return VO_ERROR; | |
734 } | |
735 | |
736 return 0; /* Success */ | |
737 } | |
738 | |
739 /** @brief libvo Callback: Unused function | |
740 * @return N/A | |
741 */ | |
742 static int draw_frame(uint8_t *src[]) | |
743 { | |
744 mp_msg(MSGT_VO,MSGL_V,"<vo_direct3d>draw_frame called\n"); | |
745 return VO_FALSE; | |
746 } | |
747 | |
748 | |
749 | |
750 | |
751 |