1b8e80941Smrg/* 2b8e80941Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 8b8e80941Smrg * license, and/or sell copies of the Software, and to permit persons to whom 9b8e80941Smrg * the Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19b8e80941Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20b8e80941Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21b8e80941Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22b8e80941Smrg 23b8e80941Smrg#include "device9.h" 24b8e80941Smrg#include "volumetexture9.h" 25b8e80941Smrg#include "nine_helpers.h" 26b8e80941Smrg#include "nine_pipe.h" 27b8e80941Smrg 28b8e80941Smrg#define DBG_CHANNEL DBG_VOLUMETEXTURE 29b8e80941Smrg 30b8e80941Smrgstatic HRESULT 31b8e80941SmrgNineVolumeTexture9_ctor( struct NineVolumeTexture9 *This, 32b8e80941Smrg struct NineUnknownParams *pParams, 33b8e80941Smrg UINT Width, UINT Height, UINT Depth, UINT Levels, 34b8e80941Smrg DWORD Usage, 35b8e80941Smrg D3DFORMAT Format, 36b8e80941Smrg D3DPOOL Pool, 37b8e80941Smrg HANDLE *pSharedHandle ) 38b8e80941Smrg{ 39b8e80941Smrg struct pipe_resource *info = &This->base.base.info; 40b8e80941Smrg struct pipe_screen *screen = pParams->device->screen; 41b8e80941Smrg enum pipe_format pf; 42b8e80941Smrg unsigned l; 43b8e80941Smrg D3DVOLUME_DESC voldesc; 44b8e80941Smrg HRESULT hr; 45b8e80941Smrg 46b8e80941Smrg DBG("This=%p pParams=%p Width=%u Height=%u Depth=%u Levels=%u " 47b8e80941Smrg "Usage=%d Format=%d Pool=%d pSharedHandle=%p\n", 48b8e80941Smrg This, pParams, Width, Height, Depth, Levels, 49b8e80941Smrg Usage, Format, Pool, pSharedHandle); 50b8e80941Smrg 51b8e80941Smrg user_assert(Width && Height && Depth, D3DERR_INVALIDCALL); 52b8e80941Smrg 53b8e80941Smrg /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ 54b8e80941Smrg user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ 55b8e80941Smrg 56b8e80941Smrg /* An IDirect3DVolume9 cannot be bound as a render target can it ? */ 57b8e80941Smrg user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)), 58b8e80941Smrg D3DERR_INVALIDCALL); 59b8e80941Smrg user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); 60b8e80941Smrg 61b8e80941Smrg pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_3D, 0, 62b8e80941Smrg PIPE_BIND_SAMPLER_VIEW, FALSE, 63b8e80941Smrg Pool == D3DPOOL_SCRATCH); 64b8e80941Smrg 65b8e80941Smrg if (pf == PIPE_FORMAT_NONE) 66b8e80941Smrg return D3DERR_INVALIDCALL; 67b8e80941Smrg 68b8e80941Smrg /* We support ATI1 and ATI2 hacks only for 2D and Cube textures */ 69b8e80941Smrg if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2) 70b8e80941Smrg return D3DERR_INVALIDCALL; 71b8e80941Smrg 72b8e80941Smrg if (compressed_format(Format)) { 73b8e80941Smrg const unsigned w = util_format_get_blockwidth(pf); 74b8e80941Smrg const unsigned h = util_format_get_blockheight(pf); 75b8e80941Smrg /* Compressed formats are not compressed on depth component */ 76b8e80941Smrg user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); 77b8e80941Smrg } 78b8e80941Smrg 79b8e80941Smrg info->screen = pParams->device->screen; 80b8e80941Smrg info->target = PIPE_TEXTURE_3D; 81b8e80941Smrg info->format = pf; 82b8e80941Smrg info->width0 = Width; 83b8e80941Smrg info->height0 = Height; 84b8e80941Smrg info->depth0 = Depth; 85b8e80941Smrg if (Levels) 86b8e80941Smrg info->last_level = Levels - 1; 87b8e80941Smrg else 88b8e80941Smrg info->last_level = util_logbase2(MAX2(MAX2(Width, Height), Depth)); 89b8e80941Smrg info->array_size = 1; 90b8e80941Smrg info->nr_samples = 0; 91b8e80941Smrg info->nr_storage_samples = 0; 92b8e80941Smrg info->bind = PIPE_BIND_SAMPLER_VIEW; 93b8e80941Smrg info->usage = PIPE_USAGE_DEFAULT; 94b8e80941Smrg info->flags = 0; 95b8e80941Smrg 96b8e80941Smrg if (Usage & D3DUSAGE_DYNAMIC) { 97b8e80941Smrg info->usage = PIPE_USAGE_DYNAMIC; 98b8e80941Smrg } 99b8e80941Smrg if (Usage & D3DUSAGE_SOFTWAREPROCESSING) 100b8e80941Smrg DBG("Application asked for Software Vertex Processing, " 101b8e80941Smrg "but this is unimplemented\n"); 102b8e80941Smrg 103b8e80941Smrg This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes)); 104b8e80941Smrg if (!This->volumes) 105b8e80941Smrg return E_OUTOFMEMORY; 106b8e80941Smrg This->base.pstype = 3; 107b8e80941Smrg 108b8e80941Smrg hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, 109b8e80941Smrg D3DRTYPE_VOLUMETEXTURE, Format, Pool, Usage); 110b8e80941Smrg if (FAILED(hr)) 111b8e80941Smrg return hr; 112b8e80941Smrg 113b8e80941Smrg voldesc.Format = Format; 114b8e80941Smrg voldesc.Type = D3DRTYPE_VOLUME; 115b8e80941Smrg voldesc.Usage = Usage; 116b8e80941Smrg voldesc.Pool = Pool; 117b8e80941Smrg for (l = 0; l <= info->last_level; ++l) { 118b8e80941Smrg voldesc.Width = u_minify(Width, l); 119b8e80941Smrg voldesc.Height = u_minify(Height, l); 120b8e80941Smrg voldesc.Depth = u_minify(Depth, l); 121b8e80941Smrg 122b8e80941Smrg hr = NineVolume9_new(This->base.base.base.device, NineUnknown(This), 123b8e80941Smrg This->base.base.resource, l, 124b8e80941Smrg &voldesc, &This->volumes[l]); 125b8e80941Smrg if (FAILED(hr)) 126b8e80941Smrg return hr; 127b8e80941Smrg } 128b8e80941Smrg 129b8e80941Smrg /* Textures start initially dirty */ 130b8e80941Smrg NineVolumeTexture9_AddDirtyBox(This, NULL); 131b8e80941Smrg 132b8e80941Smrg return D3D_OK; 133b8e80941Smrg} 134b8e80941Smrg 135b8e80941Smrgstatic void 136b8e80941SmrgNineVolumeTexture9_dtor( struct NineVolumeTexture9 *This ) 137b8e80941Smrg{ 138b8e80941Smrg unsigned l; 139b8e80941Smrg 140b8e80941Smrg DBG("This=%p\n", This); 141b8e80941Smrg 142b8e80941Smrg if (This->volumes) { 143b8e80941Smrg for (l = 0; l <= This->base.base.info.last_level; ++l) 144b8e80941Smrg if (This->volumes[l]) 145b8e80941Smrg NineUnknown_Destroy(&This->volumes[l]->base); 146b8e80941Smrg FREE(This->volumes); 147b8e80941Smrg } 148b8e80941Smrg 149b8e80941Smrg NineBaseTexture9_dtor(&This->base); 150b8e80941Smrg} 151b8e80941Smrg 152b8e80941SmrgHRESULT NINE_WINAPI 153b8e80941SmrgNineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, 154b8e80941Smrg UINT Level, 155b8e80941Smrg D3DVOLUME_DESC *pDesc ) 156b8e80941Smrg{ 157b8e80941Smrg user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); 158b8e80941Smrg 159b8e80941Smrg *pDesc = This->volumes[Level]->desc; 160b8e80941Smrg 161b8e80941Smrg return D3D_OK; 162b8e80941Smrg} 163b8e80941Smrg 164b8e80941SmrgHRESULT NINE_WINAPI 165b8e80941SmrgNineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, 166b8e80941Smrg UINT Level, 167b8e80941Smrg IDirect3DVolume9 **ppVolumeLevel ) 168b8e80941Smrg{ 169b8e80941Smrg user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); 170b8e80941Smrg 171b8e80941Smrg NineUnknown_AddRef(NineUnknown(This->volumes[Level])); 172b8e80941Smrg *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level]; 173b8e80941Smrg 174b8e80941Smrg return D3D_OK; 175b8e80941Smrg} 176b8e80941Smrg 177b8e80941SmrgHRESULT NINE_WINAPI 178b8e80941SmrgNineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, 179b8e80941Smrg UINT Level, 180b8e80941Smrg D3DLOCKED_BOX *pLockedVolume, 181b8e80941Smrg const D3DBOX *pBox, 182b8e80941Smrg DWORD Flags ) 183b8e80941Smrg{ 184b8e80941Smrg DBG("This=%p Level=%u pLockedVolume=%p pBox=%p Flags=%d\n", 185b8e80941Smrg This, Level, pLockedVolume, pBox, Flags); 186b8e80941Smrg 187b8e80941Smrg user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); 188b8e80941Smrg 189b8e80941Smrg return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox, 190b8e80941Smrg Flags); 191b8e80941Smrg} 192b8e80941Smrg 193b8e80941SmrgHRESULT NINE_WINAPI 194b8e80941SmrgNineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, 195b8e80941Smrg UINT Level ) 196b8e80941Smrg{ 197b8e80941Smrg DBG("This=%p Level=%u\n", This, Level); 198b8e80941Smrg 199b8e80941Smrg user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); 200b8e80941Smrg 201b8e80941Smrg return NineVolume9_UnlockBox(This->volumes[Level]); 202b8e80941Smrg} 203b8e80941Smrg 204b8e80941SmrgHRESULT NINE_WINAPI 205b8e80941SmrgNineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, 206b8e80941Smrg const D3DBOX *pDirtyBox ) 207b8e80941Smrg{ 208b8e80941Smrg DBG("This=%p pDirtybox=%p\n", This, pDirtyBox); 209b8e80941Smrg 210b8e80941Smrg if (This->base.base.pool == D3DPOOL_DEFAULT) { 211b8e80941Smrg return D3D_OK; 212b8e80941Smrg } 213b8e80941Smrg 214b8e80941Smrg if (This->base.base.pool == D3DPOOL_MANAGED) { 215b8e80941Smrg This->base.managed.dirty = TRUE; 216b8e80941Smrg BASETEX_REGISTER_UPDATE(&This->base); 217b8e80941Smrg } 218b8e80941Smrg 219b8e80941Smrg if (!pDirtyBox) { 220b8e80941Smrg This->dirty_box.x = 0; 221b8e80941Smrg This->dirty_box.y = 0; 222b8e80941Smrg This->dirty_box.z = 0; 223b8e80941Smrg This->dirty_box.width = This->base.base.info.width0; 224b8e80941Smrg This->dirty_box.height = This->base.base.info.height0; 225b8e80941Smrg This->dirty_box.depth = This->base.base.info.depth0; 226b8e80941Smrg } else { 227b8e80941Smrg if (This->dirty_box.width == 0) { 228b8e80941Smrg d3dbox_to_pipe_box(&This->dirty_box, pDirtyBox); 229b8e80941Smrg } else { 230b8e80941Smrg struct pipe_box box; 231b8e80941Smrg d3dbox_to_pipe_box(&box, pDirtyBox); 232b8e80941Smrg u_box_union_3d(&This->dirty_box, &This->dirty_box, &box); 233b8e80941Smrg } 234b8e80941Smrg This->dirty_box.x = MAX2(This->dirty_box.x, 0); 235b8e80941Smrg This->dirty_box.y = MAX2(This->dirty_box.y, 0); 236b8e80941Smrg This->dirty_box.z = MAX2(This->dirty_box.z, 0); 237b8e80941Smrg This->dirty_box.width = MIN2(This->dirty_box.width, 238b8e80941Smrg This->base.base.info.width0 - This->dirty_box.x); 239b8e80941Smrg This->dirty_box.height = MIN2(This->dirty_box.height, 240b8e80941Smrg This->base.base.info.height0 - This->dirty_box.y); 241b8e80941Smrg This->dirty_box.depth = MIN2(This->dirty_box.depth, 242b8e80941Smrg This->base.base.info.depth0 - This->dirty_box.z); 243b8e80941Smrg } 244b8e80941Smrg return D3D_OK; 245b8e80941Smrg} 246b8e80941Smrg 247b8e80941SmrgIDirect3DVolumeTexture9Vtbl NineVolumeTexture9_vtable = { 248b8e80941Smrg (void *)NineUnknown_QueryInterface, 249b8e80941Smrg (void *)NineUnknown_AddRef, 250b8e80941Smrg (void *)NineUnknown_Release, 251b8e80941Smrg (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ 252b8e80941Smrg (void *)NineUnknown_SetPrivateData, 253b8e80941Smrg (void *)NineUnknown_GetPrivateData, 254b8e80941Smrg (void *)NineUnknown_FreePrivateData, 255b8e80941Smrg (void *)NineResource9_SetPriority, 256b8e80941Smrg (void *)NineResource9_GetPriority, 257b8e80941Smrg (void *)NineBaseTexture9_PreLoad, 258b8e80941Smrg (void *)NineResource9_GetType, 259b8e80941Smrg (void *)NineBaseTexture9_SetLOD, 260b8e80941Smrg (void *)NineBaseTexture9_GetLOD, 261b8e80941Smrg (void *)NineBaseTexture9_GetLevelCount, 262b8e80941Smrg (void *)NineBaseTexture9_SetAutoGenFilterType, 263b8e80941Smrg (void *)NineBaseTexture9_GetAutoGenFilterType, 264b8e80941Smrg (void *)NineBaseTexture9_GenerateMipSubLevels, 265b8e80941Smrg (void *)NineVolumeTexture9_GetLevelDesc, 266b8e80941Smrg (void *)NineVolumeTexture9_GetVolumeLevel, 267b8e80941Smrg (void *)NineVolumeTexture9_LockBox, 268b8e80941Smrg (void *)NineVolumeTexture9_UnlockBox, 269b8e80941Smrg (void *)NineVolumeTexture9_AddDirtyBox 270b8e80941Smrg}; 271b8e80941Smrg 272b8e80941Smrgstatic const GUID *NineVolumeTexture9_IIDs[] = { 273b8e80941Smrg &IID_IDirect3DVolumeTexture9, 274b8e80941Smrg &IID_IDirect3DBaseTexture9, 275b8e80941Smrg &IID_IDirect3DResource9, 276b8e80941Smrg &IID_IUnknown, 277b8e80941Smrg NULL 278b8e80941Smrg}; 279b8e80941Smrg 280b8e80941SmrgHRESULT 281b8e80941SmrgNineVolumeTexture9_new( struct NineDevice9 *pDevice, 282b8e80941Smrg UINT Width, UINT Height, UINT Depth, UINT Levels, 283b8e80941Smrg DWORD Usage, 284b8e80941Smrg D3DFORMAT Format, 285b8e80941Smrg D3DPOOL Pool, 286b8e80941Smrg struct NineVolumeTexture9 **ppOut, 287b8e80941Smrg HANDLE *pSharedHandle ) 288b8e80941Smrg{ 289b8e80941Smrg NINE_DEVICE_CHILD_NEW(VolumeTexture9, ppOut, pDevice, 290b8e80941Smrg Width, Height, Depth, Levels, 291b8e80941Smrg Usage, Format, Pool, pSharedHandle); 292b8e80941Smrg} 293b8e80941Smrg 294