2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
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:
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
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. */
23 #include "c99_alloca.h"
26 #include "cubetexture9.h"
27 #include "nine_helpers.h"
28 #include "nine_pipe.h"
30 #define DBG_CHANNEL DBG_CUBETEXTURE
34 NineCubeTexture9_ctor( struct NineCubeTexture9
*This
,
35 struct NineUnknownParams
*pParams
,
36 UINT EdgeLength
, UINT Levels
,
40 HANDLE
*pSharedHandle
)
42 struct pipe_resource
*info
= &This
->base
.base
.info
;
43 struct pipe_screen
*screen
= pParams
->device
->screen
;
45 unsigned i
, l
, f
, offset
, face_size
= 0;
46 unsigned *level_offsets
= NULL
;
47 D3DSURFACE_DESC sfdesc
;
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
);
56 user_assert(EdgeLength
, D3DERR_INVALIDCALL
);
58 /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */
59 user_assert(!pSharedHandle
, D3DERR_INVALIDCALL
); /* TODO */
61 user_assert(!(Usage
& D3DUSAGE_AUTOGENMIPMAP
) ||
62 (Pool
!= D3DPOOL_SYSTEMMEM
&& Levels
<= 1), D3DERR_INVALIDCALL
);
64 if (Usage
& D3DUSAGE_AUTOGENMIPMAP
)
67 pf
= d3d9_to_pipe_format_checked(screen
, Format
, PIPE_TEXTURE_CUBE
, 0,
68 PIPE_BIND_SAMPLER_VIEW
, FALSE
,
69 Pool
== D3DPOOL_SCRATCH
);
71 if (pf
== PIPE_FORMAT_NONE
)
72 return D3DERR_INVALIDCALL
;
74 if (compressed_format(Format
)) {
75 const unsigned w
= util_format_get_blockwidth(pf
);
76 const unsigned h
= util_format_get_blockheight(pf
);
78 user_assert(!(EdgeLength
% w
) && !(EdgeLength
% h
), D3DERR_INVALIDCALL
);
81 info
->screen
= pParams
->device
->screen
;
82 info
->target
= PIPE_TEXTURE_CUBE
;
84 info
->width0
= EdgeLength
;
85 info
->height0
= EdgeLength
;
88 info
->last_level
= Levels
- 1;
90 info
->last_level
= util_logbase2(EdgeLength
);
93 info
->nr_storage_samples
= 0;
94 info
->bind
= PIPE_BIND_SAMPLER_VIEW
;
95 info
->usage
= PIPE_USAGE_DEFAULT
;
98 if (Usage
& D3DUSAGE_RENDERTARGET
)
99 info
->bind
|= PIPE_BIND_RENDER_TARGET
;
100 if (Usage
& D3DUSAGE_DEPTHSTENCIL
)
101 info
->bind
|= PIPE_BIND_DEPTH_STENCIL
;
103 if (Usage
& D3DUSAGE_DYNAMIC
) {
104 info
->usage
= PIPE_USAGE_DYNAMIC
;
106 if (Usage
& D3DUSAGE_SOFTWAREPROCESSING
)
107 DBG("Application asked for Software Vertex Processing, "
108 "but this is unimplemented\n");
110 if (Pool
!= D3DPOOL_DEFAULT
) {
111 level_offsets
= alloca(sizeof(unsigned) * (info
->last_level
+ 1));
112 face_size
= nine_format_get_size_and_offsets(pf
, level_offsets
,
113 EdgeLength
, EdgeLength
,
115 This
->managed_buffer
= align_calloc(6 * face_size
, 32);
116 if (!This
->managed_buffer
)
117 return E_OUTOFMEMORY
;
120 This
->surfaces
= CALLOC(6 * (info
->last_level
+ 1), sizeof(*This
->surfaces
));
122 return E_OUTOFMEMORY
;
124 hr
= NineBaseTexture9_ctor(&This
->base
, pParams
, NULL
, D3DRTYPE_CUBETEXTURE
,
125 Format
, Pool
, Usage
);
128 This
->base
.pstype
= 2;
130 /* Create all the surfaces right away.
131 * They manage backing storage, and transfers (LockRect) are deferred
134 sfdesc
.Format
= Format
;
135 sfdesc
.Type
= D3DRTYPE_SURFACE
;
136 sfdesc
.Usage
= Usage
;
138 sfdesc
.MultiSampleType
= D3DMULTISAMPLE_NONE
;
139 sfdesc
.MultiSampleQuality
= 0;
140 /* We allocate the memory for the surfaces as continous blocks.
141 * This is the expected behaviour, however we haven't tested for
142 * cube textures in which order the faces/levels should be in memory
144 for (f
= 0; f
< 6; f
++) {
145 offset
= f
* face_size
;
146 for (l
= 0; l
<= info
->last_level
; l
++) {
147 sfdesc
.Width
= sfdesc
.Height
= u_minify(EdgeLength
, l
);
148 p
= This
->managed_buffer
? This
->managed_buffer
+ offset
+
149 level_offsets
[l
] : NULL
;
151 hr
= NineSurface9_new(This
->base
.base
.base
.device
, NineUnknown(This
),
152 This
->base
.base
.resource
, p
, D3DRTYPE_CUBETEXTURE
,
153 l
, f
, &sfdesc
, &This
->surfaces
[f
+ 6 * l
]);
159 for (i
= 0; i
< 6; ++i
) {
160 /* Textures start initially dirty */
161 This
->dirty_rect
[i
].width
= EdgeLength
;
162 This
->dirty_rect
[i
].height
= EdgeLength
;
163 This
->dirty_rect
[i
].depth
= 1;
170 NineCubeTexture9_dtor( struct NineCubeTexture9
*This
)
174 DBG("This=%p\n", This
);
176 if (This
->surfaces
) {
177 for (i
= 0; i
< (This
->base
.base
.info
.last_level
+ 1) * 6; ++i
)
178 NineUnknown_Destroy(&This
->surfaces
[i
]->base
.base
);
179 FREE(This
->surfaces
);
182 if (This
->managed_buffer
)
183 align_free(This
->managed_buffer
);
185 NineBaseTexture9_dtor(&This
->base
);
189 NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9
*This
,
191 D3DSURFACE_DESC
*pDesc
)
193 DBG("This=%p Level=%u pDesc=%p\n", This
, Level
, pDesc
);
195 user_assert(Level
<= This
->base
.base
.info
.last_level
, D3DERR_INVALIDCALL
);
196 user_assert(Level
== 0 || !(This
->base
.base
.usage
& D3DUSAGE_AUTOGENMIPMAP
),
199 *pDesc
= This
->surfaces
[Level
* 6]->desc
;
205 NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9
*This
,
206 D3DCUBEMAP_FACES FaceType
,
208 IDirect3DSurface9
**ppCubeMapSurface
)
210 const unsigned s
= Level
* 6 + FaceType
;
212 DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n",
213 This
, FaceType
, Level
, ppCubeMapSurface
);
215 user_assert(Level
<= This
->base
.base
.info
.last_level
, D3DERR_INVALIDCALL
);
216 user_assert(Level
== 0 || !(This
->base
.base
.usage
& D3DUSAGE_AUTOGENMIPMAP
),
218 user_assert(FaceType
< 6, D3DERR_INVALIDCALL
);
220 NineUnknown_AddRef(NineUnknown(This
->surfaces
[s
]));
221 *ppCubeMapSurface
= (IDirect3DSurface9
*)This
->surfaces
[s
];
227 NineCubeTexture9_LockRect( struct NineCubeTexture9
*This
,
228 D3DCUBEMAP_FACES FaceType
,
230 D3DLOCKED_RECT
*pLockedRect
,
234 const unsigned s
= Level
* 6 + FaceType
;
236 DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n",
237 This
, FaceType
, Level
, pLockedRect
, pRect
, Flags
);
239 user_assert(Level
<= This
->base
.base
.info
.last_level
, D3DERR_INVALIDCALL
);
240 user_assert(Level
== 0 || !(This
->base
.base
.usage
& D3DUSAGE_AUTOGENMIPMAP
),
242 user_assert(FaceType
< 6, D3DERR_INVALIDCALL
);
244 return NineSurface9_LockRect(This
->surfaces
[s
], pLockedRect
, pRect
, Flags
);
248 NineCubeTexture9_UnlockRect( struct NineCubeTexture9
*This
,
249 D3DCUBEMAP_FACES FaceType
,
252 const unsigned s
= Level
* 6 + FaceType
;
254 DBG("This=%p FaceType=%d Level=%u\n", This
, FaceType
, Level
);
256 user_assert(Level
<= This
->base
.base
.info
.last_level
, D3DERR_INVALIDCALL
);
257 user_assert(FaceType
< 6, D3DERR_INVALIDCALL
);
259 return NineSurface9_UnlockRect(This
->surfaces
[s
]);
263 NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9
*This
,
264 D3DCUBEMAP_FACES FaceType
,
265 const RECT
*pDirtyRect
)
267 DBG("This=%p FaceType=%d pDirtyRect=%p\n", This
, FaceType
, pDirtyRect
);
269 user_assert(FaceType
< 6, D3DERR_INVALIDCALL
);
271 if (This
->base
.base
.pool
!= D3DPOOL_MANAGED
) {
272 if (This
->base
.base
.usage
& D3DUSAGE_AUTOGENMIPMAP
) {
273 This
->base
.dirty_mip
= TRUE
;
274 BASETEX_REGISTER_UPDATE(&This
->base
);
279 if (This
->base
.base
.pool
== D3DPOOL_MANAGED
) {
280 This
->base
.managed
.dirty
= TRUE
;
281 BASETEX_REGISTER_UPDATE(&This
->base
);
285 u_box_origin_2d(This
->base
.base
.info
.width0
,
286 This
->base
.base
.info
.height0
,
287 &This
->dirty_rect
[FaceType
]);
289 if (This
->dirty_rect
[FaceType
].width
== 0) {
290 rect_to_pipe_box_clamp(&This
->dirty_rect
[FaceType
], pDirtyRect
);
293 rect_to_pipe_box_clamp(&box
, pDirtyRect
);
294 u_box_union_2d(&This
->dirty_rect
[FaceType
], &This
->dirty_rect
[FaceType
],
297 (void) u_box_clip_2d(&This
->dirty_rect
[FaceType
],
298 &This
->dirty_rect
[FaceType
],
299 This
->base
.base
.info
.width0
,
300 This
->base
.base
.info
.height0
);
305 IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable
= {
306 (void *)NineUnknown_QueryInterface
,
307 (void *)NineUnknown_AddRef
,
308 (void *)NineUnknown_Release
,
309 (void *)NineUnknown_GetDevice
, /* actually part of Resource9 iface */
310 (void *)NineUnknown_SetPrivateData
,
311 (void *)NineUnknown_GetPrivateData
,
312 (void *)NineUnknown_FreePrivateData
,
313 (void *)NineResource9_SetPriority
,
314 (void *)NineResource9_GetPriority
,
315 (void *)NineBaseTexture9_PreLoad
,
316 (void *)NineResource9_GetType
,
317 (void *)NineBaseTexture9_SetLOD
,
318 (void *)NineBaseTexture9_GetLOD
,
319 (void *)NineBaseTexture9_GetLevelCount
,
320 (void *)NineBaseTexture9_SetAutoGenFilterType
,
321 (void *)NineBaseTexture9_GetAutoGenFilterType
,
322 (void *)NineBaseTexture9_GenerateMipSubLevels
,
323 (void *)NineCubeTexture9_GetLevelDesc
,
324 (void *)NineCubeTexture9_GetCubeMapSurface
,
325 (void *)NineCubeTexture9_LockRect
,
326 (void *)NineCubeTexture9_UnlockRect
,
327 (void *)NineCubeTexture9_AddDirtyRect
330 static const GUID
*NineCubeTexture9_IIDs
[] = {
331 &IID_IDirect3DCubeTexture9
,
332 &IID_IDirect3DBaseTexture9
,
333 &IID_IDirect3DResource9
,
339 NineCubeTexture9_new( struct NineDevice9
*pDevice
,
340 UINT EdgeLength
, UINT Levels
,
344 struct NineCubeTexture9
**ppOut
,
345 HANDLE
*pSharedHandle
)
347 NINE_DEVICE_CHILD_NEW(CubeTexture9
, ppOut
, pDevice
,
349 Usage
, Format
, Pool
, pSharedHandle
);