ntdll: Load .so builtin modules without using libwine.
[wine/zf.git] / dlls / wined3d / query.c
blobab3bb743809920d2ca1a1d3f15d142d6089c0c21
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 static void wined3d_query_buffer_invalidate(struct wined3d_query *query)
30 /* map[0] != map[1]: exact values do not have any significance. */
31 query->map_ptr[0] = 0;
32 query->map_ptr[1] = ~(UINT64)0;
35 static BOOL wined3d_query_buffer_is_valid(struct wined3d_query *query)
37 return query->map_ptr[0] == query->map_ptr[1];
40 static void wined3d_query_create_buffer_object(struct wined3d_context_gl *context_gl, struct wined3d_query *query)
42 const GLuint map_flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
43 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
44 GLuint buffer_object;
46 GL_EXTCALL(glGenBuffers(1, &buffer_object));
47 GL_EXTCALL(glBindBuffer(GL_QUERY_BUFFER, buffer_object));
48 GL_EXTCALL(glBufferStorage(GL_QUERY_BUFFER, sizeof(query->map_ptr[0]) * 2, NULL, map_flags));
49 query->map_ptr = GL_EXTCALL(glMapBufferRange(GL_QUERY_BUFFER, 0, sizeof(query->map_ptr[0]) * 2, map_flags));
50 GL_EXTCALL(glBindBuffer(GL_QUERY_BUFFER, 0));
51 checkGLcall("query buffer object creation");
53 wined3d_query_buffer_invalidate(query);
54 query->buffer_object = buffer_object;
57 void wined3d_query_gl_destroy_buffer_object(struct wined3d_context_gl *context_gl, struct wined3d_query *query)
59 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
61 GL_EXTCALL(glDeleteBuffers(1, &query->buffer_object));
62 checkGLcall("query buffer object destruction");
64 query->buffer_object = 0;
65 query->map_ptr = NULL;
68 /* From ARB_occlusion_query: "Querying the state for a given occlusion query
69 * forces that occlusion query to complete within a finite amount of time."
70 * In practice, that means drivers flush when retrieving
71 * GL_QUERY_RESULT_AVAILABLE, which can be undesirable when applications use a
72 * significant number of queries. Using a persistently mapped query buffer
73 * object allows us to avoid these implicit flushes. An additional benefit is
74 * that it allows us to poll the query status from the application-thread
75 * instead of from the csmt-thread. */
76 static BOOL wined3d_query_buffer_queue_result(struct wined3d_context_gl *context_gl,
77 struct wined3d_query *query, GLuint id)
79 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
80 GLsync tmp_sync;
82 if (!gl_info->supported[ARB_QUERY_BUFFER_OBJECT] || !gl_info->supported[ARB_BUFFER_STORAGE])
83 return FALSE;
84 /* Don't use query buffers without CSMT, mainly for simplicity. */
85 if (!context_gl->c.device->cs->thread)
86 return FALSE;
88 if (query->buffer_object)
90 /* If there's still a query result in-flight for the existing buffer
91 * object (i.e., the query was restarted before we received its
92 * result), we can't reuse the existing buffer object. */
93 if (wined3d_query_buffer_is_valid(query))
94 wined3d_query_buffer_invalidate(query);
95 else
96 wined3d_query_gl_destroy_buffer_object(context_gl, query);
99 if (!query->buffer_object)
100 wined3d_query_create_buffer_object(context_gl, query);
102 GL_EXTCALL(glBindBuffer(GL_QUERY_BUFFER, query->buffer_object));
103 /* Read the same value twice. We know we have the result if map_ptr[0] == map_ptr[1]. */
104 GL_EXTCALL(glGetQueryObjectui64v(id, GL_QUERY_RESULT, (void *)0));
105 GL_EXTCALL(glGetQueryObjectui64v(id, GL_QUERY_RESULT, (void *)sizeof(query->map_ptr[0])));
106 GL_EXTCALL(glBindBuffer(GL_QUERY_BUFFER, 0));
107 checkGLcall("queue query result");
109 /* ARB_buffer_storage requires the client to call FenceSync with
110 * SYNC_GPU_COMMANDS_COMPLETE after the server does a write. This behavior
111 * is not enforced by Mesa.
113 tmp_sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
114 GL_EXTCALL(glDeleteSync(tmp_sync));
115 checkGLcall("query buffer sync");
117 return TRUE;
120 static UINT64 get_query_result64(GLuint id, const struct wined3d_gl_info *gl_info)
122 if (gl_info->supported[ARB_TIMER_QUERY])
124 GLuint64 result;
125 GL_EXTCALL(glGetQueryObjectui64v(id, GL_QUERY_RESULT, &result));
126 return result;
128 else
130 GLuint result;
131 GL_EXTCALL(glGetQueryObjectuiv(id, GL_QUERY_RESULT, &result));
132 return result;
136 static void wined3d_query_init(struct wined3d_query *query, struct wined3d_device *device,
137 enum wined3d_query_type type, const void *data, DWORD data_size,
138 const struct wined3d_query_ops *query_ops, void *parent, const struct wined3d_parent_ops *parent_ops)
140 query->ref = 1;
141 query->parent = parent;
142 query->parent_ops = parent_ops;
143 query->device = device;
144 query->state = QUERY_CREATED;
145 query->type = type;
146 query->data = data;
147 query->data_size = data_size;
148 query->query_ops = query_ops;
149 list_init(&query->poll_list_entry);
152 static struct wined3d_event_query *wined3d_event_query_from_query(struct wined3d_query *query)
154 return CONTAINING_RECORD(query, struct wined3d_event_query, query);
157 static struct wined3d_occlusion_query *wined3d_occlusion_query_from_query(struct wined3d_query *query)
159 return CONTAINING_RECORD(query, struct wined3d_occlusion_query, query);
162 static struct wined3d_timestamp_query *wined3d_timestamp_query_from_query(struct wined3d_query *query)
164 return CONTAINING_RECORD(query, struct wined3d_timestamp_query, query);
167 static struct wined3d_so_statistics_query *wined3d_so_statistics_query_from_query(struct wined3d_query *query)
169 return CONTAINING_RECORD(query, struct wined3d_so_statistics_query, query);
172 static struct wined3d_pipeline_statistics_query *wined3d_pipeline_statistics_query_from_query(
173 struct wined3d_query *query)
175 return CONTAINING_RECORD(query, struct wined3d_pipeline_statistics_query, query);
178 static BOOL wined3d_fence_supported(const struct wined3d_gl_info *gl_info)
180 return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
183 static enum wined3d_fence_result wined3d_fence_test(const struct wined3d_fence *fence,
184 struct wined3d_device *device, DWORD flags)
186 const struct wined3d_gl_info *gl_info;
187 struct wined3d_context_gl *context_gl;
188 enum wined3d_fence_result ret;
189 BOOL fence_result;
191 TRACE("fence %p, device %p, flags %#x.\n", fence, device, flags);
193 if (!fence->context_gl)
195 TRACE("Fence not issued.\n");
196 return WINED3D_FENCE_NOT_STARTED;
199 if (!(context_gl = wined3d_context_gl_reacquire(fence->context_gl)))
201 if (!fence->context_gl->gl_info->supported[ARB_SYNC])
203 WARN("Fence tested from wrong thread.\n");
204 return WINED3D_FENCE_WRONG_THREAD;
206 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
208 gl_info = context_gl->gl_info;
210 if (gl_info->supported[ARB_SYNC])
212 GLenum gl_ret = GL_EXTCALL(glClientWaitSync(fence->object.sync,
213 (flags & WINED3DGETDATA_FLUSH) ? GL_SYNC_FLUSH_COMMANDS_BIT : 0, 0));
214 checkGLcall("glClientWaitSync");
216 switch (gl_ret)
218 case GL_ALREADY_SIGNALED:
219 case GL_CONDITION_SATISFIED:
220 ret = WINED3D_FENCE_OK;
221 break;
223 case GL_TIMEOUT_EXPIRED:
224 ret = WINED3D_FENCE_WAITING;
225 break;
227 case GL_WAIT_FAILED:
228 default:
229 ERR("glClientWaitSync returned %#x.\n", gl_ret);
230 ret = WINED3D_FENCE_ERROR;
233 else if (gl_info->supported[APPLE_FENCE])
235 fence_result = GL_EXTCALL(glTestFenceAPPLE(fence->object.id));
236 checkGLcall("glTestFenceAPPLE");
237 if (fence_result)
238 ret = WINED3D_FENCE_OK;
239 else
240 ret = WINED3D_FENCE_WAITING;
242 else if (gl_info->supported[NV_FENCE])
244 fence_result = GL_EXTCALL(glTestFenceNV(fence->object.id));
245 checkGLcall("glTestFenceNV");
246 if (fence_result)
247 ret = WINED3D_FENCE_OK;
248 else
249 ret = WINED3D_FENCE_WAITING;
251 else
253 ERR("Fence created despite lack of GL support.\n");
254 ret = WINED3D_FENCE_ERROR;
257 context_release(&context_gl->c);
258 return ret;
261 enum wined3d_fence_result wined3d_fence_wait(const struct wined3d_fence *fence,
262 struct wined3d_device *device)
264 const struct wined3d_gl_info *gl_info;
265 struct wined3d_context_gl *context_gl;
266 enum wined3d_fence_result ret;
268 TRACE("fence %p, device %p.\n", fence, device);
270 if (!fence->context_gl)
272 TRACE("Fence not issued.\n");
273 return WINED3D_FENCE_NOT_STARTED;
275 gl_info = fence->context_gl->gl_info;
277 if (!(context_gl = wined3d_context_gl_reacquire(fence->context_gl)))
279 /* A glFinish does not reliably wait for draws in other contexts. The caller has
280 * to find its own way to cope with the thread switch
282 if (!gl_info->supported[ARB_SYNC])
284 WARN("Fence finished from wrong thread.\n");
285 return WINED3D_FENCE_WRONG_THREAD;
287 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
289 gl_info = context_gl->gl_info;
291 if (gl_info->supported[ARB_SYNC])
293 /* Timeouts near 0xffffffffffffffff may immediately return GL_TIMEOUT_EXPIRED,
294 * possibly because macOS internally adds some slop to the timer. To avoid this,
295 * we use a large number that isn't near the point of overflow (macOS 10.12.5).
297 GLenum gl_ret = GL_EXTCALL(glClientWaitSync(fence->object.sync,
298 GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0 >> 1));
299 checkGLcall("glClientWaitSync");
301 switch (gl_ret)
303 case GL_ALREADY_SIGNALED:
304 case GL_CONDITION_SATISFIED:
305 ret = WINED3D_FENCE_OK;
306 break;
308 /* We don't expect a timeout for a ~292 year wait */
309 default:
310 ERR("glClientWaitSync returned %#x.\n", gl_ret);
311 ret = WINED3D_FENCE_ERROR;
314 else if (gl_info->supported[APPLE_FENCE])
316 GL_EXTCALL(glFinishFenceAPPLE(fence->object.id));
317 checkGLcall("glFinishFenceAPPLE");
318 ret = WINED3D_FENCE_OK;
320 else if (gl_info->supported[NV_FENCE])
322 GL_EXTCALL(glFinishFenceNV(fence->object.id));
323 checkGLcall("glFinishFenceNV");
324 ret = WINED3D_FENCE_OK;
326 else
328 ERR("Fence created without GL support.\n");
329 ret = WINED3D_FENCE_ERROR;
332 context_release(&context_gl->c);
333 return ret;
336 void wined3d_fence_issue(struct wined3d_fence *fence, struct wined3d_device *device)
338 struct wined3d_context_gl *context_gl = NULL;
339 const struct wined3d_gl_info *gl_info;
341 if (fence->context_gl && !(context_gl = wined3d_context_gl_reacquire(fence->context_gl))
342 && !fence->context_gl->gl_info->supported[ARB_SYNC])
343 wined3d_context_gl_free_fence(fence);
344 if (!context_gl)
345 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
346 gl_info = context_gl->gl_info;
347 if (!fence->context_gl)
348 wined3d_context_gl_alloc_fence(context_gl, fence);
350 if (gl_info->supported[ARB_SYNC])
352 if (fence->object.sync)
353 GL_EXTCALL(glDeleteSync(fence->object.sync));
354 checkGLcall("glDeleteSync");
355 fence->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
356 checkGLcall("glFenceSync");
358 else if (gl_info->supported[APPLE_FENCE])
360 GL_EXTCALL(glSetFenceAPPLE(fence->object.id));
361 checkGLcall("glSetFenceAPPLE");
363 else if (gl_info->supported[NV_FENCE])
365 GL_EXTCALL(glSetFenceNV(fence->object.id, GL_ALL_COMPLETED_NV));
366 checkGLcall("glSetFenceNV");
369 context_release(&context_gl->c);
372 static void wined3d_fence_free(struct wined3d_fence *fence)
374 if (fence->context_gl)
375 wined3d_context_gl_free_fence(fence);
378 void wined3d_fence_destroy(struct wined3d_fence *fence)
380 wined3d_fence_free(fence);
381 heap_free(fence);
384 static HRESULT wined3d_fence_init(struct wined3d_fence *fence, const struct wined3d_gl_info *gl_info)
386 if (!wined3d_fence_supported(gl_info))
388 WARN("Fences not supported.\n");
389 return WINED3DERR_NOTAVAILABLE;
392 return WINED3D_OK;
395 HRESULT wined3d_fence_create(struct wined3d_device *device, struct wined3d_fence **fence)
397 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
398 struct wined3d_fence *object;
399 HRESULT hr;
401 TRACE("device %p, fence %p.\n", device, fence);
403 if (!(object = heap_alloc_zero(sizeof(*object))))
404 return E_OUTOFMEMORY;
406 if (FAILED(hr = wined3d_fence_init(object, gl_info)))
408 heap_free(object);
409 return hr;
412 TRACE("Created fence %p.\n", object);
413 *fence = object;
415 return WINED3D_OK;
418 ULONG CDECL wined3d_query_incref(struct wined3d_query *query)
420 ULONG refcount = InterlockedIncrement(&query->ref);
422 TRACE("%p increasing refcount to %u.\n", query, refcount);
424 return refcount;
427 static void wined3d_query_destroy_object(void *object)
429 struct wined3d_query *query = object;
431 if (!list_empty(&query->poll_list_entry))
432 list_remove(&query->poll_list_entry);
435 ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
437 ULONG refcount = InterlockedDecrement(&query->ref);
439 TRACE("%p decreasing refcount to %u.\n", query, refcount);
441 if (!refcount)
443 struct wined3d_device *device = query->device;
445 query->parent_ops->wined3d_object_destroyed(query->parent);
446 wined3d_cs_destroy_object(device->cs, wined3d_query_destroy_object, query);
447 device->adapter->adapter_ops->adapter_destroy_query(query);
450 return refcount;
453 HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query,
454 void *data, UINT data_size, DWORD flags)
456 TRACE("query %p, data %p, data_size %u, flags %#x.\n",
457 query, data, data_size, flags);
459 if (query->state == QUERY_BUILDING)
461 WARN("Query is building, returning S_FALSE.\n");
462 return S_FALSE;
465 if (query->state == QUERY_CREATED)
467 WARN("Query wasn't started yet.\n");
468 return WINED3DERR_INVALIDCALL;
471 if (query->device->cs->thread)
473 if (query->counter_main != query->counter_retrieved
474 || (query->buffer_object && !wined3d_query_buffer_is_valid(query)))
476 if (flags & WINED3DGETDATA_FLUSH && !query->device->cs->queries_flushed)
477 wined3d_cs_emit_flush(query->device->cs);
478 return S_FALSE;
480 if (query->buffer_object)
481 query->data = query->map_ptr;
483 else if (!query->query_ops->query_poll(query, flags))
485 return S_FALSE;
488 if (data)
489 memcpy(data, query->data, min(data_size, query->data_size));
491 return S_OK;
494 UINT CDECL wined3d_query_get_data_size(const struct wined3d_query *query)
496 TRACE("query %p.\n", query);
498 return query->data_size;
501 HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags)
503 TRACE("query %p, flags %#x.\n", query, flags);
505 if (flags & WINED3DISSUE_END)
506 ++query->counter_main;
508 wined3d_cs_emit_query_issue(query->device->cs, query, flags);
510 if (flags & WINED3DISSUE_BEGIN)
511 query->state = QUERY_BUILDING;
512 else
513 query->state = QUERY_SIGNALLED;
515 return WINED3D_OK;
518 static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query, DWORD flags)
520 struct wined3d_occlusion_query *oq = wined3d_occlusion_query_from_query(query);
521 const struct wined3d_gl_info *gl_info;
522 struct wined3d_context_gl *context_gl;
523 GLuint available;
525 TRACE("query %p, flags %#x.\n", query, flags);
527 if (!(context_gl = wined3d_context_gl_reacquire(oq->context_gl)))
529 FIXME("%p Wrong thread, returning 1.\n", query);
530 oq->samples = 1;
531 return TRUE;
533 gl_info = context_gl->gl_info;
535 GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT_AVAILABLE, &available));
536 TRACE("Available %#x.\n", available);
538 if (available)
540 oq->samples = get_query_result64(oq->id, gl_info);
541 TRACE("Returning 0x%s samples.\n", wine_dbgstr_longlong(oq->samples));
544 checkGLcall("poll occlusion query");
545 context_release(&context_gl->c);
547 return available;
550 static BOOL wined3d_event_query_ops_poll(struct wined3d_query *query, DWORD flags)
552 struct wined3d_event_query *event_query = wined3d_event_query_from_query(query);
553 enum wined3d_fence_result ret;
555 TRACE("query %p, flags %#x.\n", query, flags);
557 ret = wined3d_fence_test(&event_query->fence, query->device, flags);
558 switch (ret)
560 case WINED3D_FENCE_OK:
561 case WINED3D_FENCE_NOT_STARTED:
562 return event_query->signalled = TRUE;
564 case WINED3D_FENCE_WAITING:
565 return event_query->signalled = FALSE;
567 case WINED3D_FENCE_WRONG_THREAD:
568 FIXME("(%p) Wrong thread, reporting GPU idle.\n", query);
569 return event_query->signalled = TRUE;
571 case WINED3D_FENCE_ERROR:
572 ERR("The GL event query failed.\n");
573 return event_query->signalled = TRUE;
575 default:
576 ERR("Unexpected wined3d_event_query_test result %#x.\n", ret);
577 return event_query->signalled = TRUE;
581 void * CDECL wined3d_query_get_parent(const struct wined3d_query *query)
583 TRACE("query %p.\n", query);
585 return query->parent;
588 enum wined3d_query_type CDECL wined3d_query_get_type(const struct wined3d_query *query)
590 TRACE("query %p.\n", query);
592 return query->type;
595 static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags)
597 TRACE("query %p, flags %#x.\n", query, flags);
599 if (flags & WINED3DISSUE_END)
601 struct wined3d_event_query *event_query = wined3d_event_query_from_query(query);
603 wined3d_fence_issue(&event_query->fence, query->device);
604 return TRUE;
606 else if (flags & WINED3DISSUE_BEGIN)
608 /* Started implicitly at query creation. */
609 ERR("Event query issued with START flag - what to do?\n");
612 return FALSE;
615 static BOOL wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags)
617 struct wined3d_occlusion_query *oq = wined3d_occlusion_query_from_query(query);
618 struct wined3d_device *device = query->device;
619 const struct wined3d_gl_info *gl_info;
620 struct wined3d_context_gl *context_gl;
621 BOOL poll = FALSE;
623 TRACE("query %p, flags %#x.\n", query, flags);
625 /* This is allowed according to MSDN and our tests. Reset the query and
626 * restart. */
627 if (flags & WINED3DISSUE_BEGIN)
629 if (oq->started)
631 if ((context_gl = wined3d_context_gl_reacquire(oq->context_gl)))
633 gl_info = context_gl->gl_info;
634 GL_EXTCALL(glEndQuery(GL_SAMPLES_PASSED));
635 checkGLcall("glEndQuery()");
637 else
639 FIXME("Wrong thread, can't restart query.\n");
640 wined3d_context_gl_free_occlusion_query(oq);
641 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
642 wined3d_context_gl_alloc_occlusion_query(context_gl, oq);
645 else
647 if (oq->context_gl)
648 wined3d_context_gl_free_occlusion_query(oq);
649 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
650 wined3d_context_gl_alloc_occlusion_query(context_gl, oq);
652 gl_info = context_gl->gl_info;
654 GL_EXTCALL(glBeginQuery(GL_SAMPLES_PASSED, oq->id));
655 checkGLcall("glBeginQuery()");
657 context_release(&context_gl->c);
658 oq->started = TRUE;
660 if (flags & WINED3DISSUE_END)
662 /* MSDN says END on a non-building occlusion query returns an error,
663 * but our tests show that it returns OK. But OpenGL doesn't like it,
664 * so avoid generating an error. */
665 if (oq->started)
667 if ((context_gl = wined3d_context_gl_reacquire(oq->context_gl)))
669 gl_info = context_gl->gl_info;
670 GL_EXTCALL(glEndQuery(GL_SAMPLES_PASSED));
671 checkGLcall("glEndQuery()");
672 wined3d_query_buffer_queue_result(context_gl, query, oq->id);
674 context_release(&context_gl->c);
675 poll = TRUE;
677 else
679 FIXME("Wrong thread, can't end query.\n");
682 oq->started = FALSE;
685 return poll;
688 static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query, DWORD flags)
690 struct wined3d_timestamp_query *tq = wined3d_timestamp_query_from_query(query);
691 const struct wined3d_gl_info *gl_info;
692 struct wined3d_context_gl *context_gl;
693 GLuint64 timestamp;
694 GLuint available;
696 TRACE("query %p, flags %#x.\n", query, flags);
698 if (!(context_gl = wined3d_context_gl_reacquire(tq->context_gl)))
700 FIXME("%p Wrong thread, returning 1.\n", query);
701 tq->timestamp = 1;
702 return TRUE;
704 gl_info = context_gl->gl_info;
706 GL_EXTCALL(glGetQueryObjectuiv(tq->id, GL_QUERY_RESULT_AVAILABLE, &available));
707 checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)");
708 TRACE("available %#x.\n", available);
710 if (available)
712 GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, &timestamp));
713 checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)");
714 TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp));
715 tq->timestamp = timestamp;
718 context_release(&context_gl->c);
720 return available;
723 static BOOL wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags)
725 struct wined3d_timestamp_query *tq = wined3d_timestamp_query_from_query(query);
726 const struct wined3d_gl_info *gl_info;
727 struct wined3d_context_gl *context_gl;
729 TRACE("query %p, flags %#x.\n", query, flags);
731 if (flags & WINED3DISSUE_BEGIN)
733 WARN("Ignoring WINED3DISSUE_BEGIN with a TIMESTAMP query.\n");
735 if (flags & WINED3DISSUE_END)
737 if (tq->context_gl)
738 wined3d_context_gl_free_timestamp_query(tq);
739 context_gl = wined3d_context_gl(context_acquire(query->device, NULL, 0));
740 gl_info = context_gl->gl_info;
741 wined3d_context_gl_alloc_timestamp_query(context_gl, tq);
742 GL_EXTCALL(glQueryCounter(tq->id, GL_TIMESTAMP));
743 checkGLcall("glQueryCounter()");
744 context_release(&context_gl->c);
746 return TRUE;
749 return FALSE;
752 static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *query, DWORD flags)
754 TRACE("query %p, flags %#x.\n", query, flags);
756 return TRUE;
759 static BOOL wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags)
761 TRACE("query %p, flags %#x.\n", query, flags);
763 return FALSE;
766 static BOOL wined3d_so_statistics_query_ops_poll(struct wined3d_query *query, DWORD flags)
768 struct wined3d_so_statistics_query *pq = wined3d_so_statistics_query_from_query(query);
769 GLuint written_available, generated_available;
770 const struct wined3d_gl_info *gl_info;
771 struct wined3d_context_gl *context_gl;
773 TRACE("query %p, flags %#x.\n", query, flags);
775 if (!(context_gl = wined3d_context_gl_reacquire(pq->context_gl)))
777 FIXME("%p Wrong thread, returning 0 primitives.\n", query);
778 memset(&pq->statistics, 0, sizeof(pq->statistics));
779 return TRUE;
781 gl_info = context_gl->gl_info;
783 GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.written,
784 GL_QUERY_RESULT_AVAILABLE, &written_available));
785 GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.generated,
786 GL_QUERY_RESULT_AVAILABLE, &generated_available));
787 TRACE("Available %#x, %#x.\n", written_available, generated_available);
789 if (written_available && generated_available)
791 pq->statistics.primitives_written = get_query_result64(pq->u.query.written, gl_info);
792 pq->statistics.primitives_generated = get_query_result64(pq->u.query.generated, gl_info);
793 TRACE("Returning %s, %s primitives.\n",
794 wine_dbgstr_longlong(pq->statistics.primitives_written),
795 wine_dbgstr_longlong(pq->statistics.primitives_generated));
798 checkGLcall("poll SO statistics query");
799 context_release(&context_gl->c);
801 return written_available && generated_available;
804 static void wined3d_so_statistics_query_end(struct wined3d_so_statistics_query *query,
805 struct wined3d_context_gl *context_gl)
807 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
809 if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
811 GL_EXTCALL(glEndQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->stream_idx));
812 GL_EXTCALL(glEndQueryIndexed(GL_PRIMITIVES_GENERATED, query->stream_idx));
814 else
816 GL_EXTCALL(glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN));
817 GL_EXTCALL(glEndQuery(GL_PRIMITIVES_GENERATED));
819 checkGLcall("end query");
822 static BOOL wined3d_so_statistics_query_ops_issue(struct wined3d_query *query, DWORD flags)
824 struct wined3d_so_statistics_query *pq = wined3d_so_statistics_query_from_query(query);
825 struct wined3d_device *device = query->device;
826 const struct wined3d_gl_info *gl_info;
827 struct wined3d_context_gl *context_gl;
828 BOOL poll = FALSE;
830 TRACE("query %p, flags %#x.\n", query, flags);
832 if (flags & WINED3DISSUE_BEGIN)
834 if (pq->started)
836 if ((context_gl = wined3d_context_gl_reacquire(pq->context_gl)))
838 wined3d_so_statistics_query_end(pq, context_gl);
840 else
842 FIXME("Wrong thread, can't restart query.\n");
843 wined3d_context_gl_free_so_statistics_query(pq);
844 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
845 wined3d_context_gl_alloc_so_statistics_query(context_gl, pq);
848 else
850 if (pq->context_gl)
851 wined3d_context_gl_free_so_statistics_query(pq);
852 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
853 wined3d_context_gl_alloc_so_statistics_query(context_gl, pq);
855 gl_info = context_gl->gl_info;
857 if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
859 GL_EXTCALL(glBeginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
860 pq->stream_idx, pq->u.query.written));
861 GL_EXTCALL(glBeginQueryIndexed(GL_PRIMITIVES_GENERATED,
862 pq->stream_idx, pq->u.query.generated));
864 else
866 GL_EXTCALL(glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
867 pq->u.query.written));
868 GL_EXTCALL(glBeginQuery(GL_PRIMITIVES_GENERATED,
869 pq->u.query.generated));
871 checkGLcall("begin query");
873 context_release(&context_gl->c);
874 pq->started = TRUE;
876 if (flags & WINED3DISSUE_END)
878 if (pq->started)
880 if ((context_gl = wined3d_context_gl_reacquire(pq->context_gl)))
882 wined3d_so_statistics_query_end(pq, context_gl);
884 context_release(&context_gl->c);
885 poll = TRUE;
887 else
889 FIXME("Wrong thread, can't end query.\n");
892 pq->started = FALSE;
895 return poll;
898 static BOOL wined3d_pipeline_query_ops_poll(struct wined3d_query *query, DWORD flags)
900 struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query);
901 const struct wined3d_gl_info *gl_info;
902 struct wined3d_context_gl *context_gl;
903 GLuint available;
904 int i;
906 TRACE("query %p, flags %#x.\n", query, flags);
908 if (!(context_gl = wined3d_context_gl_reacquire(pq->context_gl)))
910 FIXME("%p Wrong thread.\n", query);
911 memset(&pq->statistics, 0, sizeof(pq->statistics));
912 return TRUE;
914 gl_info = context_gl->gl_info;
916 for (i = 0; i < ARRAY_SIZE(pq->u.id); ++i)
918 GL_EXTCALL(glGetQueryObjectuiv(pq->u.id[i], GL_QUERY_RESULT_AVAILABLE, &available));
919 if (!available)
920 break;
923 if (available)
925 pq->statistics.vertices_submitted = get_query_result64(pq->u.query.vertices, gl_info);
926 pq->statistics.primitives_submitted = get_query_result64(pq->u.query.primitives, gl_info);
927 pq->statistics.vs_invocations = get_query_result64(pq->u.query.vertex_shader, gl_info);
928 pq->statistics.hs_invocations = get_query_result64(pq->u.query.tess_control_shader, gl_info);
929 pq->statistics.ds_invocations = get_query_result64(pq->u.query.tess_eval_shader, gl_info);
930 pq->statistics.gs_invocations = get_query_result64(pq->u.query.geometry_shader, gl_info);
931 pq->statistics.gs_primitives = get_query_result64(pq->u.query.geometry_primitives, gl_info);
932 pq->statistics.ps_invocations = get_query_result64(pq->u.query.fragment_shader, gl_info);
933 pq->statistics.cs_invocations = get_query_result64(pq->u.query.compute_shader, gl_info);
934 pq->statistics.clipping_input_primitives = get_query_result64(pq->u.query.clipping_input, gl_info);
935 pq->statistics.clipping_output_primitives = get_query_result64(pq->u.query.clipping_output, gl_info);
938 checkGLcall("poll pipeline statistics query");
939 context_release(&context_gl->c);
940 return available;
943 static void wined3d_pipeline_statistics_query_end(struct wined3d_pipeline_statistics_query *query,
944 struct wined3d_context_gl *context_gl)
946 const struct wined3d_gl_info *gl_info = context_gl->gl_info;
948 GL_EXTCALL(glEndQuery(GL_VERTICES_SUBMITTED_ARB));
949 GL_EXTCALL(glEndQuery(GL_PRIMITIVES_SUBMITTED_ARB));
950 GL_EXTCALL(glEndQuery(GL_VERTEX_SHADER_INVOCATIONS_ARB));
951 GL_EXTCALL(glEndQuery(GL_TESS_CONTROL_SHADER_PATCHES_ARB));
952 GL_EXTCALL(glEndQuery(GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB));
953 GL_EXTCALL(glEndQuery(GL_GEOMETRY_SHADER_INVOCATIONS));
954 GL_EXTCALL(glEndQuery(GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB));
955 GL_EXTCALL(glEndQuery(GL_FRAGMENT_SHADER_INVOCATIONS_ARB));
956 GL_EXTCALL(glEndQuery(GL_COMPUTE_SHADER_INVOCATIONS_ARB));
957 GL_EXTCALL(glEndQuery(GL_CLIPPING_INPUT_PRIMITIVES_ARB));
958 GL_EXTCALL(glEndQuery(GL_CLIPPING_OUTPUT_PRIMITIVES_ARB));
959 checkGLcall("end query");
962 static BOOL wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD flags)
964 struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query);
965 struct wined3d_device *device = query->device;
966 const struct wined3d_gl_info *gl_info;
967 struct wined3d_context_gl *context_gl;
968 BOOL poll = FALSE;
970 TRACE("query %p, flags %#x.\n", query, flags);
972 if (flags & WINED3DISSUE_BEGIN)
974 if (pq->started)
976 if ((context_gl = wined3d_context_gl_reacquire(pq->context_gl)))
978 wined3d_pipeline_statistics_query_end(pq, context_gl);
980 else
982 FIXME("Wrong thread, can't restart query.\n");
983 wined3d_context_gl_free_pipeline_statistics_query(pq);
984 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
985 wined3d_context_gl_alloc_pipeline_statistics_query(context_gl, pq);
988 else
990 if (pq->context_gl)
991 wined3d_context_gl_free_pipeline_statistics_query(pq);
992 context_gl = wined3d_context_gl(context_acquire(device, NULL, 0));
993 wined3d_context_gl_alloc_pipeline_statistics_query(context_gl, pq);
995 gl_info = context_gl->gl_info;
997 GL_EXTCALL(glBeginQuery(GL_VERTICES_SUBMITTED_ARB, pq->u.query.vertices));
998 GL_EXTCALL(glBeginQuery(GL_PRIMITIVES_SUBMITTED_ARB, pq->u.query.primitives));
999 GL_EXTCALL(glBeginQuery(GL_VERTEX_SHADER_INVOCATIONS_ARB, pq->u.query.vertex_shader));
1000 GL_EXTCALL(glBeginQuery(GL_TESS_CONTROL_SHADER_PATCHES_ARB, pq->u.query.tess_control_shader));
1001 GL_EXTCALL(glBeginQuery(GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB, pq->u.query.tess_eval_shader));
1002 GL_EXTCALL(glBeginQuery(GL_GEOMETRY_SHADER_INVOCATIONS, pq->u.query.geometry_shader));
1003 GL_EXTCALL(glBeginQuery(GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB, pq->u.query.geometry_primitives));
1004 GL_EXTCALL(glBeginQuery(GL_FRAGMENT_SHADER_INVOCATIONS_ARB, pq->u.query.fragment_shader));
1005 GL_EXTCALL(glBeginQuery(GL_COMPUTE_SHADER_INVOCATIONS_ARB, pq->u.query.compute_shader));
1006 GL_EXTCALL(glBeginQuery(GL_CLIPPING_INPUT_PRIMITIVES_ARB, pq->u.query.clipping_input));
1007 GL_EXTCALL(glBeginQuery(GL_CLIPPING_OUTPUT_PRIMITIVES_ARB, pq->u.query.clipping_output));
1008 checkGLcall("begin query");
1010 context_release(&context_gl->c);
1011 pq->started = TRUE;
1013 if (flags & WINED3DISSUE_END)
1015 if (pq->started)
1017 if ((context_gl = wined3d_context_gl_reacquire(pq->context_gl)))
1019 wined3d_pipeline_statistics_query_end(pq, context_gl);
1020 context_release(&context_gl->c);
1021 poll = TRUE;
1023 else
1025 FIXME("Wrong thread, can't end query.\n");
1028 pq->started = FALSE;
1031 return poll;
1034 static void wined3d_event_query_ops_destroy(struct wined3d_query *query)
1036 struct wined3d_event_query *event_query = wined3d_event_query_from_query(query);
1038 wined3d_fence_free(&event_query->fence);
1039 heap_free(event_query);
1042 static const struct wined3d_query_ops event_query_ops =
1044 wined3d_event_query_ops_poll,
1045 wined3d_event_query_ops_issue,
1046 wined3d_event_query_ops_destroy,
1049 static HRESULT wined3d_event_query_create(struct wined3d_device *device,
1050 enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
1051 struct wined3d_query **query)
1053 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1054 struct wined3d_event_query *object;
1055 HRESULT hr;
1057 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1058 device, type, parent, parent_ops, query);
1060 if (!(object = heap_alloc_zero(sizeof(*object))))
1061 return E_OUTOFMEMORY;
1063 if (FAILED(hr = wined3d_fence_init(&object->fence, gl_info)))
1065 WARN("Event queries not supported.\n");
1066 heap_free(object);
1067 return hr;
1070 wined3d_query_init(&object->query, device, type, &object->signalled,
1071 sizeof(object->signalled), &event_query_ops, parent, parent_ops);
1073 TRACE("Created query %p.\n", object);
1074 *query = &object->query;
1076 return WINED3D_OK;
1079 static void wined3d_occlusion_query_ops_destroy(struct wined3d_query *query)
1081 struct wined3d_occlusion_query *oq = wined3d_occlusion_query_from_query(query);
1083 if (oq->context_gl)
1084 wined3d_context_gl_free_occlusion_query(oq);
1085 heap_free(oq);
1088 static const struct wined3d_query_ops occlusion_query_ops =
1090 wined3d_occlusion_query_ops_poll,
1091 wined3d_occlusion_query_ops_issue,
1092 wined3d_occlusion_query_ops_destroy,
1095 static HRESULT wined3d_occlusion_query_create(struct wined3d_device *device,
1096 enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
1097 struct wined3d_query **query)
1099 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1100 struct wined3d_occlusion_query *object;
1102 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1103 device, type, parent, parent_ops, query);
1105 if (!gl_info->supported[ARB_OCCLUSION_QUERY])
1107 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY.\n");
1108 return WINED3DERR_NOTAVAILABLE;
1111 if (!(object = heap_alloc_zero(sizeof(*object))))
1112 return E_OUTOFMEMORY;
1114 wined3d_query_init(&object->query, device, type, &object->samples,
1115 sizeof(object->samples), &occlusion_query_ops, parent, parent_ops);
1117 TRACE("Created query %p.\n", object);
1118 *query = &object->query;
1120 return WINED3D_OK;
1123 static void wined3d_timestamp_query_ops_destroy(struct wined3d_query *query)
1125 struct wined3d_timestamp_query *tq = wined3d_timestamp_query_from_query(query);
1127 if (tq->context_gl)
1128 wined3d_context_gl_free_timestamp_query(tq);
1129 heap_free(tq);
1132 static const struct wined3d_query_ops timestamp_query_ops =
1134 wined3d_timestamp_query_ops_poll,
1135 wined3d_timestamp_query_ops_issue,
1136 wined3d_timestamp_query_ops_destroy,
1139 static HRESULT wined3d_timestamp_query_create(struct wined3d_device *device,
1140 enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
1141 struct wined3d_query **query)
1143 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1144 struct wined3d_timestamp_query *object;
1146 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1147 device, type, parent, parent_ops, query);
1149 if (!gl_info->supported[ARB_TIMER_QUERY])
1151 WARN("Unsupported in local OpenGL implementation: ARB_TIMER_QUERY.\n");
1152 return WINED3DERR_NOTAVAILABLE;
1155 if (!(object = heap_alloc_zero(sizeof(*object))))
1156 return E_OUTOFMEMORY;
1158 wined3d_query_init(&object->query, device, type, &object->timestamp,
1159 sizeof(object->timestamp), &timestamp_query_ops, parent, parent_ops);
1161 TRACE("Created query %p.\n", object);
1162 *query = &object->query;
1164 return WINED3D_OK;
1167 static void wined3d_timestamp_disjoint_query_ops_destroy(struct wined3d_query *query)
1169 heap_free(query);
1172 static const struct wined3d_query_ops timestamp_disjoint_query_ops =
1174 wined3d_timestamp_disjoint_query_ops_poll,
1175 wined3d_timestamp_disjoint_query_ops_issue,
1176 wined3d_timestamp_disjoint_query_ops_destroy,
1179 static HRESULT wined3d_timestamp_disjoint_query_create(struct wined3d_device *device,
1180 enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
1181 struct wined3d_query **query)
1183 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1184 struct wined3d_query *object;
1186 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1187 device, type, parent, parent_ops, query);
1189 if (!gl_info->supported[ARB_TIMER_QUERY])
1191 WARN("Unsupported in local OpenGL implementation: ARB_TIMER_QUERY.\n");
1192 return WINED3DERR_NOTAVAILABLE;
1195 if (!(object = heap_alloc_zero(sizeof(*object))))
1196 return E_OUTOFMEMORY;
1198 if (type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT)
1200 static const struct wined3d_query_data_timestamp_disjoint disjoint_data = {1000 * 1000 * 1000, FALSE};
1202 wined3d_query_init(object, device, type, &disjoint_data,
1203 sizeof(disjoint_data), &timestamp_disjoint_query_ops, parent, parent_ops);
1205 else
1207 static const UINT64 freq = 1000 * 1000 * 1000;
1209 wined3d_query_init(object, device, type, &freq,
1210 sizeof(freq), &timestamp_disjoint_query_ops, parent, parent_ops);
1213 TRACE("Created query %p.\n", object);
1214 *query = object;
1216 return WINED3D_OK;
1219 static void wined3d_so_statistics_query_ops_destroy(struct wined3d_query *query)
1221 struct wined3d_so_statistics_query *pq = wined3d_so_statistics_query_from_query(query);
1223 if (pq->context_gl)
1224 wined3d_context_gl_free_so_statistics_query(pq);
1225 heap_free(pq);
1228 static const struct wined3d_query_ops so_statistics_query_ops =
1230 wined3d_so_statistics_query_ops_poll,
1231 wined3d_so_statistics_query_ops_issue,
1232 wined3d_so_statistics_query_ops_destroy,
1235 static HRESULT wined3d_so_statistics_query_create(struct wined3d_device *device,
1236 enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
1237 struct wined3d_query **query)
1239 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1240 struct wined3d_so_statistics_query *object;
1241 unsigned int stream_idx;
1243 if (WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3)
1244 stream_idx = type - WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0;
1245 else if (type == WINED3D_QUERY_TYPE_SO_STATISTICS)
1246 stream_idx = 0;
1247 else
1248 return WINED3DERR_NOTAVAILABLE;
1250 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1251 device, type, parent, parent_ops, query);
1253 if (!gl_info->supported[WINED3D_GL_PRIMITIVE_QUERY])
1255 WARN("OpenGL implementation does not support primitive queries.\n");
1256 return WINED3DERR_NOTAVAILABLE;
1258 if (stream_idx && !gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
1260 WARN("OpenGL implementation does not support indexed queries.\n");
1261 return WINED3DERR_NOTAVAILABLE;
1264 if (!(object = heap_alloc_zero(sizeof(*object))))
1265 return E_OUTOFMEMORY;
1267 wined3d_query_init(&object->query, device, type, &object->statistics,
1268 sizeof(object->statistics), &so_statistics_query_ops, parent, parent_ops);
1269 object->stream_idx = stream_idx;
1271 TRACE("Created query %p.\n", object);
1272 *query = &object->query;
1274 return WINED3D_OK;
1277 static void wined3d_pipeline_query_ops_destroy(struct wined3d_query *query)
1279 struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query);
1280 if (pq->context_gl)
1281 wined3d_context_gl_free_pipeline_statistics_query(pq);
1282 heap_free(pq);
1285 static const struct wined3d_query_ops pipeline_query_ops =
1287 wined3d_pipeline_query_ops_poll,
1288 wined3d_pipeline_query_ops_issue,
1289 wined3d_pipeline_query_ops_destroy,
1292 static HRESULT wined3d_pipeline_query_create(struct wined3d_device *device,
1293 enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
1294 struct wined3d_query **query)
1296 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1297 struct wined3d_pipeline_statistics_query *object;
1299 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1300 device, type, parent, parent_ops, query);
1302 if (!gl_info->supported[ARB_PIPELINE_STATISTICS_QUERY])
1304 WARN("OpenGL implementation does not support pipeline statistics queries.\n");
1305 return WINED3DERR_NOTAVAILABLE;
1308 if (!(object = heap_alloc_zero(sizeof(*object))))
1309 return E_OUTOFMEMORY;
1311 wined3d_query_init(&object->query, device, type, &object->statistics,
1312 sizeof(object->statistics), &pipeline_query_ops, parent, parent_ops);
1314 TRACE("Created query %p.\n", object);
1315 *query = &object->query;
1317 return WINED3D_OK;
1320 HRESULT wined3d_query_gl_create(struct wined3d_device *device, enum wined3d_query_type type,
1321 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
1323 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1324 device, type, parent, parent_ops, query);
1326 switch (type)
1328 case WINED3D_QUERY_TYPE_EVENT:
1329 return wined3d_event_query_create(device, type, parent, parent_ops, query);
1331 case WINED3D_QUERY_TYPE_OCCLUSION:
1332 return wined3d_occlusion_query_create(device, type, parent, parent_ops, query);
1334 case WINED3D_QUERY_TYPE_TIMESTAMP:
1335 return wined3d_timestamp_query_create(device, type, parent, parent_ops, query);
1337 case WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT:
1338 case WINED3D_QUERY_TYPE_TIMESTAMP_FREQ:
1339 return wined3d_timestamp_disjoint_query_create(device, type, parent, parent_ops, query);
1341 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1342 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1343 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1344 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1345 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1346 return wined3d_so_statistics_query_create(device, type, parent, parent_ops, query);
1348 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1349 return wined3d_pipeline_query_create(device, type, parent, parent_ops, query);
1351 default:
1352 FIXME("Unhandled query type %#x.\n", type);
1353 return WINED3DERR_NOTAVAILABLE;
1357 HRESULT CDECL wined3d_query_create(struct wined3d_device *device, enum wined3d_query_type type,
1358 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
1360 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1361 device, type, parent, parent_ops, query);
1363 return device->adapter->adapter_ops->adapter_create_query(device, type, parent, parent_ops, query);