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
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
;
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
;
82 if (!gl_info
->supported
[ARB_QUERY_BUFFER_OBJECT
] || !gl_info
->supported
[ARB_BUFFER_STORAGE
])
84 /* Don't use query buffers without CSMT, mainly for simplicity. */
85 if (!context_gl
->c
.device
->cs
->thread
)
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
);
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");
120 static UINT64
get_query_result64(GLuint id
, const struct wined3d_gl_info
*gl_info
)
122 if (gl_info
->supported
[ARB_TIMER_QUERY
])
125 GL_EXTCALL(glGetQueryObjectui64v(id
, GL_QUERY_RESULT
, &result
));
131 GL_EXTCALL(glGetQueryObjectuiv(id
, GL_QUERY_RESULT
, &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
)
141 query
->parent
= parent
;
142 query
->parent_ops
= parent_ops
;
143 query
->device
= device
;
144 query
->state
= QUERY_CREATED
;
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
;
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");
218 case GL_ALREADY_SIGNALED
:
219 case GL_CONDITION_SATISFIED
:
220 ret
= WINED3D_FENCE_OK
;
223 case GL_TIMEOUT_EXPIRED
:
224 ret
= WINED3D_FENCE_WAITING
;
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");
238 ret
= WINED3D_FENCE_OK
;
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");
247 ret
= WINED3D_FENCE_OK
;
249 ret
= WINED3D_FENCE_WAITING
;
253 ERR("Fence created despite lack of GL support.\n");
254 ret
= WINED3D_FENCE_ERROR
;
257 context_release(&context_gl
->c
);
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");
303 case GL_ALREADY_SIGNALED
:
304 case GL_CONDITION_SATISFIED
:
305 ret
= WINED3D_FENCE_OK
;
308 /* We don't expect a timeout for a ~292 year wait */
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
;
328 ERR("Fence created without GL support.\n");
329 ret
= WINED3D_FENCE_ERROR
;
332 context_release(&context_gl
->c
);
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
);
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
);
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
;
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
;
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
)))
412 TRACE("Created fence %p.\n", object
);
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
);
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
);
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
);
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");
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
);
480 if (query
->buffer_object
)
481 query
->data
= query
->map_ptr
;
483 else if (!query
->query_ops
->query_poll(query
, flags
))
489 memcpy(data
, query
->data
, min(data_size
, query
->data_size
));
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
;
513 query
->state
= QUERY_SIGNALLED
;
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
;
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
);
533 gl_info
= context_gl
->gl_info
;
535 GL_EXTCALL(glGetQueryObjectuiv(oq
->id
, GL_QUERY_RESULT_AVAILABLE
, &available
));
536 TRACE("Available %#x.\n", 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
);
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
);
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
;
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
);
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
);
606 else if (flags
& WINED3DISSUE_BEGIN
)
608 /* Started implicitly at query creation. */
609 ERR("Event query issued with START flag - what to do?\n");
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
;
623 TRACE("query %p, flags %#x.\n", query
, flags
);
625 /* This is allowed according to MSDN and our tests. Reset the query and
627 if (flags
& WINED3DISSUE_BEGIN
)
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()");
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
);
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
);
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. */
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
);
679 FIXME("Wrong thread, can't end query.\n");
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
;
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
);
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
);
712 GL_EXTCALL(glGetQueryObjectui64v(tq
->id
, GL_QUERY_RESULT
, ×tamp
));
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
);
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
)
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
);
752 static BOOL
wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query
*query
, DWORD flags
)
754 TRACE("query %p, flags %#x.\n", query
, flags
);
759 static BOOL
wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query
*query
, DWORD flags
)
761 TRACE("query %p, flags %#x.\n", query
, flags
);
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
));
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
));
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
;
830 TRACE("query %p, flags %#x.\n", query
, flags
);
832 if (flags
& WINED3DISSUE_BEGIN
)
836 if ((context_gl
= wined3d_context_gl_reacquire(pq
->context_gl
)))
838 wined3d_so_statistics_query_end(pq
, context_gl
);
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
);
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
));
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
);
876 if (flags
& WINED3DISSUE_END
)
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
);
889 FIXME("Wrong thread, can't end query.\n");
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
;
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
));
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
));
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
);
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
;
970 TRACE("query %p, flags %#x.\n", query
, flags
);
972 if (flags
& WINED3DISSUE_BEGIN
)
976 if ((context_gl
= wined3d_context_gl_reacquire(pq
->context_gl
)))
978 wined3d_pipeline_statistics_query_end(pq
, context_gl
);
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
);
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
);
1013 if (flags
& WINED3DISSUE_END
)
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
);
1025 FIXME("Wrong thread, can't end query.\n");
1028 pq
->started
= FALSE
;
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
;
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");
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
;
1079 static void wined3d_occlusion_query_ops_destroy(struct wined3d_query
*query
)
1081 struct wined3d_occlusion_query
*oq
= wined3d_occlusion_query_from_query(query
);
1084 wined3d_context_gl_free_occlusion_query(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
;
1123 static void wined3d_timestamp_query_ops_destroy(struct wined3d_query
*query
)
1125 struct wined3d_timestamp_query
*tq
= wined3d_timestamp_query_from_query(query
);
1128 wined3d_context_gl_free_timestamp_query(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
), ×tamp_query_ops
, parent
, parent_ops
);
1161 TRACE("Created query %p.\n", object
);
1162 *query
= &object
->query
;
1167 static void wined3d_timestamp_disjoint_query_ops_destroy(struct wined3d_query
*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
), ×tamp_disjoint_query_ops
, parent
, parent_ops
);
1207 static const UINT64 freq
= 1000 * 1000 * 1000;
1209 wined3d_query_init(object
, device
, type
, &freq
,
1210 sizeof(freq
), ×tamp_disjoint_query_ops
, parent
, parent_ops
);
1213 TRACE("Created query %p.\n", object
);
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
);
1224 wined3d_context_gl_free_so_statistics_query(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
)
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
;
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
);
1281 wined3d_context_gl_free_pipeline_statistics_query(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
;
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
);
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
);
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
);