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 "Direct3DTexture9.hpp"
16 
17 #include "Direct3DDevice9.hpp"
18 #include "Direct3DSurface9.hpp"
19 #include "Resource.hpp"
20 #include "Debug.hpp"
21 
22 #include <assert.h>
23 
24 namespace D3D9
25 {
Direct3DTexture9(Direct3DDevice9 * device,unsigned int width,unsigned int height,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool)26 	Direct3DTexture9::Direct3DTexture9(Direct3DDevice9 *device, unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool) : Direct3DBaseTexture9(device, D3DRTYPE_TEXTURE, format, pool, levels, usage), width(width), height(height)
27 	{
28 		if(levels == 0)
29 		{
30 			this->levels = sw::log2(sw::max((int)width, (int)height, 1)) + 1;
31 		}
32 
33 		for(unsigned int level = 0; level < sw::MIPMAP_LEVELS; level++)
34 		{
35 			if(level < this->levels)
36 			{
37 				surfaceLevel[level] = new Direct3DSurface9(device, this, width, height, format, pool, D3DMULTISAMPLE_NONE, 0, false, usage);
38 				surfaceLevel[level]->bind();
39 			}
40 			else
41 			{
42 				surfaceLevel[level] = 0;
43 			}
44 
45 			width = sw::max(1, (int)width / 2);
46 			height = sw::max(1, (int)height / 2);
47 		}
48 	}
49 
~Direct3DTexture9()50 	Direct3DTexture9::~Direct3DTexture9()
51 	{
52 		resource->lock(sw::DESTRUCT);
53 
54 		for(int level = 0; level < sw::MIPMAP_LEVELS; level++)
55 		{
56 			if(surfaceLevel[level])
57 			{
58 				surfaceLevel[level]->unbind();
59 				surfaceLevel[level] = 0;
60 			}
61 		}
62 
63 		resource->unlock();
64 	}
65 
QueryInterface(const IID & iid,void ** object)66 	long Direct3DTexture9::QueryInterface(const IID &iid, void **object)
67 	{
68 		CriticalSection cs(device);
69 
70 		TRACE("");
71 
72 		if(iid == IID_IDirect3DTexture9 ||
73 		   iid == IID_IDirect3DBaseTexture9 ||
74 		   iid == IID_IDirect3DResource9 ||
75 		   iid == IID_IUnknown)
76 		{
77 			AddRef();
78 			*object = this;
79 
80 			return S_OK;
81 		}
82 
83 		*object = 0;
84 
85 		return NOINTERFACE(iid);
86 	}
87 
AddRef()88 	unsigned long Direct3DTexture9::AddRef()
89 	{
90 		TRACE("");
91 
92 		return Direct3DBaseTexture9::AddRef();
93 	}
94 
Release()95 	unsigned long Direct3DTexture9::Release()
96 	{
97 		TRACE("");
98 
99 		return Direct3DBaseTexture9::Release();
100 	}
101 
FreePrivateData(const GUID & guid)102 	long Direct3DTexture9::FreePrivateData(const GUID &guid)
103 	{
104 		CriticalSection cs(device);
105 
106 		TRACE("");
107 
108 		return Direct3DBaseTexture9::FreePrivateData(guid);
109 	}
110 
GetPrivateData(const GUID & guid,void * data,unsigned long * size)111 	long Direct3DTexture9::GetPrivateData(const GUID &guid, void *data, unsigned long *size)
112 	{
113 		CriticalSection cs(device);
114 
115 		TRACE("");
116 
117 		return Direct3DBaseTexture9::GetPrivateData(guid, data, size);
118 	}
119 
PreLoad()120 	void Direct3DTexture9::PreLoad()
121 	{
122 		CriticalSection cs(device);
123 
124 		TRACE("");
125 
126 		Direct3DBaseTexture9::PreLoad();
127 	}
128 
SetPrivateData(const GUID & guid,const void * data,unsigned long size,unsigned long flags)129 	long Direct3DTexture9::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags)
130 	{
131 		CriticalSection cs(device);
132 
133 		TRACE("");
134 
135 		return Direct3DBaseTexture9::SetPrivateData(guid, data, size, flags);
136 	}
137 
GetDevice(IDirect3DDevice9 ** device)138 	long Direct3DTexture9::GetDevice(IDirect3DDevice9 **device)
139 	{
140 		CriticalSection cs(this->device);
141 
142 		TRACE("IDirect3DDevice9 **device = 0x%0.8p", device);
143 
144 		return Direct3DBaseTexture9::GetDevice(device);
145 	}
146 
SetPriority(unsigned long newPriority)147 	unsigned long Direct3DTexture9::SetPriority(unsigned long newPriority)
148 	{
149 		CriticalSection cs(device);
150 
151 		TRACE("unsigned long newPriority = %d", newPriority);
152 
153 		return Direct3DBaseTexture9::SetPriority(newPriority);
154 	}
155 
GetPriority()156 	unsigned long Direct3DTexture9::GetPriority()
157 	{
158 		CriticalSection cs(device);
159 
160 		TRACE("");
161 
162 		return Direct3DBaseTexture9::GetPriority();
163 	}
164 
GetType()165 	D3DRESOURCETYPE Direct3DTexture9::GetType()
166 	{
167 		CriticalSection cs(device);
168 
169 		TRACE("");
170 
171 		return Direct3DBaseTexture9::GetType();
172 	}
173 
GenerateMipSubLevels()174 	void Direct3DTexture9::GenerateMipSubLevels()
175 	{
176 		CriticalSection cs(device);
177 
178 		TRACE("");
179 
180 		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !surfaceLevel[0]->hasDirtyMipmaps())
181 		{
182 			return;
183 		}
184 
185 		resource->lock(sw::PUBLIC);
186 
187 		for(unsigned int i = 0; i < levels - 1; i++)
188 		{
189 			device->stretchRect(surfaceLevel[i], 0, surfaceLevel[i + 1], 0, GetAutoGenFilterType());
190 		}
191 
192 		surfaceLevel[0]->cleanMipmaps();
193 
194 		resource->unlock();
195 	}
196 
GetAutoGenFilterType()197 	D3DTEXTUREFILTERTYPE Direct3DTexture9::GetAutoGenFilterType()
198 	{
199 		CriticalSection cs(device);
200 
201 		TRACE("");
202 
203 		return Direct3DBaseTexture9::GetAutoGenFilterType();
204 	}
205 
GetLevelCount()206 	unsigned long Direct3DTexture9::GetLevelCount()
207 	{
208 		CriticalSection cs(device);
209 
210 		TRACE("");
211 
212 		return Direct3DBaseTexture9::GetLevelCount();
213 	}
214 
GetLOD()215 	unsigned long Direct3DTexture9::GetLOD()
216 	{
217 		CriticalSection cs(device);
218 
219 		TRACE("");
220 
221 		return Direct3DBaseTexture9::GetLOD();
222 	}
223 
SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType)224 	long Direct3DTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType)
225 	{
226 		CriticalSection cs(device);
227 
228 		TRACE("D3DTEXTUREFILTERTYPE filterType = %d", filterType);
229 
230 		return Direct3DBaseTexture9::SetAutoGenFilterType(filterType);
231 	}
232 
SetLOD(unsigned long newLOD)233 	unsigned long Direct3DTexture9::SetLOD(unsigned long newLOD)
234 	{
235 		CriticalSection cs(device);
236 
237 		TRACE("unsigned long newLOD = %d", newLOD);
238 
239 		return Direct3DBaseTexture9::SetLOD(newLOD);
240 	}
241 
GetLevelDesc(unsigned int level,D3DSURFACE_DESC * description)242 	long Direct3DTexture9::GetLevelDesc(unsigned int level, D3DSURFACE_DESC *description)
243 	{
244 		CriticalSection cs(device);
245 
246 		TRACE("unsigned int level = %d, D3DSURFACE_DESC *description = 0x%0.8p", level, description);
247 
248 		if(!description || level >= GetLevelCount() || !surfaceLevel[level])
249 		{
250 			return INVALIDCALL();
251 		}
252 
253 		return surfaceLevel[level]->GetDesc(description);
254 	}
255 
LockRect(unsigned int level,D3DLOCKED_RECT * lockedRect,const RECT * rect,unsigned long flags)256 	long Direct3DTexture9::LockRect(unsigned int level, D3DLOCKED_RECT *lockedRect, const RECT *rect, unsigned long flags)
257 	{
258 		CriticalSection cs(device);
259 
260 		TRACE("unsigned int level = %d, D3DLOCKED_RECT *lockedRect = 0x%0.8p, const RECT *rect = 0x%0.8p, unsigned long flags = %d", level, lockedRect, rect, flags);
261 
262 		if(!lockedRect || level >= GetLevelCount() || !surfaceLevel[level])
263 		{
264 			return INVALIDCALL();
265 		}
266 
267 		return surfaceLevel[level]->LockRect(lockedRect, rect, flags);
268 	}
269 
GetSurfaceLevel(unsigned int level,IDirect3DSurface9 ** surface)270 	long Direct3DTexture9::GetSurfaceLevel(unsigned int level, IDirect3DSurface9 **surface)
271 	{
272 		CriticalSection cs(device);
273 
274 		TRACE("unsigned int level = %d, IDirect3DSurface9 **surface = 0x%0.8p", level, surface);
275 
276 		*surface = 0;
277 
278 		if(level >= GetLevelCount() || !surfaceLevel[level])
279 		{
280 			return INVALIDCALL();
281 		}
282 
283 		surfaceLevel[level]->AddRef();
284 		*surface = surfaceLevel[level];
285 
286 		return D3D_OK;
287 	}
288 
UnlockRect(unsigned int level)289 	long Direct3DTexture9::UnlockRect(unsigned int level)
290 	{
291 		CriticalSection cs(device);
292 
293 		TRACE("unsigned int level = %d", level);
294 
295 		if(level >= GetLevelCount() || !surfaceLevel[level])
296 		{
297 			return INVALIDCALL();
298 		}
299 
300 		return surfaceLevel[level]->UnlockRect();
301 	}
302 
AddDirtyRect(const RECT * dirtyRect)303 	long Direct3DTexture9::AddDirtyRect(const RECT *dirtyRect)
304 	{
305 		CriticalSection cs(device);
306 
307 		TRACE("");
308 
309 	//	UNIMPLEMENTED();
310 
311 		return D3D_OK;
312 	}
313 
getInternalSurfaceLevel(unsigned int level)314 	Direct3DSurface9 *Direct3DTexture9::getInternalSurfaceLevel(unsigned int level)
315 	{
316 		return surfaceLevel[level];
317 	}
318 }
319