From 2bfc5214be461882ee314cf5301e7a98e84ac94c Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 18 Jul 2012 21:32:30 +0200 Subject: [PATCH] ddraw: Implement ddraw7_GetScanLine() on top of wined3d_get_adapter_raster_status(). --- dlls/ddraw/ddraw.c | 42 +++++----------------------------- dlls/wined3d/directx.c | 47 +++++++++++++++++++++++++++++++++++++++ dlls/wined3d/swapchain.c | 43 +++-------------------------------- dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 2 ++ 5 files changed, 58 insertions(+), 77 deletions(-) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 1963de2f183..b96fd487b94 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1931,60 +1931,28 @@ static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flag return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event); } -/***************************************************************************** - * IDirectDraw7::GetScanLine - * - * Returns the scan line that is being drawn on the monitor - * - * Parameters: - * Scanline: Address to write the scan line value to - * - * Returns: - * Always returns DD_OK - * - *****************************************************************************/ static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline) { struct ddraw *ddraw = impl_from_IDirectDraw7(iface); - struct wined3d_display_mode mode; - static BOOL hide = FALSE; - DWORD time, frame_progress, lines; + struct wined3d_raster_status raster_status; HRESULT hr; TRACE("iface %p, line %p.\n", iface, Scanline); - /* This function is called often, so print the fixme only once */ - if(!hide) - { - FIXME("iface %p, line %p partial stub!\n", iface, Scanline); - hide = TRUE; - } - wined3d_mutex_lock(); - hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL); + hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status); wined3d_mutex_unlock(); if (FAILED(hr)) { - ERR("Failed to get display mode, hr %#x.\n", hr); + WARN("Failed to get raster status, hr %#x.\n", hr); return hr; } - /* Fake the line sweeping of the monitor */ - /* FIXME: We should synchronize with a source to keep the refresh rate */ + *Scanline = raster_status.scan_line; - /* Simulate a 60Hz display */ - time = GetTickCount(); - frame_progress = time & 15; /* time % (1000 / 60) */ - if (!frame_progress) - { - *Scanline = 0; + if (raster_status.in_vblank) return DDERR_VERTICALBLANKINPROGRESS; - } - /* Convert frame_progress to estimated scan line. Return any line from - * block determined by time. Some lines may be never returned */ - lines = mode.height / 15; - *Scanline = (frame_progress - 1) * lines + time % lines; return DD_OK; } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index f80e80c7737..9e9af8ad5b0 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3225,6 +3225,53 @@ HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d, return WINED3D_OK; } +HRESULT CDECL wined3d_get_adapter_raster_status(const struct wined3d *wined3d, UINT adapter_idx, + struct wined3d_raster_status *raster_status) +{ + LONGLONG freq_per_frame, freq_per_line; + LARGE_INTEGER counter, freq_per_sec; + struct wined3d_display_mode mode; + static UINT once; + + if (!once++) + FIXME("wined3d %p, adapter_idx %u, raster_status %p semi-stub!\n", + wined3d, adapter_idx, raster_status); + else + WARN("wined3d %p, adapter_idx %u, raster_status %p semi-stub!\n", + wined3d, adapter_idx, raster_status); + + /* Obtaining the raster status is a widely implemented but optional + * feature. When this method returns OK StarCraft 2 expects the + * raster_status->InVBlank value to actually change over time. + * And Endless Alice Crysis doesn't care even if this method fails. + * Thus this method returns OK and fakes raster_status by + * QueryPerformanceCounter. */ + + if (!QueryPerformanceCounter(&counter) || !QueryPerformanceFrequency(&freq_per_sec)) + return WINED3DERR_INVALIDCALL; + if (FAILED(wined3d_get_adapter_display_mode(wined3d, adapter_idx, &mode, NULL))) + return WINED3DERR_INVALIDCALL; + if (mode.refresh_rate == DEFAULT_REFRESH_RATE) + mode.refresh_rate = 60; + + freq_per_frame = freq_per_sec.QuadPart / mode.refresh_rate; + /* Assume 20 scan lines in the vertical blank. */ + freq_per_line = freq_per_frame / (mode.height + 20); + raster_status->scan_line = (counter.QuadPart % freq_per_frame) / freq_per_line; + if (raster_status->scan_line < mode.height) + raster_status->in_vblank = FALSE; + else + { + raster_status->scan_line = 0; + raster_status->in_vblank = TRUE; + } + + TRACE("Returning fake value, in_vblank %u, scan_line %u.\n", + raster_status->in_vblank, raster_status->scan_line); + + return WINED3D_OK; +} + static BOOL wined3d_check_pixel_format_color(const struct wined3d_gl_info *gl_info, const struct wined3d_pixel_format *cfg, const struct wined3d_format *format) { diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index dd00e55bb7a..8c3765917d7 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -220,47 +220,10 @@ HRESULT CDECL wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain * HRESULT CDECL wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain, struct wined3d_raster_status *raster_status) { - static BOOL warned; - LARGE_INTEGER counter, freq_per_sec; - LONGLONG freq_per_frame, freq_per_line; - struct wined3d_display_mode mode; + TRACE("swapchain %p, raster_status %p.\n", swapchain, raster_status); - /* No OpenGL equivalent */ - if (!warned) - { - FIXME("swapchain %p, raster_status %p semi-stub!\n", swapchain, raster_status); - warned = TRUE; - } - - /* Obtaining the raster status is a widely implemented but optional - * feature. When this method returns OK StarCraft 2 expects the - * raster_status->InVBlank value to actually change over time. - * And Endless Alice Crysis doesn't care even if this method fails. - * Thus this method returns OK and fakes raster_status by - * QueryPerformanceCounter. */ - - if (!QueryPerformanceCounter(&counter) || !QueryPerformanceFrequency(&freq_per_sec)) - return WINED3DERR_INVALIDCALL; - - if (FAILED(wined3d_swapchain_get_display_mode(swapchain, &mode, NULL))) - return WINED3DERR_INVALIDCALL; - if (mode.refresh_rate == DEFAULT_REFRESH_RATE) - mode.refresh_rate = 60; - - freq_per_frame = freq_per_sec.QuadPart / mode.refresh_rate; - /* Assume 20 scan lines in the vertical blank */ - freq_per_line = freq_per_frame / (mode.height + 20); - raster_status->scan_line = (counter.QuadPart % freq_per_frame) / freq_per_line; - if (raster_status->scan_line < mode.height) - raster_status->in_vblank = FALSE; - else - { - raster_status->scan_line = 0; - raster_status->in_vblank = TRUE; - } - TRACE("Returning fake value, in_vblank %u, scan_line %u.\n", - raster_status->in_vblank, raster_status->scan_line); - return WINED3D_OK; + return wined3d_get_adapter_raster_status(swapchain->device->wined3d, + swapchain->device->adapter->ordinal, raster_status); } HRESULT CDECL wined3d_swapchain_get_display_mode(const struct wined3d_swapchain *swapchain, diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index a22ebd18642..eed1174605c 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -14,6 +14,7 @@ @ cdecl wined3d_get_adapter_identifier(ptr long long ptr) @ cdecl wined3d_get_adapter_mode_count(ptr long long long) @ cdecl wined3d_get_adapter_monitor(ptr long) +@ cdecl wined3d_get_adapter_raster_status(ptr long ptr) @ cdecl wined3d_get_device_caps(ptr long long ptr) @ cdecl wined3d_incref(ptr) @ cdecl wined3d_register_software_device(ptr ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index f587e440041..5208a799406 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2045,6 +2045,8 @@ HRESULT __cdecl wined3d_get_adapter_identifier(const struct wined3d *wined3d, UI UINT __cdecl wined3d_get_adapter_mode_count(const struct wined3d *wined3d, UINT adapter_idx, enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering); HMONITOR __cdecl wined3d_get_adapter_monitor(const struct wined3d *wined3d, UINT adapter_idx); +HRESULT __cdecl wined3d_get_adapter_raster_status(const struct wined3d *wined3d, UINT adapter_idx, + struct wined3d_raster_status *raster_status); HRESULT __cdecl wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapter_idx, enum wined3d_device_type device_type, WINED3DCAPS *caps); ULONG __cdecl wined3d_incref(struct wined3d *wined3d);