#include "device9.h"
#include "query9.h"
#include "nine_helpers.h"
+#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "util/u_math.h"
#include "nine_dump.h"
#define DBG_CHANNEL DBG_QUERY
-#define QUERY_TYPE_MAP_CASE(a, b) case D3DQUERYTYPE_##a: return PIPE_QUERY_##b
static inline unsigned
-d3dquerytype_to_pipe_query(D3DQUERYTYPE type)
+d3dquerytype_to_pipe_query(struct pipe_screen *screen, D3DQUERYTYPE type)
{
switch (type) {
- QUERY_TYPE_MAP_CASE(EVENT, GPU_FINISHED);
- QUERY_TYPE_MAP_CASE(OCCLUSION, OCCLUSION_COUNTER);
- QUERY_TYPE_MAP_CASE(TIMESTAMP, TIMESTAMP);
- QUERY_TYPE_MAP_CASE(TIMESTAMPDISJOINT, TIMESTAMP_DISJOINT);
- QUERY_TYPE_MAP_CASE(TIMESTAMPFREQ, TIMESTAMP_DISJOINT);
- QUERY_TYPE_MAP_CASE(VERTEXSTATS, PIPELINE_STATISTICS);
- case D3DQUERYTYPE_VCACHE:
- case D3DQUERYTYPE_RESOURCEMANAGER:
- case D3DQUERYTYPE_PIPELINETIMINGS:
- case D3DQUERYTYPE_INTERFACETIMINGS:
- case D3DQUERYTYPE_VERTEXTIMINGS:
- case D3DQUERYTYPE_PIXELTIMINGS:
- case D3DQUERYTYPE_BANDWIDTHTIMINGS:
- case D3DQUERYTYPE_CACHEUTILIZATION:
- return PIPE_QUERY_TYPES;
+ case D3DQUERYTYPE_EVENT:
+ return PIPE_QUERY_GPU_FINISHED;
+ case D3DQUERYTYPE_OCCLUSION:
+ return screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY) ?
+ PIPE_QUERY_OCCLUSION_COUNTER : PIPE_QUERY_TYPES;
+ case D3DQUERYTYPE_TIMESTAMP:
+ return screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP) ?
+ PIPE_QUERY_TIMESTAMP : PIPE_QUERY_TYPES;
+ case D3DQUERYTYPE_TIMESTAMPDISJOINT:
+ case D3DQUERYTYPE_TIMESTAMPFREQ:
+ return screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP) ?
+ PIPE_QUERY_TIMESTAMP_DISJOINT : PIPE_QUERY_TYPES;
+ case D3DQUERYTYPE_VERTEXSTATS:
+ return screen->get_param(screen,
+ PIPE_CAP_QUERY_PIPELINE_STATISTICS) ?
+ PIPE_QUERY_PIPELINE_STATISTICS : PIPE_QUERY_TYPES;
default:
- return ~0;
+ return PIPE_QUERY_TYPES; /* Query not supported */
}
}
}
HRESULT
-nine_is_query_supported(D3DQUERYTYPE type)
+nine_is_query_supported(struct pipe_screen *screen, D3DQUERYTYPE type)
{
- const unsigned ptype = d3dquerytype_to_pipe_query(type);
+ const unsigned ptype = d3dquerytype_to_pipe_query(screen, type);
user_assert(ptype != ~0, D3DERR_INVALIDCALL);
D3DQUERYTYPE Type )
{
struct pipe_context *pipe = pParams->device->pipe;
- const unsigned ptype = d3dquerytype_to_pipe_query(Type);
+ const unsigned ptype = d3dquerytype_to_pipe_query(pParams->device->screen, Type);
HRESULT hr;
DBG("This=%p pParams=%p Type=%d\n", This, pParams, Type);
DBG("This=%p dwIssueFlags=%d\n", This, dwIssueFlags);
- user_assert((dwIssueFlags == D3DISSUE_BEGIN && !This->instant) ||
+ user_assert((dwIssueFlags == D3DISSUE_BEGIN) ||
(dwIssueFlags == 0) ||
(dwIssueFlags == D3DISSUE_END), D3DERR_INVALIDCALL);
+ /* Wine tests: always return D3D_OK on D3DISSUE_BEGIN
+ * even when the call is supposed to be forbidden */
+ if (dwIssueFlags == D3DISSUE_BEGIN && This->instant)
+ return D3D_OK;
+
if (dwIssueFlags == D3DISSUE_BEGIN) {
if (This->state == NINE_QUERY_STATE_RUNNING) {
pipe->end_query(pipe, This->pq);
pipe->begin_query(pipe, This->pq);
This->state = NINE_QUERY_STATE_RUNNING;
} else {
- if (This->state == NINE_QUERY_STATE_RUNNING) {
- pipe->end_query(pipe, This->pq);
- This->state = NINE_QUERY_STATE_ENDED;
- }
+ if (This->state != NINE_QUERY_STATE_RUNNING &&
+ This->type != D3DQUERYTYPE_EVENT &&
+ This->type != D3DQUERYTYPE_TIMESTAMP)
+ pipe->begin_query(pipe, This->pq);
+ pipe->end_query(pipe, This->pq);
+ This->state = NINE_QUERY_STATE_ENDED;
}
return D3D_OK;
}
DWORD dwGetDataFlags )
{
struct pipe_context *pipe = This->base.device->pipe;
- boolean ok;
- unsigned i;
+ boolean ok, wait_query_result = FALSE;
union pipe_query_result presult;
union nine_query_result nresult;
DBG("This=%p pData=%p dwSize=%d dwGetDataFlags=%d\n",
This, pData, dwSize, dwGetDataFlags);
- user_assert(This->state != NINE_QUERY_STATE_RUNNING, D3DERR_INVALIDCALL);
+ /* according to spec we should return D3DERR_INVALIDCALL here, but
+ * wine returns S_FALSE because it is apparently the behaviour
+ * on windows */
+ user_assert(This->state != NINE_QUERY_STATE_RUNNING, S_FALSE);
user_assert(dwSize == 0 || pData, D3DERR_INVALIDCALL);
user_assert(dwGetDataFlags == 0 ||
dwGetDataFlags == D3DGETDATA_FLUSH, D3DERR_INVALIDCALL);
- if (This->state == NINE_QUERY_STATE_FRESH)
- return S_OK;
-
- ok = pipe->get_query_result(pipe, This->pq, FALSE, &presult);
- if (!ok) {
- if (dwGetDataFlags) {
- if (This->state != NINE_QUERY_STATE_FLUSHED)
- pipe->flush(pipe, NULL, 0);
- This->state = NINE_QUERY_STATE_FLUSHED;
- }
- return S_FALSE;
+ if (This->state == NINE_QUERY_STATE_FRESH) {
+ /* App forgot calling Issue. call it for it.
+ * However Wine states that return value should
+ * be S_OK, so wait for the result to return S_OK. */
+ NineQuery9_Issue(This, D3DISSUE_END);
+ wait_query_result = TRUE;
}
+ /* Wine tests: D3DQUERYTYPE_TIMESTAMP always succeeds */
+ wait_query_result |= This->type == D3DQUERYTYPE_TIMESTAMP;
+
+ /* Note: We ignore dwGetDataFlags, because get_query_result will
+ * flush automatically if needed */
+
+ ok = pipe->get_query_result(pipe, This->pq, wait_query_result, &presult);
+
+ if (!ok) return S_FALSE;
+
if (!dwSize)
return S_OK;