Mercurial > mplayer.hg
annotate libvo/vo_directx.c @ 8843:c70444c5b516
I have seen problems where DVD subtitles don't display
at the right time and sometimes they don't appear at
all. The problem stems from the fact that subtitle
command packets are being applied as soon as they are
read and assembled from the input stream. Sometimes,
a fully assembled subtitle packet arrives at the
spudec_assemble function before the previous subtitle
appears onscreen and thus the viewer only sees the
second subtitle. So I created a patch that queues
assembled subtitle packets and applies them at the
appropriate time within the heartbeat function. The
reset function clears the packet queue when seeking
through the video.
Tomasz Farkas <tomasz_farkas@yahoo.co.uk>
author | arpi |
---|---|
date | Wed, 08 Jan 2003 18:36:36 +0000 |
parents | 7e14d06ab255 |
children | edfe34c5405d |
rev | line source |
---|---|
7537 | 1 /****************************************************************************** |
2 * vo_directx.c: Directx v2 or later DirectDraw interface for MPlayer | |
3 * Copyright (c) 2002 Sascha Sommer <saschasommer@freenet.de>. | |
4 * | |
5 * This program is free software; you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License as published by | |
7 * the Free Software Foundation; either version 2 of the License, or | |
8 * (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. | |
18 * | |
19 *****************************************************************************/ | |
20 | |
21 #include <windows.h> | |
22 #include <windowsx.h> | |
23 #include <ddraw.h> | |
24 #include <stdlib.h> | |
25 #include <errno.h> | |
26 #include "config.h" | |
27 #include "video_out.h" | |
28 #include "video_out_internal.h" | |
29 #include "fastmemcpy.h" | |
30 #include "../input/input.h" | |
31 #include "../linux/keycodes.h" | |
32 #include "../mp_msg.h" | |
8519 | 33 #include "aspect.h" |
7537 | 34 |
35 static LPDIRECTDRAW2 g_lpdd = NULL; //DirectDraw Object | |
36 static LPDIRECTDRAWSURFACE g_lpddsPrimary = NULL; //Primary Surface: viewport through the Desktop | |
37 static LPDIRECTDRAWSURFACE g_lpddsOverlay = NULL; //Overlay Surface | |
38 static LPDIRECTDRAWSURFACE g_lpddsBack = NULL; //Back surface | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
39 static LPDIRECTDRAWCLIPPER g_lpddclipper; //clipper object, can only be used without overlay |
7537 | 40 static DDSURFACEDESC ddsdsf; //surface descripiton needed for locking |
7778
f804db78f704
10l - noticed by Soeren Mueller <soeren.mueller at webwasher.com>
faust3
parents:
7713
diff
changeset
|
41 static HINSTANCE hddraw_dll; //handle to ddraw.dll |
7537 | 42 static RECT rd; //rect of our stretched image |
43 static RECT rs; //rect of our source image | |
44 static HWND hWnd=NULL; //handle to the window | |
45 static uint32_t ontop=0; //always in foreground | |
46 static uint32_t image_width, image_height; //image width and height | |
47 static uint32_t d_image_width, d_image_height; //image width and height zoomed | |
48 static uint8_t *image=NULL; //image data | |
49 static uint32_t image_format; //image format | |
50 static uint32_t vm = 0; //exclusive mode, allows resolution switching (not implemented yet) | |
51 static uint32_t fs = 0; //display in window or fullscreen | |
52 static uint32_t dstride; //surface stride | |
7682 | 53 static uint32_t nooverlay = 0; //NonOverlay mode |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
54 static DWORD destcolorkey; //colorkey for our surface |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
55 static COLORREF windowcolor = RGB(0,0,16); //windowcolor == colorkey |
7537 | 56 |
57 extern void mplayer_put_key(int code); //let mplayer handel the keyevents | |
8667 | 58 extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); |
7537 | 59 extern int vo_doublebuffering; //tribblebuffering |
60 | |
61 /***************************************************************************** | |
62 * DirectDraw GUIDs. | |
63 * Defining them here allows us to get rid of the dxguid library during | |
64 * the linking stage. | |
65 *****************************************************************************/ | |
8667 | 66 static const GUID IID_IDirectDraw2 = |
67 { | |
68 0xB3A6F3E0,0x2B43,0x11CF,{0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56} | |
69 }; | |
7537 | 70 |
71 typedef struct directx_fourcc_caps | |
72 { | |
73 char* img_format_name; //human readable name | |
74 uint32_t img_format; //as MPlayer image format | |
75 uint32_t drv_caps; //what hw supports with this format | |
76 DDPIXELFORMAT g_ddpfOverlay; //as Directx Sourface description | |
77 } directx_fourcc_caps; | |
78 | |
79 | |
80 static directx_fourcc_caps g_ddpf[] = | |
81 { | |
82 {"YV12 ",IMGFMT_YV12 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','V','1','2'),0,0,0,0,0}}, | |
83 {"I420 ",IMGFMT_I420 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('I','4','2','0'),0,0,0,0,0}}, //yv12 with swapped uv | |
84 {"IYUV ",IMGFMT_IYUV ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('I','Y','U','V'),0,0,0,0,0}}, //same as i420 | |
85 {"YVU9 ",IMGFMT_YVU9 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','V','U','9'),0,0,0,0,0}}, | |
86 {"YUY2 ",IMGFMT_YUY2 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0}}, | |
87 // {"UYVY ",IMGFMT_UYVY ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}}, | |
88 {"RGB15",IMGFMT_RGB15,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000003E0, 0x00007C00, 0}}, //RGB 5:5:5 | |
89 {"BGR15",IMGFMT_BGR15,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x00007C00, 0x000003E0, 0x0000001F, 0}}, | |
90 {"RGB16",IMGFMT_RGB16,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0}}, //RGB 5:6:5 | |
91 {"BGR16",IMGFMT_BGR16,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000007E0, 0x0000F800, 0}}, | |
92 {"RGB24",IMGFMT_RGB24,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0}}, | |
93 {"BGR24",IMGFMT_BGR24,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0}}, | |
94 {"RGB32",IMGFMT_RGB32,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0}}, | |
95 {"BGR32",IMGFMT_BGR32,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0}} | |
96 }; | |
97 #define NUM_FORMATS (sizeof(g_ddpf) / sizeof(g_ddpf[0])) | |
98 | |
8148
5b39e79af5fe
removed get_info, using the same sheme as in libmpcodecs instead
alex
parents:
7778
diff
changeset
|
99 static vo_info_t info = |
7537 | 100 { |
101 "Directx DDraw YUV/RGB/BGR renderer", | |
102 "directx", | |
103 "Sascha Sommer <saschasommer@freenet.de>", | |
104 "" | |
105 }; | |
106 | |
8148
5b39e79af5fe
removed get_info, using the same sheme as in libmpcodecs instead
alex
parents:
7778
diff
changeset
|
107 LIBVO_EXTERN(directx) |
7537 | 108 |
109 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, | |
110 unsigned char *srca, int stride) | |
111 { | |
112 switch(image_format) { | |
113 case IMGFMT_YV12 : | |
114 case IMGFMT_I420 : | |
115 case IMGFMT_IYUV : | |
116 case IMGFMT_YVU9 : | |
8495 | 117 vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + x0,dstride); |
7537 | 118 break; |
119 case IMGFMT_YUY2 : | |
8495 | 120 vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride); |
7537 | 121 break; |
122 case IMGFMT_UYVY : | |
8495 | 123 vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + 2*x0 + 1,dstride); |
7537 | 124 break; |
125 case IMGFMT_RGB15: | |
126 case IMGFMT_BGR15: | |
127 vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride); | |
128 break; | |
129 case IMGFMT_RGB16: | |
130 case IMGFMT_BGR16: | |
131 vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride); | |
132 break; | |
133 case IMGFMT_RGB24: | |
134 case IMGFMT_BGR24: | |
135 vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride); | |
136 break; | |
137 case IMGFMT_RGB32: | |
138 case IMGFMT_BGR32: | |
139 vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride); | |
140 break; | |
141 } | |
142 } | |
143 | |
144 static void draw_osd(void) | |
145 { | |
146 vo_draw_text(image_width,image_height,draw_alpha); | |
147 } | |
148 | |
149 static uint32_t | |
150 query_format(uint32_t format) | |
151 { | |
152 uint32_t i=0; | |
153 while ( i < NUM_FORMATS ) | |
154 { | |
155 if (g_ddpf[i].img_format == format) | |
156 return g_ddpf[i].drv_caps; | |
157 i++; | |
158 } | |
159 return 0; | |
160 } | |
161 | |
162 static uint32_t Directx_CreatePrimarySurface() | |
163 { | |
164 DDSURFACEDESC ddsd; | |
165 //cleanup | |
166 if(g_lpddsPrimary)g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary); | |
167 g_lpddsPrimary=NULL; | |
168 ZeroMemory(&ddsd, sizeof(ddsd)); | |
169 ddsd.dwSize = sizeof(ddsd); | |
170 //set flags and create a primary surface. | |
171 ddsd.dwFlags = DDSD_CAPS; | |
172 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; | |
173 if(g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsd, &g_lpddsPrimary, NULL )== DD_OK) | |
174 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>primary surface created\n"); | |
175 else | |
176 { | |
177 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>could not create primary surface\n"); | |
178 return 1; | |
179 } | |
180 return 0; | |
181 } | |
182 | |
183 static uint32_t Directx_CreateOverlay(uint32_t imgfmt) | |
184 { | |
185 HRESULT ddrval; | |
186 DDSURFACEDESC ddsdOverlay; | |
187 uint32_t i=0; | |
188 while ( i < NUM_FORMATS +1 && imgfmt != g_ddpf[i].img_format) | |
189 { | |
190 i++; | |
191 } | |
192 if (!g_lpdd || !g_lpddsPrimary) | |
193 return 1; | |
194 //cleanup | |
195 if (g_lpddsOverlay)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay); | |
196 if (g_lpddsBack)g_lpddsBack->lpVtbl->Release(g_lpddsBack); | |
197 g_lpddsOverlay= NULL; | |
198 g_lpddsBack = NULL; | |
199 //create our overlay | |
200 ZeroMemory(&ddsdOverlay, sizeof(ddsdOverlay)); | |
201 ddsdOverlay.dwSize = sizeof(ddsdOverlay); | |
202 ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY; | |
203 ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT| DDSD_PIXELFORMAT; | |
204 ddsdOverlay.dwWidth=image_width; | |
205 ddsdOverlay.dwHeight=image_height; | |
206 ddsdOverlay.dwBackBufferCount=2; | |
207 ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay; | |
208 if(vo_doublebuffering) //tribblebuffering | |
209 { | |
210 if (g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL)== DD_OK) | |
211 { | |
212 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>overlay with format %s created\n",g_ddpf[i].img_format_name); | |
213 //get the surface directly attached to the primary (the back buffer) | |
214 ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; | |
215 if(g_lpddsOverlay->lpVtbl->GetAttachedSurface(g_lpddsOverlay,&ddsdOverlay.ddsCaps, &g_lpddsBack) != DD_OK) | |
216 { | |
217 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't get attached surface\n"); | |
218 return 1; | |
219 } | |
220 return 0; | |
221 } | |
222 vo_doublebuffering=0; //disable tribblebuffering | |
223 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><WARN>cannot create tribblebuffer overlay with format %s\n",g_ddpf[i].img_format_name); | |
224 } | |
225 //single buffer | |
226 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>using singlebuffer overlay\n"); | |
227 ddsdOverlay.dwBackBufferCount=0; | |
228 ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; | |
229 ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT; | |
230 ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay; | |
231 // try to create the overlay surface | |
232 ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL); | |
233 if(ddrval != DD_OK) | |
234 { | |
235 mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>"); | |
236 switch(ddrval) | |
237 { | |
238 case DDERR_INCOMPATIBLEPRIMARY: | |
239 {mp_msg(MSGT_VO, MSGL_ERR,"incompatible primary surface\n");break;} | |
240 case DDERR_INVALIDCAPS: | |
241 {mp_msg(MSGT_VO, MSGL_ERR,"invalid caps\n");break;} | |
242 case DDERR_INVALIDOBJECT: | |
243 {mp_msg(MSGT_VO, MSGL_ERR,"invalid object\n");break;} | |
244 case DDERR_INVALIDPARAMS: | |
245 {mp_msg(MSGT_VO, MSGL_ERR,"invalid parameters\n");break;} | |
246 case DDERR_INVALIDPIXELFORMAT: | |
7713 | 247 {mp_msg(MSGT_VO, MSGL_ERR,"invalid pixelformat: %s\n",g_ddpf[i].img_format_name);break;} |
7537 | 248 case DDERR_NODIRECTDRAWHW: |
249 {mp_msg(MSGT_VO, MSGL_ERR,"no directdraw hardware\n");break;} | |
250 case DDERR_NOEMULATION: | |
251 {mp_msg(MSGT_VO, MSGL_ERR,"cant emulate\n");break;} | |
252 case DDERR_NOFLIPHW: | |
253 {mp_msg(MSGT_VO, MSGL_ERR,"hardware can't do flip\n");break;} | |
254 case DDERR_NOOVERLAYHW: | |
255 {mp_msg(MSGT_VO, MSGL_ERR,"hardware can't do overlay\n");break;} | |
256 case DDERR_OUTOFMEMORY: | |
257 {mp_msg(MSGT_VO, MSGL_ERR,"not enough system memory\n");break;} | |
258 case DDERR_UNSUPPORTEDMODE: | |
259 {mp_msg(MSGT_VO, MSGL_ERR,"unsupported mode\n");break;} | |
260 case DDERR_OUTOFVIDEOMEMORY: | |
261 {mp_msg(MSGT_VO, MSGL_ERR,"not enough video memory\n");break;} | |
262 } | |
263 return 1; | |
264 } | |
265 g_lpddsBack = g_lpddsOverlay; | |
266 return 0; | |
267 } | |
268 | |
269 static uint32_t Directx_CreateBackpuffer() | |
270 { | |
271 DDSURFACEDESC ddsd; | |
272 //cleanup | |
273 if (g_lpddsBack)g_lpddsBack->lpVtbl->Release(g_lpddsBack); | |
274 g_lpddsBack=NULL; | |
275 ZeroMemory(&ddsd, sizeof(ddsd)); | |
276 ddsd.dwSize = sizeof(ddsd); | |
277 ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; | |
278 ddsd.dwFlags= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; | |
279 ddsd.dwWidth=image_width; | |
280 ddsd.dwHeight=image_height; | |
281 if(g_lpdd->lpVtbl->CreateSurface( g_lpdd, &ddsd, &g_lpddsBack, 0 ) != DD_OK ) | |
282 { | |
283 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't create backpuffer\n"); | |
284 return 1; | |
285 } | |
286 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>backbuffer created\n"); | |
287 return 0; | |
288 } | |
289 | |
290 static void uninit(void) | |
291 { | |
292 if (g_lpddclipper != NULL) g_lpddclipper->lpVtbl->Release(g_lpddclipper); | |
293 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>clipper released\n"); | |
294 if (g_lpddsBack != NULL) g_lpddsBack->lpVtbl->Release(g_lpddsBack); | |
295 g_lpddsBack = NULL; | |
296 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>back surface released\n"); | |
297 if(vo_doublebuffering) | |
298 { | |
299 if (g_lpddsOverlay != NULL)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay); | |
300 g_lpddsOverlay = NULL; | |
301 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>overlay surface released\n"); | |
302 } | |
303 if (g_lpddsPrimary != NULL) g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary); | |
7682 | 304 g_lpddsPrimary = NULL; |
305 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>primary released\n"); | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
306 if(hWnd != NULL)DestroyWindow(hWnd); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
307 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>window destroyed\n"); |
7537 | 308 if (g_lpdd != NULL) g_lpdd->lpVtbl->Release(g_lpdd); |
309 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>directdrawobject released\n"); | |
7778
f804db78f704
10l - noticed by Soeren Mueller <soeren.mueller at webwasher.com>
faust3
parents:
7713
diff
changeset
|
310 FreeLibrary( hddraw_dll); |
f804db78f704
10l - noticed by Soeren Mueller <soeren.mueller at webwasher.com>
faust3
parents:
7713
diff
changeset
|
311 hddraw_dll= NULL; |
f804db78f704
10l - noticed by Soeren Mueller <soeren.mueller at webwasher.com>
faust3
parents:
7713
diff
changeset
|
312 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>ddraw.dll freed\n"); |
7537 | 313 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>uninited\n"); |
314 } | |
315 | |
316 static uint32_t Directx_InitDirectDraw() | |
317 { | |
318 HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *); | |
319 LPDIRECTDRAW lpDDraw; | |
320 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>Initing DirectDraw\n" ); | |
321 | |
322 //load direct draw DLL: based on videolans code | |
323 hddraw_dll = LoadLibrary("DDRAW.DLL"); | |
324 if( hddraw_dll == NULL ) | |
325 { | |
326 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed loading ddraw.dll\n" ); | |
327 return 1; | |
328 } | |
329 OurDirectDrawCreate = (void *)GetProcAddress(hddraw_dll, "DirectDrawCreate"); | |
330 if ( OurDirectDrawCreate == NULL ) | |
331 { | |
332 FreeLibrary( hddraw_dll ); | |
333 hddraw_dll = NULL; | |
334 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed geting proc address\n"); | |
335 return 1; | |
336 } | |
337 // initialize DirectDraw and create directx v1 object | |
338 if (OurDirectDrawCreate( NULL, &lpDDraw, NULL ) != DD_OK ) | |
339 { | |
340 lpDDraw = NULL; | |
341 FreeLibrary( hddraw_dll ); | |
342 hddraw_dll = NULL; | |
343 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't initialize ddraw\n"); | |
344 return 1; | |
345 } | |
346 // ask IDirectDraw for IDirectDraw2 | |
347 if (lpDDraw->lpVtbl->QueryInterface(lpDDraw, &IID_IDirectDraw2, (void **)&g_lpdd) != DD_OK) | |
348 { | |
349 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>no directx 2 installed\n"); | |
350 return 1; | |
351 } | |
352 //release our old interface and free ddraw.dll | |
353 lpDDraw->lpVtbl->Release(lpDDraw); | |
7778
f804db78f704
10l - noticed by Soeren Mueller <soeren.mueller at webwasher.com>
faust3
parents:
7713
diff
changeset
|
354 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>lpDDraw released\n" ); |
7537 | 355 //set cooperativelevel: for our tests, no handle to a window is needed |
356 if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, NULL, DDSCL_NORMAL) != DD_OK) | |
357 { | |
358 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>could not set cooperativelevel for hardwarecheck\n"); | |
359 return 1; | |
360 } | |
361 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>DirectDraw Inited\n"); | |
362 return 0; | |
363 } | |
364 | |
365 static void check_events(void) | |
366 { | |
367 MSG msg; | |
368 while (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE)) | |
369 { | |
370 TranslateMessage(&msg); | |
371 DispatchMessage(&msg); | |
372 } | |
373 } | |
374 | |
8667 | 375 static uint32_t Directx_ManageDisplay(uint32_t width,uint32_t height) |
7537 | 376 { |
8667 | 377 RECT rd_window; |
7537 | 378 HRESULT ddrval; |
379 DDCAPS capsDrv; | |
380 DDOVERLAYFX ovfx; | |
8667 | 381 DWORD dwUpdateFlags=0; |
7537 | 382 HWND hWndafter; |
383 uint32_t xscreen = GetSystemMetrics(SM_CXSCREEN); | |
384 uint32_t yscreen = GetSystemMetrics(SM_CYSCREEN); | |
8667 | 385 POINT point_window; |
386 if(fs) | |
387 { | |
388 /*center and zoom image*/ | |
389 rd_window.top = 0; | |
390 rd_window.left = 0; | |
391 rd_window.right = xscreen; | |
392 rd_window.bottom = yscreen; | |
393 aspect(&width,&height,A_ZOOM); | |
394 rd.left = (xscreen-width)/2; | |
395 rd.right = rd.left+width; | |
396 rd.top = (yscreen-height)/2; | |
397 rd.bottom = rd.top + height; | |
398 } | |
399 else /*windowed*/ | |
7537 | 400 { |
401 GetClientRect (hWnd, &rd_window); | |
8667 | 402 if((rd_window.top == rd_window.bottom)&&!nooverlay) |
7537 | 403 { |
8667 | 404 /*window is minimized let's hide our overlay*/ |
7537 | 405 ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,NULL, g_lpddsPrimary, NULL, DDOVER_HIDE, NULL); //hide the overlay |
406 return 0; | |
407 } | |
8667 | 408 /*width and height are zero therefore we have to get them from the window size*/ |
409 if(!width)width = rd_window.right - rd_window.left; | |
410 if(!height)height = rd_window.bottom - rd_window.top; | |
411 point_window.x = 0; //overlayposition relative to the window | |
7537 | 412 point_window.y = 0; |
413 ClientToScreen(hWnd,&point_window); | |
8667 | 414 rd.left = point_window.x; |
7537 | 415 rd.top = point_window.y; |
8667 | 416 rd.bottom = rd.top + height; |
417 rd.right = rd.left + width; | |
418 rd_window = rd; | |
419 } | |
420 | |
421 /*ok, let's workaround some overlay limitations*/ | |
422 if(!nooverlay) | |
423 { | |
424 uint32_t uStretchFactor1000; //minimum stretch | |
425 uint32_t xstretch1000,ystretch1000; | |
426 /*get driver capabilities*/ | |
427 ZeroMemory(&capsDrv, sizeof(capsDrv)); | |
428 capsDrv.dwSize = sizeof(capsDrv); | |
429 if(g_lpdd->lpVtbl->GetCaps(g_lpdd,&capsDrv, NULL) != DD_OK)return 1; | |
430 /*do not allow to zoom or shrink if hardware isn't able to do so*/ | |
431 if((width < image_width)&& !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKX)) | |
432 { | |
433 if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKXN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only shrinkN\n"); | |
434 else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't shrink x\n"); | |
435 width=image_width; | |
436 } | |
437 else if((width > image_width)&& !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHX)) | |
438 { | |
439 if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHXN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only stretchN\n"); | |
440 else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't stretch x\n"); | |
441 width = image_width; | |
442 } | |
443 if((height < image_height) && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKY)) | |
444 { | |
445 if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKYN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only shrinkN\n"); | |
446 else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't shrink y\n"); | |
447 height = image_height; | |
448 } | |
449 else if((height > image_height ) && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHY)) | |
450 { | |
451 if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHYN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only stretchN\n"); | |
452 else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't stretch y\n"); | |
453 height = image_height; | |
454 } | |
455 /*get minimum stretch, depends on display adaptor and mode (refresh rate!) */ | |
456 uStretchFactor1000 = capsDrv.dwMinOverlayStretch>1000 ? capsDrv.dwMinOverlayStretch : 1000; | |
457 rd.right = ((width+rd.left)*uStretchFactor1000+999)/1000; | |
458 rd.bottom = (height+rd.top)*uStretchFactor1000/1000; | |
459 /*calculate xstretch1000 and ystretch1000*/ | |
7537 | 460 xstretch1000 = ((rd.right - rd.left)* 1000)/image_width ; |
461 ystretch1000 = ((rd.bottom - rd.top)* 1000)/image_height; | |
8667 | 462 /*handle move outside of window with cropping |
463 not really needed with colorkey, but shouldn't hurt*/ | |
464 rs.left=0; | |
465 rs.right=image_width; | |
466 rs.top=0; | |
467 rs.bottom=image_height; | |
468 if(!fs)rd_window = rd; /*don't crop the window !!!*/ | |
7537 | 469 if(rd.left < 0) //move out left |
470 { | |
471 rs.left=(-rd.left*1000)/xstretch1000; | |
472 rd.left = 0; | |
473 } | |
474 else rs.left=0; | |
475 if(rd.top < 0) //move out up | |
476 { | |
477 rs.top=(-rd.top*1000)/ystretch1000; | |
478 rd.top = 0; | |
479 } | |
480 else rs.top = 0; | |
481 if(rd.right > xscreen) //move out right | |
482 { | |
483 rs.right=((xscreen-rd.left)*1000)/xstretch1000; | |
484 rd.right= xscreen; | |
485 } | |
486 else rs.right = image_width; | |
487 if(rd.bottom > yscreen) //move out down | |
488 { | |
489 rs.bottom=((yscreen-rd.top)*1000)/ystretch1000; | |
490 rd.bottom= yscreen; | |
491 } | |
492 else rs.bottom= image_height; | |
8667 | 493 /*the last thing to check are alignment restrictions |
494 these expressions (x & -y) just do alignment by dropping low order bits... | |
495 so to round up, we add first, then truncate*/ | |
496 if ((capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) && capsDrv.dwAlignBoundarySrc) | |
497 rs.left = (rs.left + capsDrv.dwAlignBoundarySrc / 2) & -(signed)(capsDrv.dwAlignBoundarySrc); | |
498 if ((capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC) && capsDrv.dwAlignSizeSrc) | |
499 rs.right = rs.left + ((rs.right - rs.left + capsDrv.dwAlignSizeSrc / 2) & -(signed) (capsDrv.dwAlignSizeSrc)); | |
500 if ((capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && capsDrv.dwAlignBoundaryDest) | |
501 { | |
502 rd.left = (rd.left + capsDrv.dwAlignBoundaryDest / 2) & -(signed)(capsDrv.dwAlignBoundaryDest); | |
503 if(!fs)rd_window.left = (rd_window.left + capsDrv.dwAlignBoundaryDest / 2) & -(signed)(capsDrv.dwAlignBoundaryDest); //don't forget the window | |
504 } | |
505 if ((capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST) && capsDrv.dwAlignSizeDest) | |
506 { | |
507 rd.right = rd.left + ((rd.right - rd.left) & -(signed) (capsDrv.dwAlignSizeDest)); | |
508 if(!fs)rd_window.right = rd_window.left + ((rd_window.right - rd_window.left) & -(signed) (capsDrv.dwAlignSizeDest)); //don't forget the window | |
509 } | |
510 /*create an overlay FX structure to specify a destination color key*/ | |
511 ZeroMemory(&ovfx, sizeof(ovfx)); | |
512 ovfx.dwSize = sizeof(ovfx); | |
513 if(fs) | |
514 { | |
515 ovfx.dckDestColorkey.dwColorSpaceLowValue = 0; | |
516 ovfx.dckDestColorkey.dwColorSpaceHighValue = 0; | |
517 } | |
518 else | |
519 { | |
520 ovfx.dckDestColorkey.dwColorSpaceLowValue = destcolorkey; | |
521 ovfx.dckDestColorkey.dwColorSpaceHighValue = destcolorkey; | |
522 } | |
523 // set the flags we'll send to UpdateOverlay //DDOVER_AUTOFLIP|DDOVERFX_MIRRORLEFTRIGHT|DDOVERFX_MIRRORUPDOWN could be usefull?; | |
524 dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX; | |
525 /*if hardware can't do colorkeying set the window on top*/ | |
526 if(capsDrv.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY) dwUpdateFlags |= DDOVER_KEYDESTOVERRIDE; | |
527 else ontop = 1; | |
7537 | 528 } |
8667 | 529 /*calculate window rect with borders*/ |
530 if(!fs)AdjustWindowRect(&rd_window,WS_OVERLAPPEDWINDOW|WS_SIZEBOX,0); | |
531 | |
532 if((fs) || (!fs && ontop))hWndafter=HWND_TOPMOST; | |
533 else hWndafter=HWND_NOTOPMOST; | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
534 |
8667 | 535 /*display the window*/ |
536 SetWindowPos(hWnd, | |
537 hWndafter, | |
538 rd_window.left, | |
539 rd_window.top, | |
540 rd_window.right - rd_window.left, | |
541 rd_window.bottom - rd_window.top, | |
542 SWP_SHOWWINDOW|SWP_NOOWNERZORDER); | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
543 //printf("Window:x:%i,y:%i,w:%i,h:%i\n",rd_window.left,rd_window.top,rd_window.right - rd_window.left,rd_window.bottom - rd_window.top); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
544 //printf("Overlay:x1:%i,y1:%i,x2:%i,y2:%i,w:%i,h:%i\n",rd.left,rd.top,rd.right,rd.bottom,rd.right - rd.left,rd.bottom - rd.top); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
545 //printf("Source:x1:%i,x2:%i,y1:%i,y2:%i\n",rs.left,rs.right,rs.top,rs.bottom); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
546 //printf("Image:x:%i->%i,y:%i->%i\n",image_width,d_image_width,image_height,d_image_height); |
8667 | 547 |
548 | |
549 /*for nonoverlay mode we are finished, for overlay mode we have to display the overlay first*/ | |
550 if(nooverlay)return 0; | |
551 | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
552 ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx); |
7537 | 553 if(FAILED(ddrval)) |
554 { | |
8667 | 555 // one cause might be the driver lied about minimum stretch |
7537 | 556 // we should try upping the destination size a bit, or |
557 // perhaps shrinking the source size | |
558 mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>UpdateOverlay failed\n" ); | |
559 mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>Overlay:x1:%i,y1:%i,x2:%i,y2:%i,w:%i,h:%i\n",rd.left,rd.top,rd.right,rd.bottom,rd.right - rd.left,rd.bottom - rd.top ); | |
560 mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>"); | |
561 switch (ddrval) | |
562 { | |
563 case DDERR_NOSTRETCHHW: | |
564 {mp_msg(MSGT_VO, MSGL_ERR ,"hardware can't stretch: try to size the window back\n");break;} | |
565 case DDERR_INVALIDRECT: | |
566 {mp_msg(MSGT_VO, MSGL_ERR ,"invalid rectangle\n");break;} | |
567 case DDERR_INVALIDPARAMS: | |
568 {mp_msg(MSGT_VO, MSGL_ERR ,"invalid parameters\n");break;} | |
569 case DDERR_HEIGHTALIGN: | |
570 {mp_msg(MSGT_VO, MSGL_ERR ,"height align\n");break;} | |
571 case DDERR_XALIGN: | |
572 {mp_msg(MSGT_VO, MSGL_ERR ,"x align\n");break;} | |
573 case DDERR_UNSUPPORTED: | |
574 {mp_msg(MSGT_VO, MSGL_ERR ,"unsupported\n");break;} | |
575 case DDERR_INVALIDSURFACETYPE: | |
576 {mp_msg(MSGT_VO, MSGL_ERR ,"invalid surfacetype\n");break;} | |
577 case DDERR_INVALIDOBJECT: | |
578 {mp_msg(MSGT_VO, MSGL_ERR ,"invalid object\n");break;} | |
579 case DDERR_SURFACELOST: | |
580 { | |
581 mp_msg(MSGT_VO, MSGL_ERR ,"surfaces lost\n"); | |
582 g_lpddsOverlay->lpVtbl->Restore( g_lpddsOverlay ); //restore and try again | |
583 g_lpddsPrimary->lpVtbl->Restore( g_lpddsPrimary ); | |
584 ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx); | |
585 if(ddrval !=DD_OK)mp_msg(MSGT_VO, MSGL_FATAL ,"<vo_directx><FATAL ERROR>UpdateOverlay failed again\n" ); | |
586 break; | |
587 } | |
588 } | |
8667 | 589 /*ok we can't do anything about it -> hide overlay*/ |
7537 | 590 if(ddrval != DD_OK) |
591 { | |
592 ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,NULL, g_lpddsPrimary, NULL, DDOVER_HIDE, NULL); | |
593 return 1; | |
594 } | |
595 } | |
596 return 0; | |
597 } | |
598 | |
599 //find out supported overlay pixelformats | |
600 static uint32_t Directx_CheckOverlayPixelformats() | |
601 { | |
602 DDCAPS capsDrv; | |
603 HRESULT ddrval; | |
604 DDSURFACEDESC ddsdOverlay; | |
605 uint32_t i; | |
606 uint32_t formatcount = 0; | |
607 //get driver caps to determine overlay support | |
608 ZeroMemory(&capsDrv, sizeof(capsDrv)); | |
609 capsDrv.dwSize = sizeof(capsDrv); | |
610 ddrval = g_lpdd->lpVtbl->GetCaps(g_lpdd,&capsDrv, NULL); | |
611 if (FAILED(ddrval)) | |
612 { | |
613 mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>failed getting ddrawcaps\n"); | |
614 return 1; | |
615 } | |
616 if (!(capsDrv.dwCaps & DDCAPS_OVERLAY)) | |
617 { | |
618 mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>Your card doesn't support overlay\n"); | |
619 return 1; | |
620 } | |
621 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>testing supported overlay pixelformats\n"); | |
622 //it is not possible to query for pixel formats supported by the | |
623 //overlay hardware: try out various formats till one works | |
624 ZeroMemory(&ddsdOverlay, sizeof(ddsdOverlay)); | |
625 ddsdOverlay.dwSize = sizeof(ddsdOverlay); | |
626 ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; | |
627 ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH| DDSD_PIXELFORMAT; | |
628 ddsdOverlay.dwWidth=300; | |
629 ddsdOverlay.dwHeight=280; | |
630 ddsdOverlay.dwBackBufferCount=0; | |
631 //try to create an overlay surface using one of the pixel formats in our global list | |
632 i=0; | |
633 do | |
634 { | |
635 ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay; | |
636 ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL); | |
637 if (ddrval == DD_OK) | |
638 { | |
639 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><FORMAT OVERLAY>%i %s supported\n",i,g_ddpf[i].img_format_name); | |
640 g_ddpf[i].drv_caps = VFCAP_CSP_SUPPORTED |VFCAP_OSD |VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP; | |
641 formatcount++;} | |
642 else mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><FORMAT OVERLAY>%i %s not supported\n",i,g_ddpf[i].img_format_name); | |
643 if (g_lpddsOverlay != NULL) {g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);g_lpddsOverlay = NULL;} | |
644 } while( ++i < NUM_FORMATS ); | |
645 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>Your card supports %i of %i overlayformats\n",formatcount, NUM_FORMATS); | |
646 if (formatcount == 0) | |
647 { | |
648 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><WARN>Your card supports overlay, but we couldn't create one\n"); | |
649 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>This can have the following reasons:\n"); | |
650 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>- you are already using an overlay with another app\n"); | |
651 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>- you don't have enough videomemory\n"); | |
652 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>- vo_directx doesn't support the cards overlay pixelformat\n"); | |
653 return 1; | |
654 } | |
655 if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYMIRRORLEFTRIGHT)mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>can mirror left right\n"); //I don't have hardware which | |
656 if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYMIRRORUPDOWN )mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>can mirror up down\n"); //supports those send me one and I'll implement ;) | |
657 return 0; | |
658 } | |
659 | |
660 //find out the Pixelformat of the Primary Surface | |
661 static uint32_t Directx_CheckPrimaryPixelformat() | |
662 { | |
663 uint32_t i=0; | |
664 uint32_t formatcount = 0; | |
665 DDPIXELFORMAT ddpf; | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
666 DDSURFACEDESC ddsd; |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
667 HDC hdc; |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
668 HRESULT hres; |
8667 | 669 COLORREF rgbT=RGB(0,0,0); |
7537 | 670 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>checking primary surface\n"); |
671 memset( &ddpf, 0, sizeof( DDPIXELFORMAT )); | |
672 ddpf.dwSize = sizeof( DDPIXELFORMAT ); | |
673 //we have to create a primary surface first | |
674 if(Directx_CreatePrimarySurface()!=0)return 1; | |
675 if(g_lpddsPrimary->lpVtbl->GetPixelFormat( g_lpddsPrimary, &ddpf ) != DD_OK ) | |
676 { | |
677 mp_msg(MSGT_VO, MSGL_FATAL ,"<vo_directx><FATAL ERROR>can't get pixelformat\n"); | |
678 return 1; | |
679 } | |
680 while ( i < NUM_FORMATS ) | |
681 { | |
682 if (g_ddpf[i].g_ddpfOverlay.dwRGBBitCount == ddpf.dwRGBBitCount) | |
683 { | |
684 if (g_ddpf[i].g_ddpfOverlay.dwRBitMask == ddpf.dwRBitMask) | |
685 { | |
686 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><FORMAT PRIMARY>%i %s supported\n",i,g_ddpf[i].img_format_name); | |
7713 | 687 g_ddpf[i].drv_caps = VFCAP_CSP_SUPPORTED |VFCAP_OSD; |
7537 | 688 formatcount++; |
689 } | |
690 } | |
691 i++; | |
692 } | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
693 //get the colorkey for overlay mode |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
694 destcolorkey = CLR_INVALID; |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
695 if (windowcolor != CLR_INVALID && g_lpddsPrimary->lpVtbl->GetDC(g_lpddsPrimary,&hdc) == DD_OK) |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
696 { |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
697 rgbT = GetPixel(hdc, 0, 0); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
698 SetPixel(hdc, 0, 0, windowcolor); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
699 g_lpddsPrimary->lpVtbl->ReleaseDC(g_lpddsPrimary,hdc); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
700 } |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
701 // read back the converted color |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
702 ddsd.dwSize = sizeof(ddsd); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
703 while ((hres = g_lpddsPrimary->lpVtbl->Lock(g_lpddsPrimary,NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
704 ; |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
705 if (hres == DD_OK) |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
706 { |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
707 destcolorkey = *(DWORD *) ddsd.lpSurface; |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
708 if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32) |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
709 destcolorkey &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
710 g_lpddsPrimary->lpVtbl->Unlock(g_lpddsPrimary,NULL); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
711 } |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
712 if (windowcolor != CLR_INVALID && g_lpddsPrimary->lpVtbl->GetDC(g_lpddsPrimary,&hdc) == DD_OK) |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
713 { |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
714 SetPixel(hdc, 0, 0, rgbT); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
715 g_lpddsPrimary->lpVtbl->ReleaseDC(g_lpddsPrimary,hdc); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
716 } |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
717 //release primary |
7537 | 718 g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary); |
719 g_lpddsPrimary = NULL; | |
720 if(formatcount==0) | |
721 { | |
722 mp_msg(MSGT_VO, MSGL_FATAL ,"<vo_directx><FATAL ERROR>Unknown Pixelformat\n"); | |
723 return 1; | |
724 } | |
725 return 0; | |
726 } | |
727 | |
728 //function handles input | |
729 static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | |
730 { | |
731 switch (message) | |
732 { | |
733 case WM_DESTROY: | |
734 { | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
735 PostQuitMessage(0); |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
736 return 0; |
7537 | 737 } |
738 case WM_CLOSE: | |
739 { | |
740 mplayer_put_key('q'); | |
741 return 0; | |
742 } | |
743 case WM_WINDOWPOSCHANGED: | |
744 { | |
745 //printf("Windowposchange\n"); | |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
746 if(g_lpddsBack != NULL) //or it will crash with -vm |
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
747 { |
8667 | 748 Directx_ManageDisplay(0,0); |
7624
b1a3b979c630
This patch hopefully fixes colorkeying and a segfault in exclusive mode
arpi
parents:
7537
diff
changeset
|
749 } |
7537 | 750 break; |
751 } | |
752 case WM_SYSCOMMAND: | |
753 { | |
754 switch (wParam) | |
755 { //kill screensaver etc. | |
756 //note: works only when the window is active | |
757 //you can workaround this by disabling the allow screensaver option in | |
758 //the link to the app | |
759 case SC_SCREENSAVE: | |
760 case SC_MONITORPOWER: | |
761 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>killing screensaver\n" ); | |
762 return 0; | |
763 } | |
764 } | |
765 case WM_KEYDOWN: | |
766 { | |
767 switch (wParam) | |
768 { | |
769 case VK_LEFT: | |
770 {mplayer_put_key(KEY_LEFT);break;} | |
771 case VK_UP: | |
772 {mplayer_put_key(KEY_UP);break;} | |
773 case VK_RIGHT: | |
774 {mplayer_put_key(KEY_RIGHT);break;} | |
775 case VK_DOWN: | |
776 {mplayer_put_key(KEY_DOWN);break;} | |
777 case VK_TAB: | |
778 {mplayer_put_key(KEY_TAB);break;} | |
779 case VK_CONTROL: | |
780 {mplayer_put_key(KEY_CTRL);break;} | |
781 case VK_DELETE: | |
782 {mplayer_put_key(KEY_DELETE);break;} | |
783 case VK_INSERT: | |
784 {mplayer_put_key(KEY_INSERT);break;} | |
785 case VK_HOME: | |
786 {mplayer_put_key(KEY_HOME);break;} | |
787 case VK_END: | |
788 {mplayer_put_key(VK_END);break;} | |
789 case VK_PRIOR: | |
790 {mplayer_put_key(KEY_PAGE_UP);break;} | |
791 case VK_NEXT: | |
792 {mplayer_put_key(KEY_PAGE_DOWN);break;} | |
793 case VK_ESCAPE: | |
794 {mplayer_put_key(KEY_ESC);break;} | |
795 } | |
796 break; | |
797 } | |
798 case WM_CHAR: | |
799 { | |
800 mplayer_put_key(wParam); | |
801 break; | |
802 } | |
803 | |
804 } | |
805 return DefWindowProc(hWnd, message, wParam, lParam); | |
806 } | |
807 | |
8667 | 808 static uint32_t preinit(const char *arg) |
7537 | 809 { |
810 HINSTANCE hInstance = GetModuleHandle(NULL); | |
811 WNDCLASS wc; | |
7682 | 812 if(arg) |
813 { | |
814 if(!strcmp(arg,"noaccel")) | |
815 { | |
816 mp_msg(MSGT_VO,MSGL_V,"<vo_directx><INFO>disabled overlay\n"); | |
817 nooverlay = 1; | |
818 } | |
819 else | |
820 { | |
821 mp_msg(MSGT_VO,MSGL_ERR,"<vo_directx><ERROR>unknown subdevice: %s\n",arg); | |
822 return ENOSYS; | |
823 } | |
824 } | |
7537 | 825 if (Directx_InitDirectDraw()!= 0)return 1; //init DirectDraw |
826 if (Directx_CheckPrimaryPixelformat()!=0)return 1; | |
7682 | 827 if (!nooverlay && Directx_CheckOverlayPixelformats() == 0) //check for supported hardware |
7537 | 828 { |
829 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>hardware supports overlay\n"); | |
830 nooverlay = 0; | |
831 } | |
832 else //if we can't have overlay we create a backpuffer with the same imageformat as the primary surface | |
833 { | |
834 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>using backpuffer\n"); | |
835 nooverlay = 1; | |
836 } | |
8667 | 837 wc.style = CS_HREDRAW | CS_VREDRAW; |
838 wc.lpfnWndProc = WndProc; | |
839 wc.cbClsExtra = 0; | |
840 wc.cbWndExtra = 0; | |
841 wc.hInstance = hInstance; | |
842 wc.hCursor = LoadCursor(NULL,IDC_ARROW); | |
843 wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); | |
844 wc.hbrBackground = CreateSolidBrush(windowcolor); | |
845 wc.lpszClassName = "Mplayer - Movieplayer for Linux"; | |
846 wc.lpszMenuName = NULL; | |
847 RegisterClass(&wc); | |
848 hWnd = CreateWindow("MPlayer - Movieplayer for Linux", | |
849 "", | |
850 WS_OVERLAPPEDWINDOW| WS_SIZEBOX, | |
851 CW_USEDEFAULT, //position x | |
852 CW_USEDEFAULT, //position y | |
853 100, //width | |
854 100, //height | |
855 NULL, | |
856 NULL, | |
857 hInstance, | |
858 NULL); | |
859 mp_msg(MSGT_VO, MSGL_DBG3 ,"<vo_directx><INFO>initial mplayer window created\n"); | |
7537 | 860 mp_msg(MSGT_VO, MSGL_DBG3 ,"<vo_directx><INFO>preinit succesfully finished\n"); |
861 return 0; | |
862 } | |
863 | |
864 static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y ) | |
865 { | |
866 uint8_t *s; | |
867 uint8_t *d; | |
8490
ac40496c7d9e
1000l! I have no idea how this code worked at all before. I guess no
rfelker
parents:
8148
diff
changeset
|
868 uint32_t i=0, uvstride=dstride/2; |
7537 | 869 // copy Y |
870 d=image+dstride*y+x; | |
871 s=src[0]; | |
872 for(i=0;i<h;i++){ | |
873 memcpy(d,s,w); | |
874 s+=stride[0]; | |
8490
ac40496c7d9e
1000l! I have no idea how this code worked at all before. I guess no
rfelker
parents:
8148
diff
changeset
|
875 d+=dstride; |
7537 | 876 } |
877 | |
878 w/=2;h/=2;x/=2;y/=2; | |
879 | |
880 // copy U | |
8490
ac40496c7d9e
1000l! I have no idea how this code worked at all before. I guess no
rfelker
parents:
8148
diff
changeset
|
881 d=image+dstride*image_height + uvstride*y+x; |
8667 | 882 if(image_format == IMGFMT_YV12)s=src[2]; |
7537 | 883 else s=src[1]; |
884 for(i=0;i<h;i++){ | |
885 memcpy(d,s,w); | |
886 s+=stride[1]; | |
8490
ac40496c7d9e
1000l! I have no idea how this code worked at all before. I guess no
rfelker
parents:
8148
diff
changeset
|
887 d+=uvstride; |
7537 | 888 } |
889 | |
890 // copy V | |
8490
ac40496c7d9e
1000l! I have no idea how this code worked at all before. I guess no
rfelker
parents:
8148
diff
changeset
|
891 d=image+dstride*image_height +uvstride*(image_height/2) + uvstride*y+x; |
8667 | 892 if(image_format == IMGFMT_YV12)s=src[1]; |
7537 | 893 else s=src[2]; |
894 for(i=0;i<h;i++){ | |
895 memcpy(d,s,w); | |
896 s+=stride[2]; | |
8490
ac40496c7d9e
1000l! I have no idea how this code worked at all before. I guess no
rfelker
parents:
8148
diff
changeset
|
897 d+=uvstride; |
7537 | 898 } |
899 return 0; | |
900 } | |
901 | |
902 static void flip_page(void) | |
903 { | |
904 HRESULT dxresult; | |
8519 | 905 g_lpddsBack->lpVtbl->Unlock (g_lpddsBack,NULL); |
7537 | 906 if (vo_doublebuffering) |
907 { | |
908 // flip to the next image in the sequence | |
909 dxresult = g_lpddsOverlay->lpVtbl->Flip( g_lpddsOverlay,NULL, DDFLIP_WAIT); | |
910 if(dxresult == DDERR_SURFACELOST) | |
911 { | |
912 mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR><vo_directx><INFO>Restoring Surface\n"); | |
913 g_lpddsBack->lpVtbl->Restore( g_lpddsBack ); | |
914 dxresult = g_lpddsOverlay->lpVtbl->Flip( g_lpddsOverlay,NULL, DDFLIP_WAIT); | |
915 } | |
916 if(dxresult != DD_OK)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't flip page\n"); | |
917 } | |
8495 | 918 if(nooverlay) |
7537 | 919 { |
920 DDBLTFX ddbltfx; | |
921 // ask for the "NOTEARING" option | |
922 memset( &ddbltfx, 0, sizeof(DDBLTFX) ); | |
923 ddbltfx.dwSize = sizeof(DDBLTFX); | |
924 ddbltfx.dwDDFX = DDBLTFX_NOTEARING; | |
925 g_lpddsPrimary->lpVtbl->Blt(g_lpddsPrimary, &rd, g_lpddsBack, NULL, DDBLT_WAIT, &ddbltfx); | |
926 } | |
8495 | 927 g_lpddsBack->lpVtbl->Lock(g_lpddsBack,NULL,&ddsdsf, DDLOCK_NOSYSLOCK | DDLOCK_WAIT , NULL); |
928 dstride = ddsdsf.lPitch; | |
929 image = ddsdsf.lpSurface; | |
7537 | 930 } |
931 | |
932 static uint32_t draw_frame(uint8_t *src[]) | |
933 { | |
934 memcpy( image, *src, dstride * image_height ); | |
935 return 0; | |
936 } | |
937 | |
938 static uint32_t get_image(mp_image_t *mpi) | |
939 { | |
940 if(mpi->flags&MP_IMGFLAG_READABLE) {mp_msg(MSGT_VO, MSGL_V,"<vo_directx><ERROR>slow video ram\n");return VO_FALSE;} | |
941 if(mpi->type==MP_IMGTYPE_STATIC) {mp_msg(MSGT_VO, MSGL_V,"<vo_directx><ERROR>not static\n");return VO_FALSE;} | |
942 if((mpi->width==dstride) || (mpi->flags&(MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ACCEPT_WIDTH))) | |
943 { | |
8667 | 944 if(mpi->flags&MP_IMGFLAG_PLANAR) |
7537 | 945 { |
8667 | 946 if(image_format == IMGFMT_YV12) |
7537 | 947 { |
948 mpi->planes[2]= image + dstride*image_height; | |
949 mpi->planes[1]= image + dstride*image_height+ dstride*image_height/4; | |
8667 | 950 mpi->stride[1]=mpi->stride[2]=dstride/2; |
7537 | 951 } |
8667 | 952 else if(image_format == IMGFMT_IYUV || image_format == IMGFMT_I420) |
7537 | 953 { |
954 mpi->planes[1]= image + dstride*image_height; | |
955 mpi->planes[2]= image + dstride*image_height+ dstride*image_height/4; | |
8667 | 956 mpi->stride[1]=mpi->stride[2]=dstride/2; |
7537 | 957 } |
8667 | 958 else if(image_format == IMGFMT_YVU9) |
959 { | |
960 mpi->planes[2] = image + dstride*image_height; | |
961 mpi->planes[1] = image + dstride*image_height+ dstride*image_height/16; | |
962 mpi->stride[1]=mpi->stride[2]=dstride/4; | |
963 } | |
7537 | 964 } |
8667 | 965 mpi->planes[0]=image; |
966 mpi->stride[0]=dstride; | |
967 mpi->width=image_width; | |
968 mpi->height=image_height; | |
7537 | 969 mpi->flags|=MP_IMGFLAG_DIRECT; |
970 mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>Direct Rendering ENABLED\n"); | |
971 return VO_TRUE; | |
972 } | |
973 return VO_FALSE; | |
974 } | |
975 | |
976 static uint32_t put_image(mp_image_t *mpi){ | |
977 | |
978 uint32_t i = 0; | |
979 uint8_t *d; | |
980 uint8_t *s; | |
981 uint32_t x = mpi->x; | |
982 uint32_t y = mpi->y; | |
983 uint32_t w = mpi->w; | |
984 uint32_t h = mpi->h; | |
985 | |
8667 | 986 if((mpi->flags&MP_IMGFLAG_DIRECT)||(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)) |
7537 | 987 { |
988 mp_msg(MSGT_VO, MSGL_DBG3 ,"<vo_directx><INFO>put_image: nothing to do: drawslices\n"); | |
989 return VO_TRUE; | |
990 } | |
991 | |
992 if (mpi->flags&MP_IMGFLAG_PLANAR) | |
993 { | |
8667 | 994 |
995 if(image_format!=IMGFMT_YVU9)draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,0,0); | |
996 else | |
7537 | 997 { |
998 // copy Y | |
999 d=image+dstride*y+x; | |
1000 s=mpi->planes[0]; | |
1001 for(i=0;i<h;i++){ | |
1002 memcpy(d,s,w); | |
1003 s+=mpi->stride[0]; | |
1004 d+=dstride; | |
1005 } | |
8519 | 1006 w/=4;h/=4;x/=4;y/=4; |
7537 | 1007 // copy V |
8519 | 1008 d=image+dstride*image_height + dstride*y/4+x; |
8667 | 1009 s=mpi->planes[2]; |
7537 | 1010 for(i=0;i<h;i++){ |
1011 memcpy(d,s,w); | |
1012 s+=mpi->stride[1]; | |
8519 | 1013 d+=dstride/4; |
7537 | 1014 } |
1015 // copy U | |
8519 | 1016 d=image+dstride*image_height + dstride*image_height/16 + dstride/4*y+x; |
8667 | 1017 s=mpi->planes[1]; |
7537 | 1018 for(i=0;i<h;i++){ |
1019 memcpy(d,s,w); | |
1020 s+=mpi->stride[2]; | |
8519 | 1021 d+=dstride/4; |
7537 | 1022 } |
1023 } | |
1024 } | |
1025 else //packed | |
1026 { | |
1027 memcpy( image, mpi->planes[0], image_height * dstride); | |
1028 } | |
1029 return VO_TRUE; | |
1030 } | |
1031 | |
1032 static uint32_t | |
1033 config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t options, char *title, uint32_t format) | |
1034 { | |
1035 fs = options & 0x01; | |
1036 vm = options & 0x02; | |
1037 image_format = format; | |
1038 image_width = width; | |
1039 image_height = height; | |
8519 | 1040 d_image_width = d_width; |
1041 d_image_height = d_height; | |
1042 aspect_save_orig(image_width,image_height); | |
1043 aspect_save_prescale(d_image_width,d_image_height); | |
1044 aspect_save_screenres(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); | |
1045 aspect(&d_image_width,&d_image_height,A_NOZOOM); | |
8667 | 1046 SetWindowText(hWnd,title); |
1047 /*release all surfaces*/ | |
7682 | 1048 if (g_lpddsBack != NULL) g_lpddsBack->lpVtbl->Release(g_lpddsBack); |
1049 g_lpddsBack = NULL; | |
1050 if(vo_doublebuffering) | |
1051 { | |
1052 if (g_lpddsOverlay != NULL)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay); | |
1053 } | |
1054 g_lpddsOverlay = NULL; | |
1055 if (g_lpddsPrimary != NULL) g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary); | |
1056 g_lpddsPrimary = NULL; | |
1057 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>overlay surfaces released\n"); | |
8667 | 1058 /*set cooperativelevel*/ |
1059 if(vm) /*exclusive mode*/ | |
1060 { | |
1061 fs=1; | |
1062 if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK) | |
1063 { | |
1064 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't set cooperativelevel for exclusive mode"); | |
1065 return 1; | |
1066 } | |
1067 SetWindowLong( hWnd, GWL_STYLE, 0 ); | |
1068 /*SetDisplayMode(ddobject,width,height,bpp,refreshrate,aditionalflags)*/ | |
1069 if(g_lpdd->lpVtbl->SetDisplayMode(g_lpdd,640, 480, 16,0,0) != DD_OK) | |
1070 { | |
1071 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't set displaymode\n"); | |
1072 return 1; | |
1073 } | |
1074 aspect_save_screenres(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); | |
1075 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>using exclusive mode\n"); | |
7537 | 1076 } |
1077 else | |
1078 { | |
8667 | 1079 if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, hWnd, DDSCL_NORMAL) != DD_OK) |
7537 | 1080 { |
8667 | 1081 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't set cooperativelevel for windowed mode"); |
1082 return 1; | |
7537 | 1083 } |
8667 | 1084 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>using normal cooperativelevel\n"); |
7537 | 1085 } |
8667 | 1086 if(fs) |
1087 { | |
1088 /*remove the borders*/ | |
1089 SetWindowLong( hWnd, GWL_STYLE, 0 ); | |
1090 /*change backgroundcolor*/ | |
1091 SetClassLongA(hWnd,GCL_HBRBACKGROUND,(int)CreateSolidBrush(RGB(0,0,0))); | |
1092 /*repaint*/ | |
1093 RedrawWindow(hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_INTERNALPAINT); | |
1094 /*hide mouse*/ | |
1095 ShowCursor(FALSE); | |
1096 } | |
1097 /*create the surfaces*/ | |
1098 if(Directx_CreatePrimarySurface())return 1; | |
1099 if (!nooverlay && Directx_CreateOverlay(image_format)) | |
7537 | 1100 { |
8667 | 1101 nooverlay=1; /*overlay creation failed*/ |
1102 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><WARN>can't use overlay mode => switching to nonoverlay\n"); | |
7537 | 1103 } |
8667 | 1104 if(nooverlay) |
1105 { | |
1106 if(Directx_CreateBackpuffer()) | |
1107 { | |
1108 mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't get the driver to work on your system :(\n"); | |
1109 return 1; | |
1110 } | |
1111 mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>back surface created\n"); | |
1112 vo_doublebuffering = 0; | |
1113 /*create clipper for nonoverlay mode*/ | |
1114 if(g_lpddclipper)g_lpddclipper->lpVtbl->Release(g_lpddclipper); | |
1115 g_lpddclipper=NULL; | |
1116 if(g_lpdd->lpVtbl->CreateClipper(g_lpdd, 0, &g_lpddclipper,NULL)!= DD_OK){mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't create clipper\n");return 1;} | |
1117 if(g_lpddclipper->lpVtbl->SetHWnd (g_lpddclipper, 0, hWnd)!= DD_OK){mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't associate clipper with window\n");return 1;} | |
1118 if(g_lpddsPrimary->lpVtbl->SetClipper (g_lpddsPrimary,g_lpddclipper)!=DD_OK){mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't associate primary surface with clipper\n");return 1;} | |
1119 mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>clipper succesfully created\n"); | |
1120 } | |
1121 Directx_ManageDisplay(d_image_width,d_image_height); | |
7537 | 1122 memset(&ddsdsf, 0,sizeof(DDSURFACEDESC)); |
1123 ddsdsf.dwSize = sizeof (DDSURFACEDESC); | |
1124 g_lpddsBack->lpVtbl->Lock(g_lpddsBack,NULL,&ddsdsf, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL); | |
1125 dstride = ddsdsf.lPitch; | |
1126 image = ddsdsf.lpSurface; | |
1127 return 0; | |
1128 } | |
1129 | |
1130 static uint32_t control(uint32_t request, void *data, ...) | |
1131 { | |
1132 switch (request) { | |
1133 | |
1134 case VOCTRL_GET_IMAGE: | |
1135 return get_image(data); | |
1136 case VOCTRL_QUERY_FORMAT: | |
1137 return query_format(*((uint32_t*)data)); | |
1138 case VOCTRL_DRAW_IMAGE: | |
1139 return put_image(data); | |
1140 case VOCTRL_FULLSCREEN: | |
1141 { | |
1142 if(vm) | |
1143 { | |
1144 mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>currently we do not allow to switch from exclusive to windowed mode\n"); | |
1145 } | |
1146 else | |
1147 { | |
8667 | 1148 WINDOWPLACEMENT window_placement; |
1149 uint32_t width = 0; /*default: restore to the size it had before maximizing*/ | |
1150 uint32_t height = 0; | |
1151 window_placement.length = sizeof(WINDOWPLACEMENT); | |
1152 GetWindowPlacement(hWnd, &window_placement); | |
1153 if(fs) /*go to windowed*/ | |
1154 { | |
1155 fs = 0; | |
1156 /*prevent the screen being filled with garbage*/ | |
1157 window_placement.showCmd = SW_SHOWMINIMIZED; | |
1158 SetWindowPlacement(hWnd,&window_placement); | |
1159 /*change style and restore the window*/ | |
1160 SetWindowLong(hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW|WS_SIZEBOX); | |
1161 window_placement.showCmd = SW_SHOWNORMAL; | |
1162 SetWindowPlacement(hWnd,&window_placement ); | |
1163 /*restore backgroundcolor*/ | |
1164 SetClassLongA(hWnd,GCL_HBRBACKGROUND,(int)CreateSolidBrush(windowcolor)); | |
1165 /*never ever make a big window*/ | |
1166 if(((window_placement.rcNormalPosition.bottom - window_placement.rcNormalPosition.top)==GetSystemMetrics(SM_CYSCREEN)) | |
1167 &&((window_placement.rcNormalPosition.right - window_placement.rcNormalPosition.left)==GetSystemMetrics(SM_CXSCREEN))) | |
1168 { | |
1169 width = d_image_width; | |
1170 height = d_image_height; | |
1171 } | |
1172 /*show cursor again*/ | |
1173 ShowCursor(TRUE); | |
1174 } | |
1175 else /*go to fullscreen*/ | |
1176 { | |
1177 fs = 1; | |
1178 /*remove decoration and maximize*/ | |
1179 SetWindowLong(hWnd,GWL_STYLE,0); | |
1180 window_placement.showCmd = SW_SHOWMAXIMIZED; | |
1181 SetWindowPlacement(hWnd,&window_placement); | |
1182 /*make the window really black*/ | |
1183 SetClassLongA(hWnd,GCL_HBRBACKGROUND,(int)CreateSolidBrush(RGB(0,0,0))); | |
1184 /*hide mouse cursor in fullscreen mode*/ | |
1185 if(ShowCursor(FALSE)<0); | |
1186 else while(ShowCursor(FALSE)>=0)mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx>ShowCursor(FALSE)>=0\n"); | |
1187 } | |
1188 RedrawWindow(hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_INTERNALPAINT); | |
1189 Directx_ManageDisplay(width,height); | |
7537 | 1190 } |
1191 return VO_TRUE; | |
1192 } | |
1193 }; | |
1194 return VO_NOTIMPL; | |
1195 } |