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