71
71
* the linking stage.
72
72
*****************************************************************************/
73
73
#define IID_IDirectDraw7 MP_IID_IDirectDraw7
74
static const GUID MP_IID_IDirectDraw7 =
76
0x15e65ec0,0x3b9c,0x11d2,{0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b}
74
static const GUID MP_IID_IDirectDraw7 = {
75
0x15e65ec0, 0x3b9c, 0x11d2, { 0xb9, 0x2f, 0x00, 0x60, 0x97, 0x97, 0xea, 0x5b }
79
78
#define IID_IDirectDrawColorControl MP_IID_IDirectDrawColorControl
80
static const GUID MP_IID_IDirectDrawColorControl =
82
0x4b9f0ee0,0x0d7e,0x11d0,{0x9b,0x06,0x00,0xa0,0xc9,0x03,0xa3,0xb8}
79
static const GUID MP_IID_IDirectDrawColorControl = {
80
0x4b9f0ee0, 0x0d7e, 0x11d0, { 0x9b, 0x06, 0x00, 0xa0, 0xc9, 0x03, 0xa3, 0xb8 }
86
typedef struct directx_fourcc_caps
88
char* img_format_name; //human readable name
89
uint32_t img_format; //as MPlayer image format
90
uint32_t drv_caps; //what hw supports with this format
91
DDPIXELFORMAT g_ddpfOverlay; //as Directx Sourface description
92
} directx_fourcc_caps;
95
static directx_fourcc_caps g_ddpf[] =
97
{"YV12 ",IMGFMT_YV12 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','V','1','2'),0,0,0,0,0}},
98
{"I420 ",IMGFMT_I420 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('I','4','2','0'),0,0,0,0,0}}, //yv12 with swapped uv
99
{"IYUV ",IMGFMT_IYUV ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('I','Y','U','V'),0,0,0,0,0}}, //same as i420
100
{"YVU9 ",IMGFMT_YVU9 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','V','U','9'),0,0,0,0,0}},
101
{"YUY2 ",IMGFMT_YUY2 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0}},
102
{"UYVY ",IMGFMT_UYVY ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}},
103
{"BGR8 ",IMGFMT_BGR8 ,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 8, 0x00000000, 0x00000000, 0x00000000, 0}},
104
{"RGB15",IMGFMT_RGB15,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000003E0, 0x00007C00, 0}}, //RGB 5:5:5
105
{"BGR15",IMGFMT_BGR15,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x00007C00, 0x000003E0, 0x0000001F, 0}},
106
{"RGB16",IMGFMT_RGB16,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000007E0, 0x0000F800, 0}}, //RGB 5:6:5
107
{"BGR16",IMGFMT_BGR16,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0}},
108
{"RGB24",IMGFMT_RGB24,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0}},
109
{"BGR24",IMGFMT_BGR24,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0}},
110
{"RGB32",IMGFMT_RGB32,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0}},
111
{"BGR32",IMGFMT_BGR32,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0}}
83
struct directx_fourcc_caps {
84
char img_format_name[6]; //human readable name
85
uint32_t img_format; //as MPlayer image format
86
DDPIXELFORMAT g_ddpfOverlay; //as Directx Sourface description
87
} static const g_ddpf[] = {
88
{ "YV12 ", IMGFMT_YV12, { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'V', '1', '2'), 0, 0, 0, 0, 0 } },
89
{ "I420 ", IMGFMT_I420, { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('I', '4', '2', '0'), 0, 0, 0, 0, 0 } }, //yv12 with swapped uv
90
{ "IYUV ", IMGFMT_IYUV, { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('I', 'Y', 'U', 'V'), 0, 0, 0, 0, 0 } }, //same as i420
91
{ "YVU9 ", IMGFMT_YVU9, { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'V', 'U', '9'), 0, 0, 0, 0, 0 } },
92
{ "YUY2 ", IMGFMT_YUY2, { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'), 0, 0, 0, 0, 0 } },
93
{ "UYVY ", IMGFMT_UYVY, { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'), 0, 0, 0, 0, 0 } },
94
{ "BGR8 ", IMGFMT_BGR8, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 8, 0x00000000, 0x00000000, 0x00000000, 0 } },
95
{ "RGB15", IMGFMT_RGB15, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000003E0, 0x00007C00, 0 } }, //RGB 5:5:5
96
{ "BGR15", IMGFMT_BGR15, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x00007C00, 0x000003E0, 0x0000001F, 0 } },
97
{ "RGB16", IMGFMT_RGB16, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000007E0, 0x0000F800, 0 } }, //RGB 5:6:5
98
{ "BGR16", IMGFMT_BGR16, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0 } },
99
{ "RGB24", IMGFMT_RGB24, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0 } },
100
{ "BGR24", IMGFMT_BGR24, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0 } },
101
{ "RGB32", IMGFMT_RGB32, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0 } },
102
{ "BGR32", IMGFMT_BGR32, { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0 } }
113
104
#define NUM_FORMATS (sizeof(g_ddpf) / sizeof(g_ddpf[0]))
115
static const vo_info_t info =
117
"Directx DDraw YUV/RGB/BGR renderer",
119
"Sascha Sommer <saschasommer@freenet.de>",
106
// what hw supports with corresponding format in g_ddpf
107
static uint32_t drv_caps[NUM_FORMATS];
109
static const vo_info_t info = {
110
"Directx DDraw YUV/RGB/BGR renderer",
112
"Sascha Sommer <saschasommer@freenet.de>",
123
116
const LIBVO_EXTERN(directx)
125
118
static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
126
unsigned char *srca, int stride)
119
unsigned char *srca, int stride)
128
switch(image_format) {
133
vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + x0,dstride);
136
vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride);
139
vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + 2*x0 + 1,dstride);
121
switch (image_format) {
126
vo_draw_alpha_yv12(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + x0, dstride);
129
vo_draw_alpha_yuy2(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + 2 * x0, dstride);
132
vo_draw_alpha_yuy2(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + 2 * x0 + 1, dstride);
142
135
case IMGFMT_BGR15:
143
vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride);
136
vo_draw_alpha_rgb15(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + 2 * x0, dstride);
145
138
case IMGFMT_RGB16:
147
vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride);
140
vo_draw_alpha_rgb16(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + 2 * x0, dstride);
149
142
case IMGFMT_RGB24:
151
vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride);
144
vo_draw_alpha_rgb24(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + 4 * x0, dstride);
153
146
case IMGFMT_RGB32:
155
vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride);
148
vo_draw_alpha_rgb32(w, h, src, srca, stride, ((uint8_t *)image) + dstride * y0 + 4 * x0, dstride);
160
153
static void draw_osd(void)
162
vo_draw_text(image_width,image_height,draw_alpha);
155
vo_draw_text(image_width, image_height, draw_alpha);
166
query_format(uint32_t format)
158
static int query_format(uint32_t format)
169
while ( i < NUM_FORMATS )
171
if (g_ddpf[i].img_format == format)
172
return g_ddpf[i].drv_caps;
161
for (i = 0; i < NUM_FORMATS; i++)
162
if (g_ddpf[i].img_format == format)
170
} static const dd_errmap[] = {
171
{DDERR_INCOMPATIBLEPRIMARY, "incompatible primary surface"},
172
{DDERR_INVALIDCAPS, "invalid caps"},
173
{DDERR_INVALIDOBJECT, "invalid object"},
174
{DDERR_INVALIDPARAMS, "invalid parameters"},
175
{DDERR_INVALIDRECT, "invalid rectangle"},
176
{DDERR_INVALIDSURFACETYPE, "invalid surfacetype"},
177
{DDERR_NODIRECTDRAWHW, "no directdraw hardware"},
178
{DDERR_NOEMULATION, "can't emulate"},
179
{DDERR_NOFLIPHW, "hardware can't do flip"},
180
{DDERR_NOOVERLAYHW, "hardware can't do overlay"},
181
{DDERR_NOSTRETCHHW, "hardware can't stretch: try to size the window back"},
182
{DDERR_OUTOFMEMORY, "not enough system memory"},
183
{DDERR_OUTOFVIDEOMEMORY, "not enough video memory"},
184
{DDERR_UNSUPPORTED, "unsupported"},
185
{DDERR_UNSUPPORTEDMODE, "unsupported mode"},
186
{DDERR_HEIGHTALIGN, "height align"},
187
{DDERR_XALIGN, "x align"},
188
{DDERR_SURFACELOST, "surfaces lost"},
192
static const char *dd_errstr(HRESULT res)
195
for (i = 0; dd_errmap[i].errstr; i++)
196
if (dd_errmap[i].err == res)
197
return dd_errmap[i].errstr;
198
return "unknown error";
178
201
static uint32_t Directx_CreatePrimarySurface(void)
203
DDSURFACEDESC2 ddsd = { .dwSize = sizeof(ddsd) };
182
if(g_lpddsPrimary)g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
206
g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
207
g_lpddsPrimary = NULL;
185
if(vidmode)g_lpdd->lpVtbl->SetDisplayMode(g_lpdd,vm_width,vm_height,vm_bpp,vo_refresh_rate,0);
186
ZeroMemory(&ddsd, sizeof(ddsd));
187
ddsd.dwSize = sizeof(ddsd);
210
g_lpdd->lpVtbl->SetDisplayMode(g_lpdd, vm_width, vm_height, vm_bpp, vo_refresh_rate, 0);
188
211
//set flags and create a primary surface.
189
212
ddsd.dwFlags = DDSD_CAPS;
190
213
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
191
if(g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsd, &g_lpddsPrimary, NULL )== DD_OK)
192
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>primary surface created\n");
195
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>could not create primary surface\n");
214
if (g_lpdd->lpVtbl->CreateSurface(g_lpdd, &ddsd, &g_lpddsPrimary, NULL) == DD_OK)
215
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>primary surface created\n");
217
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>could not create primary surface\n");
201
223
static uint32_t Directx_CreateOverlay(uint32_t imgfmt)
204
DDSURFACEDESC2 ddsdOverlay;
206
while ( i < NUM_FORMATS && imgfmt != g_ddpf[i].img_format)
210
if (!g_lpdd || !g_lpddsPrimary || i == NUM_FORMATS)
226
DDSURFACEDESC2 ddsdOverlay = {
227
.dwSize = sizeof(ddsdOverlay),
228
.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
229
.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT,
230
.dwWidth = image_width,
231
.dwHeight = image_height,
234
ddsdOverlay.dwBackBufferCount = 2;
235
while (i < NUM_FORMATS && imgfmt != g_ddpf[i].img_format)
237
if (!g_lpdd || !g_lpddsPrimary || i == NUM_FORMATS)
213
if (g_lpddsOverlay)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
214
if (g_lpddsBack)g_lpddsBack->lpVtbl->Release(g_lpddsBack);
215
g_lpddsOverlay= NULL;
218
ZeroMemory(&ddsdOverlay, sizeof(ddsdOverlay));
219
ddsdOverlay.dwSize = sizeof(ddsdOverlay);
220
ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY;
221
ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT| DDSD_PIXELFORMAT;
222
ddsdOverlay.dwWidth=image_width;
223
ddsdOverlay.dwHeight=image_height;
224
ddsdOverlay.dwBackBufferCount=2;
225
ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay;
226
if(vo_doublebuffering) //tribblebuffering
228
if (g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL)== DD_OK)
230
mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>overlay with format %s created\n",g_ddpf[i].img_format_name);
241
g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
243
g_lpddsBack->lpVtbl->Release(g_lpddsBack);
244
g_lpddsOverlay = NULL;
247
ddsdOverlay.ddpfPixelFormat = g_ddpf[i].g_ddpfOverlay;
248
if (vo_doublebuffering) { //tribblebuffering
249
if (g_lpdd->lpVtbl->CreateSurface(g_lpdd, &ddsdOverlay, &g_lpddsOverlay, NULL) == DD_OK) {
250
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>overlay with format %s created\n", g_ddpf[i].img_format_name);
231
251
//get the surface directly attached to the primary (the back buffer)
232
252
ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
233
if(g_lpddsOverlay->lpVtbl->GetAttachedSurface(g_lpddsOverlay,&ddsdOverlay.ddsCaps, &g_lpddsBack) != DD_OK)
235
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't get attached surface\n");
240
vo_doublebuffering=0; //disable tribblebuffering
241
mp_msg(MSGT_VO, MSGL_V,"<vo_directx><WARN>cannot create tribblebuffer overlay with format %s\n",g_ddpf[i].img_format_name);
244
mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>using singlebuffer overlay\n");
245
ddsdOverlay.dwBackBufferCount=0;
246
ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
247
ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
248
ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay;
249
// try to create the overlay surface
250
ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL);
253
if(ddrval == DDERR_INVALIDPIXELFORMAT)mp_msg(MSGT_VO,MSGL_V,"<vo_directx><ERROR> invalid pixelformat: %s\n",g_ddpf[i].img_format_name);
254
else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>");
257
case DDERR_INCOMPATIBLEPRIMARY:
258
{mp_msg(MSGT_VO, MSGL_ERR,"incompatible primary surface\n");break;}
259
case DDERR_INVALIDCAPS:
260
{mp_msg(MSGT_VO, MSGL_ERR,"invalid caps\n");break;}
261
case DDERR_INVALIDOBJECT:
262
{mp_msg(MSGT_VO, MSGL_ERR,"invalid object\n");break;}
263
case DDERR_INVALIDPARAMS:
264
{mp_msg(MSGT_VO, MSGL_ERR,"invalid parameters\n");break;}
265
case DDERR_NODIRECTDRAWHW:
266
{mp_msg(MSGT_VO, MSGL_ERR,"no directdraw hardware\n");break;}
267
case DDERR_NOEMULATION:
268
{mp_msg(MSGT_VO, MSGL_ERR,"can't emulate\n");break;}
270
{mp_msg(MSGT_VO, MSGL_ERR,"hardware can't do flip\n");break;}
271
case DDERR_NOOVERLAYHW:
272
{mp_msg(MSGT_VO, MSGL_ERR,"hardware can't do overlay\n");break;}
273
case DDERR_OUTOFMEMORY:
274
{mp_msg(MSGT_VO, MSGL_ERR,"not enough system memory\n");break;}
275
case DDERR_UNSUPPORTEDMODE:
276
{mp_msg(MSGT_VO, MSGL_ERR,"unsupported mode\n");break;}
277
case DDERR_OUTOFVIDEOMEMORY:
278
{mp_msg(MSGT_VO, MSGL_ERR,"not enough video memory\n");break;}
280
mp_msg(MSGT_VO, MSGL_ERR,"create surface failed with 0x%x\n",ddrval);
253
if (g_lpddsOverlay->lpVtbl->GetAttachedSurface(g_lpddsOverlay, &ddsdOverlay.ddsCaps, &g_lpddsBack) != DD_OK) {
254
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't get attached surface\n");
259
vo_doublebuffering = 0; //disable tribblebuffering
260
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><WARN>cannot create tribblebuffer overlay with format %s\n", g_ddpf[i].img_format_name);
263
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>using singlebuffer overlay\n");
264
ddsdOverlay.dwBackBufferCount = 0;
265
ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
266
ddsdOverlay.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
267
ddsdOverlay.ddpfPixelFormat = g_ddpf[i].g_ddpfOverlay;
268
// try to create the overlay surface
269
ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd, &ddsdOverlay, &g_lpddsOverlay, NULL);
270
if (ddrval != DD_OK) {
271
if (ddrval == DDERR_INVALIDPIXELFORMAT)
272
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><ERROR> invalid pixelformat: %s\n", g_ddpf[i].img_format_name);
274
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>create surface failed: %s (0x%x)\n", dd_errstr(ddrval), ddrval);
284
277
g_lpddsBack = g_lpddsOverlay;
288
281
static uint32_t Directx_CreateBackpuffer(void)
292
if (g_lpddsBack)g_lpddsBack->lpVtbl->Release(g_lpddsBack);
294
ZeroMemory(&ddsd, sizeof(ddsd));
295
ddsd.dwSize = sizeof(ddsd);
296
ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
297
ddsd.dwFlags= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
298
ddsd.dwWidth=image_width;
299
ddsd.dwHeight=image_height;
300
if(g_lpdd->lpVtbl->CreateSurface( g_lpdd, &ddsd, &g_lpddsBack, 0 ) != DD_OK )
302
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't create backpuffer\n");
305
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>backbuffer created\n");
283
DDSURFACEDESC2 ddsd = {
284
.dwSize = sizeof(ddsd),
285
.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
286
.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT,
287
.dwWidth = image_width,
288
.dwHeight = image_height,
292
g_lpddsBack->lpVtbl->Release(g_lpddsBack);
294
if (g_lpdd->lpVtbl->CreateSurface(g_lpdd, &ddsd, &g_lpddsBack, 0) != DD_OK) {
295
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't create backpuffer\n");
298
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>backbuffer created\n");
309
302
static void uninit(void)
313
g_cc->lpVtbl->Release(g_cc);
316
if (g_lpddclipper != NULL) g_lpddclipper->lpVtbl->Release(g_lpddclipper);
317
g_lpddclipper = NULL;
318
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>clipper released\n");
319
if (g_lpddsBack != NULL) g_lpddsBack->lpVtbl->Release(g_lpddsBack);
321
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>back surface released\n");
322
if(vo_doublebuffering && !nooverlay)
324
if (g_lpddsOverlay != NULL)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
305
g_cc->lpVtbl->Release(g_cc);
308
g_lpddclipper->lpVtbl->Release(g_lpddclipper);
309
g_lpddclipper = NULL;
310
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>clipper released\n");
312
g_lpddsBack->lpVtbl->Release(g_lpddsBack);
314
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>back surface released\n");
315
if (vo_doublebuffering && !nooverlay) {
317
g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
325
318
g_lpddsOverlay = NULL;
326
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>overlay surface released\n");
328
if (g_lpddsPrimary != NULL) g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
319
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>overlay surface released\n");
322
g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
329
323
g_lpddsPrimary = NULL;
330
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>primary released\n");
331
if (colorbrush) DeleteObject(colorbrush);
333
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>GDI resources deleted\n");
335
if(vidmode)g_lpdd->lpVtbl->RestoreDisplayMode(g_lpdd);
336
g_lpdd->lpVtbl->Release(g_lpdd);
338
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>directdrawobject released\n");
339
FreeLibrary( hddraw_dll);
341
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>ddraw.dll freed\n");
342
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>uninitialized\n");
324
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>primary released\n");
326
DeleteObject(colorbrush);
328
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>GDI resources deleted\n");
331
g_lpdd->lpVtbl->RestoreDisplayMode(g_lpdd);
332
g_lpdd->lpVtbl->Release(g_lpdd);
334
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>directdrawobject released\n");
335
FreeLibrary(hddraw_dll);
337
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>ddraw.dll freed\n");
338
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>uninitialized\n");
346
static BOOL WINAPI EnumCallbackEx(GUID FAR *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
342
static BOOL WINAPI EnumCallbackEx(GUID FAR *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
349
345
lpDriverDescription = "Primary Display Adapter";
350
mp_msg(MSGT_VO, MSGL_INFO ,"<vo_directx> adapter %d: %s", adapter_count, lpDriverDescription);
346
mp_msg(MSGT_VO, MSGL_INFO, "<vo_directx> adapter %d: %s", adapter_count, lpDriverDescription);
352
if(adapter_count == vo_adapter_num){
348
if (adapter_count == vo_adapter_num) {
354
350
selected_guid_ptr = NULL;
357
selected_guid = *lpGUID;
352
selected_guid = *lpGUID;
358
353
selected_guid_ptr = &selected_guid;
361
mp_msg(MSGT_VO, MSGL_INFO ,"\t\t<--");
356
mp_msg(MSGT_VO, MSGL_INFO, "\t\t<--");
363
mp_msg(MSGT_VO, MSGL_INFO ,"\n");
358
mp_msg(MSGT_VO, MSGL_INFO, "\n");
370
365
static uint32_t Directx_InitDirectDraw(void)
372
HRESULT (WINAPI *OurDirectDrawCreateEx)(GUID *,LPVOID *, REFIID,IUnknown FAR *);
374
LPDIRECTDRAWENUMERATEEX OurDirectDrawEnumerateEx;
378
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>Initing DirectDraw\n" );
380
//load direct draw DLL: based on videolans code
381
hddraw_dll = LoadLibrary("DDRAW.DLL");
382
if( hddraw_dll == NULL )
384
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed loading ddraw.dll\n" );
367
HRESULT (WINAPI *OurDirectDrawCreateEx)(GUID *, LPVOID *, REFIID, IUnknown FAR *);
368
DDSURFACEDESC2 ddsd = {
369
.dwSize = sizeof(ddsd),
370
.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT,
372
LPDIRECTDRAWENUMERATEEX OurDirectDrawEnumerateEx;
376
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>Initing DirectDraw\n");
378
//load direct draw DLL: based on videolans code
379
hddraw_dll = LoadLibrary("DDRAW.DLL");
381
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>failed loading ddraw.dll\n");
388
if(vo_adapter_num){ //display other than default
389
OurDirectDrawEnumerateEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress(hddraw_dll,"DirectDrawEnumerateExA");
390
if (!OurDirectDrawEnumerateEx){
391
FreeLibrary( hddraw_dll );
385
if (vo_adapter_num) { //display other than default
386
OurDirectDrawEnumerateEx = (LPDIRECTDRAWENUMERATEEX)GetProcAddress(hddraw_dll, "DirectDrawEnumerateExA");
387
if (!OurDirectDrawEnumerateEx) {
388
FreeLibrary(hddraw_dll);
392
389
hddraw_dll = NULL;
393
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed geting proc address: DirectDrawEnumerateEx\n");
394
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>no directx 7 or higher installed\n");
390
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>failed geting proc address: DirectDrawEnumerateEx\n");
391
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>no directx 7 or higher installed\n");
398
395
// enumerate all display devices attached to the desktop
399
OurDirectDrawEnumerateEx(EnumCallbackEx, NULL, DDENUM_ATTACHEDSECONDARYDEVICES );
401
if(vo_adapter_num >= adapter_count)
402
mp_msg(MSGT_VO, MSGL_ERR,"Selected adapter (%d) doesn't exist: Default Display Adapter selected\n",vo_adapter_num);
405
OurDirectDrawCreateEx = (void *)GetProcAddress(hddraw_dll, "DirectDrawCreateEx");
406
if ( OurDirectDrawCreateEx == NULL )
408
FreeLibrary( hddraw_dll );
410
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed geting proc address: DirectDrawCreateEx\n");
414
// initialize DirectDraw and create directx v7 object
415
if (OurDirectDrawCreateEx(selected_guid_ptr, (VOID**)&g_lpdd, &IID_IDirectDraw7, NULL ) != DD_OK )
417
FreeLibrary( hddraw_dll );
419
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't initialize ddraw\n");
423
//get current screen siz for selected monitor ...
424
ddsd.dwSize=sizeof(ddsd);
425
ddsd.dwFlags=DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
426
g_lpdd->lpVtbl->GetDisplayMode(g_lpdd, &ddsd);
427
if(vo_screenwidth && vo_screenheight)
429
vm_height=vo_screenheight;
430
vm_width=vo_screenwidth;
396
OurDirectDrawEnumerateEx(EnumCallbackEx, NULL, DDENUM_ATTACHEDSECONDARYDEVICES);
398
if (vo_adapter_num >= adapter_count)
399
mp_msg(MSGT_VO, MSGL_ERR, "Selected adapter (%d) doesn't exist: Default Display Adapter selected\n", vo_adapter_num);
402
OurDirectDrawCreateEx = (void *)GetProcAddress(hddraw_dll, "DirectDrawCreateEx");
403
if (!OurDirectDrawCreateEx) {
404
FreeLibrary(hddraw_dll);
406
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>failed geting proc address: DirectDrawCreateEx\n");
410
// initialize DirectDraw and create directx v7 object
411
if (OurDirectDrawCreateEx(selected_guid_ptr, (VOID **)&g_lpdd, &IID_IDirectDraw7, NULL) != DD_OK) {
412
FreeLibrary(hddraw_dll);
414
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't initialize ddraw\n");
418
//get current screen siz for selected monitor ...
419
g_lpdd->lpVtbl->GetDisplayMode(g_lpdd, &ddsd);
420
if (vo_screenwidth && vo_screenheight) {
421
vm_height = vo_screenheight;
422
vm_width = vo_screenwidth;
424
vm_height = ddsd.dwHeight;
425
vm_width = ddsd.dwWidth;
434
vm_height=ddsd.dwHeight;
435
vm_width=ddsd.dwWidth;
439
if(vo_dbpp)vm_bpp=vo_dbpp;
440
else vm_bpp=ddsd.ddpfPixelFormat.dwRGBBitCount;
443
if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, vo_w32_window, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK)
445
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't set cooperativelevel for exclusive mode\n");
448
/*SetDisplayMode(ddobject,width,height,bpp,refreshrate,aditionalflags)*/
449
if(g_lpdd->lpVtbl->SetDisplayMode(g_lpdd,vm_width, vm_height, vm_bpp,0,0) != DD_OK)
451
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't set displaymode\n");
454
mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>Initialized adapter %i for %i x %i @ %i \n",vo_adapter_num,vm_width,vm_height,vm_bpp);
457
if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, vo_w32_window, DDSCL_NORMAL) != DD_OK) // or DDSCL_SETFOCUSWINDOW
459
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>could not set cooperativelevel for hardwarecheck\n");
462
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>DirectDraw Initialized\n");
431
vm_bpp = ddsd.ddpfPixelFormat.dwRGBBitCount;
434
if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, vo_w32_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) != DD_OK) {
435
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't set cooperativelevel for exclusive mode\n");
438
/*SetDisplayMode(ddobject,width,height,bpp,refreshrate,aditionalflags)*/
439
if (g_lpdd->lpVtbl->SetDisplayMode(g_lpdd, vm_width, vm_height, vm_bpp, 0, 0) != DD_OK) {
440
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't set displaymode\n");
443
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>Initialized adapter %i for %i x %i @ %i \n", vo_adapter_num, vm_width, vm_height, vm_bpp);
446
if (g_lpdd->lpVtbl->SetCooperativeLevel(g_lpdd, vo_w32_window, DDSCL_NORMAL) != DD_OK) { // or DDSCL_SETFOCUSWINDOW
447
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>could not set cooperativelevel for hardwarecheck\n");
450
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>DirectDraw Initialized\n");
466
454
static uint32_t Directx_ManageDisplay(void)
471
DWORD dwUpdateFlags=0;
457
DDCAPS capsDrv = { .dwSize = sizeof(capsDrv) };
458
DDOVERLAYFX ovfx = { .dwSize = sizeof(ovfx) };
459
DWORD dwUpdateFlags = 0;
474
462
rd.left = vo_dx - xinerama_x;
475
463
rd.top = vo_dy - xinerama_y;
479
467
aspect(&width, &height, A_WINZOOM);
480
468
panscan_calc_windowed();
481
width += vo_panscan_x;
482
height += vo_panscan_y;
483
width = FFMIN(width, vo_screenwidth);
484
height = FFMIN(height, vo_screenheight);
485
rd.left += (vo_dwidth - width ) / 2;
469
width += vo_panscan_x;
470
height += vo_panscan_y;
471
width = FFMIN(width, vo_screenwidth);
472
height = FFMIN(height, vo_screenheight);
473
rd.left += (vo_dwidth - width) / 2;
486
474
rd.top += (vo_dheight - height) / 2;
488
rd.right=rd.left+width;
489
rd.bottom=rd.top+height;
491
/*ok, let's workaround some overlay limitations*/
494
uint32_t uStretchFactor1000; //minimum stretch
495
uint32_t xstretch1000,ystretch1000;
496
/*get driver capabilities*/
497
ZeroMemory(&capsDrv, sizeof(capsDrv));
498
capsDrv.dwSize = sizeof(capsDrv);
499
if(g_lpdd->lpVtbl->GetCaps(g_lpdd,&capsDrv, NULL) != DD_OK)return 1;
500
/*get minimum stretch, depends on display adaptor and mode (refresh rate!) */
501
uStretchFactor1000 = capsDrv.dwMinOverlayStretch>1000 ? capsDrv.dwMinOverlayStretch : 1000;
502
rd.right = ((width+rd.left)*uStretchFactor1000+999)/1000;
503
rd.bottom = (height+rd.top)*uStretchFactor1000/1000;
476
rd.right = rd.left + width;
477
rd.bottom = rd.top + height;
479
/*ok, let's workaround some overlay limitations*/
481
uint32_t uStretchFactor1000; //minimum stretch
482
uint32_t xstretch1000, ystretch1000;
484
if (!width || !height) {
485
// window is minimized, so we should hide the overlay in case
486
// colorkeying is not used or working.
487
// In addition trying to set width/height to 0 would crash
488
g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay, NULL, g_lpddsPrimary, NULL, DDOVER_HIDE, NULL);
492
/*get driver capabilities*/
493
if (g_lpdd->lpVtbl->GetCaps(g_lpdd, &capsDrv, NULL) != DD_OK)
495
/*get minimum stretch, depends on display adaptor and mode (refresh rate!) */
496
uStretchFactor1000 = capsDrv.dwMinOverlayStretch > 1000 ? capsDrv.dwMinOverlayStretch : 1000;
497
rd.right = ((width + rd.left) * uStretchFactor1000 + 999) / 1000;
498
rd.bottom = (height + rd.top) * uStretchFactor1000 / 1000;
504
499
/*calculate xstretch1000 and ystretch1000*/
505
xstretch1000 = ((rd.right - rd.left)* 1000)/image_width ;
506
ystretch1000 = ((rd.bottom - rd.top)* 1000)/image_height;
508
rs.right=image_width;
510
rs.bottom=image_height;
511
if(rd.left < 0)rs.left=(-rd.left*1000)/xstretch1000;
512
if(rd.top < 0)rs.top=(-rd.top*1000)/ystretch1000;
513
if(rd.right > vo_screenwidth)rs.right=((vo_screenwidth-rd.left)*1000)/xstretch1000;
514
if(rd.bottom > vo_screenheight)rs.bottom=((vo_screenheight-rd.top)*1000)/ystretch1000;
515
/*do not allow to zoom or shrink if hardware isn't able to do so*/
516
if((width < image_width)&& !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKX))
518
if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKXN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only shrinkN\n");
519
else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't shrink x\n");
520
rd.right=rd.left+image_width;
522
else if((width > image_width)&& !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHX))
524
if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHXN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only stretchN\n");
525
else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't stretch x\n");
526
rd.right = rd.left+image_width;
528
if((height < image_height) && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKY))
530
if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKYN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only shrinkN\n");
531
else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't shrink y\n");
532
rd.bottom = rd.top + image_height;
534
else if((height > image_height ) && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHY))
536
if(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHYN)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can only stretchN\n");
537
else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't stretch y\n");
538
rd.bottom = rd.top + image_height;
540
/*the last thing to check are alignment restrictions
541
these expressions (x & -y) just do alignment by dropping low order bits...
542
so to round up, we add first, then truncate*/
543
if((capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) && capsDrv.dwAlignBoundarySrc)
544
rs.left = (rs.left + capsDrv.dwAlignBoundarySrc / 2) & -(signed)(capsDrv.dwAlignBoundarySrc);
545
if((capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC) && capsDrv.dwAlignSizeSrc)
546
rs.right = rs.left + ((rs.right - rs.left + capsDrv.dwAlignSizeSrc / 2) & -(signed) (capsDrv.dwAlignSizeSrc));
547
if((capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && capsDrv.dwAlignBoundaryDest)
548
rd.left = (rd.left + capsDrv.dwAlignBoundaryDest / 2) & -(signed)(capsDrv.dwAlignBoundaryDest);
549
if((capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST) && capsDrv.dwAlignSizeDest)
550
rd.right = rd.left + ((rd.right - rd.left) & -(signed) (capsDrv.dwAlignSizeDest));
551
/*create an overlay FX structure to specify a destination color key*/
552
ZeroMemory(&ovfx, sizeof(ovfx));
553
ovfx.dwSize = sizeof(ovfx);
556
ovfx.dckDestColorkey.dwColorSpaceLowValue = 0;
500
xstretch1000 = ((rd.right - rd.left) * 1000) / image_width;
501
ystretch1000 = ((rd.bottom - rd.top) * 1000) / image_height;
503
rs.right = image_width;
505
rs.bottom = image_height;
507
rs.left = (-rd.left * 1000) / xstretch1000;
509
rs.top = (-rd.top * 1000) / ystretch1000;
510
if (rd.right > vo_screenwidth)
511
rs.right = ((vo_screenwidth - rd.left) * 1000) / xstretch1000;
512
if (rd.bottom > vo_screenheight)
513
rs.bottom = ((vo_screenheight - rd.top) * 1000) / ystretch1000;
514
/*do not allow to zoom or shrink if hardware isn't able to do so*/
515
if (width < image_width && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKX)) {
516
if (capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKXN)
517
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can only shrinkN\n");
519
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can't shrink x\n");
520
rd.right = rd.left + image_width;
521
} else if (width > image_width && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHX)) {
522
if (capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHXN)
523
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can only stretchN\n");
525
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can't stretch x\n");
526
rd.right = rd.left + image_width;
528
if (height < image_height && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKY)) {
529
if (capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSHRINKYN)
530
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can only shrinkN\n");
532
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can't shrink y\n");
533
rd.bottom = rd.top + image_height;
534
} else if (height > image_height && !(capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHY)) {
535
if (capsDrv.dwFXCaps & DDFXCAPS_OVERLAYSTRETCHYN)
536
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can only stretchN\n");
538
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can't stretch y\n");
539
rd.bottom = rd.top + image_height;
541
/*the last thing to check are alignment restrictions
542
* these expressions (x & -y) just do alignment by dropping low order bits...
543
* so to round up, we add first, then truncate*/
544
if ((capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) && capsDrv.dwAlignBoundarySrc)
545
rs.left = (rs.left + capsDrv.dwAlignBoundarySrc / 2) & - (signed)(capsDrv.dwAlignBoundarySrc);
546
if ((capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC) && capsDrv.dwAlignSizeSrc)
547
rs.right = rs.left + ((rs.right - rs.left + capsDrv.dwAlignSizeSrc / 2) & - (signed)(capsDrv.dwAlignSizeSrc));
548
if ((capsDrv.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && capsDrv.dwAlignBoundaryDest)
549
rd.left = (rd.left + capsDrv.dwAlignBoundaryDest / 2) & - (signed)(capsDrv.dwAlignBoundaryDest);
550
if ((capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST) && capsDrv.dwAlignSizeDest)
551
rd.right = rd.left + ((rd.right - rd.left) & - (signed)(capsDrv.dwAlignSizeDest));
552
/*create an overlay FX structure to specify a destination color key*/
553
if (vo_fs || vidmode) {
554
ovfx.dckDestColorkey.dwColorSpaceLowValue = 0;
557
555
ovfx.dckDestColorkey.dwColorSpaceHighValue = 0;
561
ovfx.dckDestColorkey.dwColorSpaceLowValue = destcolorkey;
557
ovfx.dckDestColorkey.dwColorSpaceLowValue = destcolorkey;
562
558
ovfx.dckDestColorkey.dwColorSpaceHighValue = destcolorkey;
564
560
// set the flags we'll send to UpdateOverlay //DDOVER_AUTOFLIP|DDOVERFX_MIRRORLEFTRIGHT|DDOVERFX_MIRRORUPDOWN could be useful?;
565
561
dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX;
566
562
/*if hardware can't do colorkeying set the window on top*/
567
if(capsDrv.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY) dwUpdateFlags |= DDOVER_KEYDESTOVERRIDE;
568
else if (!tmp_image) vo_ontop = 1;
563
if (capsDrv.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY)
564
dwUpdateFlags |= DDOVER_KEYDESTOVERRIDE;
572
568
g_lpddclipper->lpVtbl->SetHWnd(g_lpddclipper, 0, vo_w32_window);
575
571
/*make sure the overlay is inside the screen*/
576
if(rd.left<0)rd.left=0;
577
if(rd.right>vo_screenwidth)rd.right=vo_screenwidth;
578
if(rd.top<0)rd.top=0;
579
if(rd.bottom>vo_screenheight)rd.bottom=vo_screenheight;
572
rd.top = FFMAX(rd.top, 0);
573
rd.left = FFMAX(rd.left, 0);
574
rd.bottom = FFMIN(rd.bottom, vo_screenheight);
575
rd.right = FFMIN(rd.right, vo_screenwidth);
581
/*for nonoverlay mode we are finished, for overlay mode we have to display the overlay first*/
582
if(nooverlay)return 0;
577
/*for nonoverlay mode we are finished, for overlay mode we have to display the overlay first*/
584
581
// printf("overlay: %i %i %ix%i\n",rd.left,rd.top,rd.right - rd.left,rd.bottom - rd.top);
585
ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
582
ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay, &rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
583
if (FAILED(ddrval)) {
588
584
// one cause might be the driver lied about minimum stretch
589
585
// we should try upping the destination size a bit, or
590
586
// perhaps shrinking the source size
591
mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>UpdateOverlay failed\n" );
592
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 );
593
mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>");
596
case DDERR_NOSTRETCHHW:
597
{mp_msg(MSGT_VO, MSGL_ERR ,"hardware can't stretch: try to size the window back\n");break;}
598
case DDERR_INVALIDRECT:
599
{mp_msg(MSGT_VO, MSGL_ERR ,"invalid rectangle\n");break;}
600
case DDERR_INVALIDPARAMS:
601
{mp_msg(MSGT_VO, MSGL_ERR ,"invalid parameters\n");break;}
602
case DDERR_HEIGHTALIGN:
603
{mp_msg(MSGT_VO, MSGL_ERR ,"height align\n");break;}
605
{mp_msg(MSGT_VO, MSGL_ERR ,"x align\n");break;}
606
case DDERR_UNSUPPORTED:
607
{mp_msg(MSGT_VO, MSGL_ERR ,"unsupported\n");break;}
608
case DDERR_INVALIDSURFACETYPE:
609
{mp_msg(MSGT_VO, MSGL_ERR ,"invalid surfacetype\n");break;}
610
case DDERR_INVALIDOBJECT:
611
{mp_msg(MSGT_VO, MSGL_ERR ,"invalid object\n");break;}
612
case DDERR_SURFACELOST:
614
mp_msg(MSGT_VO, MSGL_ERR ,"surfaces lost\n");
615
g_lpddsOverlay->lpVtbl->Restore( g_lpddsOverlay ); //restore and try again
616
g_lpddsPrimary->lpVtbl->Restore( g_lpddsPrimary );
617
ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
618
if(ddrval !=DD_OK)mp_msg(MSGT_VO, MSGL_FATAL ,"<vo_directx><FATAL ERROR>UpdateOverlay failed again\n" );
622
mp_msg(MSGT_VO, MSGL_ERR ," 0x%x\n",ddrval);
624
/*ok we can't do anything about it -> hide overlay*/
627
ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay,NULL, g_lpddsPrimary, NULL, DDOVER_HIDE, NULL);
587
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>UpdateOverlay failed\n");
588
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);
589
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>%s (0x%x)\n", dd_errstr(ddrval), ddrval);
590
if (ddrval == DDERR_SURFACELOST) {
591
g_lpddsOverlay->lpVtbl->Restore(g_lpddsOverlay); //restore and try again
592
g_lpddsPrimary->lpVtbl->Restore(g_lpddsPrimary);
593
ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay, &rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
595
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>UpdateOverlay failed again\n");
597
/*ok we can't do anything about it -> hide overlay*/
598
if (ddrval != DD_OK) {
599
ddrval = g_lpddsOverlay->lpVtbl->UpdateOverlay(g_lpddsOverlay, NULL, g_lpddsPrimary, NULL, DDOVER_HIDE, NULL);
648
620
//find out supported overlay pixelformats
649
621
static uint32_t Directx_CheckOverlayPixelformats(void)
653
DDSURFACEDESC2 ddsdOverlay;
655
uint32_t formatcount = 0;
656
//get driver caps to determine overlay support
657
ZeroMemory(&capsDrv, sizeof(capsDrv));
658
capsDrv.dwSize = sizeof(capsDrv);
659
ddrval = g_lpdd->lpVtbl->GetCaps(g_lpdd,&capsDrv, NULL);
662
mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>failed getting ddrawcaps\n");
665
if (!(capsDrv.dwCaps & DDCAPS_OVERLAY))
667
mp_msg(MSGT_VO, MSGL_ERR ,"<vo_directx><ERROR>Your card doesn't support overlay\n");
670
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>testing supported overlay pixelformats\n");
623
DDCAPS capsDrv = { .dwSize = sizeof(capsDrv) };
625
DDSURFACEDESC2 ddsdOverlay = {
626
.dwSize = sizeof(ddsdOverlay),
627
.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
628
.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT,
633
uint32_t formatcount = 0;
634
ddsdOverlay.dwBackBufferCount = 0;
635
//get driver caps to determine overlay support
636
ddrval = g_lpdd->lpVtbl->GetCaps(g_lpdd, &capsDrv, NULL);
637
if (FAILED(ddrval)) {
638
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>failed getting ddrawcaps\n");
641
if (!(capsDrv.dwCaps & DDCAPS_OVERLAY)) {
642
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>Your card doesn't support overlay\n");
645
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>testing supported overlay pixelformats\n");
671
646
//it is not possible to query for pixel formats supported by the
672
647
//overlay hardware: try out various formats till one works
673
ZeroMemory(&ddsdOverlay, sizeof(ddsdOverlay));
674
ddsdOverlay.dwSize = sizeof(ddsdOverlay);
675
ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
676
ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH| DDSD_PIXELFORMAT;
677
ddsdOverlay.dwWidth=300;
678
ddsdOverlay.dwHeight=280;
679
ddsdOverlay.dwBackBufferCount=0;
680
648
//try to create an overlay surface using one of the pixel formats in our global list
684
ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay;
685
ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL);
688
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><FORMAT OVERLAY>%i %s supported\n",i,g_ddpf[i].img_format_name);
689
g_ddpf[i].drv_caps = VFCAP_CSP_SUPPORTED |VFCAP_OSD |VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP;
691
else mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><FORMAT OVERLAY>%i %s not supported\n",i,g_ddpf[i].img_format_name);
692
if (g_lpddsOverlay != NULL) {g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);g_lpddsOverlay = NULL;}
693
} while( ++i < NUM_FORMATS );
694
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>Your card supports %i of %i overlayformats\n",formatcount, NUM_FORMATS);
695
if (formatcount == 0)
697
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><WARN>Your card supports overlay, but we couldn't create one\n");
698
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>This can have the following reasons:\n");
699
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>- you are already using an overlay with another app\n");
700
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>- you don't have enough videomemory\n");
701
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>- vo_directx doesn't support the cards overlay pixelformat\n");
704
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
705
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 ;)
649
for (i = 0; i < NUM_FORMATS; i++) {
650
ddsdOverlay.ddpfPixelFormat = g_ddpf[i].g_ddpfOverlay;
651
ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd, &ddsdOverlay, &g_lpddsOverlay, NULL);
652
if (ddrval == DD_OK) {
653
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><FORMAT OVERLAY>%i %s supported\n", i, g_ddpf[i].img_format_name);
654
drv_caps[i] = VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP;
657
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><FORMAT OVERLAY>%i %s not supported\n", i, g_ddpf[i].img_format_name);
658
if (g_lpddsOverlay) {
659
g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
660
g_lpddsOverlay = NULL;
663
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>Your card supports %i of %i overlayformats\n", formatcount, NUM_FORMATS);
664
if (formatcount == 0) {
665
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><WARN>Your card supports overlay, but we couldn't create one\n");
666
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>This can have the following reasons:\n");
667
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>- you are already using an overlay with another app\n");
668
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>- you don't have enough videomemory\n");
669
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>- vo_directx doesn't support the cards overlay pixelformat\n");
672
if (capsDrv.dwFXCaps & DDFXCAPS_OVERLAYMIRRORLEFTRIGHT)
673
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>can mirror left right\n"); //I don't have hardware which
674
if (capsDrv.dwFXCaps & DDFXCAPS_OVERLAYMIRRORUPDOWN)
675
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>can mirror up down\n"); //supports those send me one and I'll implement ;)
709
679
//find out the Pixelformat of the Primary Surface
710
680
static uint32_t Directx_CheckPrimaryPixelformat(void)
713
683
uint32_t formatcount = 0;
718
COLORREF rgbT=RGB(0,0,0);
719
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>checking primary surface\n");
720
memset( &ddpf, 0, sizeof( DDPIXELFORMAT ));
721
ddpf.dwSize = sizeof( DDPIXELFORMAT );
684
DDPIXELFORMAT ddpf = { .dwSize = sizeof(ddpf) };
688
COLORREF rgbT = RGB(0, 0, 0);
689
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>checking primary surface\n");
722
690
//we have to create a primary surface first
723
if(Directx_CreatePrimarySurface()!=0)return 1;
724
if(g_lpddsPrimary->lpVtbl->GetPixelFormat( g_lpddsPrimary, &ddpf ) != DD_OK )
726
mp_msg(MSGT_VO, MSGL_FATAL ,"<vo_directx><FATAL ERROR>can't get pixelformat\n");
729
while ( i < NUM_FORMATS )
731
if (g_ddpf[i].g_ddpfOverlay.dwRGBBitCount == ddpf.dwRGBBitCount)
733
if (g_ddpf[i].g_ddpfOverlay.dwRBitMask == ddpf.dwRBitMask)
735
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><FORMAT PRIMARY>%i %s supported\n",i,g_ddpf[i].img_format_name);
736
g_ddpf[i].drv_caps = VFCAP_CSP_SUPPORTED |VFCAP_OSD;
738
primary_image_format=g_ddpf[i].img_format;
691
if (Directx_CreatePrimarySurface() != 0)
693
if (g_lpddsPrimary->lpVtbl->GetPixelFormat(g_lpddsPrimary, &ddpf) != DD_OK) {
694
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't get pixelformat\n");
697
for (i = 0; i < NUM_FORMATS; i++) {
698
if (g_ddpf[i].g_ddpfOverlay.dwRGBBitCount == ddpf.dwRGBBitCount) {
699
if (g_ddpf[i].g_ddpfOverlay.dwRBitMask == ddpf.dwRBitMask) {
700
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><FORMAT PRIMARY>%i %s supported\n", i, g_ddpf[i].img_format_name);
701
drv_caps[i] = VFCAP_CSP_SUPPORTED | VFCAP_OSD;
703
primary_image_format = g_ddpf[i].img_format;
743
707
//get the colorkey for overlay mode
744
destcolorkey = CLR_INVALID;
745
if (windowcolor != CLR_INVALID && g_lpddsPrimary->lpVtbl->GetDC(g_lpddsPrimary,&hdc) == DD_OK)
708
destcolorkey = CLR_INVALID;
709
if (windowcolor != CLR_INVALID && g_lpddsPrimary->lpVtbl->GetDC(g_lpddsPrimary, &hdc) == DD_OK) {
747
710
rgbT = GetPixel(hdc, 0, 0);
748
711
SetPixel(hdc, 0, 0, windowcolor);
749
g_lpddsPrimary->lpVtbl->ReleaseDC(g_lpddsPrimary,hdc);
712
g_lpddsPrimary->lpVtbl->ReleaseDC(g_lpddsPrimary, hdc);
751
714
// read back the converted color
752
715
ddsd.dwSize = sizeof(ddsd);
753
while ((hres = g_lpddsPrimary->lpVtbl->Lock(g_lpddsPrimary,NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
716
while ((hres = g_lpddsPrimary->lpVtbl->Lock(g_lpddsPrimary, NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
757
destcolorkey = *(DWORD *) ddsd.lpSurface;
719
destcolorkey = *(DWORD *)ddsd.lpSurface;
758
720
if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
759
721
destcolorkey &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
760
g_lpddsPrimary->lpVtbl->Unlock(g_lpddsPrimary,NULL);
722
g_lpddsPrimary->lpVtbl->Unlock(g_lpddsPrimary, NULL);
762
if (windowcolor != CLR_INVALID && g_lpddsPrimary->lpVtbl->GetDC(g_lpddsPrimary,&hdc) == DD_OK)
724
if (windowcolor != CLR_INVALID && g_lpddsPrimary->lpVtbl->GetDC(g_lpddsPrimary, &hdc) == DD_OK) {
764
725
SetPixel(hdc, 0, 0, rgbT);
765
g_lpddsPrimary->lpVtbl->ReleaseDC(g_lpddsPrimary,hdc);
768
g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
769
g_lpddsPrimary = NULL;
772
mp_msg(MSGT_VO, MSGL_FATAL ,"<vo_directx><FATAL ERROR>Unknown Pixelformat\n");
726
g_lpddsPrimary->lpVtbl->ReleaseDC(g_lpddsPrimary, hdc);
729
g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
730
g_lpddsPrimary = NULL;
731
if (formatcount == 0) {
732
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>Unknown Pixelformat\n");
778
738
static int preinit(const char *arg)
782
if(strstr(arg,"noaccel"))
784
mp_msg(MSGT_VO,MSGL_V,"<vo_directx><INFO>disabled overlay\n");
741
if (strstr(arg, "noaccel")) {
742
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>disabled overlay\n");
789
747
windowcolor = vo_colorkey;
790
colorbrush = CreateSolidBrush(windowcolor);
791
blackbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
794
if (!vo_w32_config(100, 100, VOFLAG_HIDDEN))
797
if (Directx_InitDirectDraw()!= 0)return 1; //init DirectDraw
799
if (Directx_CheckPrimaryPixelformat()!=0)return 1;
800
if (!nooverlay && Directx_CheckOverlayPixelformats() == 0) //check for supported hardware
802
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>hardware supports overlay\n");
805
else //if we can't have overlay we create a backpuffer with the same imageformat as the primary surface
807
mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>using backpuffer\n");
810
mp_msg(MSGT_VO, MSGL_DBG3 ,"<vo_directx><INFO>preinit succesfully finished\n");
748
colorbrush = CreateSolidBrush(windowcolor);
749
blackbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
752
if (!vo_w32_config(100, 100, VOFLAG_HIDDEN))
755
if (Directx_InitDirectDraw() != 0)
756
return 1; //init DirectDraw
758
if (Directx_CheckPrimaryPixelformat() != 0)
760
if (!nooverlay && Directx_CheckOverlayPixelformats() == 0) { //check for supported hardware
761
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>hardware supports overlay\n");
763
} else { //if we can't have overlay we create a backpuffer with the same imageformat as the primary surface
764
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>using backpuffer\n");
767
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>preinit succesfully finished\n");
814
static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y )
771
static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
818
uint32_t uvstride=dstride/2;
822
mem2agpcpy_pic(d,s,w,h,dstride,stride[0]);
827
d=image+dstride*image_height + uvstride*y+x;
828
if(image_format == IMGFMT_YV12)s=src[2];
830
mem2agpcpy_pic(d,s,w,h,uvstride,stride[1]);
833
d=image+dstride*image_height +uvstride*(image_height/2) + uvstride*y+x;
834
if(image_format == IMGFMT_YV12)s=src[1];
836
mem2agpcpy_pic(d,s,w,h,uvstride,stride[2]);
775
uint32_t uvstride = dstride / 2;
777
d = image + dstride * y + x;
779
mem2agpcpy_pic(d, s, w, h, dstride, stride[0]);
787
d = image + dstride * image_height + uvstride * y + x;
788
if (image_format == IMGFMT_YV12)
792
mem2agpcpy_pic(d, s, w, h, uvstride, stride[1]);
795
d = image + dstride * image_height + uvstride * (image_height / 2) + uvstride * y + x;
796
if (image_format == IMGFMT_YV12)
800
mem2agpcpy_pic(d, s, w, h, uvstride, stride[2]);
840
804
static void flip_page(void)
843
g_lpddsBack->lpVtbl->Unlock (g_lpddsBack,NULL);
844
if (vo_doublebuffering)
846
// flip to the next image in the sequence
847
dxresult = g_lpddsOverlay->lpVtbl->Flip( g_lpddsOverlay,NULL, DDFLIP_WAIT);
848
if(dxresult == DDERR_SURFACELOST)
850
mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR><vo_directx><INFO>Restoring Surface\n");
851
g_lpddsBack->lpVtbl->Restore( g_lpddsBack );
852
// restore overlay and primary before calling
853
// Directx_ManageDisplay() to avoid error messages
854
g_lpddsOverlay->lpVtbl->Restore( g_lpddsOverlay );
855
g_lpddsPrimary->lpVtbl->Restore( g_lpddsPrimary );
856
// update overlay in case we return from screensaver
857
Directx_ManageDisplay();
858
dxresult = g_lpddsOverlay->lpVtbl->Flip( g_lpddsOverlay,NULL, DDFLIP_WAIT);
860
if(dxresult != DD_OK)mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>can't flip page\n");
807
g_lpddsBack->lpVtbl->Unlock(g_lpddsBack, NULL);
808
if (vo_doublebuffering) {
809
// flip to the next image in the sequence
810
dxresult = g_lpddsOverlay->lpVtbl->Flip(g_lpddsOverlay, NULL, DDFLIP_WAIT);
811
if (dxresult == DDERR_SURFACELOST) {
812
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR><vo_directx><INFO>Restoring Surface\n");
813
g_lpddsBack->lpVtbl->Restore(g_lpddsBack);
814
// restore overlay and primary before calling
815
// Directx_ManageDisplay() to avoid error messages
816
g_lpddsOverlay->lpVtbl->Restore(g_lpddsOverlay);
817
g_lpddsPrimary->lpVtbl->Restore(g_lpddsPrimary);
818
// update overlay in case we return from screensaver
819
Directx_ManageDisplay();
820
dxresult = g_lpddsOverlay->lpVtbl->Flip(g_lpddsOverlay, NULL, DDFLIP_WAIT);
822
if (dxresult != DD_OK)
823
mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx><ERROR>can't flip page\n");
865
826
// ask for the "NOTEARING" option
866
memset( &ddbltfx, 0, sizeof(DDBLTFX) );
867
ddbltfx.dwSize = sizeof(DDBLTFX);
868
ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
828
.dwSize = sizeof(ddbltfx),
829
.dwDDFX = DDBLTFX_NOTEARING,
869
831
g_lpddsPrimary->lpVtbl->Blt(g_lpddsPrimary, &rd, g_lpddsBack, NULL, DDBLT_WAIT, &ddbltfx);
871
if (g_lpddsBack->lpVtbl->Lock(g_lpddsBack,NULL,&ddsdsf, DDLOCK_NOSYSLOCK | DDLOCK_WAIT , NULL) == DD_OK) {
872
if(vo_directrendering && (dstride != ddsdsf.lPitch)){
873
mp_msg(MSGT_VO,MSGL_WARN,"<vo_directx><WARN>stride changed !!!! disabling direct rendering\n");
874
vo_directrendering=0;
878
dstride = ddsdsf.lPitch;
879
image = ddsdsf.lpSurface;
880
} else if (!tmp_image) {
881
mp_msg(MSGT_VO, MSGL_WARN, "<vo_directx><WARN>Locking the surface failed, rendering to a hidden surface!\n");
882
tmp_image = image = calloc(1, image_height * dstride * 2);
833
if (g_lpddsBack->lpVtbl->Lock(g_lpddsBack, NULL, &ddsdsf, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL) == DD_OK) {
834
if (vo_directrendering && (dstride != ddsdsf.lPitch)) {
835
mp_msg(MSGT_VO, MSGL_WARN, "<vo_directx><WARN>stride changed !!!! disabling direct rendering\n");
836
vo_directrendering = 0;
840
dstride = ddsdsf.lPitch;
841
image = ddsdsf.lpSurface;
842
} else if (!tmp_image) {
843
mp_msg(MSGT_VO, MSGL_WARN, "<vo_directx><WARN>Locking the surface failed, rendering to a hidden surface!\n");
844
tmp_image = image = calloc(1, image_height * dstride * 2);
886
848
static int draw_frame(uint8_t *src[])
888
fast_memcpy( image, *src, dstride * image_height );
850
fast_memcpy(image, *src, dstride * image_height);
892
854
static uint32_t get_image(mp_image_t *mpi)
894
if(mpi->flags&MP_IMGFLAG_READABLE) {mp_msg(MSGT_VO, MSGL_V,"<vo_directx><ERROR>slow video ram\n");return VO_FALSE;}
895
if(mpi->type==MP_IMGTYPE_STATIC) {mp_msg(MSGT_VO, MSGL_V,"<vo_directx><ERROR>not static\n");return VO_FALSE;}
896
if((mpi->width==dstride) || (mpi->flags&(MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ACCEPT_WIDTH)))
898
if(mpi->flags&MP_IMGFLAG_PLANAR)
900
if(image_format == IMGFMT_YV12)
902
mpi->planes[2]= image + dstride*image_height;
903
mpi->planes[1]= image + dstride*image_height+ dstride*image_height/4;
904
mpi->stride[1]=mpi->stride[2]=dstride/2;
906
else if(image_format == IMGFMT_IYUV || image_format == IMGFMT_I420)
908
mpi->planes[1]= image + dstride*image_height;
909
mpi->planes[2]= image + dstride*image_height+ dstride*image_height/4;
910
mpi->stride[1]=mpi->stride[2]=dstride/2;
912
else if(image_format == IMGFMT_YVU9)
914
mpi->planes[2] = image + dstride*image_height;
915
mpi->planes[1] = image + dstride*image_height+ dstride*image_height/16;
916
mpi->stride[1]=mpi->stride[2]=dstride/4;
919
mpi->planes[0]=image;
920
mpi->stride[0]=dstride;
921
mpi->width=image_width;
922
mpi->height=image_height;
923
mpi->flags|=MP_IMGFLAG_DIRECT;
856
if (mpi->flags & MP_IMGFLAG_READABLE) {
857
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><ERROR>slow video ram\n");
860
if (mpi->type == MP_IMGTYPE_STATIC) {
861
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><ERROR>not static\n");
864
if (mpi->width == dstride || (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))) {
865
if (mpi->flags & MP_IMGFLAG_PLANAR) {
866
if (image_format == IMGFMT_YV12) {
867
mpi->planes[2] = image + dstride * image_height;
868
mpi->planes[1] = image + dstride * image_height + dstride * image_height / 4;
869
mpi->stride[1] = mpi->stride[2] = dstride / 2;
870
} else if (image_format == IMGFMT_IYUV || image_format == IMGFMT_I420) {
871
mpi->planes[1] = image + dstride * image_height;
872
mpi->planes[2] = image + dstride * image_height + dstride * image_height / 4;
873
mpi->stride[1] = mpi->stride[2] = dstride / 2;
874
} else if (image_format == IMGFMT_YVU9) {
875
mpi->planes[2] = image + dstride * image_height;
876
mpi->planes[1] = image + dstride * image_height + dstride * image_height / 16;
877
mpi->stride[1] = mpi->stride[2] = dstride / 4;
880
mpi->planes[0] = image;
881
mpi->stride[0] = dstride;
882
mpi->width = image_width;
883
mpi->height = image_height;
884
mpi->flags |= MP_IMGFLAG_DIRECT;
924
885
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>Direct Rendering ENABLED\n");
930
static uint32_t put_image(mp_image_t *mpi){
891
static uint32_t put_image(mp_image_t *mpi)
934
895
uint32_t x = mpi->x;
939
if((mpi->flags&MP_IMGFLAG_DIRECT)||(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK))
941
mp_msg(MSGT_VO, MSGL_DBG3 ,"<vo_directx><INFO>put_image: nothing to do: drawslices\n");
945
if (mpi->flags&MP_IMGFLAG_PLANAR)
948
if(image_format!=IMGFMT_YVU9)draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,0,0);
954
mem2agpcpy_pic(d,s,w,h,dstride,mpi->stride[0]);
957
d=image+dstride*image_height + dstride*y/4+x;
959
mem2agpcpy_pic(d,s,w,h,dstride/4,mpi->stride[1]);
961
d=image+dstride*image_height + dstride*image_height/16 + dstride/4*y+x;
963
mem2agpcpy_pic(d,s,w,h,dstride/4,mpi->stride[2]);
968
mem2agpcpy_pic(image, mpi->planes[0], w * (mpi->bpp / 8), h, dstride, mpi->stride[0]);
900
if ((mpi->flags & MP_IMGFLAG_DIRECT) || (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)) {
901
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>put_image: nothing to do: drawslices\n");
905
if (mpi->flags & MP_IMGFLAG_PLANAR) {
906
if (image_format != IMGFMT_YVU9)
907
draw_slice(mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
910
d = image + dstride * y + x;
912
mem2agpcpy_pic(d, s, w, h, dstride, mpi->stride[0]);
918
d = image + dstride * image_height + dstride * y / 4 + x;
920
mem2agpcpy_pic(d, s, w, h, dstride / 4, mpi->stride[1]);
922
d = image + dstride * image_height + dstride * image_height / 16 + dstride / 4 * y + x;
924
mem2agpcpy_pic(d, s, w, h, dstride / 4, mpi->stride[2]);
927
mem2agpcpy_pic(image, mpi->planes[0], w * (mpi->bpp / 8), h, dstride, mpi->stride[0]);
974
config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t options, char *title, uint32_t format)
932
static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t options, char *title, uint32_t format)
976
image_format = format;
978
image_height = height;
979
if(format != primary_image_format)nooverlay = 0;
934
image_format = format;
936
image_height = height;
937
if (format != primary_image_format)
981
940
/*release all directx objects*/
982
if (g_cc != NULL)g_cc->lpVtbl->Release(g_cc);
984
if(g_lpddclipper)g_lpddclipper->lpVtbl->Release(g_lpddclipper);
986
if (g_lpddsBack != NULL) g_lpddsBack->lpVtbl->Release(g_lpddsBack);
942
g_cc->lpVtbl->Release(g_cc);
945
g_lpddclipper->lpVtbl->Release(g_lpddclipper);
946
g_lpddclipper = NULL;
948
g_lpddsBack->lpVtbl->Release(g_lpddsBack);
987
949
g_lpddsBack = NULL;
988
if(vo_doublebuffering)
989
if (g_lpddsOverlay != NULL)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
950
if (vo_doublebuffering)
952
g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay);
990
953
g_lpddsOverlay = NULL;
991
if (g_lpddsPrimary != NULL) g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
955
g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary);
992
956
g_lpddsPrimary = NULL;
993
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>overlay surfaces released\n");
995
if (!vo_w32_config(d_width, d_height, options))
999
SetWindowText(vo_w32_window,title);
1002
/*create the surfaces*/
1003
if(Directx_CreatePrimarySurface())return 1;
1005
//create palette for 256 color mode
1006
if(image_format==IMGFMT_BGR8){
1007
LPDIRECTDRAWPALETTE ddpalette=NULL;
1008
LPPALETTEENTRY palette=calloc(256, sizeof(*palette));
1010
for(i=0; i<256; i++){
1011
palette[i].peRed = ((i >> 5) & 0x07) * 255 / 7;
1012
palette[i].peGreen = ((i >> 2) & 0x07) * 255 / 7;
1013
palette[i].peBlue = ((i >> 0) & 0x03) * 255 / 3;
1014
palette[i].peFlags = PC_NOCOLLAPSE;
1016
g_lpdd->lpVtbl->CreatePalette(g_lpdd,DDPCAPS_8BIT|DDPCAPS_INITIALIZE,palette,&ddpalette,NULL);
1017
g_lpddsPrimary->lpVtbl->SetPalette(g_lpddsPrimary,ddpalette);
1019
ddpalette->lpVtbl->Release(ddpalette);
1022
if (!nooverlay && Directx_CreateOverlay(image_format))
1024
if(format == primary_image_format)nooverlay=1; /*overlay creation failed*/
1026
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't use overlay mode: please use -vo directx:noaccel\n");
1032
if(Directx_CreateBackpuffer())
1034
mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't get the driver to work on your system :(\n");
1037
mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>back surface created\n");
1038
vo_doublebuffering = 0;
1039
/*create clipper for nonoverlay mode*/
1040
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;}
1041
if(g_lpddclipper->lpVtbl->SetHWnd (g_lpddclipper, 0, vo_w32_window)!= DD_OK){mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't associate clipper with window\n");return 1;}
1042
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;}
1043
mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>clipper succesfully created\n");
1045
if(DD_OK != g_lpddsOverlay->lpVtbl->QueryInterface(g_lpddsOverlay,&IID_IDirectDrawColorControl,(void**)&g_cc))
1046
mp_msg(MSGT_VO, MSGL_V,"<vo_directx><WARN>unable to get DirectDraw ColorControl interface\n");
1048
Directx_ManageDisplay();
1049
memset(&ddsdsf, 0,sizeof(DDSURFACEDESC2));
1050
ddsdsf.dwSize = sizeof (DDSURFACEDESC2);
1051
if (g_lpddsBack->lpVtbl->Lock(g_lpddsBack,NULL,&ddsdsf, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL) == DD_OK) {
957
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>overlay surfaces released\n");
959
if (!vo_w32_config(d_width, d_height, options))
962
/*create the surfaces*/
963
if (Directx_CreatePrimarySurface())
966
//create palette for 256 color mode
967
if (image_format == IMGFMT_BGR8) {
968
LPDIRECTDRAWPALETTE ddpalette = NULL;
969
LPPALETTEENTRY palette = calloc(256, sizeof(*palette));
971
for (i = 0; i < 256; i++) {
972
palette[i].peRed = ((i >> 5) & 0x07) * 255 / 7;
973
palette[i].peGreen = ((i >> 2) & 0x07) * 255 / 7;
974
palette[i].peBlue = ((i >> 0) & 0x03) * 255 / 3;
975
palette[i].peFlags = PC_NOCOLLAPSE;
977
g_lpdd->lpVtbl->CreatePalette(g_lpdd, DDPCAPS_8BIT | DDPCAPS_INITIALIZE, palette, &ddpalette, NULL);
978
g_lpddsPrimary->lpVtbl->SetPalette(g_lpddsPrimary, ddpalette);
980
ddpalette->lpVtbl->Release(ddpalette);
983
if (!nooverlay && Directx_CreateOverlay(image_format)) {
984
if (format == primary_image_format)
985
nooverlay = 1; /*overlay creation failed*/
987
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't use overlay mode: please use -vo directx:noaccel\n");
992
if (Directx_CreateBackpuffer()) {
993
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't get the driver to work on your system :(\n");
996
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><INFO>back surface created\n");
997
vo_doublebuffering = 0;
998
/*create clipper for nonoverlay mode*/
999
if (g_lpdd->lpVtbl->CreateClipper(g_lpdd, 0, &g_lpddclipper, NULL) != DD_OK) {
1000
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't create clipper\n");
1003
if (g_lpddclipper->lpVtbl->SetHWnd(g_lpddclipper, 0, vo_w32_window) != DD_OK) {
1004
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't associate clipper with window\n");
1007
if (g_lpddsPrimary->lpVtbl->SetClipper(g_lpddsPrimary, g_lpddclipper) != DD_OK) {
1008
mp_msg(MSGT_VO, MSGL_FATAL, "<vo_directx><FATAL ERROR>can't associate primary surface with clipper\n");
1011
mp_msg(MSGT_VO, MSGL_DBG3, "<vo_directx><INFO>clipper succesfully created\n");
1013
if (DD_OK != g_lpddsOverlay->lpVtbl->QueryInterface(g_lpddsOverlay, &IID_IDirectDrawColorControl, (void **)&g_cc))
1014
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><WARN>unable to get DirectDraw ColorControl interface\n");
1016
Directx_ManageDisplay();
1017
memset(&ddsdsf, 0, sizeof(DDSURFACEDESC2));
1018
ddsdsf.dwSize = sizeof(DDSURFACEDESC2);
1019
if (g_lpddsBack->lpVtbl->Lock(g_lpddsBack, NULL, &ddsdsf, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL) == DD_OK) {
1052
1020
dstride = ddsdsf.lPitch;
1053
image = ddsdsf.lpSurface;
1021
image = ddsdsf.lpSurface;
1056
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><ERROR>Initial Lock on the Surface failed.\n");
1024
mp_msg(MSGT_VO, MSGL_V, "<vo_directx><ERROR>Initial Lock on the Surface failed.\n");
1060
1028
//function to set color controls