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