Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright 2011 Joakim Sindholt |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * on the rights to use, copy, modify, merge, publish, distribute, sub |
||
8 | * license, and/or sell copies of the Software, and to permit persons to whom |
||
9 | * the Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
18 | * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||
19 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
20 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
21 | * USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
||
22 | |||
23 | #include "c99_alloca.h" |
||
24 | |||
25 | #include "device9.h" |
||
26 | #include "cubetexture9.h" |
||
27 | #include "nine_helpers.h" |
||
28 | #include "nine_pipe.h" |
||
29 | |||
30 | #define DBG_CHANNEL DBG_CUBETEXTURE |
||
31 | |||
32 | |||
33 | static HRESULT |
||
34 | NineCubeTexture9_ctor( struct NineCubeTexture9 *This, |
||
35 | struct NineUnknownParams *pParams, |
||
36 | UINT EdgeLength, UINT Levels, |
||
37 | DWORD Usage, |
||
38 | D3DFORMAT Format, |
||
39 | D3DPOOL Pool, |
||
40 | HANDLE *pSharedHandle ) |
||
41 | { |
||
42 | struct pipe_resource *info = &This->base.base.info; |
||
43 | struct pipe_screen *screen = pParams->device->screen; |
||
44 | enum pipe_format pf; |
||
45 | unsigned i, l, f, offset, face_size = 0; |
||
46 | unsigned *level_offsets; |
||
47 | D3DSURFACE_DESC sfdesc; |
||
48 | void *p; |
||
49 | HRESULT hr; |
||
50 | |||
51 | DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d " |
||
52 | "Format=%d Pool=%d pSharedHandle=%p\n", |
||
53 | This, pParams, EdgeLength, Levels, Usage, |
||
54 | Format, Pool, pSharedHandle); |
||
55 | |||
56 | user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || |
||
57 | (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL); |
||
58 | |||
59 | user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ |
||
60 | |||
61 | if (Usage & D3DUSAGE_AUTOGENMIPMAP) |
||
62 | Levels = 0; |
||
63 | |||
64 | pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_CUBE, 0, |
||
65 | PIPE_BIND_SAMPLER_VIEW, FALSE); |
||
66 | if (pf == PIPE_FORMAT_NONE) |
||
67 | return D3DERR_INVALIDCALL; |
||
68 | |||
69 | /* We support ATI1 and ATI2 hacks only for 2D textures */ |
||
70 | if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2) |
||
71 | return D3DERR_INVALIDCALL; |
||
72 | |||
73 | info->screen = pParams->device->screen; |
||
74 | info->target = PIPE_TEXTURE_CUBE; |
||
75 | info->format = pf; |
||
76 | info->width0 = EdgeLength; |
||
77 | info->height0 = EdgeLength; |
||
78 | info->depth0 = 1; |
||
79 | if (Levels) |
||
80 | info->last_level = Levels - 1; |
||
81 | else |
||
82 | info->last_level = util_logbase2(EdgeLength); |
||
83 | info->array_size = 6; |
||
84 | info->nr_samples = 0; |
||
85 | info->bind = PIPE_BIND_SAMPLER_VIEW; |
||
86 | info->usage = PIPE_USAGE_DEFAULT; |
||
87 | info->flags = 0; |
||
88 | |||
89 | if (Usage & D3DUSAGE_RENDERTARGET) |
||
90 | info->bind |= PIPE_BIND_RENDER_TARGET; |
||
91 | if (Usage & D3DUSAGE_DEPTHSTENCIL) |
||
92 | info->bind |= PIPE_BIND_DEPTH_STENCIL; |
||
93 | |||
94 | if (Usage & D3DUSAGE_DYNAMIC) { |
||
95 | info->usage = PIPE_USAGE_DYNAMIC; |
||
96 | info->bind |= |
||
97 | PIPE_BIND_TRANSFER_READ | |
||
98 | PIPE_BIND_TRANSFER_WRITE; |
||
99 | } |
||
100 | if (Usage & D3DUSAGE_SOFTWAREPROCESSING) |
||
101 | DBG("Application asked for Software Vertex Processing, " |
||
102 | "but this is unimplemented\n"); |
||
103 | |||
104 | if (Pool != D3DPOOL_DEFAULT) { |
||
105 | level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); |
||
106 | face_size = nine_format_get_size_and_offsets(pf, level_offsets, |
||
107 | EdgeLength, EdgeLength, |
||
108 | info->last_level); |
||
109 | This->managed_buffer = MALLOC(6 * face_size); |
||
110 | if (!This->managed_buffer) |
||
111 | return E_OUTOFMEMORY; |
||
112 | } |
||
113 | |||
114 | This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces)); |
||
115 | if (!This->surfaces) |
||
116 | return E_OUTOFMEMORY; |
||
117 | |||
118 | hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE, |
||
119 | Format, Pool, Usage); |
||
120 | if (FAILED(hr)) |
||
121 | return hr; |
||
122 | This->base.pstype = 2; |
||
123 | |||
124 | /* Create all the surfaces right away. |
||
125 | * They manage backing storage, and transfers (LockRect) are deferred |
||
126 | * to them. |
||
127 | */ |
||
128 | sfdesc.Format = Format; |
||
129 | sfdesc.Type = D3DRTYPE_SURFACE; |
||
130 | sfdesc.Usage = Usage; |
||
131 | sfdesc.Pool = Pool; |
||
132 | sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; |
||
133 | sfdesc.MultiSampleQuality = 0; |
||
134 | /* We allocate the memory for the surfaces as continous blocks. |
||
135 | * This is the expected behaviour, however we haven't tested for |
||
136 | * cube textures in which order the faces/levels should be in memory |
||
137 | */ |
||
138 | for (f = 0; f < 6; f++) { |
||
139 | offset = f * face_size; |
||
140 | for (l = 0; l <= info->last_level; l++) { |
||
141 | sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l); |
||
142 | p = This->managed_buffer ? This->managed_buffer + offset + |
||
143 | level_offsets[l] : NULL; |
||
144 | |||
145 | hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), |
||
146 | This->base.base.resource, p, D3DRTYPE_CUBETEXTURE, |
||
147 | l, f, &sfdesc, &This->surfaces[f + 6 * l]); |
||
148 | if (FAILED(hr)) |
||
149 | return hr; |
||
150 | } |
||
151 | } |
||
152 | |||
153 | for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */ |
||
154 | This->dirty_rect[i].depth = 1; |
||
155 | |||
156 | return D3D_OK; |
||
157 | } |
||
158 | |||
159 | static void |
||
160 | NineCubeTexture9_dtor( struct NineCubeTexture9 *This ) |
||
161 | { |
||
162 | unsigned i; |
||
163 | |||
164 | DBG("This=%p\n", This); |
||
165 | |||
166 | if (This->surfaces) { |
||
167 | for (i = 0; i < This->base.base.info.last_level * 6; ++i) |
||
168 | NineUnknown_Destroy(&This->surfaces[i]->base.base); |
||
169 | FREE(This->surfaces); |
||
170 | } |
||
171 | |||
172 | if (This->managed_buffer) |
||
173 | FREE(This->managed_buffer); |
||
174 | |||
175 | NineBaseTexture9_dtor(&This->base); |
||
176 | } |
||
177 | |||
178 | HRESULT WINAPI |
||
179 | NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, |
||
180 | UINT Level, |
||
181 | D3DSURFACE_DESC *pDesc ) |
||
182 | { |
||
183 | DBG("This=%p Level=%u pDesc=%p\n", This, Level, pDesc); |
||
184 | |||
185 | user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); |
||
186 | user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), |
||
187 | D3DERR_INVALIDCALL); |
||
188 | |||
189 | *pDesc = This->surfaces[Level * 6]->desc; |
||
190 | |||
191 | return D3D_OK; |
||
192 | } |
||
193 | |||
194 | HRESULT WINAPI |
||
195 | NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, |
||
196 | D3DCUBEMAP_FACES FaceType, |
||
197 | UINT Level, |
||
198 | IDirect3DSurface9 **ppCubeMapSurface ) |
||
199 | { |
||
200 | const unsigned s = Level * 6 + FaceType; |
||
201 | |||
202 | DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n", |
||
203 | This, FaceType, Level, ppCubeMapSurface); |
||
204 | |||
205 | user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); |
||
206 | user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), |
||
207 | D3DERR_INVALIDCALL); |
||
208 | user_assert(FaceType < 6, D3DERR_INVALIDCALL); |
||
209 | |||
210 | NineUnknown_AddRef(NineUnknown(This->surfaces[s])); |
||
211 | *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s]; |
||
212 | |||
213 | return D3D_OK; |
||
214 | } |
||
215 | |||
216 | HRESULT WINAPI |
||
217 | NineCubeTexture9_LockRect( struct NineCubeTexture9 *This, |
||
218 | D3DCUBEMAP_FACES FaceType, |
||
219 | UINT Level, |
||
220 | D3DLOCKED_RECT *pLockedRect, |
||
221 | const RECT *pRect, |
||
222 | DWORD Flags ) |
||
223 | { |
||
224 | const unsigned s = Level * 6 + FaceType; |
||
225 | |||
226 | DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n", |
||
227 | This, FaceType, Level, pLockedRect, pRect, Flags); |
||
228 | |||
229 | user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); |
||
230 | user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), |
||
231 | D3DERR_INVALIDCALL); |
||
232 | user_assert(FaceType < 6, D3DERR_INVALIDCALL); |
||
233 | |||
234 | return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags); |
||
235 | } |
||
236 | |||
237 | HRESULT WINAPI |
||
238 | NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, |
||
239 | D3DCUBEMAP_FACES FaceType, |
||
240 | UINT Level ) |
||
241 | { |
||
242 | const unsigned s = Level * 6 + FaceType; |
||
243 | |||
244 | DBG("This=%p FaceType=%d Level=%u\n", This, FaceType, Level); |
||
245 | |||
246 | user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); |
||
247 | user_assert(FaceType < 6, D3DERR_INVALIDCALL); |
||
248 | |||
249 | return NineSurface9_UnlockRect(This->surfaces[s]); |
||
250 | } |
||
251 | |||
252 | HRESULT WINAPI |
||
253 | NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, |
||
254 | D3DCUBEMAP_FACES FaceType, |
||
255 | const RECT *pDirtyRect ) |
||
256 | { |
||
257 | DBG("This=%p FaceType=%d pDirtyRect=%p\n", This, FaceType, pDirtyRect); |
||
258 | |||
259 | user_assert(FaceType < 6, D3DERR_INVALIDCALL); |
||
260 | |||
261 | if (This->base.base.pool != D3DPOOL_MANAGED) { |
||
262 | if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) |
||
263 | This->base.dirty_mip = TRUE; |
||
264 | return D3D_OK; |
||
265 | } |
||
266 | This->base.managed.dirty = TRUE; |
||
267 | |||
268 | BASETEX_REGISTER_UPDATE(&This->base); |
||
269 | |||
270 | if (!pDirtyRect) { |
||
271 | u_box_origin_2d(This->base.base.info.width0, |
||
272 | This->base.base.info.height0, |
||
273 | &This->dirty_rect[FaceType]); |
||
274 | } else { |
||
275 | struct pipe_box box; |
||
276 | rect_to_pipe_box_clamp(&box, pDirtyRect); |
||
277 | u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType], |
||
278 | &box); |
||
279 | (void) u_box_clip_2d(&This->dirty_rect[FaceType], |
||
280 | &This->dirty_rect[FaceType], |
||
281 | This->base.base.info.width0, |
||
282 | This->base.base.info.height0); |
||
283 | } |
||
284 | return D3D_OK; |
||
285 | } |
||
286 | |||
287 | IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = { |
||
288 | (void *)NineUnknown_QueryInterface, |
||
289 | (void *)NineUnknown_AddRef, |
||
290 | (void *)NineUnknown_Release, |
||
291 | (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ |
||
292 | (void *)NineResource9_SetPrivateData, |
||
293 | (void *)NineResource9_GetPrivateData, |
||
294 | (void *)NineResource9_FreePrivateData, |
||
295 | (void *)NineResource9_SetPriority, |
||
296 | (void *)NineResource9_GetPriority, |
||
297 | (void *)NineBaseTexture9_PreLoad, |
||
298 | (void *)NineResource9_GetType, |
||
299 | (void *)NineBaseTexture9_SetLOD, |
||
300 | (void *)NineBaseTexture9_GetLOD, |
||
301 | (void *)NineBaseTexture9_GetLevelCount, |
||
302 | (void *)NineBaseTexture9_SetAutoGenFilterType, |
||
303 | (void *)NineBaseTexture9_GetAutoGenFilterType, |
||
304 | (void *)NineBaseTexture9_GenerateMipSubLevels, |
||
305 | (void *)NineCubeTexture9_GetLevelDesc, |
||
306 | (void *)NineCubeTexture9_GetCubeMapSurface, |
||
307 | (void *)NineCubeTexture9_LockRect, |
||
308 | (void *)NineCubeTexture9_UnlockRect, |
||
309 | (void *)NineCubeTexture9_AddDirtyRect |
||
310 | }; |
||
311 | |||
312 | static const GUID *NineCubeTexture9_IIDs[] = { |
||
313 | &IID_IDirect3DCubeTexture9, |
||
314 | &IID_IDirect3DBaseTexture9, |
||
315 | &IID_IDirect3DResource9, |
||
316 | &IID_IUnknown, |
||
317 | NULL |
||
318 | }; |
||
319 | |||
320 | HRESULT |
||
321 | NineCubeTexture9_new( struct NineDevice9 *pDevice, |
||
322 | UINT EdgeLength, UINT Levels, |
||
323 | DWORD Usage, |
||
324 | D3DFORMAT Format, |
||
325 | D3DPOOL Pool, |
||
326 | struct NineCubeTexture9 **ppOut, |
||
327 | HANDLE *pSharedHandle ) |
||
328 | { |
||
329 | NINE_DEVICE_CHILD_NEW(CubeTexture9, ppOut, pDevice, |
||
330 | EdgeLength, Levels, |
||
331 | Usage, Format, Pool, pSharedHandle); |
||
332 | }>>=>>=>>=>=>>>=>>=> |