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