1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Direct3DQuery9.hpp"
16 
17 #include "Direct3DDevice9.hpp"
18 #include "Timer.hpp"
19 #include "Renderer.hpp"
20 #include "Debug.hpp"
21 
22 #include <assert.h>
23 
24 namespace D3D9
25 {
Direct3DQuery9(Direct3DDevice9 * device,D3DQUERYTYPE type)26 	Direct3DQuery9::Direct3DQuery9(Direct3DDevice9 *device, D3DQUERYTYPE type) : device(device), type(type)
27 	{
28 		if(type == D3DQUERYTYPE_OCCLUSION)
29 		{
30 			query = new sw::Query(sw::Query::FRAGMENTS_PASSED);
31 		}
32 		else
33 		{
34 			query = 0;
35 		}
36 	}
37 
~Direct3DQuery9()38 	Direct3DQuery9::~Direct3DQuery9()
39 	{
40 		if(query)
41 		{
42 			device->removeQuery(query);
43 
44 			query->release();
45 		}
46 	}
47 
QueryInterface(const IID & iid,void ** object)48 	long Direct3DQuery9::QueryInterface(const IID &iid, void **object)
49 	{
50 		CriticalSection cs(device);
51 
52 		TRACE("");
53 
54 		if(iid == IID_IDirect3DQuery9 ||
55 		   iid == IID_IUnknown)
56 		{
57 			AddRef();
58 			*object = this;
59 
60 			return S_OK;
61 		}
62 
63 		*object = 0;
64 
65 		return NOINTERFACE(iid);
66 	}
67 
AddRef()68 	unsigned long Direct3DQuery9::AddRef()
69 	{
70 		TRACE("");
71 
72 		return Unknown::AddRef();
73 	}
74 
Release()75 	unsigned long Direct3DQuery9::Release()
76 	{
77 		TRACE("");
78 
79 		return Unknown::Release();
80 	}
81 
GetDevice(IDirect3DDevice9 ** device)82 	long __stdcall Direct3DQuery9::GetDevice(IDirect3DDevice9 **device)
83 	{
84 		CriticalSection cs(this->device);
85 
86 		TRACE("");
87 
88 		if(!device)
89 		{
90 			return INVALIDCALL();
91 		}
92 
93 		this->device->AddRef();
94 		*device = this->device;
95 
96 		return D3D_OK;
97 	}
98 
GetType()99 	D3DQUERYTYPE Direct3DQuery9::GetType()
100 	{
101 		CriticalSection cs(device);
102 
103 		return type;
104 	}
105 
GetDataSize()106 	unsigned long Direct3DQuery9::GetDataSize()
107 	{
108 		CriticalSection cs(device);
109 
110 		TRACE("");
111 
112 		switch(type)
113 		{
114 		case D3DQUERYTYPE_VCACHE:				return sizeof(D3DDEVINFO_VCACHE);
115 		case D3DQUERYTYPE_RESOURCEMANAGER:		return sizeof(D3DDEVINFO_RESOURCEMANAGER);
116 		case D3DQUERYTYPE_VERTEXSTATS:			return sizeof(D3DDEVINFO_D3DVERTEXSTATS);
117 		case D3DQUERYTYPE_EVENT:				return sizeof(BOOL);
118 		case D3DQUERYTYPE_OCCLUSION:			return sizeof(DWORD);
119 		case D3DQUERYTYPE_TIMESTAMP:			return sizeof(UINT64);
120 		case D3DQUERYTYPE_TIMESTAMPDISJOINT:	return sizeof(BOOL);
121 		case D3DQUERYTYPE_TIMESTAMPFREQ:		return sizeof(UINT64);
122 		case D3DQUERYTYPE_PIPELINETIMINGS:		return sizeof(D3DDEVINFO_D3D9PIPELINETIMINGS);
123 		case D3DQUERYTYPE_INTERFACETIMINGS:		return sizeof(D3DDEVINFO_D3D9INTERFACETIMINGS);
124 		case D3DQUERYTYPE_VERTEXTIMINGS:		return sizeof(D3DDEVINFO_D3D9STAGETIMINGS);
125 		case D3DQUERYTYPE_PIXELTIMINGS:			return sizeof(D3DDEVINFO_D3D9PIPELINETIMINGS);
126 		case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return sizeof(D3DDEVINFO_D3D9BANDWIDTHTIMINGS);
127 		case D3DQUERYTYPE_CACHEUTILIZATION:		return sizeof(D3DDEVINFO_D3D9CACHEUTILIZATION);
128 		default:
129 			ASSERT(false);
130 		}
131 
132 		return D3D_OK;
133 	}
134 
Issue(unsigned long flags)135 	long Direct3DQuery9::Issue(unsigned long flags)
136 	{
137 		CriticalSection cs(device);
138 
139 		TRACE("");
140 
141 		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END)
142 		{
143 			return INVALIDCALL();
144 		}
145 
146 		switch(type)
147 		{
148 		case D3DQUERYTYPE_VCACHE:				if(flags != D3DISSUE_END) return INVALIDCALL(); break;
149 		case D3DQUERYTYPE_RESOURCEMANAGER:		if(flags != D3DISSUE_END) return INVALIDCALL(); break;
150 		case D3DQUERYTYPE_VERTEXSTATS:			if(flags != D3DISSUE_END) return INVALIDCALL(); break;
151 		case D3DQUERYTYPE_EVENT:
152 			if(flags == D3DISSUE_END)
153 			{
154 			//	device->renderer->synchronize();   // FIXME
155 			}
156 			else return INVALIDCALL();
157 			break;
158 		case D3DQUERYTYPE_OCCLUSION:
159 			if(flags == D3DISSUE_BEGIN)
160 			{
161 				query->begin();
162 				device->addQuery(query);
163 				device->setOcclusionEnabled(true);
164 			}
165 			else   // flags == D3DISSUE_END
166 			{
167 				query->end();
168 				device->removeQuery(query);
169 				device->setOcclusionEnabled(false);
170 			}
171 			break;
172 		case D3DQUERYTYPE_TIMESTAMP:
173 			if(flags == D3DISSUE_END)
174 			{
175 				timestamp = sw::Timer::counter();
176 			}
177 			else return INVALIDCALL();
178 			break;
179 		case D3DQUERYTYPE_TIMESTAMPDISJOINT:	if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
180 		case D3DQUERYTYPE_TIMESTAMPFREQ:		if(flags != D3DISSUE_END) return INVALIDCALL(); break;
181 		case D3DQUERYTYPE_PIPELINETIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
182 		case D3DQUERYTYPE_INTERFACETIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
183 		case D3DQUERYTYPE_VERTEXTIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
184 		case D3DQUERYTYPE_PIXELTIMINGS:			if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
185 		case D3DQUERYTYPE_BANDWIDTHTIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
186 		case D3DQUERYTYPE_CACHEUTILIZATION:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
187 		default:
188 			ASSERT(false);
189 		}
190 
191 		return D3D_OK;
192 	}
193 
GetData(void * data,unsigned long size,unsigned long flags)194 	long Direct3DQuery9::GetData(void *data, unsigned long size, unsigned long flags)
195 	{
196 		CriticalSection cs(device);
197 
198 		TRACE("void *data = %p, unsigned long size = %d, unsigned long flags = %d", data, size, flags);
199 
200 		if(query && query->building)
201 		{
202 			return INVALIDCALL();
203 		}
204 
205 		bool signaled = !query || query->isReady();
206 
207 		if(size && signaled)
208 		{
209 			if(!data)
210 			{
211 				return INVALIDCALL();
212 			}
213 
214 			// FIXME: Check size
215 
216 			switch(type)
217 			{
218 			case D3DQUERYTYPE_VCACHE:
219 				{
220 					D3DDEVINFO_VCACHE vcache;
221 
222 					vcache.Pattern = 'CACH';
223 					vcache.OptMethod = 1;   // Vertex-cache based optimization
224 					vcache.CacheSize = 16;
225 					vcache.MagicNumber = 8;
226 
227 					*(D3DDEVINFO_VCACHE*)data = vcache;
228 				}
229 				break;
230 			case D3DQUERYTYPE_RESOURCEMANAGER:		UNIMPLEMENTED(); break;
231 			case D3DQUERYTYPE_VERTEXSTATS:			UNIMPLEMENTED(); break;
232 			case D3DQUERYTYPE_EVENT:				*(BOOL*)data = TRUE; break;                       // FIXME
233 			case D3DQUERYTYPE_OCCLUSION:
234 				*(DWORD*)data = query->data;
235 				break;
236 			case D3DQUERYTYPE_TIMESTAMP:			*(UINT64*)data = timestamp; break;                // FIXME: Verify behaviour
237 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	*(BOOL*)data = FALSE; break;                      // FIXME: Verify behaviour
238 			case D3DQUERYTYPE_TIMESTAMPFREQ:		*(UINT64*)data = sw::Timer::frequency(); break;   // FIXME: Verify behaviour
239 			case D3DQUERYTYPE_PIPELINETIMINGS:		UNIMPLEMENTED(); break;
240 			case D3DQUERYTYPE_INTERFACETIMINGS:		UNIMPLEMENTED(); break;
241 			case D3DQUERYTYPE_VERTEXTIMINGS:		UNIMPLEMENTED(); break;
242 			case D3DQUERYTYPE_PIXELTIMINGS:			UNIMPLEMENTED(); break;
243 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		UNIMPLEMENTED(); break;
244 			case D3DQUERYTYPE_CACHEUTILIZATION:		UNIMPLEMENTED(); break;
245 			default:
246 				ASSERT(false);
247 			}
248 		}
249 
250 		return signaled ? S_OK : S_FALSE;
251 	}
252 }
253