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 "Direct3DVolumeTexture9.hpp"
16 
17 #include "Direct3DVolume9.hpp"
18 #include "Direct3DDevice9.hpp"
19 #include "Resource.hpp"
20 #include "Debug.hpp"
21 
22 #include <assert.h>
23 
24 namespace D3D9
25 {
Direct3DVolumeTexture9(Direct3DDevice9 * device,unsigned int width,unsigned int height,unsigned int depth,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool)26 	Direct3DVolumeTexture9::Direct3DVolumeTexture9(Direct3DDevice9 *device, unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool) : Direct3DBaseTexture9(device, D3DRTYPE_VOLUMETEXTURE, format, pool, levels, usage), width(width), height(height), depth(depth)
27 	{
28 		if(levels == 0)
29 		{
30 			this->levels = sw::log2(sw::max((int)width, (int)height, (int)depth, 1)) + 1;
31 		}
32 
33 		for(unsigned int level = 0; level < sw::MIPMAP_LEVELS; level++)
34 		{
35 			if(level < this->levels)
36 			{
37 				volumeLevel[level] = new Direct3DVolume9(device, this, width, height, depth, format, pool, usage);
38 				volumeLevel[level]->bind();
39 			}
40 			else
41 			{
42 				volumeLevel[level] = 0;
43 			}
44 
45 			width = sw::max(1, (int)width / 2);
46 			height = sw::max(1, (int)height / 2);
47 			depth = sw::max(1, (int)depth / 2);
48 		}
49 	}
50 
~Direct3DVolumeTexture9()51 	Direct3DVolumeTexture9::~Direct3DVolumeTexture9()
52 	{
53 		for(int level = 0; level < sw::MIPMAP_LEVELS; level++)
54 		{
55 			if(volumeLevel[level])
56 			{
57 				volumeLevel[level]->unbind();
58 				volumeLevel[level] = 0;
59 			}
60 		}
61 	}
62 
QueryInterface(const IID & iid,void ** object)63 	long Direct3DVolumeTexture9::QueryInterface(const IID &iid, void **object)
64 	{
65 		CriticalSection cs(device);
66 
67 		TRACE("");
68 
69 		if(iid == IID_IDirect3DVolumeTexture9 ||
70 		   iid == IID_IDirect3DBaseTexture9 ||
71 		   iid == IID_IDirect3DResource9 ||
72 		   iid == IID_IUnknown)
73 		{
74 			AddRef();
75 			*object = this;
76 
77 			return S_OK;
78 		}
79 
80 		*object = 0;
81 
82 		return NOINTERFACE(iid);
83 	}
84 
AddRef()85 	unsigned long Direct3DVolumeTexture9::AddRef()
86 	{
87 		TRACE("");
88 
89 		return Direct3DBaseTexture9::AddRef();
90 	}
91 
Release()92 	unsigned long Direct3DVolumeTexture9::Release()
93 	{
94 		TRACE("");
95 
96 		return Direct3DBaseTexture9::Release();
97 	}
98 
FreePrivateData(const GUID & guid)99 	long Direct3DVolumeTexture9::FreePrivateData(const GUID &guid)
100 	{
101 		CriticalSection cs(device);
102 
103 		TRACE("");
104 
105 		return Direct3DBaseTexture9::FreePrivateData(guid);
106 	}
107 
GetPrivateData(const GUID & guid,void * data,unsigned long * size)108 	long Direct3DVolumeTexture9::GetPrivateData(const GUID &guid, void *data, unsigned long *size)
109 	{
110 		CriticalSection cs(device);
111 
112 		TRACE("");
113 
114 		return Direct3DBaseTexture9::GetPrivateData(guid, data, size);
115 	}
116 
PreLoad()117 	void Direct3DVolumeTexture9::PreLoad()
118 	{
119 		CriticalSection cs(device);
120 
121 		TRACE("");
122 
123 		Direct3DBaseTexture9::PreLoad();
124 	}
125 
SetPrivateData(const GUID & guid,const void * data,unsigned long size,unsigned long flags)126 	long Direct3DVolumeTexture9::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags)
127 	{
128 		CriticalSection cs(device);
129 
130 		TRACE("");
131 
132 		return Direct3DBaseTexture9::SetPrivateData(guid, data, size, flags);
133 	}
134 
GetDevice(IDirect3DDevice9 ** device)135 	long Direct3DVolumeTexture9::GetDevice(IDirect3DDevice9 **device)
136 	{
137 		CriticalSection(this->device);
138 
139 		TRACE("");
140 
141 		return Direct3DBaseTexture9::GetDevice(device);
142 	}
143 
SetPriority(unsigned long newPriority)144 	unsigned long Direct3DVolumeTexture9::SetPriority(unsigned long newPriority)
145 	{
146 		CriticalSection cs(device);
147 
148 		TRACE("");
149 
150 		return Direct3DBaseTexture9::SetPriority(newPriority);
151 	}
152 
GetPriority()153 	unsigned long Direct3DVolumeTexture9::GetPriority()
154 	{
155 		CriticalSection cs(device);
156 
157 		TRACE("");
158 
159 		return Direct3DBaseTexture9::GetPriority();
160 	}
161 
GetType()162 	D3DRESOURCETYPE Direct3DVolumeTexture9::GetType()
163 	{
164 		CriticalSection cs(device);
165 
166 		TRACE("");
167 
168 		return Direct3DBaseTexture9::GetType();
169 	}
170 
GenerateMipSubLevels()171 	void Direct3DVolumeTexture9::GenerateMipSubLevels()
172 	{
173 		CriticalSection cs(device);
174 
175 		TRACE("");
176 
177 		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !volumeLevel[0]->hasDirtyContents())
178 		{
179 			return;
180 		}
181 
182 		resource->lock(sw::PUBLIC);
183 
184 		for(unsigned int i = 0; i < levels - 1; i++)
185 		{
186 			Direct3DVolume9 *source = volumeLevel[i];
187 			Direct3DVolume9 *dest = volumeLevel[i + 1];
188 
189 			source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
190 			dest->lockInternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
191 
192 			int sWidth = source->getWidth();
193 			int sHeight = source->getHeight();
194 			int sDepth = source->getDepth();
195 
196 			int dWidth = dest->getWidth();
197 			int dHeight = dest->getHeight();
198 			int dDepth = dest->getDepth();
199 
200 			D3DTEXTUREFILTERTYPE filter = GetAutoGenFilterType();
201 
202 			float w = (float)sWidth / (float)dWidth;
203 			float h = (float)sHeight / (float)dHeight;
204 			float d = (float)sDepth / (float)dDepth;
205 
206 			float z = 0.5f * d;
207 
208 			for(int k = 0; k < dDepth; k++)
209 			{
210 				float y = 0.5f * h;
211 
212 				for(int j = 0; j < dHeight; j++)
213 				{
214 					float x = 0.5f * w;
215 
216 					for(int i = 0; i < dWidth; i++)
217 					{
218 						dest->copyInternal(source, i, j, k, x, y, z, filter > D3DTEXF_POINT);
219 
220 						x += w;
221 					}
222 
223 					y += h;
224 				}
225 
226 				z += d;
227 			}
228 
229 			source->unlockInternal();
230 			dest->unlockInternal();
231 		}
232 
233 		volumeLevel[0]->markContentsClean();
234 
235 		resource->unlock();
236 	}
237 
GetAutoGenFilterType()238 	D3DTEXTUREFILTERTYPE Direct3DVolumeTexture9::GetAutoGenFilterType()
239 	{
240 		CriticalSection cs(device);
241 
242 		TRACE("");
243 
244 		return Direct3DBaseTexture9::GetAutoGenFilterType();
245 	}
246 
GetLevelCount()247 	unsigned long Direct3DVolumeTexture9::GetLevelCount()
248 	{
249 		CriticalSection cs(device);
250 
251 		TRACE("");
252 
253 		return Direct3DBaseTexture9::GetLevelCount();
254 	}
255 
GetLOD()256 	unsigned long Direct3DVolumeTexture9::GetLOD()
257 	{
258 		CriticalSection cs(device);
259 
260 		TRACE("");
261 
262 		return Direct3DBaseTexture9::GetLOD();
263 	}
264 
SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType)265 	long Direct3DVolumeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType)
266 	{
267 		CriticalSection cs(device);
268 
269 		TRACE("");
270 
271 		return Direct3DBaseTexture9::SetAutoGenFilterType(filterType);
272 	}
273 
SetLOD(unsigned long newLOD)274 	unsigned long Direct3DVolumeTexture9::SetLOD(unsigned long newLOD)
275 	{
276 		CriticalSection cs(device);
277 
278 		TRACE("");
279 
280 		return Direct3DBaseTexture9::SetLOD(newLOD);
281 	}
282 
GetVolumeLevel(unsigned int level,IDirect3DVolume9 ** volume)283 	long Direct3DVolumeTexture9::GetVolumeLevel(unsigned int level, IDirect3DVolume9 **volume)
284 	{
285 		CriticalSection cs(device);
286 
287 		TRACE("");
288 
289 		*volume = 0;
290 
291 		if(level >= GetLevelCount() || !volumeLevel[level])
292 		{
293 			return INVALIDCALL();
294 		}
295 
296 		volumeLevel[level]->AddRef();
297 		*volume = volumeLevel[level];
298 
299 		return D3D_OK;
300 	}
301 
LockBox(unsigned int level,D3DLOCKED_BOX * lockedVolume,const D3DBOX * box,unsigned long flags)302 	long Direct3DVolumeTexture9::LockBox(unsigned int level, D3DLOCKED_BOX *lockedVolume, const D3DBOX *box, unsigned long flags)
303 	{
304 		CriticalSection cs(device);
305 
306 		TRACE("");
307 
308 		if(!lockedVolume || level >= GetLevelCount() || !volumeLevel[level])
309 		{
310 			return INVALIDCALL();
311 		}
312 
313 		return volumeLevel[level]->LockBox(lockedVolume, box, flags);
314 	}
315 
UnlockBox(unsigned int level)316 	long Direct3DVolumeTexture9::UnlockBox(unsigned int level)
317 	{
318 		CriticalSection cs(device);
319 
320 		TRACE("");
321 
322 		if(level >= GetLevelCount() || !volumeLevel[level])
323 		{
324 			return INVALIDCALL();
325 		}
326 
327 		return volumeLevel[level]->UnlockBox();
328 	}
329 
AddDirtyBox(const D3DBOX * dirtyBox)330 	long Direct3DVolumeTexture9::AddDirtyBox(const D3DBOX *dirtyBox)
331 	{
332 		CriticalSection cs(device);
333 
334 		TRACE("");
335 
336 	//	UNIMPLEMENTED();
337 
338 		return D3D_OK;
339 	}
340 
GetLevelDesc(unsigned int level,D3DVOLUME_DESC * description)341 	long Direct3DVolumeTexture9::GetLevelDesc(unsigned int level, D3DVOLUME_DESC *description)
342 	{
343 		CriticalSection cs(device);
344 
345 		TRACE("");
346 
347 		if(!description || level >= GetLevelCount() || !volumeLevel[level])
348 		{
349 			return INVALIDCALL();
350 		}
351 
352 		return volumeLevel[level]->GetDesc(description);
353 	}
354 
getInternalVolumeLevel(unsigned int level)355 	Direct3DVolume9 *Direct3DVolumeTexture9::getInternalVolumeLevel(unsigned int level)
356 	{
357 		return volumeLevel[level];
358 	}
359 }
360