2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
25 #include "nine_helpers.h"
26 #include "pipe/p_context.h"
27 #include "util/u_math.h"
28 #include "nine_dump.h"
30 #define DBG_CHANNEL DBG_QUERY
32 #define QUERY_TYPE_MAP_CASE(a, b) case D3DQUERYTYPE_##a: return PIPE_QUERY_##b
33 static inline unsigned
34 d3dquerytype_to_pipe_query(D3DQUERYTYPE type
)
37 QUERY_TYPE_MAP_CASE(EVENT
, GPU_FINISHED
);
38 QUERY_TYPE_MAP_CASE(OCCLUSION
, OCCLUSION_COUNTER
);
39 QUERY_TYPE_MAP_CASE(TIMESTAMP
, TIMESTAMP
);
40 QUERY_TYPE_MAP_CASE(TIMESTAMPDISJOINT
, TIMESTAMP_DISJOINT
);
41 QUERY_TYPE_MAP_CASE(TIMESTAMPFREQ
, TIMESTAMP_DISJOINT
);
42 QUERY_TYPE_MAP_CASE(VERTEXSTATS
, PIPELINE_STATISTICS
);
43 case D3DQUERYTYPE_VCACHE
:
44 case D3DQUERYTYPE_RESOURCEMANAGER
:
45 case D3DQUERYTYPE_PIPELINETIMINGS
:
46 case D3DQUERYTYPE_INTERFACETIMINGS
:
47 case D3DQUERYTYPE_VERTEXTIMINGS
:
48 case D3DQUERYTYPE_PIXELTIMINGS
:
49 case D3DQUERYTYPE_BANDWIDTHTIMINGS
:
50 case D3DQUERYTYPE_CACHEUTILIZATION
:
51 return PIPE_QUERY_TYPES
;
57 #define GET_DATA_SIZE_CASE2(a, b) case D3DQUERYTYPE_##a: return sizeof(D3DDEVINFO_##b)
58 #define GET_DATA_SIZE_CASET(a, b) case D3DQUERYTYPE_##a: return sizeof(b)
60 nine_query_result_size(D3DQUERYTYPE type
)
63 GET_DATA_SIZE_CASE2(VERTEXSTATS
, D3DVERTEXSTATS
);
64 GET_DATA_SIZE_CASET(EVENT
, BOOL
);
65 GET_DATA_SIZE_CASET(OCCLUSION
, DWORD
);
66 GET_DATA_SIZE_CASET(TIMESTAMP
, UINT64
);
67 GET_DATA_SIZE_CASET(TIMESTAMPDISJOINT
, BOOL
);
68 GET_DATA_SIZE_CASET(TIMESTAMPFREQ
, UINT64
);
76 nine_is_query_supported(D3DQUERYTYPE type
)
78 const unsigned ptype
= d3dquerytype_to_pipe_query(type
);
80 user_assert(ptype
!= ~0, D3DERR_INVALIDCALL
);
82 if (ptype
== PIPE_QUERY_TYPES
) {
83 DBG("Query type %u (%s) not supported.\n",
84 type
, nine_D3DQUERYTYPE_to_str(type
));
85 return D3DERR_NOTAVAILABLE
;
91 NineQuery9_ctor( struct NineQuery9
*This
,
92 struct NineUnknownParams
*pParams
,
95 struct pipe_context
*pipe
= pParams
->device
->pipe
;
96 const unsigned ptype
= d3dquerytype_to_pipe_query(Type
);
99 DBG("This=%p pParams=%p Type=%d\n", This
, pParams
, Type
);
101 hr
= NineUnknown_ctor(&This
->base
, pParams
);
105 This
->state
= NINE_QUERY_STATE_FRESH
;
108 user_assert(ptype
!= ~0, D3DERR_INVALIDCALL
);
110 if (ptype
< PIPE_QUERY_TYPES
) {
111 This
->pq
= pipe
->create_query(pipe
, ptype
, 0);
113 return E_OUTOFMEMORY
;
115 assert(0); /* we have checked this case before */
119 Type
== D3DQUERYTYPE_EVENT
||
120 Type
== D3DQUERYTYPE_RESOURCEMANAGER
||
121 Type
== D3DQUERYTYPE_TIMESTAMP
||
122 Type
== D3DQUERYTYPE_TIMESTAMPFREQ
||
123 Type
== D3DQUERYTYPE_VCACHE
||
124 Type
== D3DQUERYTYPE_VERTEXSTATS
;
126 This
->result_size
= nine_query_result_size(Type
);
132 NineQuery9_dtor( struct NineQuery9
*This
)
134 struct pipe_context
*pipe
= This
->base
.device
->pipe
;
137 if (This
->state
== NINE_QUERY_STATE_RUNNING
)
138 pipe
->end_query(pipe
, This
->pq
);
139 pipe
->destroy_query(pipe
, This
->pq
);
142 NineUnknown_dtor(&This
->base
);
146 NineQuery9_GetType( struct NineQuery9
*This
)
152 NineQuery9_GetDataSize( struct NineQuery9
*This
)
154 return This
->result_size
;
158 NineQuery9_Issue( struct NineQuery9
*This
,
161 struct pipe_context
*pipe
= This
->base
.device
->pipe
;
163 DBG("This=%p dwIssueFlags=%d\n", This
, dwIssueFlags
);
165 user_assert((dwIssueFlags
== D3DISSUE_BEGIN
&& !This
->instant
) ||
166 (dwIssueFlags
== 0) ||
167 (dwIssueFlags
== D3DISSUE_END
), D3DERR_INVALIDCALL
);
169 if (dwIssueFlags
== D3DISSUE_BEGIN
) {
170 if (This
->state
== NINE_QUERY_STATE_RUNNING
) {
171 pipe
->end_query(pipe
, This
->pq
);
173 pipe
->begin_query(pipe
, This
->pq
);
174 This
->state
= NINE_QUERY_STATE_RUNNING
;
176 if (This
->state
== NINE_QUERY_STATE_RUNNING
) {
177 pipe
->end_query(pipe
, This
->pq
);
178 This
->state
= NINE_QUERY_STATE_ENDED
;
184 union nine_query_result
186 D3DDEVINFO_D3DVERTEXSTATS vertexstats
;
193 NineQuery9_GetData( struct NineQuery9
*This
,
196 DWORD dwGetDataFlags
)
198 struct pipe_context
*pipe
= This
->base
.device
->pipe
;
201 union pipe_query_result presult
;
202 union nine_query_result nresult
;
204 DBG("This=%p pData=%p dwSize=%d dwGetDataFlags=%d\n",
205 This
, pData
, dwSize
, dwGetDataFlags
);
207 user_assert(This
->state
!= NINE_QUERY_STATE_RUNNING
, D3DERR_INVALIDCALL
);
208 user_assert(dwSize
== 0 || pData
, D3DERR_INVALIDCALL
);
209 user_assert(dwGetDataFlags
== 0 ||
210 dwGetDataFlags
== D3DGETDATA_FLUSH
, D3DERR_INVALIDCALL
);
212 if (This
->state
== NINE_QUERY_STATE_FRESH
)
215 /* Note: We ignore dwGetDataFlags, because get_query_result will
216 * flush automatically if needed */
218 ok
= pipe
->get_query_result(pipe
, This
->pq
, FALSE
, &presult
);
220 if (!ok
) return S_FALSE
;
225 switch (This
->type
) {
226 case D3DQUERYTYPE_EVENT
:
227 nresult
.b
= presult
.b
;
229 case D3DQUERYTYPE_OCCLUSION
:
230 nresult
.dw
= presult
.u64
;
232 case D3DQUERYTYPE_TIMESTAMP
:
233 nresult
.u64
= presult
.u64
;
235 case D3DQUERYTYPE_TIMESTAMPDISJOINT
:
236 nresult
.b
= presult
.timestamp_disjoint
.disjoint
;
238 case D3DQUERYTYPE_TIMESTAMPFREQ
:
239 nresult
.u64
= presult
.timestamp_disjoint
.frequency
;
241 case D3DQUERYTYPE_VERTEXSTATS
:
242 nresult
.vertexstats
.NumRenderedTriangles
=
243 presult
.pipeline_statistics
.c_invocations
;
244 nresult
.vertexstats
.NumExtraClippingTriangles
=
245 presult
.pipeline_statistics
.c_primitives
;
251 memcpy(pData
, &nresult
, MIN2(sizeof(nresult
), dwSize
));
256 IDirect3DQuery9Vtbl NineQuery9_vtable
= {
257 (void *)NineUnknown_QueryInterface
,
258 (void *)NineUnknown_AddRef
,
259 (void *)NineUnknown_Release
,
260 (void *)NineUnknown_GetDevice
, /* actually part of Query9 iface */
261 (void *)NineQuery9_GetType
,
262 (void *)NineQuery9_GetDataSize
,
263 (void *)NineQuery9_Issue
,
264 (void *)NineQuery9_GetData
267 static const GUID
*NineQuery9_IIDs
[] = {
268 &IID_IDirect3DQuery9
,
274 NineQuery9_new( struct NineDevice9
*pDevice
,
275 struct NineQuery9
**ppOut
,
278 NINE_DEVICE_CHILD_NEW(Query9
, ppOut
, pDevice
, Type
);