#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
-#define GLINFO_LOCATION (*gl_info)
-static HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query)
+BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info)
{
- struct wined3d_event_query *ret;
- *query = NULL;
- if (!gl_info->supported[ARB_SYNC] && !gl_info->supported[NV_FENCE]
- && !gl_info->supported[APPLE_FENCE]) return E_NOTIMPL;
-
- ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
- if (!ret)
- {
- ERR("Failed to allocate a wined3d event query structure.\n");
- return E_OUTOFMEMORY;
- }
- ret->context = NULL;
- *query = ret;
- return WINED3D_OK;
+ return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
}
-static void wined3d_event_query_destroy(struct wined3d_event_query *query)
+void wined3d_event_query_destroy(struct wined3d_event_query *query)
{
if (query->context) context_free_event_query(query);
HeapFree(GetProcessHeap(), 0, query);
}
-static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
+enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
{
struct wined3d_context *context;
const struct wined3d_gl_info *gl_info;
return WINED3D_EVENT_QUERY_WRONG_THREAD;
}
- context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(device, query->context->current_rt);
gl_info = context->gl_info;
ENTER_GL();
return ret;
}
-static void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
+enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
+{
+ struct wined3d_context *context;
+ const struct wined3d_gl_info *gl_info;
+ enum wined3d_event_query_result ret;
+
+ TRACE("(%p)\n", query);
+
+ if (!query->context)
+ {
+ TRACE("Query not started\n");
+ return WINED3D_EVENT_QUERY_NOT_STARTED;
+ }
+ gl_info = query->context->gl_info;
+
+ if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC])
+ {
+ /* A glFinish does not reliably wait for draws in other contexts. The caller has
+ * to find its own way to cope with the thread switch
+ */
+ WARN("Event query finished from wrong thread\n");
+ return WINED3D_EVENT_QUERY_WRONG_THREAD;
+ }
+
+ context = context_acquire(device, query->context->current_rt);
+
+ ENTER_GL();
+ if (gl_info->supported[ARB_SYNC])
+ {
+ GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, ~(GLuint64)0));
+ checkGLcall("glClientWaitSync");
+
+ switch (gl_ret)
+ {
+ case GL_ALREADY_SIGNALED:
+ case GL_CONDITION_SATISFIED:
+ ret = WINED3D_EVENT_QUERY_OK;
+ break;
+
+ /* We don't expect a timeout for a ~584 year wait */
+ default:
+ ERR("glClientWaitSync returned %#x.\n", gl_ret);
+ ret = WINED3D_EVENT_QUERY_ERROR;
+ }
+ }
+ else if (context->gl_info->supported[APPLE_FENCE])
+ {
+ GL_EXTCALL(glFinishFenceAPPLE(query->object.id));
+ checkGLcall("glFinishFenceAPPLE");
+ ret = WINED3D_EVENT_QUERY_OK;
+ }
+ else if (context->gl_info->supported[NV_FENCE])
+ {
+ GL_EXTCALL(glFinishFenceNV(query->object.id));
+ checkGLcall("glFinishFenceNV");
+ ret = WINED3D_EVENT_QUERY_OK;
+ }
+ else
+ {
+ ERR("Event query created without GL support\n");
+ ret = WINED3D_EVENT_QUERY_ERROR;
+ }
+ LEAVE_GL();
+
+ context_release(context);
+ return ret;
+}
+
+void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
{
const struct wined3d_gl_info *gl_info;
struct wined3d_context *context;
if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
{
context_free_event_query(query);
- context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(device, NULL);
context_alloc_event_query(context, query);
}
else
{
- context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(device, query->context->current_rt);
}
}
else
{
- context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(device, NULL);
context_alloc_event_query(context, query);
}
return S_OK;
}
- context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(This->device, query->context->current_rt);
ENTER_GL();
FIXME("Wrong thread, can't restart query.\n");
context_free_occlusion_query(query);
- context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(This->device, NULL);
context_alloc_occlusion_query(context, query);
}
else
{
- context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(This->device, query->context->current_rt);
ENTER_GL();
GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
else
{
if (query->context) context_free_occlusion_query(query);
- context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(This->device, NULL);
context_alloc_occlusion_query(context, query);
}
}
else
{
- context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+ context = context_acquire(This->device, query->context->current_rt);
ENTER_GL();
GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
WINED3DQUERYTYPE type, IUnknown *parent)
{
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
- HRESULT hr;
switch (type)
{
case WINED3DQUERYTYPE_EVENT:
TRACE("Event query.\n");
- query->lpVtbl = &IWineD3DEventQuery_Vtbl;
- hr = wined3d_event_query_init(gl_info, (struct wined3d_event_query **) &query->extendedData);
- if (hr == E_NOTIMPL)
+ if (!wined3d_event_query_supported(gl_info))
{
/* Half-Life 2 needs this query. It does not render the main
* menu correctly otherwise. Pretend to support it, faking
* lowering performance. */
FIXME("Event query: Unimplemented, but pretending to be supported.\n");
}
- else if(FAILED(hr))
+ query->lpVtbl = &IWineD3DEventQuery_Vtbl;
+ query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct wined3d_event_query));
+ if (!query->extendedData)
{
- return hr;
+ ERR("Failed to allocate event query memory.\n");
+ return E_OUTOFMEMORY;
}
break;