ole32: Accept STGM_TRANSACTED with no share mode specified.
[wine/multimedia.git] / dlls / wined3d / query.c
blobef1ab17c0da10bdef301e4dc68680cdc8a0869cd
1 /*
2 * Copyright 2005 Oliver Stieber
3 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
4 * Copyright 2009-2010 Henri Verbeet for CodeWeavers.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info)
30 return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
33 void wined3d_event_query_destroy(struct wined3d_event_query *query)
35 if (query->context) context_free_event_query(query);
36 HeapFree(GetProcessHeap(), 0, query);
39 static enum wined3d_event_query_result wined3d_event_query_test(const struct wined3d_event_query *query,
40 const struct wined3d_device *device)
42 struct wined3d_context *context;
43 const struct wined3d_gl_info *gl_info;
44 enum wined3d_event_query_result ret;
45 BOOL fence_result;
47 TRACE("(%p) : device %p\n", query, device);
49 if (!query->context)
51 TRACE("Query not started\n");
52 return WINED3D_EVENT_QUERY_NOT_STARTED;
55 if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
57 WARN("Event query tested from wrong thread\n");
58 return WINED3D_EVENT_QUERY_WRONG_THREAD;
61 context = context_acquire(device, query->context->current_rt);
62 gl_info = context->gl_info;
64 if (gl_info->supported[ARB_SYNC])
66 GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
67 checkGLcall("glClientWaitSync");
69 switch (gl_ret)
71 case GL_ALREADY_SIGNALED:
72 case GL_CONDITION_SATISFIED:
73 ret = WINED3D_EVENT_QUERY_OK;
74 break;
76 case GL_TIMEOUT_EXPIRED:
77 ret = WINED3D_EVENT_QUERY_WAITING;
78 break;
80 case GL_WAIT_FAILED:
81 default:
82 ERR("glClientWaitSync returned %#x.\n", gl_ret);
83 ret = WINED3D_EVENT_QUERY_ERROR;
86 else if (gl_info->supported[APPLE_FENCE])
88 fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
89 checkGLcall("glTestFenceAPPLE");
90 if (fence_result) ret = WINED3D_EVENT_QUERY_OK;
91 else ret = WINED3D_EVENT_QUERY_WAITING;
93 else if (gl_info->supported[NV_FENCE])
95 fence_result = GL_EXTCALL(glTestFenceNV(query->object.id));
96 checkGLcall("glTestFenceNV");
97 if (fence_result) ret = WINED3D_EVENT_QUERY_OK;
98 else ret = WINED3D_EVENT_QUERY_WAITING;
100 else
102 ERR("Event query created despite lack of GL support\n");
103 ret = WINED3D_EVENT_QUERY_ERROR;
106 context_release(context);
107 return ret;
110 enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query,
111 const struct wined3d_device *device)
113 struct wined3d_context *context;
114 const struct wined3d_gl_info *gl_info;
115 enum wined3d_event_query_result ret;
117 TRACE("(%p)\n", query);
119 if (!query->context)
121 TRACE("Query not started\n");
122 return WINED3D_EVENT_QUERY_NOT_STARTED;
124 gl_info = query->context->gl_info;
126 if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC])
128 /* A glFinish does not reliably wait for draws in other contexts. The caller has
129 * to find its own way to cope with the thread switch
131 WARN("Event query finished from wrong thread\n");
132 return WINED3D_EVENT_QUERY_WRONG_THREAD;
135 context = context_acquire(device, query->context->current_rt);
137 if (gl_info->supported[ARB_SYNC])
139 /* Apple seems to be into arbitrary limits, and timeouts larger than
140 * 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't
141 * really care and can live with waiting a few μs less. (OS X 10.7.4). */
142 GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff));
143 checkGLcall("glClientWaitSync");
145 switch (gl_ret)
147 case GL_ALREADY_SIGNALED:
148 case GL_CONDITION_SATISFIED:
149 ret = WINED3D_EVENT_QUERY_OK;
150 break;
152 /* We don't expect a timeout for a ~584 year wait */
153 default:
154 ERR("glClientWaitSync returned %#x.\n", gl_ret);
155 ret = WINED3D_EVENT_QUERY_ERROR;
158 else if (context->gl_info->supported[APPLE_FENCE])
160 GL_EXTCALL(glFinishFenceAPPLE(query->object.id));
161 checkGLcall("glFinishFenceAPPLE");
162 ret = WINED3D_EVENT_QUERY_OK;
164 else if (context->gl_info->supported[NV_FENCE])
166 GL_EXTCALL(glFinishFenceNV(query->object.id));
167 checkGLcall("glFinishFenceNV");
168 ret = WINED3D_EVENT_QUERY_OK;
170 else
172 ERR("Event query created without GL support\n");
173 ret = WINED3D_EVENT_QUERY_ERROR;
176 context_release(context);
177 return ret;
180 void wined3d_event_query_issue(struct wined3d_event_query *query, const struct wined3d_device *device)
182 const struct wined3d_gl_info *gl_info;
183 struct wined3d_context *context;
185 if (query->context)
187 if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
189 context_free_event_query(query);
190 context = context_acquire(device, NULL);
191 context_alloc_event_query(context, query);
193 else
195 context = context_acquire(device, query->context->current_rt);
198 else
200 context = context_acquire(device, NULL);
201 context_alloc_event_query(context, query);
204 gl_info = context->gl_info;
206 if (gl_info->supported[ARB_SYNC])
208 if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync));
209 checkGLcall("glDeleteSync");
210 query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
211 checkGLcall("glFenceSync");
213 else if (gl_info->supported[APPLE_FENCE])
215 GL_EXTCALL(glSetFenceAPPLE(query->object.id));
216 checkGLcall("glSetFenceAPPLE");
218 else if (gl_info->supported[NV_FENCE])
220 GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV));
221 checkGLcall("glSetFenceNV");
224 context_release(context);
227 ULONG CDECL wined3d_query_incref(struct wined3d_query *query)
229 ULONG refcount = InterlockedIncrement(&query->ref);
231 TRACE("%p increasing refcount to %u.\n", query, refcount);
233 return refcount;
236 ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
238 ULONG refcount = InterlockedDecrement(&query->ref);
240 TRACE("%p decreasing refcount to %u.\n", query, refcount);
242 if (!refcount)
244 /* Queries are specific to the GL context that created them. Not
245 * deleting the query will obviously leak it, but that's still better
246 * than potentially deleting a different query with the same id in this
247 * context, and (still) leaking the actual query. */
248 if (query->type == WINED3D_QUERY_TYPE_EVENT)
250 struct wined3d_event_query *event_query = query->extendedData;
251 if (event_query) wined3d_event_query_destroy(event_query);
253 else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION)
255 struct wined3d_occlusion_query *oq = query->extendedData;
257 if (oq->context) context_free_occlusion_query(oq);
258 HeapFree(GetProcessHeap(), 0, query->extendedData);
260 else if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP)
262 struct wined3d_timestamp_query *tq = query->extendedData;
264 if (tq->context)
265 context_free_timestamp_query(tq);
266 HeapFree(GetProcessHeap(), 0, query->extendedData);
269 HeapFree(GetProcessHeap(), 0, query);
272 return refcount;
275 HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query,
276 void *data, UINT data_size, DWORD flags)
278 TRACE("query %p, data %p, data_size %u, flags %#x.\n",
279 query, data, data_size, flags);
281 return query->query_ops->query_get_data(query, data, data_size, flags);
284 UINT CDECL wined3d_query_get_data_size(const struct wined3d_query *query)
286 TRACE("query %p.\n", query);
288 return query->data_size;
291 HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags)
293 TRACE("query %p, flags %#x.\n", query, flags);
295 return query->query_ops->query_issue(query, flags);
298 static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
299 void *pData, DWORD dwSize, DWORD flags)
301 struct wined3d_occlusion_query *oq = query->extendedData;
302 struct wined3d_device *device = query->device;
303 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
304 struct wined3d_context *context;
305 DWORD* data = pData;
306 GLuint available;
307 GLuint samples;
308 HRESULT res;
310 TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
312 if (!oq->context)
313 query->state = QUERY_CREATED;
315 if (query->state == QUERY_CREATED)
317 /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
318 TRACE("Query wasn't yet started, returning S_OK\n");
319 if(data) *data = 0;
320 return S_OK;
323 if (query->state == QUERY_BUILDING)
325 /* Msdn says this returns an error, but our tests show that S_FALSE is returned */
326 TRACE("Query is building, returning S_FALSE\n");
327 return S_FALSE;
330 if (!gl_info->supported[ARB_OCCLUSION_QUERY])
332 WARN("%p Occlusion queries not supported. Returning 1.\n", query);
333 *data = 1;
334 return S_OK;
337 if (oq->context->tid != GetCurrentThreadId())
339 FIXME("%p Wrong thread, returning 1.\n", query);
340 *data = 1;
341 return S_OK;
344 context = context_acquire(query->device, oq->context->current_rt);
346 GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
347 checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
348 TRACE("available %#x.\n", available);
350 if (available)
352 if (data)
354 GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples));
355 checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
356 TRACE("Returning %d samples.\n", samples);
357 *data = samples;
359 res = S_OK;
361 else
363 res = S_FALSE;
366 context_release(context);
368 return res;
371 static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query,
372 void *pData, DWORD dwSize, DWORD flags)
374 struct wined3d_event_query *event_query = query->extendedData;
375 BOOL *data = pData;
376 enum wined3d_event_query_result ret;
378 TRACE("query %p, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
380 if (!pData || !dwSize) return S_OK;
381 if (!event_query)
383 WARN("Event query not supported by GL, reporting GPU idle.\n");
384 *data = TRUE;
385 return S_OK;
388 ret = wined3d_event_query_test(event_query, query->device);
389 switch(ret)
391 case WINED3D_EVENT_QUERY_OK:
392 case WINED3D_EVENT_QUERY_NOT_STARTED:
393 *data = TRUE;
394 break;
396 case WINED3D_EVENT_QUERY_WAITING:
397 *data = FALSE;
398 break;
400 case WINED3D_EVENT_QUERY_WRONG_THREAD:
401 FIXME("(%p) Wrong thread, reporting GPU idle.\n", query);
402 *data = TRUE;
403 break;
405 case WINED3D_EVENT_QUERY_ERROR:
406 ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n");
407 return WINED3DERR_INVALIDCALL;
410 return S_OK;
413 enum wined3d_query_type CDECL wined3d_query_get_type(const struct wined3d_query *query)
415 TRACE("query %p.\n", query);
417 return query->type;
420 static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags)
422 TRACE("query %p, flags %#x.\n", query, flags);
424 TRACE("(%p) : flags %#x, type D3DQUERY_EVENT\n", query, flags);
425 if (flags & WINED3DISSUE_END)
427 struct wined3d_event_query *event_query = query->extendedData;
429 /* Faked event query support */
430 if (!event_query) return WINED3D_OK;
432 wined3d_event_query_issue(event_query, query->device);
434 else if (flags & WINED3DISSUE_BEGIN)
436 /* Started implicitly at device creation */
437 ERR("Event query issued with START flag - what to do?\n");
440 if (flags & WINED3DISSUE_BEGIN)
441 query->state = QUERY_BUILDING;
442 else
443 query->state = QUERY_SIGNALLED;
445 return WINED3D_OK;
448 static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags)
450 struct wined3d_device *device = query->device;
451 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
453 TRACE("query %p, flags %#x.\n", query, flags);
455 if (gl_info->supported[ARB_OCCLUSION_QUERY])
457 struct wined3d_occlusion_query *oq = query->extendedData;
458 struct wined3d_context *context;
460 /* This is allowed according to msdn and our tests. Reset the query and restart */
461 if (flags & WINED3DISSUE_BEGIN)
463 if (query->state == QUERY_BUILDING)
465 if (oq->context->tid != GetCurrentThreadId())
467 FIXME("Wrong thread, can't restart query.\n");
469 context_free_occlusion_query(oq);
470 context = context_acquire(query->device, NULL);
471 context_alloc_occlusion_query(context, oq);
473 else
475 context = context_acquire(query->device, oq->context->current_rt);
477 GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
478 checkGLcall("glEndQuery()");
481 else
483 if (oq->context) context_free_occlusion_query(oq);
484 context = context_acquire(query->device, NULL);
485 context_alloc_occlusion_query(context, oq);
488 GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, oq->id));
489 checkGLcall("glBeginQuery()");
491 context_release(context);
493 if (flags & WINED3DISSUE_END)
495 /* Msdn says _END on a non-building occlusion query returns an error, but
496 * our tests show that it returns OK. But OpenGL doesn't like it, so avoid
497 * generating an error
499 if (query->state == QUERY_BUILDING)
501 if (oq->context->tid != GetCurrentThreadId())
503 FIXME("Wrong thread, can't end query.\n");
505 else
507 context = context_acquire(query->device, oq->context->current_rt);
509 GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
510 checkGLcall("glEndQuery()");
512 context_release(context);
517 else
519 FIXME("%p Occlusion queries not supported.\n", query);
522 if (flags & WINED3DISSUE_BEGIN)
523 query->state = QUERY_BUILDING;
524 else
525 query->state = QUERY_SIGNALLED;
527 return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */
530 static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
531 void *data, DWORD size, DWORD flags)
533 struct wined3d_timestamp_query *tq = query->extendedData;
534 struct wined3d_device *device = query->device;
535 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
536 struct wined3d_context *context;
537 UINT64 *u64data = data;
538 GLuint available;
539 GLuint64 timestamp;
540 HRESULT res;
542 TRACE("(%p) : type D3DQUERY_TIMESTAMP, data %p, size %#x, flags %#x.\n", query, data, size, flags);
544 if (!tq->context)
545 query->state = QUERY_CREATED;
547 if (query->state == QUERY_CREATED)
549 /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves. */
550 TRACE("Query wasn't yet started, returning S_OK.\n");
551 if (u64data)
552 *u64data = 0;
553 return S_OK;
556 if (tq->context->tid != GetCurrentThreadId())
558 FIXME("%p Wrong thread, returning 1.\n", query);
559 if (u64data)
560 *u64data = 1;
561 return S_OK;
564 context = context_acquire(query->device, tq->context->current_rt);
566 GL_EXTCALL(glGetQueryObjectuivARB(tq->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
567 checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
568 TRACE("available %#x.\n", available);
570 if (available)
572 if (u64data)
574 GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT_ARB, &timestamp));
575 checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
576 TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp));
577 *u64data = timestamp;
579 res = S_OK;
581 else
583 res = S_FALSE;
586 context_release(context);
588 return res;
591 static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags)
593 struct wined3d_device *device = query->device;
594 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
596 TRACE("query %p, flags %#x.\n", query, flags);
598 if (gl_info->supported[ARB_TIMER_QUERY])
600 struct wined3d_timestamp_query *tq = query->extendedData;
601 struct wined3d_context *context;
603 if (flags & WINED3DISSUE_BEGIN)
605 WARN("Ignoring WINED3DISSUE_BEGIN with a TIMESTAMP query.\n");
607 if (flags & WINED3DISSUE_END)
609 if (tq->context)
610 context_free_timestamp_query(tq);
611 context = context_acquire(query->device, NULL);
612 context_alloc_timestamp_query(context, tq);
613 GL_EXTCALL(glQueryCounter(tq->id, GL_TIMESTAMP));
614 checkGLcall("glQueryCounter()");
615 context_release(context);
618 else
620 ERR("Timestamp queries not supported.\n");
623 if (flags & WINED3DISSUE_END)
624 query->state = QUERY_SIGNALLED;
626 return WINED3D_OK;
629 static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query,
630 void *data, DWORD size, DWORD flags)
632 TRACE("(%p) : type D3DQUERY_TIMESTAMP_DISJOINT, data %p, size %#x, flags %#x.\n", query, data, size, flags);
634 if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT)
636 struct wined3d_query_data_timestamp_disjoint *disjoint_data = data;
638 if (query->state == QUERY_BUILDING)
640 TRACE("Query is building, returning S_FALSE.\n");
641 return S_FALSE;
644 if (disjoint_data)
646 disjoint_data->disjoint = FALSE;
647 disjoint_data->frequency = 1000 * 1000 * 1000;
650 else
652 UINT64 *u64data = data;
654 if (u64data)
655 *u64data = 1000 * 1000 * 1000;
657 return S_OK;
660 static HRESULT wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags)
662 TRACE("query %p, flags %#x.\n", query, flags);
664 if (flags & WINED3DISSUE_BEGIN)
665 query->state = QUERY_BUILDING;
666 if (flags & WINED3DISSUE_END)
667 query->state = QUERY_SIGNALLED;
669 return WINED3D_OK;
672 static const struct wined3d_query_ops event_query_ops =
674 wined3d_event_query_ops_get_data,
675 wined3d_event_query_ops_issue,
678 static const struct wined3d_query_ops occlusion_query_ops =
680 wined3d_occlusion_query_ops_get_data,
681 wined3d_occlusion_query_ops_issue,
684 static const struct wined3d_query_ops timestamp_query_ops =
686 wined3d_timestamp_query_ops_get_data,
687 wined3d_timestamp_query_ops_issue,
690 static const struct wined3d_query_ops timestamp_disjoint_query_ops =
692 wined3d_timestamp_disjoint_query_ops_get_data,
693 wined3d_timestamp_disjoint_query_ops_issue,
696 static HRESULT query_init(struct wined3d_query *query, struct wined3d_device *device, enum wined3d_query_type type)
698 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
700 switch (type)
702 case WINED3D_QUERY_TYPE_OCCLUSION:
703 TRACE("Occlusion query.\n");
704 if (!gl_info->supported[ARB_OCCLUSION_QUERY])
706 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY.\n");
707 return WINED3DERR_NOTAVAILABLE;
709 query->query_ops = &occlusion_query_ops;
710 query->data_size = sizeof(DWORD);
711 query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query));
712 if (!query->extendedData)
714 ERR("Failed to allocate occlusion query extended data.\n");
715 return E_OUTOFMEMORY;
717 ((struct wined3d_occlusion_query *)query->extendedData)->context = NULL;
718 break;
720 case WINED3D_QUERY_TYPE_EVENT:
721 TRACE("Event query.\n");
722 if (!wined3d_event_query_supported(gl_info))
724 /* Half-Life 2 needs this query. It does not render the main
725 * menu correctly otherwise. Pretend to support it, faking
726 * this query does not do much harm except potentially
727 * lowering performance. */
728 FIXME("Event query: Unimplemented, but pretending to be supported.\n");
730 query->query_ops = &event_query_ops;
731 query->data_size = sizeof(BOOL);
732 query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct wined3d_event_query));
733 if (!query->extendedData)
735 ERR("Failed to allocate event query memory.\n");
736 return E_OUTOFMEMORY;
738 break;
740 case WINED3D_QUERY_TYPE_TIMESTAMP:
741 TRACE("Timestamp query.\n");
742 if (!gl_info->supported[ARB_TIMER_QUERY])
744 WARN("Unsupported in local OpenGL implementation: ARB_TIMER_QUERY.\n");
745 return WINED3DERR_NOTAVAILABLE;
747 query->query_ops = &timestamp_query_ops;
748 query->data_size = sizeof(UINT64);
749 query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_timestamp_query));
750 if (!query->extendedData)
752 ERR("Failed to allocate timestamp query extended data.\n");
753 return E_OUTOFMEMORY;
755 ((struct wined3d_timestamp_query *)query->extendedData)->context = NULL;
756 break;
758 case WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT:
759 case WINED3D_QUERY_TYPE_TIMESTAMP_FREQ:
760 TRACE("TIMESTAMP_DISJOINT query.\n");
761 if (!gl_info->supported[ARB_TIMER_QUERY])
763 WARN("Unsupported in local OpenGL implementation: ARB_TIMER_QUERY.\n");
764 return WINED3DERR_NOTAVAILABLE;
766 query->query_ops = &timestamp_disjoint_query_ops;
767 query->data_size = type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT
768 ? sizeof(struct wined3d_query_data_timestamp_disjoint) : sizeof(UINT64);
769 query->extendedData = NULL;
770 break;
772 case WINED3D_QUERY_TYPE_VCACHE:
773 case WINED3D_QUERY_TYPE_RESOURCE_MANAGER:
774 case WINED3D_QUERY_TYPE_VERTEX_STATS:
775 case WINED3D_QUERY_TYPE_PIPELINE_TIMINGS:
776 case WINED3D_QUERY_TYPE_INTERFACE_TIMINGS:
777 case WINED3D_QUERY_TYPE_VERTEX_TIMINGS:
778 case WINED3D_QUERY_TYPE_PIXEL_TIMINGS:
779 case WINED3D_QUERY_TYPE_BANDWIDTH_TIMINGS:
780 case WINED3D_QUERY_TYPE_CACHE_UTILIZATION:
781 default:
782 FIXME("Unhandled query type %#x.\n", type);
783 return WINED3DERR_NOTAVAILABLE;
786 query->type = type;
787 query->state = QUERY_CREATED;
788 query->device = device;
789 query->ref = 1;
791 return WINED3D_OK;
794 HRESULT CDECL wined3d_query_create(struct wined3d_device *device,
795 enum wined3d_query_type type, struct wined3d_query **query)
797 struct wined3d_query *object;
798 HRESULT hr;
800 TRACE("device %p, type %#x, query %p.\n", device, type, query);
802 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
803 if (!object)
804 return E_OUTOFMEMORY;
806 hr = query_init(object, device, type);
807 if (FAILED(hr))
809 WARN("Failed to initialize query, hr %#x.\n", hr);
810 HeapFree(GetProcessHeap(), 0, object);
811 return hr;
814 TRACE("Created query %p.\n", object);
815 *query = object;
817 return WINED3D_OK;