static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, void *data, DWORD size, DWORD flags) { struct wined3d_timestamp_query *tq = query->extendedData; struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint64 timestamp; HRESULT res; TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); if (!tq->context) query->state = QUERY_CREATED; if (query->state == QUERY_CREATED) { /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves. */ TRACE("Query wasn't yet started, returning S_OK.\n"); timestamp = 0; fill_query_data(data, size, ×tamp, sizeof(timestamp)); return S_OK; } if (tq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); timestamp = 1; fill_query_data(data, size, ×tamp, sizeof(timestamp)); return S_OK; } context = context_acquire(device, context_get_rt_surface(tq->context)); GL_EXTCALL(glGetQueryObjectuiv(tq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { if (size) { GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); fill_query_data(data, size, ×tamp, sizeof(timestamp)); } res = S_OK; } else { res = S_FALSE; } context_release(context); return res; }
static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query) { struct wined3d_timestamp_query *tq = query->extendedData; struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint64 timestamp; BOOL ret; if (!gl_info->supported[ARB_TIMER_QUERY]) { TRACE("Faking timestamp.\n"); QueryPerformanceCounter((LARGE_INTEGER *)&tq->timestamp); return TRUE; } if (tq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); tq->timestamp = 1; return TRUE; } context = context_acquire(device, context_get_rt_surface(tq->context)); GL_EXTCALL(glGetQueryObjectuiv(tq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); tq->timestamp = timestamp; ret = TRUE; } else { ret = FALSE; } context_release(context); return ret; }
void wined3d_event_query_issue(struct wined3d_event_query *query, const struct wined3d_device *device) { const struct wined3d_gl_info *gl_info; struct wined3d_context *context; if (query->context) { if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId()) { context_free_event_query(query); context = context_acquire(device, NULL); context_alloc_event_query(context, query); } else { context = context_acquire(device, context_get_rt_surface(query->context)); } } else { context = context_acquire(device, NULL); context_alloc_event_query(context, query); } gl_info = context->gl_info; if (gl_info->supported[ARB_SYNC]) { if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync)); checkGLcall("glDeleteSync"); query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); checkGLcall("glFenceSync"); } else if (gl_info->supported[APPLE_FENCE]) { GL_EXTCALL(glSetFenceAPPLE(query->object.id)); checkGLcall("glSetFenceAPPLE"); } else if (gl_info->supported[NV_FENCE]) { GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV)); checkGLcall("glSetFenceNV"); } context_release(context); }
static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query) { struct wined3d_occlusion_query *oq = query->extendedData; struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint samples; BOOL ret; if (oq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); oq->samples = 1; return TRUE; } context = context_acquire(device, context_get_rt_surface(oq->context)); GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); TRACE("Returning %d samples.\n", samples); oq->samples = samples; ret = TRUE; } else { ret = FALSE; } context_release(context); return ret; }
static enum wined3d_event_query_result wined3d_event_query_test(const struct wined3d_event_query *query, const struct wined3d_device *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; BOOL fence_result; TRACE("(%p) : device %p\n", query, device); if (!query->context) { TRACE("Query not started\n"); return WINED3D_EVENT_QUERY_NOT_STARTED; } if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId()) { WARN("Event query tested from wrong thread\n"); return WINED3D_EVENT_QUERY_WRONG_THREAD; } context = context_acquire(device, context_get_rt_surface(query->context)); gl_info = context->gl_info; if (gl_info->supported[ARB_SYNC]) { GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0)); checkGLcall("glClientWaitSync"); switch (gl_ret) { case GL_ALREADY_SIGNALED: case GL_CONDITION_SATISFIED: ret = WINED3D_EVENT_QUERY_OK; break; case GL_TIMEOUT_EXPIRED: ret = WINED3D_EVENT_QUERY_WAITING; break; case GL_WAIT_FAILED: default: ERR("glClientWaitSync returned %#x.\n", gl_ret); ret = WINED3D_EVENT_QUERY_ERROR; } } else if (gl_info->supported[APPLE_FENCE]) { fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id)); checkGLcall("glTestFenceAPPLE"); if (fence_result) ret = WINED3D_EVENT_QUERY_OK; else ret = WINED3D_EVENT_QUERY_WAITING; } else if (gl_info->supported[NV_FENCE]) { fence_result = GL_EXTCALL(glTestFenceNV(query->object.id)); checkGLcall("glTestFenceNV"); if (fence_result) ret = WINED3D_EVENT_QUERY_OK; else ret = WINED3D_EVENT_QUERY_WAITING; } else { ERR("Event query created despite lack of GL support\n"); ret = WINED3D_EVENT_QUERY_ERROR; } context_release(context); return ret; }
static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query) { struct wined3d_occlusion_query *oq = wined3d_occlusion_query_from_query(query); struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint samples; BOOL ret; #endif /* STAGING_CSMT */ if (oq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); #if !defined(STAGING_CSMT) samples = 1; fill_query_data(data, size, &samples, sizeof(samples)); return S_OK; #else /* STAGING_CSMT */ oq->samples = 1; return TRUE; #endif /* STAGING_CSMT */ } context = context_acquire(device, context_get_rt_surface(oq->context)); GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { #if !defined(STAGING_CSMT) if (size) { GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); TRACE("Returning %d samples.\n", samples); fill_query_data(data, size, &samples, sizeof(samples)); } res = S_OK; #else /* STAGING_CSMT */ GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); TRACE("Returning %d samples.\n", samples); oq->samples = samples; ret = TRUE; #endif /* STAGING_CSMT */ } else { #if !defined(STAGING_CSMT) res = S_FALSE; #else /* STAGING_CSMT */ ret = FALSE; #endif /* STAGING_CSMT */ } context_release(context); #if !defined(STAGING_CSMT) return res; }
enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query, const struct wined3d_device *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; TRACE("query %p, device %p.\n", query, device); 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, context_get_rt_surface(query->context)); if (gl_info->supported[ARB_SYNC]) { /* Apple seems to be into arbitrary limits, and timeouts larger than * 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't * really care and can live with waiting a few μs less. (OS X 10.7.4). */ GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff)); 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; } context_release(context); return ret; }
static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) { struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; TRACE("query %p, flags %#x.\n", query, flags); if (gl_info->supported[ARB_OCCLUSION_QUERY]) { struct wined3d_occlusion_query *oq = query->extendedData; struct wined3d_context *context; /* This is allowed according to msdn and our tests. Reset the query and restart */ if (flags & WINED3DISSUE_BEGIN) { if (query->state == QUERY_BUILDING) { if (oq->context->tid != GetCurrentThreadId()) { FIXME("Wrong thread, can't restart query.\n"); context_free_occlusion_query(oq); context = context_acquire(query->device, NULL); context_alloc_occlusion_query(context, oq); } else { context = context_acquire(device, context_get_rt_surface(oq->context)); GL_EXTCALL(glEndQuery(GL_SAMPLES_PASSED)); checkGLcall("glEndQuery()"); } } else { if (oq->context) context_free_occlusion_query(oq); context = context_acquire(query->device, NULL); context_alloc_occlusion_query(context, oq); } GL_EXTCALL(glBeginQuery(GL_SAMPLES_PASSED, oq->id)); checkGLcall("glBeginQuery()"); context_release(context); } if (flags & WINED3DISSUE_END) { /* Msdn says _END on a non-building occlusion query returns an error, but * our tests show that it returns OK. But OpenGL doesn't like it, so avoid * generating an error */ if (query->state == QUERY_BUILDING) { if (oq->context->tid != GetCurrentThreadId()) { FIXME("Wrong thread, can't end query.\n"); } else { context = context_acquire(device, context_get_rt_surface(oq->context)); GL_EXTCALL(glEndQuery(GL_SAMPLES_PASSED)); checkGLcall("glEndQuery()"); context_release(context); } } } } else { FIXME("%p Occlusion queries not supported.\n", query); } if (flags & WINED3DISSUE_BEGIN) query->state = QUERY_BUILDING; else query->state = QUERY_SIGNALLED; return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ }
static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, void *data, DWORD size, DWORD flags) { struct wined3d_occlusion_query *oq = query->extendedData; struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint samples; HRESULT res; TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); if (!oq->context) query->state = QUERY_CREATED; if (query->state == QUERY_CREATED) { /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */ TRACE("Query wasn't yet started, returning S_OK\n"); samples = 0; fill_query_data(data, size, &samples, sizeof(samples)); return S_OK; } if (query->state == QUERY_BUILDING) { /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ TRACE("Query is building, returning S_FALSE\n"); return S_FALSE; } if (!gl_info->supported[ARB_OCCLUSION_QUERY]) { WARN("%p Occlusion queries not supported. Returning 1.\n", query); samples = 1; fill_query_data(data, size, &samples, sizeof(samples)); return S_OK; } if (oq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); samples = 1; fill_query_data(data, size, &samples, sizeof(samples)); return S_OK; } context = context_acquire(device, context_get_rt_surface(oq->context)); GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { if (size) { GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT, &samples)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT)"); TRACE("Returning %d samples.\n", samples); fill_query_data(data, size, &samples, sizeof(samples)); } res = S_OK; } else { res = S_FALSE; } context_release(context); return res; }