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