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