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