st/nine: Refactor how user constbufs sizes are calculated
[mesa.git] / src / gallium / state_trackers / nine / cubetexture9.c
1 /*
2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
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 "device9.h"
24 #include "cubetexture9.h"
25 #include "nine_helpers.h"
26 #include "nine_pipe.h"
27
28 #define DBG_CHANNEL DBG_CUBETEXTURE
29
30
31 static HRESULT
32 NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
33 struct NineUnknownParams *pParams,
34 UINT EdgeLength, UINT Levels,
35 DWORD Usage,
36 D3DFORMAT Format,
37 D3DPOOL Pool,
38 HANDLE *pSharedHandle )
39 {
40 struct pipe_resource *info = &This->base.base.info;
41 struct pipe_screen *screen = pParams->device->screen;
42 enum pipe_format pf;
43 unsigned i;
44 D3DSURFACE_DESC sfdesc;
45 HRESULT hr;
46
47 DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d "
48 "Format=%d Pool=%d pSharedHandle=%p\n",
49 This, pParams, EdgeLength, Levels, Usage,
50 Format, Pool, pSharedHandle);
51
52 user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
53 (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
54
55 user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
56
57 if (Usage & D3DUSAGE_AUTOGENMIPMAP)
58 Levels = 0;
59
60 pf = d3d9_to_pipe_format(Format);
61 if (pf == PIPE_FORMAT_NONE ||
62 !screen->is_format_supported(screen, pf, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW)) {
63 return D3DERR_INVALIDCALL;
64 }
65
66 /* We support ATI1 and ATI2 hacks only for 2D textures */
67 if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
68 return D3DERR_INVALIDCALL;
69
70 info->screen = pParams->device->screen;
71 info->target = PIPE_TEXTURE_CUBE;
72 info->format = pf;
73 info->width0 = EdgeLength;
74 info->height0 = EdgeLength;
75 info->depth0 = 1;
76 if (Levels)
77 info->last_level = Levels - 1;
78 else
79 info->last_level = util_logbase2(EdgeLength);
80 info->array_size = 6;
81 info->nr_samples = 0;
82 info->bind = PIPE_BIND_SAMPLER_VIEW;
83 info->usage = PIPE_USAGE_DEFAULT;
84 info->flags = 0;
85
86 if (Usage & D3DUSAGE_RENDERTARGET)
87 info->bind |= PIPE_BIND_RENDER_TARGET;
88 if (Usage & D3DUSAGE_DEPTHSTENCIL)
89 info->bind |= PIPE_BIND_DEPTH_STENCIL;
90
91 if (Usage & D3DUSAGE_DYNAMIC) {
92 info->usage = PIPE_USAGE_DYNAMIC;
93 info->bind |=
94 PIPE_BIND_TRANSFER_READ |
95 PIPE_BIND_TRANSFER_WRITE;
96 }
97
98 This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces));
99 if (!This->surfaces)
100 return E_OUTOFMEMORY;
101
102 hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE,
103 Format, Pool, Usage);
104 if (FAILED(hr))
105 return hr;
106 This->base.pstype = 2;
107
108 /* Create all the surfaces right away.
109 * They manage backing storage, and transfers (LockRect) are deferred
110 * to them.
111 */
112 sfdesc.Format = Format;
113 sfdesc.Type = D3DRTYPE_SURFACE;
114 sfdesc.Usage = Usage;
115 sfdesc.Pool = Pool;
116 sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
117 sfdesc.MultiSampleQuality = 0;
118 for (i = 0; i < (info->last_level + 1) * 6; ++i) {
119 sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, i / 6);
120
121 hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
122 This->base.base.resource, NULL, D3DRTYPE_CUBETEXTURE,
123 i / 6, i % 6,
124 &sfdesc, &This->surfaces[i]);
125 if (FAILED(hr))
126 return hr;
127 }
128 for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
129 This->dirty_rect[i].depth = 1;
130
131 return D3D_OK;
132 }
133
134 static void
135 NineCubeTexture9_dtor( struct NineCubeTexture9 *This )
136 {
137 unsigned i;
138
139 DBG("This=%p\n", This);
140
141 if (This->surfaces) {
142 for (i = 0; i < This->base.base.info.last_level * 6; ++i)
143 NineUnknown_Destroy(&This->surfaces[i]->base.base);
144 FREE(This->surfaces);
145 }
146
147 NineBaseTexture9_dtor(&This->base);
148 }
149
150 HRESULT WINAPI
151 NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
152 UINT Level,
153 D3DSURFACE_DESC *pDesc )
154 {
155 DBG("This=%p Level=%u pDesc=%p\n", This, Level, pDesc);
156
157 user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
158 user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
159 D3DERR_INVALIDCALL);
160
161 *pDesc = This->surfaces[Level * 6]->desc;
162
163 return D3D_OK;
164 }
165
166 HRESULT WINAPI
167 NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
168 D3DCUBEMAP_FACES FaceType,
169 UINT Level,
170 IDirect3DSurface9 **ppCubeMapSurface )
171 {
172 const unsigned s = Level * 6 + FaceType;
173
174 DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n",
175 This, FaceType, Level, ppCubeMapSurface);
176
177 user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
178 user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
179 D3DERR_INVALIDCALL);
180 user_assert(FaceType < 6, D3DERR_INVALIDCALL);
181
182 NineUnknown_AddRef(NineUnknown(This->surfaces[s]));
183 *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s];
184
185 return D3D_OK;
186 }
187
188 HRESULT WINAPI
189 NineCubeTexture9_LockRect( struct NineCubeTexture9 *This,
190 D3DCUBEMAP_FACES FaceType,
191 UINT Level,
192 D3DLOCKED_RECT *pLockedRect,
193 const RECT *pRect,
194 DWORD Flags )
195 {
196 const unsigned s = Level * 6 + FaceType;
197
198 DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n",
199 This, FaceType, Level, pLockedRect, pRect, Flags);
200
201 user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
202 user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
203 D3DERR_INVALIDCALL);
204 user_assert(FaceType < 6, D3DERR_INVALIDCALL);
205
206 return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags);
207 }
208
209 HRESULT WINAPI
210 NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
211 D3DCUBEMAP_FACES FaceType,
212 UINT Level )
213 {
214 const unsigned s = Level * 6 + FaceType;
215
216 DBG("This=%p FaceType=%d Level=%u\n", This, FaceType, Level);
217
218 user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
219 user_assert(FaceType < 6, D3DERR_INVALIDCALL);
220
221 return NineSurface9_UnlockRect(This->surfaces[s]);
222 }
223
224 HRESULT WINAPI
225 NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
226 D3DCUBEMAP_FACES FaceType,
227 const RECT *pDirtyRect )
228 {
229 DBG("This=%p FaceType=%d pDirtyRect=%p\n", This, FaceType, pDirtyRect);
230
231 user_assert(FaceType < 6, D3DERR_INVALIDCALL);
232
233 if (This->base.base.pool != D3DPOOL_MANAGED) {
234 if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
235 This->base.dirty_mip = TRUE;
236 return D3D_OK;
237 }
238 This->base.dirty = TRUE;
239
240 BASETEX_REGISTER_UPDATE(&This->base);
241
242 if (!pDirtyRect) {
243 u_box_origin_2d(This->base.base.info.width0,
244 This->base.base.info.height0,
245 &This->dirty_rect[FaceType]);
246 } else {
247 struct pipe_box box;
248 rect_to_pipe_box_clamp(&box, pDirtyRect);
249 u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType],
250 &box);
251 }
252 return D3D_OK;
253 }
254
255 IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = {
256 (void *)NineUnknown_QueryInterface,
257 (void *)NineUnknown_AddRef,
258 (void *)NineUnknown_Release,
259 (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
260 (void *)NineResource9_SetPrivateData,
261 (void *)NineResource9_GetPrivateData,
262 (void *)NineResource9_FreePrivateData,
263 (void *)NineResource9_SetPriority,
264 (void *)NineResource9_GetPriority,
265 (void *)NineBaseTexture9_PreLoad,
266 (void *)NineResource9_GetType,
267 (void *)NineBaseTexture9_SetLOD,
268 (void *)NineBaseTexture9_GetLOD,
269 (void *)NineBaseTexture9_GetLevelCount,
270 (void *)NineBaseTexture9_SetAutoGenFilterType,
271 (void *)NineBaseTexture9_GetAutoGenFilterType,
272 (void *)NineBaseTexture9_GenerateMipSubLevels,
273 (void *)NineCubeTexture9_GetLevelDesc,
274 (void *)NineCubeTexture9_GetCubeMapSurface,
275 (void *)NineCubeTexture9_LockRect,
276 (void *)NineCubeTexture9_UnlockRect,
277 (void *)NineCubeTexture9_AddDirtyRect
278 };
279
280 static const GUID *NineCubeTexture9_IIDs[] = {
281 &IID_IDirect3DCubeTexture9,
282 &IID_IDirect3DBaseTexture9,
283 &IID_IDirect3DResource9,
284 &IID_IUnknown,
285 NULL
286 };
287
288 HRESULT
289 NineCubeTexture9_new( struct NineDevice9 *pDevice,
290 UINT EdgeLength, UINT Levels,
291 DWORD Usage,
292 D3DFORMAT Format,
293 D3DPOOL Pool,
294 struct NineCubeTexture9 **ppOut,
295 HANDLE *pSharedHandle )
296 {
297 NINE_DEVICE_CHILD_NEW(CubeTexture9, ppOut, pDevice,
298 EdgeLength, Levels,
299 Usage, Format, Pool, pSharedHandle);
300 }