ddraw: Implement ddraw7_GetScanLine() on top of wined3d_get_adapter_raster_status().

This commit is contained in:
Henri Verbeet 2012-07-18 21:32:30 +02:00 committed by Alexandre Julliard
parent 9877df9aeb
commit 2bfc5214be
5 changed files with 58 additions and 77 deletions

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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,

View File

@ -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)

View File

@ -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);