Mercurial > mplayer.hg
annotate libvo/vo_direct3d.c @ 33259:04dc3e55cd90
Increase the maximum value of the DVB timeout to 240 seconds.
Some devices may need more time for the initial tune (e.g. firmware loading).
Let the user specify higher timeout value if there is need to.
The default remains 30 seconds.
author | iive |
---|---|
date | Sun, 01 May 2011 18:07:59 +0000 |
parents | fbe5c829c69b |
children | ddb45e9443ec |
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" |
32466
9e627a1793b1
Move font_load.[ch], font_load_ft.c and osd_font.h from libvo to sub.
cigaes
parents:
30149
diff
changeset
|
33 #include "sub/font_load.h" |
32467 | 34 #include "sub/sub.h" |
27921 | 35 |
36 static const vo_info_t info = | |
37 { | |
38 "Direct3D 9 Renderer", | |
39 "direct3d", | |
40 "Georgi Petrov (gogothebee) <gogothebee@gmail.com>", | |
41 "" | |
42 }; | |
43 | |
44 /* | |
45 * Link essential libvo functions: preinit, config, control, draw_frame, | |
46 * draw_slice, draw_osd, flip_page, check_events, uninit and | |
47 * the structure info. | |
48 */ | |
49 const LIBVO_EXTERN(direct3d) | |
50 | |
51 | |
27928 | 52 /* Global variables "priv" structure. I try to keep their count low. |
27921 | 53 */ |
27928 | 54 static struct global_priv { |
55 int is_paused; /**< 1 = Movie is paused, | |
56 0 = Movie is not paused */ | |
27984
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
57 int is_clear_needed; /**< 1 = Clear the backbuffer before StretchRect |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
58 0 = (default) Don't clear it */ |
28418 | 59 D3DLOCKED_RECT locked_rect; /**< The locked offscreen surface */ |
27928 | 60 RECT fs_movie_rect; /**< Rect (upscaled) of the movie when displayed |
61 in fullscreen */ | |
62 RECT fs_panscan_rect; /**< PanScan source surface cropping in | |
63 fullscreen */ | |
64 int src_width; /**< Source (movie) width */ | |
65 int src_height; /**< Source (movie) heigth */ | |
28598
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
66 int border_x; /**< horizontal border value for OSD */ |
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
67 int border_y; /**< vertical border value for OSD */ |
27921 | 68 |
27928 | 69 D3DFORMAT movie_src_fmt; /**< Movie colorspace format (depends on |
70 the movie's codec) */ | |
71 D3DFORMAT desktop_fmt; /**< Desktop (screen) colorspace format. | |
72 Usually XRGB */ | |
30148
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
73 |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
74 HANDLE d3d9_dll; /**< d3d9 Library HANDLE */ |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
75 IDirect3D9 * (WINAPI *pDirect3DCreate9)(UINT); /**< pointer to Direct3DCreate9 function */ |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
76 |
27928 | 77 LPDIRECT3D9 d3d_handle; /**< Direct3D Handle */ |
78 LPDIRECT3DDEVICE9 d3d_device; /**< The Direct3D Adapter */ | |
79 IDirect3DSurface9 *d3d_surface; /**< Offscreen Direct3D Surface. MPlayer | |
80 renders inside it. Uses colorspace | |
81 priv->movie_src_fmt */ | |
28084 | 82 IDirect3DTexture9 *d3d_texture_osd; /**< Direct3D Texture. Uses RGBA */ |
83 IDirect3DTexture9 *d3d_texture_system; /**< Direct3D Texture. System memory | |
84 cannot lock a normal texture. Uses RGBA */ | |
27928 | 85 IDirect3DSurface9 *d3d_backbuf; /**< Video card's back buffer (used to |
86 display next frame) */ | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
87 int cur_backbuf_width; /**< Current backbuffer width */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
88 int cur_backbuf_height; /**< Current backbuffer height */ |
28084 | 89 int is_osd_populated; /**< 1 = OSD texture has something to display, |
90 0 = OSD texture is clear */ | |
91 int device_caps_power2_only; /**< 1 = texture sizes have to be power 2 | |
92 0 = texture sizes can be anything */ | |
93 int device_caps_square_only; /**< 1 = textures have to be square | |
94 0 = textures do not have to be square */ | |
95 int device_texture_sys; /**< 1 = device can texture from system memory | |
96 0 = device requires shadow */ | |
97 int max_texture_width; /**< from the device capabilities */ | |
98 int max_texture_height; /**< from the device capabilities */ | |
99 int osd_width; /**< current width of the OSD */ | |
100 int osd_height; /**< current height of the OSD */ | |
101 int osd_texture_width; /**< current width of the OSD texture */ | |
102 int osd_texture_height; /**< current height of the OSD texture */ | |
27928 | 103 } *priv; |
104 | |
105 typedef struct { | |
106 const unsigned int mplayer_fmt; /**< Given by MPlayer */ | |
107 const D3DFORMAT fourcc; /**< Required by D3D's test function */ | |
108 } struct_fmt_table; | |
27921 | 109 |
110 /* Map table from reported MPlayer format to the required | |
27928 | 111 fourcc. This is needed to perform the format query. */ |
27921 | 112 |
27928 | 113 static const struct_fmt_table fmt_table[] = { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
114 {IMGFMT_YV12, MAKEFOURCC('Y','V','1','2')}, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
115 {IMGFMT_I420, MAKEFOURCC('I','4','2','0')}, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
116 {IMGFMT_IYUV, MAKEFOURCC('I','Y','U','V')}, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
117 {IMGFMT_YVU9, MAKEFOURCC('Y','V','U','9')}, |
28007
16b39ef63bb5
Use D3DFMT_ constants where possible instead of MAKEFOURCC
reimar
parents:
28006
diff
changeset
|
118 {IMGFMT_YUY2, D3DFMT_YUY2}, |
16b39ef63bb5
Use D3DFMT_ constants where possible instead of MAKEFOURCC
reimar
parents:
28006
diff
changeset
|
119 {IMGFMT_UYVY, D3DFMT_UYVY}, |
28006 | 120 {IMGFMT_BGR32, D3DFMT_X8R8G8B8}, |
121 {IMGFMT_RGB32, D3DFMT_X8B8G8R8}, | |
122 {IMGFMT_BGR24, D3DFMT_R8G8B8}, //untested | |
123 {IMGFMT_BGR16, D3DFMT_R5G6B5}, | |
124 {IMGFMT_BGR15, D3DFMT_X1R5G5B5}, | |
125 {IMGFMT_BGR8 , D3DFMT_R3G3B2}, //untested | |
27921 | 126 }; |
127 | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
128 #define DISPLAY_FORMAT_TABLE_ENTRIES (sizeof(fmt_table) / sizeof(fmt_table[0])) |
27921 | 129 |
28084 | 130 #define D3DFVF_MY_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1) |
131 | |
132 typedef struct { | |
133 float x, y, z; /* Position of vertex in 3D space */ | |
134 float tu, tv; /* Texture coordinates */ | |
135 } struct_vertex; | |
136 | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
137 typedef enum back_buffer_action { |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
138 BACKBUFFER_CREATE, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
139 BACKBUFFER_RESET |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
140 } back_buffer_action_e; |
27921 | 141 /**************************************************************************** |
142 * * | |
143 * * | |
144 * * | |
145 * Direct3D specific implementation functions * | |
146 * * | |
147 * * | |
148 * * | |
149 ****************************************************************************/ | |
150 | |
151 /** @brief Calculate scaled fullscreen movie rectangle with | |
152 * preserved aspect ratio. | |
153 */ | |
27928 | 154 static void calc_fs_rect(void) |
27921 | 155 { |
28511
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
156 struct vo_rect src_rect; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
157 struct vo_rect dst_rect; |
28598
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
158 struct vo_rect borders; |
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
159 calc_src_dst_rects(priv->src_width, priv->src_height, &src_rect, &dst_rect, &borders, NULL); |
27921 | 160 |
28511
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
161 priv->fs_movie_rect.left = dst_rect.left; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
162 priv->fs_movie_rect.right = dst_rect.right; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
163 priv->fs_movie_rect.top = dst_rect.top; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
164 priv->fs_movie_rect.bottom = dst_rect.bottom; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
165 priv->fs_panscan_rect.left = src_rect.left; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
166 priv->fs_panscan_rect.right = src_rect.right; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
167 priv->fs_panscan_rect.top = src_rect.top; |
db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
reimar
parents:
28434
diff
changeset
|
168 priv->fs_panscan_rect.bottom = src_rect.bottom; |
28598
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
169 priv->border_x = borders.left; |
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
170 priv->border_y = borders.top; |
27921 | 171 |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
172 mp_msg(MSGT_VO, MSGL_V, |
28433 | 173 "<vo_direct3d>Fullscreen movie rectangle: t: %ld, l: %ld, r: %ld, b:%ld\n", |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
174 priv->fs_movie_rect.top, priv->fs_movie_rect.left, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
175 priv->fs_movie_rect.right, priv->fs_movie_rect.bottom); |
27984
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
176 |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
177 /* The backbuffer should be cleared before next StretchRect. This is |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
178 * necessary because our new draw area could be smaller than the |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
179 * previous one used by StretchRect and without it, leftovers from the |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
180 * previous frame will be left. */ |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
181 priv->is_clear_needed = 1; |
27921 | 182 } |
183 | |
28026 | 184 /** @brief Destroy D3D Offscreen and Backbuffer surfaces. |
27921 | 185 */ |
28026 | 186 static void destroy_d3d_surfaces(void) |
27921 | 187 { |
28433 | 188 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>destroy_d3d_surfaces called.\n"); |
28026 | 189 /* Let's destroy the old (if any) D3D Surfaces */ |
27921 | 190 |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
191 if (priv->locked_rect.pBits) |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
192 IDirect3DSurface9_UnlockRect(priv->d3d_surface); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
193 priv->locked_rect.pBits = NULL; |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
194 |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
195 if (priv->d3d_surface) |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
196 IDirect3DSurface9_Release(priv->d3d_surface); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
197 priv->d3d_surface = NULL; |
27921 | 198 |
28084 | 199 /* kill the OSD texture and its shadow copy */ |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
200 if (priv->d3d_texture_osd) |
28084 | 201 IDirect3DTexture9_Release(priv->d3d_texture_osd); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
202 priv->d3d_texture_osd = NULL; |
28084 | 203 |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
204 if (priv->d3d_texture_system) |
28084 | 205 IDirect3DTexture9_Release(priv->d3d_texture_system); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
206 priv->d3d_texture_system = NULL; |
28084 | 207 |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
208 if (priv->d3d_backbuf) |
28026 | 209 IDirect3DSurface9_Release(priv->d3d_backbuf); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
210 priv->d3d_backbuf = NULL; |
28026 | 211 } |
212 | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
213 /** @brief Create D3D Offscreen and Backbuffer surfaces. Each |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
214 * surface is created only if it's not already present. |
28026 | 215 * @return 1 on success, 0 on failure |
216 */ | |
217 static int create_d3d_surfaces(void) | |
218 { | |
28084 | 219 int osd_width = vo_dwidth, osd_height = vo_dheight; |
220 int tex_width = osd_width, tex_height = osd_height; | |
28433 | 221 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>create_d3d_surfaces called.\n"); |
28026 | 222 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
223 if (!priv->d3d_surface && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
224 FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface( |
28026 | 225 priv->d3d_device, priv->src_width, priv->src_height, |
226 priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL))) { | |
227 mp_msg(MSGT_VO, MSGL_ERR, | |
28433 | 228 "<vo_direct3d>Allocating offscreen surface failed.\n"); |
28026 | 229 return 0; |
230 } | |
231 | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
232 if (!priv->d3d_backbuf && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
233 FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0, |
28026 | 234 D3DBACKBUFFER_TYPE_MONO, |
28029 | 235 &priv->d3d_backbuf))) { |
28433 | 236 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating backbuffer failed.\n"); |
28026 | 237 return 0; |
27921 | 238 } |
239 | |
28084 | 240 /* calculate the best size for the OSD depending on the factors from the device */ |
241 if (priv->device_caps_power2_only) { | |
242 tex_width = 1; | |
243 tex_height = 1; | |
244 while (tex_width < osd_width ) tex_width <<= 1; | |
245 while (tex_height < osd_height) tex_height <<= 1; | |
246 } | |
247 if (priv->device_caps_square_only) | |
248 /* device only supports square textures */ | |
249 tex_width = tex_height = tex_width > tex_height ? tex_width : tex_height; | |
250 // better round up to a multiple of 16 | |
251 tex_width = (tex_width + 15) & ~15; | |
252 tex_height = (tex_height + 15) & ~15; | |
253 | |
254 // make sure we respect the size limits without breaking aspect or pow2-requirements | |
255 while (tex_width > priv->max_texture_width || tex_height > priv->max_texture_height) { | |
28418 | 256 osd_width >>= 1; |
257 osd_height >>= 1; | |
258 tex_width >>= 1; | |
259 tex_height >>= 1; | |
28084 | 260 } |
261 | |
262 priv->osd_width = osd_width; | |
263 priv->osd_height = osd_height; | |
264 priv->osd_texture_width = tex_width; | |
265 priv->osd_texture_height = tex_height; | |
266 | |
28433 | 267 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>OSD texture size (%dx%d), requested (%dx%d).\n", |
28084 | 268 vo_dwidth, vo_dheight, priv->osd_texture_width, priv->osd_texture_height); |
269 | |
270 /* create OSD */ | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
271 if (!priv->d3d_texture_system && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
272 FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, |
28084 | 273 priv->osd_texture_width, |
274 priv->osd_texture_height, | |
275 1, | |
276 D3DUSAGE_DYNAMIC, | |
277 D3DFMT_A8L8, | |
278 D3DPOOL_SYSTEMMEM, | |
279 &priv->d3d_texture_system, | |
280 NULL))) { | |
281 mp_msg(MSGT_VO,MSGL_ERR, | |
28433 | 282 "<vo_direct3d>Allocating OSD texture in system RAM failed.\n"); |
28084 | 283 return 0; |
284 } | |
285 | |
286 if (!priv->device_texture_sys) { | |
287 /* only create if we need a shadow version on the external device */ | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
288 if (!priv->d3d_texture_osd && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
289 FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, |
28084 | 290 priv->osd_texture_width, |
291 priv->osd_texture_height, | |
292 1, | |
293 D3DUSAGE_DYNAMIC, | |
294 D3DFMT_A8L8, | |
295 D3DPOOL_DEFAULT, | |
296 &priv->d3d_texture_osd, | |
297 NULL))) { | |
298 mp_msg(MSGT_VO,MSGL_ERR, | |
28433 | 299 "<vo_direct3d>Allocating OSD texture in video RAM failed.\n"); |
28084 | 300 return 0; |
301 } | |
302 } | |
303 | |
304 /* setup default renderstate */ | |
305 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_SRCBLEND, D3DBLEND_ONE); | |
306 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |
307 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); | |
308 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAREF, (DWORD)0x0); | |
309 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_LIGHTING, FALSE); | |
310 IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); | |
311 IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); | |
312 | |
28026 | 313 return 1; |
27921 | 314 } |
315 | |
28026 | 316 /** @brief Fill D3D Presentation parameters |
317 */ | |
318 static void fill_d3d_presentparams(D3DPRESENT_PARAMETERS *present_params) | |
319 { | |
320 /* Prepare Direct3D initialization parameters. */ | |
321 memset(present_params, 0, sizeof(D3DPRESENT_PARAMETERS)); | |
322 present_params->Windowed = TRUE; | |
323 present_params->SwapEffect = D3DSWAPEFFECT_COPY; | |
324 present_params->Flags = D3DPRESENTFLAG_VIDEO; | |
325 present_params->hDeviceWindow = vo_w32_window; /* w32_common var */ | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
326 present_params->BackBufferWidth = priv->cur_backbuf_width; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
327 present_params->BackBufferHeight = priv->cur_backbuf_height; |
28026 | 328 present_params->MultiSampleType = D3DMULTISAMPLE_NONE; |
329 present_params->PresentationInterval = D3DPRESENT_INTERVAL_ONE; | |
330 present_params->BackBufferFormat = priv->desktop_fmt; | |
331 present_params->BackBufferCount = 1; | |
332 present_params->EnableAutoDepthStencil = FALSE; | |
333 } | |
27921 | 334 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
335 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
336 /** @brief Create a new backbuffer. Create or Reset the D3D |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
337 * device. |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
338 * @return 1 on success, 0 on failure |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
339 */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
340 static int change_d3d_backbuffer(back_buffer_action_e action) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
341 { |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
342 D3DPRESENT_PARAMETERS present_params; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
343 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
344 destroy_d3d_surfaces(); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
345 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
346 /* Grow the backbuffer in the required dimension. */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
347 if (vo_dwidth > priv->cur_backbuf_width) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
348 priv->cur_backbuf_width = vo_dwidth; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
349 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
350 if (vo_dheight > priv->cur_backbuf_height) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
351 priv->cur_backbuf_height = vo_dheight; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
352 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
353 /* The grown backbuffer dimensions are ready and fill_d3d_presentparams |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
354 * will use them, so we can reset the device. |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
355 */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
356 fill_d3d_presentparams(&present_params); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
357 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
358 /* vo_w32_window is w32_common variable. It's a handle to the window. */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
359 if (action == BACKBUFFER_CREATE && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
360 FAILED(IDirect3D9_CreateDevice(priv->d3d_handle, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
361 D3DADAPTER_DEFAULT, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
362 D3DDEVTYPE_HAL, vo_w32_window, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
363 D3DCREATE_SOFTWARE_VERTEXPROCESSING, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
364 &present_params, &priv->d3d_device))) { |
28434
6d926d2693ec
Avoid message spam during video adapter uncooperative state.
gogothebee
parents:
28433
diff
changeset
|
365 mp_msg(MSGT_VO, MSGL_V, |
28433 | 366 "<vo_direct3d>Creating Direct3D device failed.\n"); |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
367 return 0; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
368 } |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
369 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
370 if (action == BACKBUFFER_RESET && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
371 FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) { |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
372 mp_msg(MSGT_VO, MSGL_ERR, |
28433 | 373 "<vo_direct3d>Reseting Direct3D device failed.\n"); |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
374 return 0; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
375 } |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
376 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
377 mp_msg(MSGT_VO, MSGL_V, |
28433 | 378 "<vo_direct3d>New backbuffer (%dx%d), VO (%dx%d)\n", |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
379 present_params.BackBufferWidth, present_params.BackBufferHeight, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
380 vo_dwidth, vo_dheight); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
381 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
382 return 1; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
383 } |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
384 |
28026 | 385 /** @brief Configure initial Direct3D context. The first |
386 * function called to initialize the D3D context. | |
27921 | 387 * @return 1 on success, 0 on failure |
388 */ | |
28026 | 389 static int configure_d3d(void) |
27921 | 390 { |
27928 | 391 D3DDISPLAYMODE disp_mode; |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
392 D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1}; |
27921 | 393 |
28433 | 394 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>configure_d3d called.\n"); |
27921 | 395 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
396 destroy_d3d_surfaces(); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
397 |
27921 | 398 /* Get the current desktop display mode, so we can set up a back buffer |
399 * of the same format. */ | |
27928 | 400 if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle, |
401 D3DADAPTER_DEFAULT, | |
402 &disp_mode))) { | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
403 mp_msg(MSGT_VO, MSGL_ERR, |
28433 | 404 "<vo_direct3d>Reading adapter display mode failed.\n"); |
27921 | 405 return 0; |
406 } | |
407 | |
408 /* Write current Desktop's colorspace format in the global storage. */ | |
27928 | 409 priv->desktop_fmt = disp_mode.Format; |
27921 | 410 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
411 if (!change_d3d_backbuffer(BACKBUFFER_CREATE)) |
27921 | 412 return 0; |
413 | |
28026 | 414 if (!create_d3d_surfaces()) |
415 return 0; | |
416 | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
417 if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
418 &vp))) { |
28433 | 419 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n"); |
28416 | 420 return 0; |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
421 } |
27921 | 422 |
28026 | 423 calc_fs_rect(); |
424 | |
425 return 1; | |
426 } | |
427 | |
428 /** @brief Reconfigure the whole Direct3D. Called only | |
429 * when the video adapter becomes uncooperative. | |
430 * @return 1 on success, 0 on failure | |
431 */ | |
432 static int reconfigure_d3d(void) | |
433 { | |
28433 | 434 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>reconfigure_d3d called.\n"); |
28026 | 435 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
436 /* Destroy the offscreen, OSD and backbuffer surfaces */ |
28026 | 437 destroy_d3d_surfaces(); |
438 | |
439 /* Destroy the D3D Device */ | |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
440 if (priv->d3d_device) |
28026 | 441 IDirect3DDevice9_Release(priv->d3d_device); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
442 priv->d3d_device = NULL; |
28026 | 443 |
444 /* Stop the whole Direct3D */ | |
445 IDirect3D9_Release(priv->d3d_handle); | |
446 | |
447 /* Initialize Direct3D from the beginning */ | |
30148
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
448 priv->d3d_handle = priv->pDirect3DCreate9(D3D_SDK_VERSION); |
28026 | 449 if (!priv->d3d_handle) { |
28433 | 450 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Initializing Direct3D failed.\n"); |
28416 | 451 return 0; |
28026 | 452 } |
453 | |
454 /* Configure Direct3D */ | |
455 if (!configure_d3d()) | |
456 return 0; | |
457 | |
458 return 1; | |
459 } | |
460 | |
461 /** @brief Resize Direct3D context on window resize. | |
462 * @return 1 on success, 0 on failure | |
463 */ | |
464 static int resize_d3d(void) | |
465 { | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
466 D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1}; |
28026 | 467 |
28433 | 468 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>resize_d3d called.\n"); |
28026 | 469 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
470 /* Make sure that backbuffer is large enough to accomodate the new |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
471 viewport dimensions. Grow it if necessary. */ |
28026 | 472 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
473 if (vo_dwidth > priv->cur_backbuf_width || |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
474 vo_dheight > priv->cur_backbuf_height) { |
28417 | 475 if (!change_d3d_backbuffer(BACKBUFFER_RESET)) |
476 return 0; | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
477 } |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
478 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
479 /* Destroy the OSD textures. They should always match the new dimensions |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
480 * of the onscreen window, so on each resize we need new OSD dimensions. |
28026 | 481 */ |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
482 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
483 if (priv->d3d_texture_osd) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
484 IDirect3DTexture9_Release(priv->d3d_texture_osd); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
485 priv->d3d_texture_osd = NULL; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
486 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
487 if (priv->d3d_texture_system) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
488 IDirect3DTexture9_Release(priv->d3d_texture_system); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
489 priv->d3d_texture_system = NULL; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
490 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
491 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
492 /* Recreate the OSD. The function will observe that the offscreen plain |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
493 * surface and the backbuffer are not destroyed and will skip their creation, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
494 * effectively recreating only the OSD. |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
495 */ |
27921 | 496 |
28026 | 497 if (!create_d3d_surfaces()) |
27921 | 498 return 0; |
28026 | 499 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
500 if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
501 &vp))) { |
28433 | 502 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n"); |
28416 | 503 return 0; |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
504 } |
27921 | 505 |
27937 | 506 calc_fs_rect(); |
27921 | 507 |
28084 | 508 #ifdef CONFIG_FREETYPE |
509 // font needs to be adjusted | |
510 force_load_font = 1; | |
511 #endif | |
512 // OSD needs to be drawn fresh for new size | |
513 vo_osd_changed(OSDTYPE_OSD); | |
514 | |
27921 | 515 return 1; |
516 } | |
517 | |
518 /** @brief Uninitialize Direct3D and close the window. | |
519 */ | |
27928 | 520 static void uninit_d3d(void) |
27921 | 521 { |
28433 | 522 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit_d3d called.\n"); |
27921 | 523 |
28026 | 524 destroy_d3d_surfaces(); |
525 | |
526 /* Destroy the D3D Device */ | |
28086 | 527 if (priv->d3d_device) |
28026 | 528 IDirect3DDevice9_Release(priv->d3d_device); |
28086 | 529 priv->d3d_device = NULL; |
27921 | 530 |
531 /* Stop the whole D3D. */ | |
28028
62ccb6c80212
Consistency cosmetics: do not compare against NULL in ifs
reimar
parents:
28027
diff
changeset
|
532 if (priv->d3d_handle) { |
28433 | 533 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Stopping Direct3D.\n"); |
27928 | 534 IDirect3D9_Release(priv->d3d_handle); |
27921 | 535 } |
28087 | 536 priv->d3d_handle = NULL; |
27921 | 537 } |
538 | |
539 /** @brief Render a frame on the screen. | |
540 * @param mpi mpi structure with the decoded frame inside | |
541 * @return VO_TRUE on success, VO_ERROR on failure | |
542 */ | |
27928 | 543 static uint32_t render_d3d_frame(mp_image_t *mpi) |
27921 | 544 { |
545 /* Uncomment when direct rendering is implemented. | |
546 * if (mpi->flags & MP_IMGFLAG_DIRECT) ... | |
547 */ | |
548 | |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
549 /* If the D3D device is uncooperative (not initialized), return success. |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
550 The device will be probed for reinitialization in the next flip_page() */ |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
551 if (!priv->d3d_device) |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
552 return VO_TRUE; |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
553 |
27921 | 554 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
|
555 goto skip_upload; |
27921 | 556 |
27928 | 557 if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Copy a planar frame. */ |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
558 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
|
559 goto skip_upload; |
27921 | 560 } |
561 | |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
562 /* 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
|
563 if (!priv->locked_rect.pBits) { |
27970 | 564 if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
565 &priv->locked_rect, NULL, 0))) { |
28433 | 566 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Surface lock failed.\n"); |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
567 return VO_ERROR; |
27970 | 568 } |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
569 } |
27921 | 570 |
27968
1081658aa871
Move locked_rect from stack to priv struct in preparation for following patch.
reimar
parents:
27967
diff
changeset
|
571 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
|
572 mpi->height, priv->locked_rect.Pitch, mpi->stride[0]); |
27921 | 573 |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
574 skip_upload: |
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
575 /* This unlock is used for both slice_draw path and render_d3d_frame path. */ |
27928 | 576 if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) { |
28433 | 577 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface unlock failed.\n"); |
27921 | 578 return VO_ERROR; |
579 } | |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
580 priv->locked_rect.pBits = NULL; |
27921 | 581 |
27967
ad71ce76c6ce
Move the StretchRect call from draw_slices to render_d3d_frame.
reimar
parents:
27966
diff
changeset
|
582 if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { |
28433 | 583 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>BeginScene failed.\n"); |
27970 | 584 return VO_ERROR; |
27967
ad71ce76c6ce
Move the StretchRect call from draw_slices to render_d3d_frame.
reimar
parents:
27966
diff
changeset
|
585 } |
ad71ce76c6ce
Move the StretchRect call from draw_slices to render_d3d_frame.
reimar
parents:
27966
diff
changeset
|
586 |
27984
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
587 if (priv->is_clear_needed) { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
588 IDirect3DDevice9_Clear(priv->d3d_device, 0, NULL, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
589 D3DCLEAR_TARGET, 0, 0, 0); |
27984
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
590 priv->is_clear_needed = 0; |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
591 } |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
592 |
27928 | 593 if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device, |
594 priv->d3d_surface, | |
27937 | 595 &priv->fs_panscan_rect, |
27928 | 596 priv->d3d_backbuf, |
27937 | 597 &priv->fs_movie_rect, |
27928 | 598 D3DTEXF_LINEAR))) { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
599 mp_msg(MSGT_VO, MSGL_ERR, |
28433 | 600 "<vo_direct3d>Copying frame to the backbuffer failed.\n"); |
27921 | 601 return VO_ERROR; |
602 } | |
603 | |
27928 | 604 if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { |
28433 | 605 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>EndScene failed.\n"); |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
606 return VO_ERROR; |
27921 | 607 } |
608 | |
609 return VO_TRUE; | |
610 } | |
611 | |
612 | |
613 /** @brief Query if movie colorspace is supported by the HW. | |
614 * @return 0 on failure, device capabilities (not probed | |
615 * currently) on success. | |
616 */ | |
27928 | 617 static int query_format(uint32_t movie_fmt) |
27921 | 618 { |
619 int i; | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
620 for (i = 0; i < DISPLAY_FORMAT_TABLE_ENTRIES; i++) { |
27928 | 621 if (fmt_table[i].mplayer_fmt == movie_fmt) { |
27921 | 622 /* Test conversion from Movie colorspace to |
623 * display's target colorspace. */ | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
624 if (FAILED(IDirect3D9_CheckDeviceFormatConversion(priv->d3d_handle, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
625 D3DADAPTER_DEFAULT, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
626 D3DDEVTYPE_HAL, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
627 fmt_table[i].fourcc, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
628 priv->desktop_fmt))) { |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
629 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Rejected image format: %s\n", |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
630 vo_format_name(fmt_table[i].mplayer_fmt)); |
27928 | 631 return 0; |
632 } | |
27921 | 633 |
27928 | 634 priv->movie_src_fmt = fmt_table[i].fourcc; |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
635 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Accepted image format: %s\n", |
27928 | 636 vo_format_name(fmt_table[i].mplayer_fmt)); |
27921 | 637 return (VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
28084 | 638 | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN); |
27921 | 639 |
640 } | |
641 } | |
642 | |
643 return 0; | |
644 } | |
645 | |
646 /**************************************************************************** | |
647 * * | |
648 * * | |
649 * * | |
650 * libvo Control / Callback functions * | |
651 * * | |
652 * * | |
653 * * | |
654 ****************************************************************************/ | |
655 | |
656 | |
657 | |
658 | |
659 /** @brief libvo Callback: Preinitialize the video card. | |
660 * Preinit the hardware just enough to be queried about | |
661 * supported formats. | |
662 * | |
663 * @return 0 on success, -1 on failure | |
664 */ | |
27928 | 665 |
27921 | 666 static int preinit(const char *arg) |
667 { | |
27928 | 668 D3DDISPLAYMODE disp_mode; |
28084 | 669 D3DCAPS9 disp_caps; |
670 DWORD texture_caps; | |
671 DWORD dev_caps; | |
27928 | 672 |
27921 | 673 /* Set to zero all global variables. */ |
28027 | 674 priv = calloc(1, sizeof(struct global_priv)); |
27928 | 675 if (!priv) { |
28433 | 676 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating private memory failed.\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
677 goto err_out; |
27928 | 678 } |
27921 | 679 |
680 /* FIXME | |
681 > Please use subopt-helper.h for this, see vo_gl.c:preinit for | |
682 > an example of how to use it. | |
683 */ | |
684 | |
30148
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
685 priv->d3d9_dll = LoadLibraryA("d3d9.dll"); |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
686 if (!priv->d3d9_dll) { |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
687 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to dynamically load d3d9.dll\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
688 goto err_out; |
30148
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
689 } |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
690 |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
691 priv->pDirect3DCreate9 = (void *)GetProcAddress(priv->d3d9_dll, "Direct3DCreate9"); |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
692 if (!priv->pDirect3DCreate9) { |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
693 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to find entry point of Direct3DCreate9\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
694 goto err_out; |
30148
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
695 } |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
696 |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
697 priv->d3d_handle = priv->pDirect3DCreate9(D3D_SDK_VERSION); |
27928 | 698 if (!priv->d3d_handle) { |
28433 | 699 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Initializing Direct3D failed.\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
700 goto err_out; |
27921 | 701 } |
702 | |
27928 | 703 if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle, |
704 D3DADAPTER_DEFAULT, | |
705 &disp_mode))) { | |
28433 | 706 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Reading display mode failed.\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
707 goto err_out; |
27921 | 708 } |
709 | |
27928 | 710 /* Store in priv->desktop_fmt the user desktop's colorspace. Usually XRGB. */ |
711 priv->desktop_fmt = disp_mode.Format; | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
712 priv->cur_backbuf_width = disp_mode.Width; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
713 priv->cur_backbuf_height = disp_mode.Height; |
27921 | 714 |
28433 | 715 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Setting backbuffer dimensions to (%dx%d).\n", |
27928 | 716 disp_mode.Width, disp_mode.Height); |
27921 | 717 |
28084 | 718 if (FAILED(IDirect3D9_GetDeviceCaps(priv->d3d_handle, |
719 D3DADAPTER_DEFAULT, | |
720 D3DDEVTYPE_HAL, | |
721 &disp_caps))) { | |
28433 | 722 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Reading display capabilities failed.\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
723 goto err_out; |
28084 | 724 } |
725 | |
726 /* Store relevant information reguarding caps of device */ | |
727 texture_caps = disp_caps.TextureCaps; | |
728 dev_caps = disp_caps.DevCaps; | |
729 priv->device_caps_power2_only = (texture_caps & D3DPTEXTURECAPS_POW2) && | |
730 !(texture_caps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL); | |
731 priv->device_caps_square_only = texture_caps & D3DPTEXTURECAPS_SQUAREONLY; | |
732 priv->device_texture_sys = dev_caps & D3DDEVCAPS_TEXTURESYSTEMMEMORY; | |
733 priv->max_texture_width = disp_caps.MaxTextureWidth; | |
734 priv->max_texture_height = disp_caps.MaxTextureHeight; | |
735 | |
736 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>device_caps_power2_only %d, device_caps_square_only %d\n" | |
737 "<vo_direct3d>device_texture_sys %d\n" | |
738 "<vo_direct3d>max_texture_width %d, max_texture_height %d\n", | |
739 priv->device_caps_power2_only, priv->device_caps_square_only, | |
740 priv->device_texture_sys, priv->max_texture_width, | |
741 priv->max_texture_height); | |
742 | |
27921 | 743 /* w32_common framework call. Configures window on the screen, gets |
744 * fullscreen dimensions and does other useful stuff. | |
745 */ | |
27928 | 746 if (!vo_w32_init()) { |
28433 | 747 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Configuring onscreen window failed.\n"); |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
748 goto err_out; |
27921 | 749 } |
750 | |
751 return 0; | |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
752 |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
753 err_out: |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
754 uninit(); |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
755 return -1; |
27921 | 756 } |
757 | |
758 | |
759 | |
760 /** @brief libvo Callback: Handle control requests. | |
761 * @return VO_TRUE on success, VO_NOTIMPL when not implemented | |
762 */ | |
763 static int control(uint32_t request, void *data, ...) | |
764 { | |
27928 | 765 switch (request) { |
27921 | 766 case VOCTRL_QUERY_FORMAT: |
27928 | 767 return query_format(*(uint32_t*) data); |
27921 | 768 case VOCTRL_GET_IMAGE: /* Direct Rendering. Not implemented yet. */ |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
769 mp_msg(MSGT_VO, MSGL_V, |
28433 | 770 "<vo_direct3d>Direct Rendering request. Not implemented yet.\n"); |
27921 | 771 return VO_NOTIMPL; |
772 case VOCTRL_DRAW_IMAGE: | |
27928 | 773 return render_d3d_frame(data); |
27921 | 774 case VOCTRL_FULLSCREEN: |
775 vo_w32_fullscreen(); | |
28026 | 776 resize_d3d(); |
27921 | 777 return VO_TRUE; |
778 case VOCTRL_RESET: | |
779 return VO_NOTIMPL; | |
780 case VOCTRL_PAUSE: | |
27928 | 781 priv->is_paused = 1; |
27921 | 782 return VO_TRUE; |
783 case VOCTRL_RESUME: | |
27928 | 784 priv->is_paused = 0; |
27921 | 785 return VO_TRUE; |
786 case VOCTRL_GUISUPPORT: | |
787 return VO_NOTIMPL; | |
788 case VOCTRL_SET_EQUALIZER: | |
789 return VO_NOTIMPL; | |
790 case VOCTRL_GET_EQUALIZER: | |
791 return VO_NOTIMPL; | |
792 case VOCTRL_ONTOP: | |
793 vo_w32_ontop(); | |
794 return VO_TRUE; | |
795 case VOCTRL_BORDER: | |
796 vo_w32_border(); | |
28026 | 797 resize_d3d(); |
27921 | 798 return VO_TRUE; |
799 case VOCTRL_UPDATE_SCREENINFO: | |
800 w32_update_xinerama_info(); | |
801 return VO_TRUE; | |
802 case VOCTRL_SET_PANSCAN: | |
28027 | 803 calc_fs_rect(); |
27921 | 804 return VO_TRUE; |
805 case VOCTRL_GET_PANSCAN: | |
806 return VO_TRUE; | |
807 } | |
808 return VO_FALSE; | |
809 } | |
810 | |
811 /** @brief libvo Callback: Configre the Direct3D adapter. | |
812 * @param width Movie source width | |
813 * @param height Movie source height | |
814 * @param d_width Screen (destination) width | |
815 * @param d_height Screen (destination) height | |
816 * @param options Options bitmap | |
817 * @param title Window title | |
818 * @param format Movie colorspace format (using MPlayer's | |
819 * defines, e.g. IMGFMT_YUY2) | |
820 * @return 0 on success, VO_ERROR on failure | |
821 */ | |
822 static int config(uint32_t width, uint32_t height, uint32_t d_width, | |
823 uint32_t d_height, uint32_t options, char *title, | |
824 uint32_t format) | |
825 { | |
27928 | 826 |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
827 priv->src_width = width; |
27928 | 828 priv->src_height = height; |
27921 | 829 |
830 /* w32_common framework call. Creates window on the screen with | |
831 * the given coordinates. | |
832 */ | |
27928 | 833 if (!vo_w32_config(d_width, d_height, options)) { |
28433 | 834 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Creating onscreen window failed.\n"); |
27921 | 835 return VO_ERROR; |
836 } | |
837 | |
28026 | 838 /* "config" may be called several times, so if this is not the first |
839 * call, we should destroy Direct3D adapter and surfaces before | |
840 * calling configure_d3d, which will create them again. | |
841 */ | |
842 | |
843 destroy_d3d_surfaces(); | |
844 | |
845 /* Destroy the D3D Device */ | |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
846 if (priv->d3d_device) |
28026 | 847 IDirect3DDevice9_Release(priv->d3d_device); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
848 priv->d3d_device = NULL; |
28026 | 849 |
850 if (!configure_d3d()) | |
27966 | 851 return VO_ERROR; |
852 | |
27921 | 853 return 0; /* Success */ |
854 } | |
855 | |
856 /** @brief libvo Callback: Flip next already drawn frame on the | |
857 * screen. | |
858 */ | |
859 static void flip_page(void) | |
860 { | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
861 RECT rect = {0, 0, vo_dwidth, vo_dheight}; |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
862 if (!priv->d3d_device || |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
863 FAILED(IDirect3DDevice9_Present(priv->d3d_device, &rect, 0, 0, 0))) { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
864 mp_msg(MSGT_VO, MSGL_V, |
28419
d4fbeeaa1c76
Cosmetics: remove empty line, improve some messages.
reimar
parents:
28418
diff
changeset
|
865 "<vo_direct3d>Trying to reinitialize uncooperative video adapter.\n"); |
27928 | 866 if (!reconfigure_d3d()) { |
28419
d4fbeeaa1c76
Cosmetics: remove empty line, improve some messages.
reimar
parents:
28418
diff
changeset
|
867 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization failed.\n"); |
27921 | 868 return; |
869 } | |
870 else | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
871 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Video adapter reinitialized.\n"); |
27921 | 872 } |
873 } | |
874 | |
875 /** @brief libvo Callback: Uninitializes all pointers and closes | |
876 * all D3D related stuff, | |
877 */ | |
878 static void uninit(void) | |
879 { | |
28433 | 880 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit called.\n"); |
27921 | 881 |
27928 | 882 uninit_d3d(); |
27921 | 883 vo_w32_uninit(); /* w32_common framework call */ |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
884 if (priv->d3d9_dll) |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
885 FreeLibrary(priv->d3d9_dll); |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
886 priv->d3d9_dll = NULL; |
28027 | 887 free(priv); |
27928 | 888 priv = NULL; |
27921 | 889 } |
890 | |
891 /** @brief libvo Callback: Handles video window events. | |
892 */ | |
893 static void check_events(void) | |
894 { | |
895 int flags; | |
896 /* w32_common framework call. Handles video window events. | |
897 * Updates global libvo's vo_dwidth/vo_dheight upon resize | |
898 * with the new window width/height. | |
899 */ | |
900 flags = vo_w32_check_events(); | |
901 if (flags & VO_EVENT_RESIZE) | |
28026 | 902 resize_d3d(); |
27921 | 903 |
27928 | 904 if ((flags & VO_EVENT_EXPOSE) && priv->is_paused) |
27921 | 905 flip_page(); |
906 } | |
907 | |
908 /** @brief libvo Callback: Draw slice | |
909 * @return 0 on success | |
910 */ | |
911 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y ) | |
912 { | |
27971 | 913 char *my_src; /**< Pointer to the source image */ |
914 char *dst; /**< Pointer to the destination image */ | |
915 int uv_stride; /**< Stride of the U/V planes */ | |
27921 | 916 |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
917 /* If the D3D device is uncooperative (not initialized), return success. |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
918 The device will be probed for reinitialization in the next flip_page() */ |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
919 if (!priv->d3d_device) |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
920 return 0; |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
921 |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
922 /* 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
|
923 if (!priv->locked_rect.pBits) { |
27970 | 924 if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
925 &priv->locked_rect, NULL, 0))) { |
28433 | 926 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface lock failure.\n"); |
27970 | 927 return VO_FALSE; |
928 } | |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
929 } |
27921 | 930 |
27971 | 931 uv_stride = priv->locked_rect.Pitch / 2; |
27921 | 932 |
933 /* Copy Y */ | |
27971 | 934 dst = priv->locked_rect.pBits; |
935 dst = dst + priv->locked_rect.Pitch * y + x; | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
936 my_src = src[0]; |
27971 | 937 memcpy_pic(dst, my_src, w, h, priv->locked_rect.Pitch, stride[0]); |
27921 | 938 |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
939 w /= 2; |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
940 h /= 2; |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
941 x /= 2; |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
942 y /= 2; |
27921 | 943 |
944 /* Copy U */ | |
27971 | 945 dst = priv->locked_rect.pBits; |
946 dst = dst + priv->locked_rect.Pitch * priv->src_height | |
947 + uv_stride * y + x; | |
27928 | 948 if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
949 my_src = src[2]; |
27921 | 950 else |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
951 my_src = src[1]; |
27921 | 952 |
27971 | 953 memcpy_pic(dst, my_src, w, h, uv_stride, stride[1]); |
27921 | 954 |
955 /* Copy V */ | |
27971 | 956 dst = priv->locked_rect.pBits; |
957 dst = dst + priv->locked_rect.Pitch * priv->src_height | |
958 + uv_stride * (priv->src_height / 2) + uv_stride * y + x; | |
27928 | 959 if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) |
27971 | 960 my_src=src[1]; |
27921 | 961 else |
27971 | 962 my_src=src[2]; |
27921 | 963 |
27971 | 964 memcpy_pic(dst, my_src, w, h, uv_stride, stride[2]); |
27921 | 965 |
966 return 0; /* Success */ | |
967 } | |
968 | |
969 /** @brief libvo Callback: Unused function | |
970 */ | |
971 static int draw_frame(uint8_t *src[]) | |
972 { | |
28433 | 973 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>draw_frame called.\n"); |
27921 | 974 return VO_FALSE; |
975 } | |
28084 | 976 |
977 /** @brief Maps MPlayer alpha to D3D | |
978 * 0x0 -> transparent and discarded by alpha test | |
979 * 0x1 -> 0xFF to become opaque | |
980 * other alpha values are inverted +1 (2 = -2) | |
981 * These values are then inverted again with | |
982 the texture filter D3DBLEND_INVSRCALPHA | |
983 */ | |
984 void vo_draw_alpha_l8a8(int w, int h, unsigned char* src, unsigned char *srca, | |
985 int srcstride, unsigned char* dstbase, int dststride) | |
986 { | |
987 int y; | |
988 for (y = 0; y < h; y++) { | |
989 unsigned short *dst = (unsigned short*)dstbase; | |
990 int x; | |
991 for (x = 0; x < w; x++) { | |
992 dst[x] = (-srca[x] << 8) | src[x]; | |
993 } | |
994 src += srcstride; | |
995 srca += srcstride; | |
996 dstbase += dststride; | |
997 } | |
998 } | |
999 | |
1000 /** @brief Callback function to render the OSD to the texture | |
1001 */ | |
1002 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | |
1003 unsigned char *srca, int stride) | |
1004 { | |
1005 D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order | |
1006 to copy MPlayer's frame inside it.*/ | |
1007 | |
1008 if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, | |
1009 &locked_rect, NULL, 0))) { | |
28433 | 1010 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>OSD texture lock failed.\n"); |
28084 | 1011 return; |
1012 } | |
1013 | |
1014 vo_draw_alpha_l8a8(w, h, src, srca, stride, | |
1015 (unsigned char *)locked_rect.pBits + locked_rect.Pitch*y0 + 2*x0, locked_rect.Pitch); | |
1016 | |
1017 /* this unlock is used for both slice_draw path and D3DRenderFrame path */ | |
1018 if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { | |
28433 | 1019 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>OSD texture unlock failed.\n"); |
28084 | 1020 return; |
1021 } | |
1022 | |
1023 priv->is_osd_populated = 1; | |
1024 } | |
1025 | |
1026 /** @brief libvo Callback: Draw OSD/Subtitles, | |
1027 */ | |
1028 static void draw_osd(void) | |
1029 { | |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
1030 // we can not render OSD if we lost the device e.g. because it was uncooperative |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
1031 if (!priv->d3d_device) |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
1032 return; |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
1033 |
28084 | 1034 if (vo_osd_changed(0)) { |
1035 D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order | |
1036 to copy MPlayer's frame inside it.*/ | |
1037 | |
1038 /* clear the OSD */ | |
1039 if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, | |
1040 &locked_rect, NULL, 0))) { | |
28433 | 1041 mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture lock failed.\n"); |
28084 | 1042 return; |
1043 } | |
1044 | |
1045 /* clear the whole texture to avoid issues due to interpolation */ | |
1046 memset(locked_rect.pBits, 0, locked_rect.Pitch * priv->osd_texture_height); | |
1047 | |
1048 /* this unlock is used for both slice_draw path and D3DRenderFrame path */ | |
1049 if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { | |
28433 | 1050 mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture unlock failed.\n"); |
28084 | 1051 return; |
1052 } | |
1053 | |
1054 priv->is_osd_populated = 0; | |
1055 /* required for if subs are in the boarder region */ | |
1056 priv->is_clear_needed = 1; | |
1057 | |
28598
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
1058 vo_draw_text_ext(priv->osd_width, priv->osd_height, priv->border_x, priv->border_y, |
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
1059 priv->border_x, priv->border_y, priv->src_width, priv->src_height, draw_alpha); |
28084 | 1060 |
1061 if (!priv->device_texture_sys) | |
1062 { | |
1063 /* only DMA to the shadow if its required */ | |
1064 if (FAILED(IDirect3DDevice9_UpdateTexture(priv->d3d_device, | |
1065 (IDirect3DBaseTexture9 *)priv->d3d_texture_system, | |
1066 (IDirect3DBaseTexture9 *)priv->d3d_texture_osd))) { | |
28433 | 1067 mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture transfer failed.\n"); |
28084 | 1068 return; |
1069 } | |
1070 } | |
1071 } | |
1072 | |
1073 /* update OSD */ | |
1074 | |
1075 if (priv->is_osd_populated) { | |
1076 | |
1077 struct_vertex osd_quad_vb[] = { | |
1078 {-1.0f, 1.0f, 0.0f, 0, 0 }, | |
1079 { 1.0f, 1.0f, 0.0f, 1, 0 }, | |
1080 {-1.0f,-1.0f, 0.0f, 0, 1 }, | |
1081 { 1.0f,-1.0f, 0.0f, 1, 1 } | |
1082 }; | |
1083 | |
1084 /* calculate the texture coordinates */ | |
1085 osd_quad_vb[1].tu = | |
1086 osd_quad_vb[3].tu = (float)priv->osd_width / priv->osd_texture_width; | |
1087 osd_quad_vb[2].tv = | |
1088 osd_quad_vb[3].tv = (float)priv->osd_height / priv->osd_texture_height; | |
1089 | |
1090 if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { | |
28433 | 1091 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed.\n"); |
28084 | 1092 return; |
1093 } | |
1094 | |
1095 /* turn on alpha test */ | |
1096 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, TRUE); | |
1097 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, TRUE); | |
1098 | |
1099 /* need to use a texture here (done here as we may be able to texture from system memory) */ | |
1100 IDirect3DDevice9_SetTexture(priv->d3d_device, 0, | |
1101 (IDirect3DBaseTexture9 *)(priv->device_texture_sys | |
1102 ? priv->d3d_texture_system : priv->d3d_texture_osd)); | |
1103 | |
1104 IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_MY_VERTEX); | |
1105 IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLESTRIP, 2, osd_quad_vb, sizeof(struct_vertex)); | |
1106 | |
1107 /* turn off alpha test */ | |
1108 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, FALSE); | |
1109 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, FALSE); | |
1110 | |
1111 if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { | |
28433 | 1112 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>EndScene failed.\n"); |
28084 | 1113 return; |
1114 } | |
1115 } | |
1116 } |