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