Mercurial > mplayer.hg
annotate libvo/vo_direct3d.c @ 36182:8587ae275646
Rename HAVE_CMOV to HAVE_I686 for FFmpeg.
Keep the cmov name in configure since it is less
confusing, since cmov is what we test for and
also since for example VIA C3 sometimes is considered
i686 that does not implement the optional CMOV
instruction.
author | reimar |
---|---|
date | Fri, 17 May 2013 15:59:38 +0000 |
parents | a6a1c973de4e |
children | 5d3f93051de9 |
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 | |
34266 | 240 if (!tex_width || !tex_height) { |
241 mp_msg(MSGT_VO, MSGL_V, | |
242 "<vo_direct3d>Deferring surface creation because width or height is 0.\n"); | |
243 return 0; | |
244 } | |
245 | |
28084 | 246 /* calculate the best size for the OSD depending on the factors from the device */ |
247 if (priv->device_caps_power2_only) { | |
248 tex_width = 1; | |
249 tex_height = 1; | |
250 while (tex_width < osd_width ) tex_width <<= 1; | |
251 while (tex_height < osd_height) tex_height <<= 1; | |
252 } | |
253 if (priv->device_caps_square_only) | |
254 /* device only supports square textures */ | |
255 tex_width = tex_height = tex_width > tex_height ? tex_width : tex_height; | |
256 // better round up to a multiple of 16 | |
257 tex_width = (tex_width + 15) & ~15; | |
258 tex_height = (tex_height + 15) & ~15; | |
259 | |
260 // make sure we respect the size limits without breaking aspect or pow2-requirements | |
261 while (tex_width > priv->max_texture_width || tex_height > priv->max_texture_height) { | |
28418 | 262 osd_width >>= 1; |
263 osd_height >>= 1; | |
264 tex_width >>= 1; | |
265 tex_height >>= 1; | |
28084 | 266 } |
267 | |
268 priv->osd_width = osd_width; | |
269 priv->osd_height = osd_height; | |
270 priv->osd_texture_width = tex_width; | |
271 priv->osd_texture_height = tex_height; | |
272 | |
28433 | 273 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>OSD texture size (%dx%d), requested (%dx%d).\n", |
28084 | 274 vo_dwidth, vo_dheight, priv->osd_texture_width, priv->osd_texture_height); |
275 | |
276 /* create OSD */ | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
277 if (!priv->d3d_texture_system && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
278 FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, |
28084 | 279 priv->osd_texture_width, |
280 priv->osd_texture_height, | |
281 1, | |
282 D3DUSAGE_DYNAMIC, | |
283 D3DFMT_A8L8, | |
284 D3DPOOL_SYSTEMMEM, | |
285 &priv->d3d_texture_system, | |
286 NULL))) { | |
287 mp_msg(MSGT_VO,MSGL_ERR, | |
28433 | 288 "<vo_direct3d>Allocating OSD texture in system RAM failed.\n"); |
28084 | 289 return 0; |
290 } | |
291 | |
292 if (!priv->device_texture_sys) { | |
293 /* 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
|
294 if (!priv->d3d_texture_osd && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
295 FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, |
28084 | 296 priv->osd_texture_width, |
297 priv->osd_texture_height, | |
298 1, | |
299 D3DUSAGE_DYNAMIC, | |
300 D3DFMT_A8L8, | |
301 D3DPOOL_DEFAULT, | |
302 &priv->d3d_texture_osd, | |
303 NULL))) { | |
304 mp_msg(MSGT_VO,MSGL_ERR, | |
28433 | 305 "<vo_direct3d>Allocating OSD texture in video RAM failed.\n"); |
28084 | 306 return 0; |
307 } | |
308 } | |
309 | |
310 /* setup default renderstate */ | |
311 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_SRCBLEND, D3DBLEND_ONE); | |
312 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |
313 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); | |
314 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAREF, (DWORD)0x0); | |
315 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_LIGHTING, FALSE); | |
316 IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); | |
317 IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); | |
318 | |
28026 | 319 return 1; |
27921 | 320 } |
321 | |
28026 | 322 /** @brief Fill D3D Presentation parameters |
323 */ | |
324 static void fill_d3d_presentparams(D3DPRESENT_PARAMETERS *present_params) | |
325 { | |
326 /* Prepare Direct3D initialization parameters. */ | |
327 memset(present_params, 0, sizeof(D3DPRESENT_PARAMETERS)); | |
328 present_params->Windowed = TRUE; | |
329 present_params->SwapEffect = D3DSWAPEFFECT_COPY; | |
330 present_params->Flags = D3DPRESENTFLAG_VIDEO; | |
331 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
|
332 present_params->BackBufferWidth = priv->cur_backbuf_width; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
333 present_params->BackBufferHeight = priv->cur_backbuf_height; |
28026 | 334 present_params->MultiSampleType = D3DMULTISAMPLE_NONE; |
335 present_params->PresentationInterval = D3DPRESENT_INTERVAL_ONE; | |
336 present_params->BackBufferFormat = priv->desktop_fmt; | |
337 present_params->BackBufferCount = 1; | |
338 present_params->EnableAutoDepthStencil = FALSE; | |
339 } | |
27921 | 340 |
28344
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 /** @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
|
343 * device. |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
344 * @return 1 on success, 0 on failure |
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 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
|
347 { |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
348 D3DPRESENT_PARAMETERS present_params; |
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 destroy_d3d_surfaces(); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
351 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
352 /* Grow the backbuffer in the required dimension. */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
353 if (vo_dwidth > priv->cur_backbuf_width) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
354 priv->cur_backbuf_width = vo_dwidth; |
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 if (vo_dheight > priv->cur_backbuf_height) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
357 priv->cur_backbuf_height = vo_dheight; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
358 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
359 /* 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
|
360 * will use them, so we can reset the device. |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
361 */ |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
362 fill_d3d_presentparams(&present_params); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
363 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
364 /* 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
|
365 if (action == BACKBUFFER_CREATE && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
366 FAILED(IDirect3D9_CreateDevice(priv->d3d_handle, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
367 D3DADAPTER_DEFAULT, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
368 D3DDEVTYPE_HAL, vo_w32_window, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
369 D3DCREATE_SOFTWARE_VERTEXPROCESSING, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
370 &present_params, &priv->d3d_device))) { |
28434
6d926d2693ec
Avoid message spam during video adapter uncooperative state.
gogothebee
parents:
28433
diff
changeset
|
371 mp_msg(MSGT_VO, MSGL_V, |
28433 | 372 "<vo_direct3d>Creating Direct3D device failed.\n"); |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
373 return 0; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
374 } |
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 if (action == BACKBUFFER_RESET && |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
377 FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) { |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
378 mp_msg(MSGT_VO, MSGL_ERR, |
28433 | 379 "<vo_direct3d>Reseting Direct3D device failed.\n"); |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
380 return 0; |
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 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
383 mp_msg(MSGT_VO, MSGL_V, |
28433 | 384 "<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
|
385 present_params.BackBufferWidth, present_params.BackBufferHeight, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
386 vo_dwidth, vo_dheight); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
387 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
388 return 1; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
389 } |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
390 |
28026 | 391 /** @brief Configure initial Direct3D context. The first |
392 * function called to initialize the D3D context. | |
27921 | 393 * @return 1 on success, 0 on failure |
394 */ | |
28026 | 395 static int configure_d3d(void) |
27921 | 396 { |
27928 | 397 D3DDISPLAYMODE disp_mode; |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
398 D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1}; |
27921 | 399 |
28433 | 400 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>configure_d3d called.\n"); |
27921 | 401 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
402 destroy_d3d_surfaces(); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
403 |
27921 | 404 /* Get the current desktop display mode, so we can set up a back buffer |
405 * of the same format. */ | |
27928 | 406 if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle, |
407 D3DADAPTER_DEFAULT, | |
408 &disp_mode))) { | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
409 mp_msg(MSGT_VO, MSGL_ERR, |
28433 | 410 "<vo_direct3d>Reading adapter display mode failed.\n"); |
27921 | 411 return 0; |
412 } | |
413 | |
414 /* Write current Desktop's colorspace format in the global storage. */ | |
27928 | 415 priv->desktop_fmt = disp_mode.Format; |
27921 | 416 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
417 if (!change_d3d_backbuffer(BACKBUFFER_CREATE)) |
27921 | 418 return 0; |
419 | |
28026 | 420 if (!create_d3d_surfaces()) |
421 return 0; | |
422 | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
423 if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
424 &vp))) { |
28433 | 425 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n"); |
28416 | 426 return 0; |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
427 } |
27921 | 428 |
28026 | 429 calc_fs_rect(); |
430 | |
431 return 1; | |
432 } | |
433 | |
434 /** @brief Reconfigure the whole Direct3D. Called only | |
435 * when the video adapter becomes uncooperative. | |
436 * @return 1 on success, 0 on failure | |
437 */ | |
438 static int reconfigure_d3d(void) | |
439 { | |
28433 | 440 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>reconfigure_d3d called.\n"); |
28026 | 441 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
442 /* Destroy the offscreen, OSD and backbuffer surfaces */ |
28026 | 443 destroy_d3d_surfaces(); |
444 | |
445 /* Destroy the D3D Device */ | |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
446 if (priv->d3d_device) |
28026 | 447 IDirect3DDevice9_Release(priv->d3d_device); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
448 priv->d3d_device = NULL; |
28026 | 449 |
450 /* Stop the whole Direct3D */ | |
451 IDirect3D9_Release(priv->d3d_handle); | |
452 | |
453 /* 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
|
454 priv->d3d_handle = priv->pDirect3DCreate9(D3D_SDK_VERSION); |
28026 | 455 if (!priv->d3d_handle) { |
28433 | 456 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Initializing Direct3D failed.\n"); |
28416 | 457 return 0; |
28026 | 458 } |
459 | |
460 /* Configure Direct3D */ | |
461 if (!configure_d3d()) | |
462 return 0; | |
463 | |
464 return 1; | |
465 } | |
466 | |
467 /** @brief Resize Direct3D context on window resize. | |
468 * @return 1 on success, 0 on failure | |
469 */ | |
470 static int resize_d3d(void) | |
471 { | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
472 D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1}; |
28026 | 473 |
28433 | 474 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>resize_d3d called.\n"); |
28026 | 475 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
476 /* 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
|
477 viewport dimensions. Grow it if necessary. */ |
28026 | 478 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
479 if (vo_dwidth > priv->cur_backbuf_width || |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
480 vo_dheight > priv->cur_backbuf_height) { |
28417 | 481 if (!change_d3d_backbuffer(BACKBUFFER_RESET)) |
482 return 0; | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
483 } |
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 /* 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
|
486 * of the onscreen window, so on each resize we need new OSD dimensions. |
28026 | 487 */ |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
488 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
489 if (priv->d3d_texture_osd) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
490 IDirect3DTexture9_Release(priv->d3d_texture_osd); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
491 priv->d3d_texture_osd = NULL; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
492 |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
493 if (priv->d3d_texture_system) |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
494 IDirect3DTexture9_Release(priv->d3d_texture_system); |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
495 priv->d3d_texture_system = NULL; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
496 |
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 /* 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
|
499 * 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
|
500 * effectively recreating only the OSD. |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
501 */ |
27921 | 502 |
28026 | 503 if (!create_d3d_surfaces()) |
27921 | 504 return 0; |
28026 | 505 |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
506 if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device, |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
507 &vp))) { |
28433 | 508 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n"); |
28416 | 509 return 0; |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
510 } |
27921 | 511 |
27937 | 512 calc_fs_rect(); |
27921 | 513 |
28084 | 514 #ifdef CONFIG_FREETYPE |
515 // font needs to be adjusted | |
516 force_load_font = 1; | |
517 #endif | |
518 // OSD needs to be drawn fresh for new size | |
519 vo_osd_changed(OSDTYPE_OSD); | |
520 | |
27921 | 521 return 1; |
522 } | |
523 | |
524 /** @brief Uninitialize Direct3D and close the window. | |
525 */ | |
27928 | 526 static void uninit_d3d(void) |
27921 | 527 { |
28433 | 528 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit_d3d called.\n"); |
27921 | 529 |
28026 | 530 destroy_d3d_surfaces(); |
531 | |
532 /* Destroy the D3D Device */ | |
28086 | 533 if (priv->d3d_device) |
28026 | 534 IDirect3DDevice9_Release(priv->d3d_device); |
28086 | 535 priv->d3d_device = NULL; |
27921 | 536 |
537 /* Stop the whole D3D. */ | |
28028
62ccb6c80212
Consistency cosmetics: do not compare against NULL in ifs
reimar
parents:
28027
diff
changeset
|
538 if (priv->d3d_handle) { |
28433 | 539 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Stopping Direct3D.\n"); |
27928 | 540 IDirect3D9_Release(priv->d3d_handle); |
27921 | 541 } |
28087 | 542 priv->d3d_handle = NULL; |
27921 | 543 } |
544 | |
545 /** @brief Render a frame on the screen. | |
546 * @param mpi mpi structure with the decoded frame inside | |
547 * @return VO_TRUE on success, VO_ERROR on failure | |
548 */ | |
27928 | 549 static uint32_t render_d3d_frame(mp_image_t *mpi) |
27921 | 550 { |
551 /* Uncomment when direct rendering is implemented. | |
552 * if (mpi->flags & MP_IMGFLAG_DIRECT) ... | |
553 */ | |
554 | |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
555 /* 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
|
556 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
|
557 if (!priv->d3d_device) |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
558 return VO_TRUE; |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
559 |
27921 | 560 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
|
561 goto skip_upload; |
27921 | 562 |
27928 | 563 if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Copy a planar frame. */ |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
564 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
|
565 goto skip_upload; |
27921 | 566 } |
567 | |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
568 /* 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
|
569 if (!priv->locked_rect.pBits) { |
27970 | 570 if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
571 &priv->locked_rect, NULL, 0))) { |
28433 | 572 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Surface lock failed.\n"); |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
573 return VO_ERROR; |
27970 | 574 } |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
575 } |
27921 | 576 |
27968
1081658aa871
Move locked_rect from stack to priv struct in preparation for following patch.
reimar
parents:
27967
diff
changeset
|
577 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
|
578 mpi->height, priv->locked_rect.Pitch, mpi->stride[0]); |
27921 | 579 |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
580 skip_upload: |
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
581 /* This unlock is used for both slice_draw path and render_d3d_frame path. */ |
27928 | 582 if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) { |
28433 | 583 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface unlock failed.\n"); |
27921 | 584 return VO_ERROR; |
585 } | |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
586 priv->locked_rect.pBits = NULL; |
27921 | 587 |
27967
ad71ce76c6ce
Move the StretchRect call from draw_slices to render_d3d_frame.
reimar
parents:
27966
diff
changeset
|
588 if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { |
28433 | 589 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>BeginScene failed.\n"); |
27970 | 590 return VO_ERROR; |
27967
ad71ce76c6ce
Move the StretchRect call from draw_slices to render_d3d_frame.
reimar
parents:
27966
diff
changeset
|
591 } |
ad71ce76c6ce
Move the StretchRect call from draw_slices to render_d3d_frame.
reimar
parents:
27966
diff
changeset
|
592 |
27984
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
593 if (priv->is_clear_needed) { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
594 IDirect3DDevice9_Clear(priv->d3d_device, 0, NULL, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
595 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
|
596 priv->is_clear_needed = 0; |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
597 } |
21221fd6d994
Make sure the backbuffer is cleared when the border size might have changed.
reimar
parents:
27971
diff
changeset
|
598 |
27928 | 599 if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device, |
600 priv->d3d_surface, | |
27937 | 601 &priv->fs_panscan_rect, |
27928 | 602 priv->d3d_backbuf, |
27937 | 603 &priv->fs_movie_rect, |
27928 | 604 D3DTEXF_LINEAR))) { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
605 mp_msg(MSGT_VO, MSGL_ERR, |
28433 | 606 "<vo_direct3d>Copying frame to the backbuffer failed.\n"); |
27921 | 607 return VO_ERROR; |
608 } | |
609 | |
27928 | 610 if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { |
28433 | 611 mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>EndScene failed.\n"); |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
612 return VO_ERROR; |
27921 | 613 } |
614 | |
615 return VO_TRUE; | |
616 } | |
617 | |
618 | |
619 /** @brief Query if movie colorspace is supported by the HW. | |
620 * @return 0 on failure, device capabilities (not probed | |
621 * currently) on success. | |
622 */ | |
27928 | 623 static int query_format(uint32_t movie_fmt) |
27921 | 624 { |
625 int i; | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
626 for (i = 0; i < DISPLAY_FORMAT_TABLE_ENTRIES; i++) { |
27928 | 627 if (fmt_table[i].mplayer_fmt == movie_fmt) { |
27921 | 628 /* Test conversion from Movie colorspace to |
629 * display's target colorspace. */ | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
630 if (FAILED(IDirect3D9_CheckDeviceFormatConversion(priv->d3d_handle, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
631 D3DADAPTER_DEFAULT, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
632 D3DDEVTYPE_HAL, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
633 fmt_table[i].fourcc, |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
634 priv->desktop_fmt))) { |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
635 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Rejected image format: %s\n", |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
636 vo_format_name(fmt_table[i].mplayer_fmt)); |
27928 | 637 return 0; |
638 } | |
27921 | 639 |
27928 | 640 priv->movie_src_fmt = fmt_table[i].fourcc; |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
641 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Accepted image format: %s\n", |
27928 | 642 vo_format_name(fmt_table[i].mplayer_fmt)); |
27921 | 643 return (VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
28084 | 644 | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN); |
27921 | 645 |
646 } | |
647 } | |
648 | |
649 return 0; | |
650 } | |
651 | |
652 /**************************************************************************** | |
653 * * | |
654 * * | |
655 * * | |
656 * libvo Control / Callback functions * | |
657 * * | |
658 * * | |
659 * * | |
660 ****************************************************************************/ | |
661 | |
662 | |
663 | |
664 | |
665 /** @brief libvo Callback: Preinitialize the video card. | |
666 * Preinit the hardware just enough to be queried about | |
667 * supported formats. | |
668 * | |
669 * @return 0 on success, -1 on failure | |
670 */ | |
27928 | 671 |
27921 | 672 static int preinit(const char *arg) |
673 { | |
27928 | 674 D3DDISPLAYMODE disp_mode; |
28084 | 675 D3DCAPS9 disp_caps; |
676 DWORD texture_caps; | |
677 DWORD dev_caps; | |
27928 | 678 |
27921 | 679 /* Set to zero all global variables. */ |
28027 | 680 priv = calloc(1, sizeof(struct global_priv)); |
27928 | 681 if (!priv) { |
28433 | 682 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
|
683 goto err_out; |
27928 | 684 } |
27921 | 685 |
686 /* FIXME | |
687 > Please use subopt-helper.h for this, see vo_gl.c:preinit for | |
688 > an example of how to use it. | |
689 */ | |
690 | |
30148
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
691 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
|
692 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
|
693 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
|
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->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
|
698 if (!priv->pDirect3DCreate9) { |
517a800e940e
Modify -vo direct3d so we do not have to link against d3d9.dll, it might
reimar
parents:
28598
diff
changeset
|
699 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
|
700 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
|
701 } |
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 priv->d3d_handle = priv->pDirect3DCreate9(D3D_SDK_VERSION); |
27928 | 704 if (!priv->d3d_handle) { |
28433 | 705 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
|
706 goto err_out; |
27921 | 707 } |
708 | |
27928 | 709 if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle, |
710 D3DADAPTER_DEFAULT, | |
711 &disp_mode))) { | |
28433 | 712 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
|
713 goto err_out; |
27921 | 714 } |
715 | |
27928 | 716 /* Store in priv->desktop_fmt the user desktop's colorspace. Usually XRGB. */ |
717 priv->desktop_fmt = disp_mode.Format; | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
718 priv->cur_backbuf_width = disp_mode.Width; |
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
719 priv->cur_backbuf_height = disp_mode.Height; |
27921 | 720 |
28433 | 721 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Setting backbuffer dimensions to (%dx%d).\n", |
27928 | 722 disp_mode.Width, disp_mode.Height); |
27921 | 723 |
28084 | 724 if (FAILED(IDirect3D9_GetDeviceCaps(priv->d3d_handle, |
725 D3DADAPTER_DEFAULT, | |
726 D3DDEVTYPE_HAL, | |
727 &disp_caps))) { | |
28433 | 728 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
|
729 goto err_out; |
28084 | 730 } |
731 | |
732 /* Store relevant information reguarding caps of device */ | |
733 texture_caps = disp_caps.TextureCaps; | |
734 dev_caps = disp_caps.DevCaps; | |
735 priv->device_caps_power2_only = (texture_caps & D3DPTEXTURECAPS_POW2) && | |
736 !(texture_caps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL); | |
737 priv->device_caps_square_only = texture_caps & D3DPTEXTURECAPS_SQUAREONLY; | |
738 priv->device_texture_sys = dev_caps & D3DDEVCAPS_TEXTURESYSTEMMEMORY; | |
739 priv->max_texture_width = disp_caps.MaxTextureWidth; | |
740 priv->max_texture_height = disp_caps.MaxTextureHeight; | |
741 | |
742 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>device_caps_power2_only %d, device_caps_square_only %d\n" | |
743 "<vo_direct3d>device_texture_sys %d\n" | |
744 "<vo_direct3d>max_texture_width %d, max_texture_height %d\n", | |
745 priv->device_caps_power2_only, priv->device_caps_square_only, | |
746 priv->device_texture_sys, priv->max_texture_width, | |
747 priv->max_texture_height); | |
748 | |
27921 | 749 /* w32_common framework call. Configures window on the screen, gets |
750 * fullscreen dimensions and does other useful stuff. | |
751 */ | |
27928 | 752 if (!vo_w32_init()) { |
28433 | 753 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
|
754 goto err_out; |
27921 | 755 } |
756 | |
757 return 0; | |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
758 |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
759 err_out: |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
760 uninit(); |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
761 return -1; |
27921 | 762 } |
763 | |
764 | |
765 | |
766 /** @brief libvo Callback: Handle control requests. | |
767 * @return VO_TRUE on success, VO_NOTIMPL when not implemented | |
768 */ | |
33305
ddb45e9443ec
Remove the variable arguments from the libvo control() functions.
iive
parents:
32467
diff
changeset
|
769 static int control(uint32_t request, void *data) |
27921 | 770 { |
27928 | 771 switch (request) { |
27921 | 772 case VOCTRL_QUERY_FORMAT: |
27928 | 773 return query_format(*(uint32_t*) data); |
27921 | 774 case VOCTRL_GET_IMAGE: /* Direct Rendering. Not implemented yet. */ |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
775 mp_msg(MSGT_VO, MSGL_V, |
28433 | 776 "<vo_direct3d>Direct Rendering request. Not implemented yet.\n"); |
27921 | 777 return VO_NOTIMPL; |
778 case VOCTRL_DRAW_IMAGE: | |
27928 | 779 return render_d3d_frame(data); |
27921 | 780 case VOCTRL_FULLSCREEN: |
781 vo_w32_fullscreen(); | |
28026 | 782 resize_d3d(); |
27921 | 783 return VO_TRUE; |
784 case VOCTRL_RESET: | |
785 return VO_NOTIMPL; | |
786 case VOCTRL_PAUSE: | |
27928 | 787 priv->is_paused = 1; |
27921 | 788 return VO_TRUE; |
789 case VOCTRL_RESUME: | |
27928 | 790 priv->is_paused = 0; |
27921 | 791 return VO_TRUE; |
792 case VOCTRL_GUISUPPORT: | |
793 return VO_NOTIMPL; | |
794 case VOCTRL_SET_EQUALIZER: | |
795 return VO_NOTIMPL; | |
796 case VOCTRL_GET_EQUALIZER: | |
797 return VO_NOTIMPL; | |
798 case VOCTRL_ONTOP: | |
799 vo_w32_ontop(); | |
800 return VO_TRUE; | |
801 case VOCTRL_BORDER: | |
802 vo_w32_border(); | |
28026 | 803 resize_d3d(); |
27921 | 804 return VO_TRUE; |
805 case VOCTRL_UPDATE_SCREENINFO: | |
806 w32_update_xinerama_info(); | |
807 return VO_TRUE; | |
808 case VOCTRL_SET_PANSCAN: | |
28027 | 809 calc_fs_rect(); |
27921 | 810 return VO_TRUE; |
811 case VOCTRL_GET_PANSCAN: | |
812 return VO_TRUE; | |
813 } | |
814 return VO_FALSE; | |
815 } | |
816 | |
817 /** @brief libvo Callback: Configre the Direct3D adapter. | |
818 * @param width Movie source width | |
819 * @param height Movie source height | |
820 * @param d_width Screen (destination) width | |
821 * @param d_height Screen (destination) height | |
822 * @param options Options bitmap | |
823 * @param title Window title | |
824 * @param format Movie colorspace format (using MPlayer's | |
825 * defines, e.g. IMGFMT_YUY2) | |
826 * @return 0 on success, VO_ERROR on failure | |
827 */ | |
828 static int config(uint32_t width, uint32_t height, uint32_t d_width, | |
829 uint32_t d_height, uint32_t options, char *title, | |
830 uint32_t format) | |
831 { | |
27928 | 832 |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
833 priv->src_width = width; |
27928 | 834 priv->src_height = height; |
27921 | 835 |
836 /* w32_common framework call. Creates window on the screen with | |
837 * the given coordinates. | |
838 */ | |
27928 | 839 if (!vo_w32_config(d_width, d_height, options)) { |
28433 | 840 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Creating onscreen window failed.\n"); |
27921 | 841 return VO_ERROR; |
842 } | |
843 | |
28026 | 844 /* "config" may be called several times, so if this is not the first |
845 * call, we should destroy Direct3D adapter and surfaces before | |
846 * calling configure_d3d, which will create them again. | |
847 */ | |
848 | |
849 destroy_d3d_surfaces(); | |
850 | |
851 /* Destroy the D3D Device */ | |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
852 if (priv->d3d_device) |
28026 | 853 IDirect3DDevice9_Release(priv->d3d_device); |
28085
f2606c3433ef
Slightly simplify the conditional release/free code
reimar
parents:
28084
diff
changeset
|
854 priv->d3d_device = NULL; |
28026 | 855 |
856 if (!configure_d3d()) | |
27966 | 857 return VO_ERROR; |
858 | |
27921 | 859 return 0; /* Success */ |
860 } | |
861 | |
862 /** @brief libvo Callback: Flip next already drawn frame on the | |
863 * screen. | |
864 */ | |
865 static void flip_page(void) | |
866 { | |
28344
a69d51cd4ee3
Allocate a larger backbuffer to allow resizing without reinit.
reimar
parents:
28087
diff
changeset
|
867 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
|
868 if (!priv->d3d_device || |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
869 FAILED(IDirect3DDevice9_Present(priv->d3d_device, &rect, 0, 0, 0))) { |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
870 mp_msg(MSGT_VO, MSGL_V, |
28419
d4fbeeaa1c76
Cosmetics: remove empty line, improve some messages.
reimar
parents:
28418
diff
changeset
|
871 "<vo_direct3d>Trying to reinitialize uncooperative video adapter.\n"); |
27928 | 872 if (!reconfigure_d3d()) { |
28419
d4fbeeaa1c76
Cosmetics: remove empty line, improve some messages.
reimar
parents:
28418
diff
changeset
|
873 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization failed.\n"); |
27921 | 874 return; |
875 } | |
876 else | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
877 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Video adapter reinitialized.\n"); |
27921 | 878 } |
879 } | |
880 | |
881 /** @brief libvo Callback: Uninitializes all pointers and closes | |
882 * all D3D related stuff, | |
883 */ | |
884 static void uninit(void) | |
885 { | |
28433 | 886 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit called.\n"); |
27921 | 887 |
27928 | 888 uninit_d3d(); |
27921 | 889 vo_w32_uninit(); /* w32_common framework call */ |
30149
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
890 if (priv->d3d9_dll) |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
891 FreeLibrary(priv->d3d9_dll); |
5f8cbd711a04
Avoid memleaks when vo_direct3d initialization fails.
reimar
parents:
30148
diff
changeset
|
892 priv->d3d9_dll = NULL; |
28027 | 893 free(priv); |
27928 | 894 priv = NULL; |
27921 | 895 } |
896 | |
897 /** @brief libvo Callback: Handles video window events. | |
898 */ | |
899 static void check_events(void) | |
900 { | |
901 int flags; | |
902 /* w32_common framework call. Handles video window events. | |
903 * Updates global libvo's vo_dwidth/vo_dheight upon resize | |
904 * with the new window width/height. | |
905 */ | |
906 flags = vo_w32_check_events(); | |
907 if (flags & VO_EVENT_RESIZE) | |
28026 | 908 resize_d3d(); |
27921 | 909 |
27928 | 910 if ((flags & VO_EVENT_EXPOSE) && priv->is_paused) |
27921 | 911 flip_page(); |
912 } | |
913 | |
914 /** @brief libvo Callback: Draw slice | |
915 * @return 0 on success | |
916 */ | |
917 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y ) | |
918 { | |
27971 | 919 char *my_src; /**< Pointer to the source image */ |
920 char *dst; /**< Pointer to the destination image */ | |
921 int uv_stride; /**< Stride of the U/V planes */ | |
27921 | 922 |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
923 /* 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
|
924 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
|
925 if (!priv->d3d_device) |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
926 return 0; |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
927 |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
928 /* 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
|
929 if (!priv->locked_rect.pBits) { |
27970 | 930 if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
931 &priv->locked_rect, NULL, 0))) { |
28433 | 932 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface lock failure.\n"); |
27970 | 933 return VO_FALSE; |
934 } | |
27969
7ddd69cf214f
Lock/unlock surface only once even when drawing many slices.
reimar
parents:
27968
diff
changeset
|
935 } |
27921 | 936 |
27971 | 937 uv_stride = priv->locked_rect.Pitch / 2; |
27921 | 938 |
939 /* Copy Y */ | |
27971 | 940 dst = priv->locked_rect.pBits; |
941 dst = dst + priv->locked_rect.Pitch * y + x; | |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
942 my_src = src[0]; |
27971 | 943 memcpy_pic(dst, my_src, w, h, priv->locked_rect.Pitch, stride[0]); |
27921 | 944 |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
945 w /= 2; |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
946 h /= 2; |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
947 x /= 2; |
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
948 y /= 2; |
27921 | 949 |
950 /* Copy U */ | |
27971 | 951 dst = priv->locked_rect.pBits; |
952 dst = dst + priv->locked_rect.Pitch * priv->src_height | |
953 + uv_stride * y + x; | |
27928 | 954 if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
955 my_src = src[2]; |
27921 | 956 else |
28011
7f7ffa0eb45a
whitespace cosmetics: prettyprinting and indentation
diego
parents:
28007
diff
changeset
|
957 my_src = src[1]; |
27921 | 958 |
27971 | 959 memcpy_pic(dst, my_src, w, h, uv_stride, stride[1]); |
27921 | 960 |
961 /* Copy V */ | |
27971 | 962 dst = priv->locked_rect.pBits; |
963 dst = dst + priv->locked_rect.Pitch * priv->src_height | |
964 + uv_stride * (priv->src_height / 2) + uv_stride * y + x; | |
27928 | 965 if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) |
27971 | 966 my_src=src[1]; |
27921 | 967 else |
27971 | 968 my_src=src[2]; |
27921 | 969 |
27971 | 970 memcpy_pic(dst, my_src, w, h, uv_stride, stride[2]); |
27921 | 971 |
972 return 0; /* Success */ | |
973 } | |
974 | |
975 /** @brief libvo Callback: Unused function | |
976 */ | |
977 static int draw_frame(uint8_t *src[]) | |
978 { | |
28433 | 979 mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>draw_frame called.\n"); |
27921 | 980 return VO_FALSE; |
981 } | |
28084 | 982 |
983 /** @brief Maps MPlayer alpha to D3D | |
984 * 0x0 -> transparent and discarded by alpha test | |
985 * 0x1 -> 0xFF to become opaque | |
986 * other alpha values are inverted +1 (2 = -2) | |
987 * These values are then inverted again with | |
988 the texture filter D3DBLEND_INVSRCALPHA | |
989 */ | |
33411
320890c90a8a
vo_direct3d: Mark function only used within the file as static.
diego
parents:
33305
diff
changeset
|
990 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
|
991 unsigned char *srca, int srcstride, |
320890c90a8a
vo_direct3d: Mark function only used within the file as static.
diego
parents:
33305
diff
changeset
|
992 unsigned char* dstbase, int dststride) |
28084 | 993 { |
994 int y; | |
995 for (y = 0; y < h; y++) { | |
996 unsigned short *dst = (unsigned short*)dstbase; | |
997 int x; | |
998 for (x = 0; x < w; x++) { | |
999 dst[x] = (-srca[x] << 8) | src[x]; | |
1000 } | |
1001 src += srcstride; | |
1002 srca += srcstride; | |
1003 dstbase += dststride; | |
1004 } | |
1005 } | |
1006 | |
1007 /** @brief Callback function to render the OSD to the texture | |
1008 */ | |
1009 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | |
1010 unsigned char *srca, int stride) | |
1011 { | |
1012 D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order | |
1013 to copy MPlayer's frame inside it.*/ | |
1014 | |
1015 if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, | |
1016 &locked_rect, NULL, 0))) { | |
28433 | 1017 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>OSD texture lock failed.\n"); |
28084 | 1018 return; |
1019 } | |
1020 | |
1021 vo_draw_alpha_l8a8(w, h, src, srca, stride, | |
1022 (unsigned char *)locked_rect.pBits + locked_rect.Pitch*y0 + 2*x0, locked_rect.Pitch); | |
1023 | |
1024 /* this unlock is used for both slice_draw path and D3DRenderFrame path */ | |
1025 if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { | |
28433 | 1026 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>OSD texture unlock failed.\n"); |
28084 | 1027 return; |
1028 } | |
1029 | |
1030 priv->is_osd_populated = 1; | |
1031 } | |
1032 | |
1033 /** @brief libvo Callback: Draw OSD/Subtitles, | |
1034 */ | |
1035 static void draw_osd(void) | |
1036 { | |
28422
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
1037 // we can not render OSD if we lost the device e.g. because it was uncooperative |
34266 | 1038 // or if the OSD textures are not allocated (e.g. the window is minimized) |
1039 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
|
1040 return; |
f7ba65621809
Add checks that a D3D device is available before attempting rendering.
reimar
parents:
28421
diff
changeset
|
1041 |
28084 | 1042 if (vo_osd_changed(0)) { |
1043 D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order | |
1044 to copy MPlayer's frame inside it.*/ | |
1045 | |
1046 /* clear the OSD */ | |
1047 if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, | |
1048 &locked_rect, NULL, 0))) { | |
28433 | 1049 mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture lock failed.\n"); |
28084 | 1050 return; |
1051 } | |
1052 | |
1053 /* clear the whole texture to avoid issues due to interpolation */ | |
1054 memset(locked_rect.pBits, 0, locked_rect.Pitch * priv->osd_texture_height); | |
1055 | |
1056 /* this unlock is used for both slice_draw path and D3DRenderFrame path */ | |
1057 if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { | |
28433 | 1058 mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture unlock failed.\n"); |
28084 | 1059 return; |
1060 } | |
1061 | |
1062 priv->is_osd_populated = 0; | |
1063 /* required for if subs are in the boarder region */ | |
1064 priv->is_clear_needed = 1; | |
1065 | |
28598
4172d83194f2
Extend calc_src_dst_rects to also calculate the border values needed for
reimar
parents:
28511
diff
changeset
|
1066 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
|
1067 priv->border_x, priv->border_y, priv->src_width, priv->src_height, draw_alpha); |
28084 | 1068 |
1069 if (!priv->device_texture_sys) | |
1070 { | |
1071 /* only DMA to the shadow if its required */ | |
1072 if (FAILED(IDirect3DDevice9_UpdateTexture(priv->d3d_device, | |
1073 (IDirect3DBaseTexture9 *)priv->d3d_texture_system, | |
1074 (IDirect3DBaseTexture9 *)priv->d3d_texture_osd))) { | |
28433 | 1075 mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture transfer failed.\n"); |
28084 | 1076 return; |
1077 } | |
1078 } | |
1079 } | |
1080 | |
1081 /* update OSD */ | |
1082 | |
1083 if (priv->is_osd_populated) { | |
1084 | |
1085 struct_vertex osd_quad_vb[] = { | |
1086 {-1.0f, 1.0f, 0.0f, 0, 0 }, | |
1087 { 1.0f, 1.0f, 0.0f, 1, 0 }, | |
1088 {-1.0f,-1.0f, 0.0f, 0, 1 }, | |
1089 { 1.0f,-1.0f, 0.0f, 1, 1 } | |
1090 }; | |
1091 | |
1092 /* calculate the texture coordinates */ | |
1093 osd_quad_vb[1].tu = | |
1094 osd_quad_vb[3].tu = (float)priv->osd_width / priv->osd_texture_width; | |
1095 osd_quad_vb[2].tv = | |
1096 osd_quad_vb[3].tv = (float)priv->osd_height / priv->osd_texture_height; | |
1097 | |
1098 if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { | |
28433 | 1099 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed.\n"); |
28084 | 1100 return; |
1101 } | |
1102 | |
1103 /* turn on alpha test */ | |
1104 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, TRUE); | |
1105 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, TRUE); | |
1106 | |
1107 /* need to use a texture here (done here as we may be able to texture from system memory) */ | |
1108 IDirect3DDevice9_SetTexture(priv->d3d_device, 0, | |
1109 (IDirect3DBaseTexture9 *)(priv->device_texture_sys | |
1110 ? priv->d3d_texture_system : priv->d3d_texture_osd)); | |
1111 | |
1112 IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_MY_VERTEX); | |
1113 IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLESTRIP, 2, osd_quad_vb, sizeof(struct_vertex)); | |
1114 | |
1115 /* turn off alpha test */ | |
1116 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, FALSE); | |
1117 IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, FALSE); | |
1118 | |
1119 if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { | |
28433 | 1120 mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>EndScene failed.\n"); |
28084 | 1121 return; |
1122 } | |
1123 } | |
1124 } |