Fix #392 - Crash when another monitor is plugged in

When we change the number of monitors, we've to restore the primary
DirectDraw surface, but it cannot be just "restored", it must be
re-created.

Note: probably the real fix for #436 too
This commit is contained in:
David Capello 2014-11-02 18:59:00 -03:00
parent 9fb3396392
commit 13fc8e03d2
4 changed files with 43 additions and 6 deletions

View File

@ -275,12 +275,14 @@ DDRAW_SURFACE *gfx_directx_create_surface(int w, int h, LPDDPIXELFORMAT pixel_fo
return NULL;
/* create the surface with the specified characteristics */
surf->id = create_directdraw2_surface(w, h, pixel_format,type, 0);
surf->id = create_directdraw2_surface(w, h, pixel_format, type, 0);
if (!surf->id) {
_AL_FREE(surf);
return NULL;
}
surf->w = w;
surf->h = h;
surf->flags = type;
surf->lock_nesting = 0;
@ -303,6 +305,40 @@ void gfx_directx_destroy_surface(DDRAW_SURFACE *surf)
int gfx_directx_restore_surface(DDRAW_SURFACE *surf)
{
int type = (surf->flags & DDRAW_SURFACE_TYPE_MASK);
HRESULT hr;
hr = IDirectDrawSurface2_Restore(surf->id);
if (FAILED(hr)) {
LPDIRECTDRAWSURFACE2 new_id;
hr = IDirectDrawSurface2_Release(surf->id);
if (FAILED(hr))
return -1;
new_id = create_directdraw2_surface(
surf->w, surf->h, ddpixel_format, type, 0);
if (!new_id) {
surf->id = 0;
return -1;
}
surf->id = new_id;
if (type == DDRAW_SURFACE_PRIMARY) {
hr = IDirectDrawSurface_SetClipper(surf->id, ddclipper);
if (FAILED(hr))
return -1;
}
}
return 0;
}
/* gfx_directx_make_bitmap_from_surface:
* Connects a DirectDraw surface with an Allegro bitmap.
*/
@ -315,7 +351,7 @@ BITMAP *gfx_directx_make_bitmap_from_surface(DDRAW_SURFACE *surf, int w, int h,
if (!bmp)
return NULL;
bmp->w =w;
bmp->w = w;
bmp->cr = w;
bmp->h = h;
bmp->cb = h;

View File

@ -114,17 +114,14 @@ void unregister_all_ddraw_surfaces(void)
int restore_all_ddraw_surfaces(void)
{
DDRAW_SURFACE *item = ddraw_surface_list;
HRESULT hr;
_enter_gfx_critical();
while (item) {
hr = IDirectDrawSurface2_Restore(item->id);
if (FAILED(hr)) {
if (gfx_directx_restore_surface(item) != 0) {
_exit_gfx_critical();
return -1;
}
item = item->next;
}

View File

@ -41,6 +41,7 @@
/* wrapper for DirectDraw surfaces */
typedef struct DDRAW_SURFACE {
LPDIRECTDRAWSURFACE2 id;
int w, h;
int flags;
int lock_nesting;
BITMAP *parent_bmp; /* only used by the flipping chain */
@ -138,6 +139,7 @@ AL_FUNCPTR(void, _al_wd_update_window, (RECT *rect));
/* bitmap creation (from wddbmp.c) */
AL_FUNC(DDRAW_SURFACE *, gfx_directx_create_surface, (int w, int h, LPDDPIXELFORMAT pixel_format, int type));
AL_FUNC(void, gfx_directx_destroy_surface, (DDRAW_SURFACE *surf));
AL_FUNC(int, gfx_directx_restore_surface, (DDRAW_SURFACE *surf));
AL_FUNC(BITMAP *, gfx_directx_make_bitmap_from_surface, (DDRAW_SURFACE *surf, int w, int h, int id));

View File

@ -133,6 +133,8 @@ static void get_working_area(RECT *working_area)
*/
static void switch_in_win(void)
{
gfx_directx_compare_color_depth(desktop_color_depth());
restore_all_ddraw_surfaces();
get_working_area(&working_area);
}