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