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