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