/* win_get_dc: (WinAPI) * Returns device context of a video or system bitmap. */ HDC win_get_dc(BITMAP *bmp) { LPDIRECTDRAWSURFACE2 ddsurf; HDC dc; HRESULT hr; if (bmp) { if (bmp->id & (BMP_ID_SYSTEM | BMP_ID_VIDEO)) { ddsurf = DDRAW_SURFACE_OF(bmp)->id; hr = IDirectDrawSurface2_GetDC(ddsurf, &dc); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to get the DC. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_GetDC(ddsurf, &dc); } if (hr == DD_OK) return dc; } } return NULL; }
/* switch_in_fullscreen: * Handles screen switched in. */ static void switch_in_fullscreen(void) { restore_all_ddraw_surfaces(); if (_color_depth == 8) set_palette(wddfull_saved_palette); }
/* gfx_directx_unlock: * Unlocks the surface. */ void gfx_directx_unlock(BITMAP *bmp) { DDRAW_SURFACE *surf; BITMAP *parent; HRESULT hr; if (bmp->id & BMP_ID_SUB) { /* recurse when unlocking sub-bitmaps */ parent = (BITMAP *)bmp->extra; gfx_directx_unlock(parent); if (!(parent->id & BMP_ID_LOCKED)) bmp->id &= ~BMP_ID_LOCKED; } else { /* regular bitmaps can be unlocked directly */ surf = DDRAW_SURFACE_OF(bmp); if (surf->lock_nesting > 0) { surf->lock_nesting--; if ((!surf->lock_nesting) && (bmp->id & BMP_ID_LOCKED)) { if (!(surf->flags & DDRAW_SURFACE_LOST)) { /* only unlock if it doesn't use pseudo video memory */ hr = IDirectDrawSurface2_Unlock(surf->id, NULL); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to unlock the surface. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_Unlock(surf->id, NULL); } if (FAILED(hr)) _TRACE(PREFIX_E "Can't unlock surface (%x)\n", hr); } bmp->id &= ~BMP_ID_LOCKED; } /* release bitmap for other threads */ _exit_gfx_critical(); } } }
/* gfx_directx_poll_scroll: */ int gfx_directx_poll_scroll(void) { HRESULT hr; ASSERT(n_flipping_pages == 3); hr = IDirectDrawSurface2_GetFlipStatus(flipping_page[0]->id, DDGFS_ISFLIPDONE); /* if the surface has been lost, try to restore all surfaces */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_GetFlipStatus(flipping_page[0]->id, DDGFS_ISFLIPDONE); } if (FAILED(hr)) return -1; return 0; }
/* flip_with_forefront_bitmap: * Worker function for DirectDraw page flipping. */ static int flip_with_forefront_bitmap(BITMAP *bmp, int wait) { DDRAW_SURFACE *surf; HRESULT hr; /* flip only in the foreground */ if (!_win_app_foreground) { _win_thread_switch_out(); return 0; } /* retrieve the underlying surface */ surf = DDRAW_SURFACE_OF(bmp); if (surf == flipping_page[0]) return 0; ASSERT((surf == flipping_page[1]) || (surf == flipping_page[2])); /* flip the contents of the surfaces */ hr = IDirectDrawSurface2_Flip(flipping_page[0]->id, surf->id, wait ? DDFLIP_WAIT : 0); /* if the surface has been lost, try to restore all surfaces */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_Flip(flipping_page[0]->id, surf->id, wait ? DDFLIP_WAIT : 0); } if (FAILED(hr)) { _TRACE(PREFIX_E "Can't flip (%s)\n", dd_err(hr)); return -1; } /* attach the surface to the former forefront bitmap */ surf->parent_bmp = flipping_page[0]->parent_bmp; surf->parent_bmp->extra = surf; /* make the bitmap point to the forefront surface */ flipping_page[0]->parent_bmp = bmp; bmp->extra = flipping_page[0]; return 0; }
/* win_release_dc: (WinAPI) * Releases device context of a video or system bitmap. */ void win_release_dc(BITMAP *bmp, HDC dc) { LPDIRECTDRAWSURFACE2 ddsurf; HRESULT hr; if (bmp) { if (bmp->id & (BMP_ID_SYSTEM | BMP_ID_VIDEO)) { ddsurf = DDRAW_SURFACE_OF(bmp)->id; hr = IDirectDrawSurface2_ReleaseDC(ddsurf, dc); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to release the DC. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_ReleaseDC(ddsurf, dc); } } } }
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); mymickey_x += x - mymickey_ox; mymickey_y += y - mymickey_oy; mymickey_ox = x; mymickey_oy = y; _exit_critical(); _handle_mouse_input(); }
/* gfx_directx_release_lock: * Releases the surface lock, for hardware accelerated drawing. */ void gfx_directx_release_lock(BITMAP *bmp) { DDRAW_SURFACE *surf; HRESULT hr; /* handle display switch */ if (!_win_app_foreground) gfx_directx_switch_out(); /* find parent */ while (bmp->id & BMP_ID_SUB) { bmp->id &= ~BMP_ID_LOCKED; bmp = (BITMAP *)bmp->extra; } if (bmp->id & BMP_ID_LOCKED) { surf = DDRAW_SURFACE_OF(bmp); if (!(surf->flags & DDRAW_SURFACE_LOST)) { /* only unlock if it doesn't use pseudo video memory */ hr = IDirectDrawSurface2_Unlock(surf->id, NULL); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to unlock the surface. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_Unlock(surf->id, NULL); } if (FAILED(hr)) _TRACE(PREFIX_E "Can't release lock (%x)\n", hr); } bmp->id &= ~BMP_ID_LOCKED; } }
/* gfx_directx_lock: * Locks the surface and prepares the lines array of the bitmap. */ void gfx_directx_lock(BITMAP *bmp) { DDRAW_SURFACE *surf; BITMAP *parent; HRESULT hr; DDSURFACEDESC ddsurf_desc; int pitch; unsigned char *data; int y; if (bmp->id & BMP_ID_SUB) { /* if it's a sub-bitmap, start by locking our parent */ parent = (BITMAP *)bmp->extra; gfx_directx_lock(parent); bmp->id |= BMP_ID_LOCKED; /* update the line array if our parent has moved */ pitch = (long)parent->line[1] - (long)parent->line[0]; data = parent->line[0] + (bmp->y_ofs - parent->y_ofs) * pitch + (bmp->x_ofs - parent->x_ofs) * BYTES_PER_PIXEL(bitmap_color_depth(bmp)); if (data != bmp->line[0]) { for (y = 0; y < bmp->h; y++) { bmp->line[y] = data; data += pitch; } } } else { /* require exclusive ownership of the bitmap */ _enter_gfx_critical(); /* handle display switch */ if (!_win_app_foreground) gfx_directx_switch_out(); /* this is a real bitmap, so can be locked directly */ surf = DDRAW_SURFACE_OF(bmp); surf->lock_nesting++; if (!(bmp->id & BMP_ID_LOCKED)) { /* try to lock surface */ bmp->id |= BMP_ID_LOCKED; surf->flags &= ~DDRAW_SURFACE_LOST; ddsurf_desc.dwSize = sizeof(DDSURFACEDESC); ddsurf_desc.dwFlags = 0; hr = IDirectDrawSurface2_Lock(surf->id, NULL, &ddsurf_desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to lock the surface. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) { ddsurf_desc.dwSize = sizeof(DDSURFACEDESC); ddsurf_desc.dwFlags = 0; hr = IDirectDrawSurface2_Lock(surf->id, NULL, &ddsurf_desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); } } if (FAILED(hr)) { _TRACE(PREFIX_E "Can't lock surface (%x)\n", hr); /* lock failed, use pseudo surface memory */ surf->flags |= DDRAW_SURFACE_LOST; data = pseudo_surf_mem; pitch = 0; } else { data = ddsurf_desc.lpSurface; pitch = ddsurf_desc.lPitch; } /* prepare line array */ if (data != bmp->line[0]) { for (y = 0; y < bmp->h; y++) { bmp->line[y] = data; data += pitch; } } } } }