diff --git a/src/allegro/src/win/wddbmp.c b/src/allegro/src/win/wddbmp.c index 01f7a0acd..3d552658e 100644 --- a/src/allegro/src/win/wddbmp.c +++ b/src/allegro/src/win/wddbmp.c @@ -307,34 +307,41 @@ void gfx_directx_destroy_surface(DDRAW_SURFACE *surf) int gfx_directx_restore_surface(DDRAW_SURFACE *surf) { + LPDIRECTDRAWSURFACE2 new_id; int type = (surf->flags & DDRAW_SURFACE_TYPE_MASK); HRESULT hr; - hr = IDirectDrawSurface2_Restore(surf->id); - if (FAILED(hr)) { - LPDIRECTDRAWSURFACE2 new_id; + if (surf->id != 0) { + hr = IDirectDrawSurface2_Restore(surf->id); + if (SUCCEEDED(hr)) + return 0; /* We were able to restore the surface successfully */ - hr = IDirectDrawSurface2_Release(surf->id); - if (FAILED(hr)) - return -1; + 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; - } + /* In this case, the surface must be recreated because: + 1) We weren't able to restore it with IDirectDrawSurface2_Restore() + 2) We weren't able to re-create it in a previous + gfx_directx_restore_surface() call + */ + 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; + surf->id = new_id; - if (type == DDRAW_SURFACE_PRIMARY) { - hr = IDirectDrawSurface_SetClipper(surf->id, ddclipper); - if (FAILED(hr)) - return -1; - } - } + if (type == DDRAW_SURFACE_PRIMARY) { + hr = IDirectDrawSurface_SetClipper(surf->id, ddclipper); + if (FAILED(hr)) + return -1; + } - return 0; + return 0; } diff --git a/src/allegro/src/win/wddwin.c b/src/allegro/src/win/wddwin.c index 7045f1133..323824291 100644 --- a/src/allegro/src/win/wddwin.c +++ b/src/allegro/src/win/wddwin.c @@ -207,8 +207,10 @@ static void paint_win(RECT *rect) /* we may have lost the DirectDraw surfaces * (e.g after the monitor has gone to low power) */ - if (IDirectDrawSurface2_IsLost(gfx_directx_primary_surface->id) == DDERR_SURFACELOST) + if (gfx_directx_primary_surface->id == 0 || + IDirectDrawSurface2_IsLost(gfx_directx_primary_surface->id) == DDERR_SURFACELOST) { switch_in_win(); + } /* clip the rectangle */ rect->right = MIN(rect->right, gfx_directx_win.w); @@ -249,9 +251,14 @@ static void update_matching_window(RECT *rect) ClientToScreen(allegro_wnd, &dest_rect.p); ClientToScreen(allegro_wnd, &dest_rect.p + 1); - /* blit offscreen backbuffer to the window */ - IDirectDrawSurface2_Blt(gfx_directx_primary_surface->id, &dest_rect.r, - offscreen_surface->id, rect, 0, NULL); + /* Blit offscreen backbuffer to the window. + The ID can be 0 when the primary surface is lost and we weren't + able to restore & recreate it in gfx_directx_restore_surface(). + */ + if (gfx_directx_primary_surface->id != 0) { + IDirectDrawSurface2_Blt(gfx_directx_primary_surface->id, &dest_rect.r, + offscreen_surface->id, rect, 0, NULL); + } _exit_gfx_critical(); } @@ -372,8 +379,10 @@ static void update_colorconv_window(RECT *rect) if (direct) { /* blit directly to the primary surface without clipping */ - ddsurf_blit_ex(gfx_directx_primary_surface->id, &dest_rect.r, - offscreen_surface->id, &src_rect); + if (gfx_directx_primary_surface->id != 0) { + ddsurf_blit_ex(gfx_directx_primary_surface->id, &dest_rect.r, + offscreen_surface->id, &src_rect); + } } else { /* blit to the window using GDI */ diff --git a/src/allegro/src/win/wmouse.c b/src/allegro/src/win/wmouse.c index 2c0c1c709..db50c0c39 100644 --- a/src/allegro/src/win/wmouse.c +++ b/src/allegro/src/win/wmouse.c @@ -10,6 +10,8 @@ #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" +#include "wddraw.h" + #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif @@ -333,6 +335,12 @@ void _al_win_mouse_handle_move(HWND hwnd, int x, int y) { _enter_critical(); + /* Try to restore the primary surface as soon as possible if we + have lost it and were not able to recreate it */ + if (gfx_directx_primary_surface && gfx_directx_primary_surface->id == 0) { + restore_all_ddraw_surfaces(); + } + _mouse_x = CLAMP(mouse_minx, x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, y, mouse_maxy);