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 "basetexture9.h" 24bf215546Sopenharmony_ci#include "device9.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci/* For UploadSelf: */ 27bf215546Sopenharmony_ci#include "texture9.h" 28bf215546Sopenharmony_ci#include "cubetexture9.h" 29bf215546Sopenharmony_ci#include "volumetexture9.h" 30bf215546Sopenharmony_ci#include "nine_pipe.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#if defined(DEBUG) || !defined(NDEBUG) 33bf215546Sopenharmony_ci#include "nine_dump.h" 34bf215546Sopenharmony_ci#endif 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "util/format/u_format.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#define DBG_CHANNEL DBG_BASETEXTURE 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ciHRESULT 41bf215546Sopenharmony_ciNineBaseTexture9_ctor( struct NineBaseTexture9 *This, 42bf215546Sopenharmony_ci struct NineUnknownParams *pParams, 43bf215546Sopenharmony_ci struct pipe_resource *initResource, 44bf215546Sopenharmony_ci D3DRESOURCETYPE Type, 45bf215546Sopenharmony_ci D3DFORMAT format, 46bf215546Sopenharmony_ci D3DPOOL Pool, 47bf215546Sopenharmony_ci DWORD Usage) 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci BOOL alloc = (Pool == D3DPOOL_DEFAULT) && !initResource && 50bf215546Sopenharmony_ci (format != D3DFMT_NULL); 51bf215546Sopenharmony_ci HRESULT hr; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci DBG("This=%p, pParams=%p initResource=%p Type=%d format=%d Pool=%d Usage=%d\n", 54bf215546Sopenharmony_ci This, pParams, initResource, Type, format, Pool, Usage); 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) || 57bf215546Sopenharmony_ci Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 58bf215546Sopenharmony_ci user_assert(!(Usage & D3DUSAGE_DYNAMIC) || 59bf215546Sopenharmony_ci !(Pool == D3DPOOL_MANAGED || 60bf215546Sopenharmony_ci Pool == D3DPOOL_SCRATCH), D3DERR_INVALIDCALL); 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci hr = NineResource9_ctor(&This->base, pParams, initResource, alloc, Type, Pool, Usage); 63bf215546Sopenharmony_ci if (FAILED(hr)) 64bf215546Sopenharmony_ci return hr; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci This->format = format; 67bf215546Sopenharmony_ci This->mipfilter = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? 68bf215546Sopenharmony_ci D3DTEXF_LINEAR : D3DTEXF_NONE; 69bf215546Sopenharmony_ci /* In the case of D3DUSAGE_AUTOGENMIPMAP, only the first level is accessible, 70bf215546Sopenharmony_ci * and thus needs a surface created. */ 71bf215546Sopenharmony_ci This->level_count = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? 1 : (This->base.info.last_level+1); 72bf215546Sopenharmony_ci This->managed.lod = 0; 73bf215546Sopenharmony_ci This->managed.lod_resident = -1; 74bf215546Sopenharmony_ci /* Mark the texture as dirty to trigger first upload when we need the texture, 75bf215546Sopenharmony_ci * even if it wasn't set by the application */ 76bf215546Sopenharmony_ci if (Pool == D3DPOOL_MANAGED) 77bf215546Sopenharmony_ci This->managed.dirty = TRUE; 78bf215546Sopenharmony_ci /* When a depth buffer is sampled, it is for shadow mapping, except for 79bf215546Sopenharmony_ci * D3DFMT_INTZ, D3DFMT_DF16 and D3DFMT_DF24. 80bf215546Sopenharmony_ci * In addition D3DFMT_INTZ can be used for both texturing and depth buffering 81bf215546Sopenharmony_ci * if z write is disabled. This particular feature may not work for us in 82bf215546Sopenharmony_ci * practice because OGL doesn't have that. However apparently it is known 83bf215546Sopenharmony_ci * some cards have performance issues with this feature, so real apps 84bf215546Sopenharmony_ci * shouldn't use it. */ 85bf215546Sopenharmony_ci This->shadow = (This->format != D3DFMT_INTZ && This->format != D3DFMT_DF16 && 86bf215546Sopenharmony_ci This->format != D3DFMT_DF24) && 87bf215546Sopenharmony_ci util_format_has_depth(util_format_description(This->base.info.format)); 88bf215546Sopenharmony_ci This->fetch4_compatible = fetch4_compatible_format(This->format); 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci list_inithead(&This->list); 91bf215546Sopenharmony_ci list_inithead(&This->list2); 92bf215546Sopenharmony_ci if (Pool == D3DPOOL_MANAGED) 93bf215546Sopenharmony_ci list_add(&This->list2, &This->base.base.device->managed_textures); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci return D3D_OK; 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_civoid 99bf215546Sopenharmony_ciNineBaseTexture9_dtor( struct NineBaseTexture9 *This ) 100bf215546Sopenharmony_ci{ 101bf215546Sopenharmony_ci DBG("This=%p\n", This); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci pipe_sampler_view_reference(&This->view[0], NULL); 104bf215546Sopenharmony_ci pipe_sampler_view_reference(&This->view[1], NULL); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (list_is_linked(&This->list)) 107bf215546Sopenharmony_ci list_del(&This->list); 108bf215546Sopenharmony_ci if (list_is_linked(&This->list2)) 109bf215546Sopenharmony_ci list_del(&This->list2); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci NineResource9_dtor(&This->base); 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ciDWORD NINE_WINAPI 115bf215546Sopenharmony_ciNineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, 116bf215546Sopenharmony_ci DWORD LODNew ) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci DWORD old = This->managed.lod; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci DBG("This=%p LODNew=%d\n", This, LODNew); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci user_assert(This->base.pool == D3DPOOL_MANAGED, 0); 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci This->managed.lod = MIN2(LODNew, This->level_count-1); 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci if (This->managed.lod != old && This->bind_count && list_is_empty(&This->list)) 127bf215546Sopenharmony_ci list_add(&This->list, &This->base.base.device->update_textures); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci return old; 130bf215546Sopenharmony_ci} 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ciDWORD NINE_WINAPI 133bf215546Sopenharmony_ciNineBaseTexture9_GetLOD( struct NineBaseTexture9 *This ) 134bf215546Sopenharmony_ci{ 135bf215546Sopenharmony_ci DBG("This=%p\n", This); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci return This->managed.lod; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ciDWORD NINE_WINAPI 141bf215546Sopenharmony_ciNineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci DBG("This=%p\n", This); 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci return This->level_count; 146bf215546Sopenharmony_ci} 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ciHRESULT NINE_WINAPI 149bf215546Sopenharmony_ciNineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, 150bf215546Sopenharmony_ci D3DTEXTUREFILTERTYPE FilterType ) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci DBG("This=%p FilterType=%d\n", This, FilterType); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci if (!(This->base.usage & D3DUSAGE_AUTOGENMIPMAP)) 155bf215546Sopenharmony_ci return D3D_OK; 156bf215546Sopenharmony_ci user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci This->mipfilter = FilterType; 159bf215546Sopenharmony_ci This->dirty_mip = TRUE; 160bf215546Sopenharmony_ci NineBaseTexture9_GenerateMipSubLevels(This); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci return D3D_OK; 163bf215546Sopenharmony_ci} 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ciD3DTEXTUREFILTERTYPE NINE_WINAPI 166bf215546Sopenharmony_ciNineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci DBG("This=%p\n", This); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci return This->mipfilter; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ciHRESULT 174bf215546Sopenharmony_ciNineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci HRESULT hr; 177bf215546Sopenharmony_ci unsigned l, min_level_dirty = This->managed.lod; 178bf215546Sopenharmony_ci BOOL update_lod; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci DBG("This=%p dirty=%i type=%s\n", This, This->managed.dirty, 181bf215546Sopenharmony_ci nine_D3DRTYPE_to_str(This->base.type)); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci assert(This->base.pool == D3DPOOL_MANAGED); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci update_lod = This->managed.lod_resident != This->managed.lod; 186bf215546Sopenharmony_ci if (!update_lod && !This->managed.dirty) 187bf215546Sopenharmony_ci return D3D_OK; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci /* Allocate a new resource with the correct number of levels, 190bf215546Sopenharmony_ci * Mark states for update, and tell the nine surfaces/volumes 191bf215546Sopenharmony_ci * their new resource. */ 192bf215546Sopenharmony_ci if (update_lod) { 193bf215546Sopenharmony_ci struct pipe_resource *res; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci DBG("updating LOD from %u to %u ...\n", This->managed.lod_resident, This->managed.lod); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci pipe_sampler_view_reference(&This->view[0], NULL); 198bf215546Sopenharmony_ci pipe_sampler_view_reference(&This->view[1], NULL); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci /* Allocate a new resource */ 201bf215546Sopenharmony_ci hr = NineBaseTexture9_CreatePipeResource(This, This->managed.lod_resident != -1); 202bf215546Sopenharmony_ci if (FAILED(hr)) 203bf215546Sopenharmony_ci return hr; 204bf215546Sopenharmony_ci res = This->base.resource; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci if (This->managed.lod_resident == -1) {/* no levels were resident */ 207bf215546Sopenharmony_ci This->managed.dirty = FALSE; /* We are going to upload everything. */ 208bf215546Sopenharmony_ci This->managed.lod_resident = This->level_count; 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_TEXTURE) { 212bf215546Sopenharmony_ci struct NineTexture9 *tex = NineTexture9(This); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* last content (if apply) has been copied to the new resource. 215bf215546Sopenharmony_ci * Note: We cannot render to surfaces of managed textures. 216bf215546Sopenharmony_ci * Note2: the level argument passed is to get the level offset 217bf215546Sopenharmony_ci * right when the texture is uploaded (the texture first level 218bf215546Sopenharmony_ci * corresponds to This->managed.lod). 219bf215546Sopenharmony_ci * Note3: We don't care about the value passed for the surfaces 220bf215546Sopenharmony_ci * before This->managed.lod, negative with this implementation. */ 221bf215546Sopenharmony_ci for (l = 0; l < This->level_count; ++l) 222bf215546Sopenharmony_ci NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); 223bf215546Sopenharmony_ci } else 224bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_CUBETEXTURE) { 225bf215546Sopenharmony_ci struct NineCubeTexture9 *tex = NineCubeTexture9(This); 226bf215546Sopenharmony_ci unsigned z; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci for (l = 0; l < This->level_count; ++l) { 229bf215546Sopenharmony_ci for (z = 0; z < 6; ++z) 230bf215546Sopenharmony_ci NineSurface9_SetResource(tex->surfaces[l * 6 + z], 231bf215546Sopenharmony_ci res, l - This->managed.lod); 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } else 234bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { 235bf215546Sopenharmony_ci struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci for (l = 0; l < This->level_count; ++l) 238bf215546Sopenharmony_ci NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); 239bf215546Sopenharmony_ci } else { 240bf215546Sopenharmony_ci assert(!"invalid texture type"); 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci /* We are going to fully upload the new levels, 244bf215546Sopenharmony_ci * no need to update dirty parts of the texture for these */ 245bf215546Sopenharmony_ci min_level_dirty = MAX2(This->managed.lod, This->managed.lod_resident); 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci /* Update dirty parts of the texture */ 249bf215546Sopenharmony_ci if (This->managed.dirty) { 250bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_TEXTURE) { 251bf215546Sopenharmony_ci struct NineTexture9 *tex = NineTexture9(This); 252bf215546Sopenharmony_ci struct pipe_box box; 253bf215546Sopenharmony_ci box.z = 0; 254bf215546Sopenharmony_ci box.depth = 1; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n", 257bf215546Sopenharmony_ci tex->dirty_rect.x, tex->dirty_rect.y, 258bf215546Sopenharmony_ci tex->dirty_rect.width, tex->dirty_rect.height); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci /* Note: for l < min_level_dirty, the resource is 261bf215546Sopenharmony_ci * either non-existing (and thus will be entirely re-uploaded 262bf215546Sopenharmony_ci * if the lod changes) or going to have a full upload */ 263bf215546Sopenharmony_ci if (tex->dirty_rect.width) { 264bf215546Sopenharmony_ci for (l = min_level_dirty; l < This->level_count; ++l) { 265bf215546Sopenharmony_ci u_box_minify_2d(&box, &tex->dirty_rect, l); 266bf215546Sopenharmony_ci NineSurface9_UploadSelf(tex->surfaces[l], &box); 267bf215546Sopenharmony_ci } 268bf215546Sopenharmony_ci memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect)); 269bf215546Sopenharmony_ci tex->dirty_rect.depth = 1; 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci } else 272bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_CUBETEXTURE) { 273bf215546Sopenharmony_ci struct NineCubeTexture9 *tex = NineCubeTexture9(This); 274bf215546Sopenharmony_ci unsigned z; 275bf215546Sopenharmony_ci struct pipe_box box; 276bf215546Sopenharmony_ci box.z = 0; 277bf215546Sopenharmony_ci box.depth = 1; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci for (z = 0; z < 6; ++z) { 280bf215546Sopenharmony_ci DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z, 281bf215546Sopenharmony_ci tex->dirty_rect[z].x, tex->dirty_rect[z].y, 282bf215546Sopenharmony_ci tex->dirty_rect[z].width, tex->dirty_rect[z].height); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci if (tex->dirty_rect[z].width) { 285bf215546Sopenharmony_ci for (l = min_level_dirty; l < This->level_count; ++l) { 286bf215546Sopenharmony_ci u_box_minify_2d(&box, &tex->dirty_rect[z], l); 287bf215546Sopenharmony_ci NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z])); 290bf215546Sopenharmony_ci tex->dirty_rect[z].depth = 1; 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci } else 294bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { 295bf215546Sopenharmony_ci struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); 296bf215546Sopenharmony_ci struct pipe_box box; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n", 299bf215546Sopenharmony_ci tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y, 300bf215546Sopenharmony_ci tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci if (tex->dirty_box.width) { 303bf215546Sopenharmony_ci for (l = min_level_dirty; l < This->level_count; ++l) { 304bf215546Sopenharmony_ci u_box_minify_3d(&box, &tex->dirty_box, l); 305bf215546Sopenharmony_ci NineVolume9_UploadSelf(tex->volumes[l], &box); 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci memset(&tex->dirty_box, 0, sizeof(tex->dirty_box)); 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci } else { 310bf215546Sopenharmony_ci assert(!"invalid texture type"); 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci This->managed.dirty = FALSE; 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci /* Upload the new levels */ 316bf215546Sopenharmony_ci if (update_lod) { 317bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_TEXTURE) { 318bf215546Sopenharmony_ci struct NineTexture9 *tex = NineTexture9(This); 319bf215546Sopenharmony_ci struct pipe_box box; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci box.x = box.y = box.z = 0; 322bf215546Sopenharmony_ci box.depth = 1; 323bf215546Sopenharmony_ci for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { 324bf215546Sopenharmony_ci box.width = u_minify(This->base.info.width0, l); 325bf215546Sopenharmony_ci box.height = u_minify(This->base.info.height0, l); 326bf215546Sopenharmony_ci NineSurface9_UploadSelf(tex->surfaces[l], &box); 327bf215546Sopenharmony_ci } 328bf215546Sopenharmony_ci } else 329bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_CUBETEXTURE) { 330bf215546Sopenharmony_ci struct NineCubeTexture9 *tex = NineCubeTexture9(This); 331bf215546Sopenharmony_ci struct pipe_box box; 332bf215546Sopenharmony_ci unsigned z; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci box.x = box.y = box.z = 0; 335bf215546Sopenharmony_ci box.depth = 1; 336bf215546Sopenharmony_ci for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { 337bf215546Sopenharmony_ci box.width = u_minify(This->base.info.width0, l); 338bf215546Sopenharmony_ci box.height = u_minify(This->base.info.height0, l); 339bf215546Sopenharmony_ci for (z = 0; z < 6; ++z) 340bf215546Sopenharmony_ci NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci } else 343bf215546Sopenharmony_ci if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { 344bf215546Sopenharmony_ci struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); 345bf215546Sopenharmony_ci struct pipe_box box; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci box.x = box.y = box.z = 0; 348bf215546Sopenharmony_ci for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { 349bf215546Sopenharmony_ci box.width = u_minify(This->base.info.width0, l); 350bf215546Sopenharmony_ci box.height = u_minify(This->base.info.height0, l); 351bf215546Sopenharmony_ci box.depth = u_minify(This->base.info.depth0, l); 352bf215546Sopenharmony_ci NineVolume9_UploadSelf(tex->volumes[l], &box); 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci } else { 355bf215546Sopenharmony_ci assert(!"invalid texture type"); 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci This->managed.lod_resident = This->managed.lod; 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) 362bf215546Sopenharmony_ci This->dirty_mip = TRUE; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci /* Set again the textures currently bound to update the texture data */ 365bf215546Sopenharmony_ci if (This->bind_count) { 366bf215546Sopenharmony_ci struct nine_state *state = &This->base.base.device->state; 367bf215546Sopenharmony_ci unsigned s; 368bf215546Sopenharmony_ci for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 369bf215546Sopenharmony_ci /* Dirty tracking is done in device9 state, not nine_context. */ 370bf215546Sopenharmony_ci if (state->texture[s] == This) 371bf215546Sopenharmony_ci nine_context_set_texture(This->base.base.device, s, This); 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci DBG("DONE, generate mip maps = %i\n", This->dirty_mip); 375bf215546Sopenharmony_ci return D3D_OK; 376bf215546Sopenharmony_ci} 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_civoid NINE_WINAPI 379bf215546Sopenharmony_ciNineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ) 380bf215546Sopenharmony_ci{ 381bf215546Sopenharmony_ci unsigned base_level = 0; 382bf215546Sopenharmony_ci unsigned last_level = This->base.info.last_level - This->managed.lod; 383bf215546Sopenharmony_ci unsigned first_layer = 0; 384bf215546Sopenharmony_ci unsigned last_layer; 385bf215546Sopenharmony_ci unsigned filter = This->mipfilter == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST 386bf215546Sopenharmony_ci : PIPE_TEX_FILTER_LINEAR; 387bf215546Sopenharmony_ci DBG("This=%p\n", This); 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci if (This->base.pool == D3DPOOL_MANAGED) 390bf215546Sopenharmony_ci NineBaseTexture9_UploadSelf(This); 391bf215546Sopenharmony_ci if (!This->dirty_mip) 392bf215546Sopenharmony_ci return; 393bf215546Sopenharmony_ci if (This->managed.lod) { 394bf215546Sopenharmony_ci ERR("AUTOGENMIPMAP if level 0 is not resident not supported yet !\n"); 395bf215546Sopenharmony_ci return; 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci if (!This->view[0]) 399bf215546Sopenharmony_ci NineBaseTexture9_UpdateSamplerView(This, 0); 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci last_layer = util_max_layer(This->view[0]->texture, base_level); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci nine_context_gen_mipmap(This->base.base.device, (struct NineUnknown *)This, 404bf215546Sopenharmony_ci This->base.resource, 405bf215546Sopenharmony_ci base_level, last_level, 406bf215546Sopenharmony_ci first_layer, last_layer, filter); 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci This->dirty_mip = FALSE; 409bf215546Sopenharmony_ci} 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ciHRESULT 412bf215546Sopenharmony_ciNineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This, 413bf215546Sopenharmony_ci BOOL CopyData ) 414bf215546Sopenharmony_ci{ 415bf215546Sopenharmony_ci struct pipe_context *pipe; 416bf215546Sopenharmony_ci struct pipe_screen *screen = This->base.info.screen; 417bf215546Sopenharmony_ci struct pipe_resource templ; 418bf215546Sopenharmony_ci unsigned l, m; 419bf215546Sopenharmony_ci struct pipe_resource *res; 420bf215546Sopenharmony_ci struct pipe_resource *old = This->base.resource; 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci DBG("This=%p lod=%u last_level=%u\n", This, 423bf215546Sopenharmony_ci This->managed.lod, This->base.info.last_level); 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci assert(This->base.pool == D3DPOOL_MANAGED); 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci templ = This->base.info; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci if (This->managed.lod) { 430bf215546Sopenharmony_ci templ.width0 = u_minify(templ.width0, This->managed.lod); 431bf215546Sopenharmony_ci templ.height0 = u_minify(templ.height0, This->managed.lod); 432bf215546Sopenharmony_ci templ.depth0 = u_minify(templ.depth0, This->managed.lod); 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci templ.last_level = This->base.info.last_level - This->managed.lod; 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci if (old) { 437bf215546Sopenharmony_ci /* LOD might have changed. */ 438bf215546Sopenharmony_ci if (old->width0 == templ.width0 && 439bf215546Sopenharmony_ci old->height0 == templ.height0 && 440bf215546Sopenharmony_ci old->depth0 == templ.depth0) 441bf215546Sopenharmony_ci return D3D_OK; 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci res = nine_resource_create_with_retry(This->base.base.device, screen, &templ); 445bf215546Sopenharmony_ci if (!res) 446bf215546Sopenharmony_ci return D3DERR_OUTOFVIDEOMEMORY; 447bf215546Sopenharmony_ci This->base.resource = res; 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci if (old && CopyData) { /* Don't return without releasing old ! */ 450bf215546Sopenharmony_ci struct pipe_box box; 451bf215546Sopenharmony_ci box.x = 0; 452bf215546Sopenharmony_ci box.y = 0; 453bf215546Sopenharmony_ci box.z = 0; 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci l = (This->managed.lod < This->managed.lod_resident) ? This->managed.lod_resident - This->managed.lod : 0; 456bf215546Sopenharmony_ci m = (This->managed.lod < This->managed.lod_resident) ? 0 : This->managed.lod - This->managed.lod_resident; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci box.width = u_minify(templ.width0, l); 459bf215546Sopenharmony_ci box.height = u_minify(templ.height0, l); 460bf215546Sopenharmony_ci box.depth = u_minify(templ.depth0, l); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci pipe = nine_context_get_pipe_acquire(This->base.base.device); 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci for (; l <= templ.last_level; ++l, ++m) { 465bf215546Sopenharmony_ci pipe->resource_copy_region(pipe, 466bf215546Sopenharmony_ci res, l, 0, 0, 0, 467bf215546Sopenharmony_ci old, m, &box); 468bf215546Sopenharmony_ci box.width = u_minify(box.width, 1); 469bf215546Sopenharmony_ci box.height = u_minify(box.height, 1); 470bf215546Sopenharmony_ci box.depth = u_minify(box.depth, 1); 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci nine_context_get_pipe_release(This->base.base.device); 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci pipe_resource_reference(&old, NULL); 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci return D3D_OK; 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci#define SWIZZLE_TO_REPLACE(s) (s == PIPE_SWIZZLE_0 || \ 481bf215546Sopenharmony_ci s == PIPE_SWIZZLE_1 || \ 482bf215546Sopenharmony_ci s == PIPE_SWIZZLE_NONE) 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ciHRESULT 485bf215546Sopenharmony_ciNineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This, 486bf215546Sopenharmony_ci const int sRGB ) 487bf215546Sopenharmony_ci{ 488bf215546Sopenharmony_ci const struct util_format_description *desc; 489bf215546Sopenharmony_ci struct pipe_context *pipe; 490bf215546Sopenharmony_ci struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); 491bf215546Sopenharmony_ci struct pipe_resource *resource = This->base.resource; 492bf215546Sopenharmony_ci struct pipe_sampler_view templ; 493bf215546Sopenharmony_ci enum pipe_format srgb_format; 494bf215546Sopenharmony_ci unsigned i; 495bf215546Sopenharmony_ci uint8_t swizzle[4]; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci DBG("This=%p sRGB=%d\n", This, sRGB); 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci if (unlikely(!resource)) { 500bf215546Sopenharmony_ci if (unlikely(This->format == D3DFMT_NULL)) 501bf215546Sopenharmony_ci return D3D_OK; 502bf215546Sopenharmony_ci NineBaseTexture9_Dump(This); 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci assert(resource); 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci pipe_sampler_view_reference(&This->view[sRGB], NULL); 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci swizzle[0] = PIPE_SWIZZLE_X; 509bf215546Sopenharmony_ci swizzle[1] = PIPE_SWIZZLE_Y; 510bf215546Sopenharmony_ci swizzle[2] = PIPE_SWIZZLE_Z; 511bf215546Sopenharmony_ci swizzle[3] = PIPE_SWIZZLE_W; 512bf215546Sopenharmony_ci desc = util_format_description(resource->format); 513bf215546Sopenharmony_ci if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { 514bf215546Sopenharmony_ci /* msdn doc is incomplete here and wrong. 515bf215546Sopenharmony_ci * The only formats that can be read directly here 516bf215546Sopenharmony_ci * are DF16, DF24 and INTZ. 517bf215546Sopenharmony_ci * Tested on win the swizzle is 518bf215546Sopenharmony_ci * R = depth, G = B = 0, A = 1 for DF16 and DF24 519bf215546Sopenharmony_ci * R = G = B = A = depth for INTZ 520bf215546Sopenharmony_ci * For the other ZS formats that can't be read directly 521bf215546Sopenharmony_ci * but can be used as shadow map, the result is duplicated on 522bf215546Sopenharmony_ci * all channel */ 523bf215546Sopenharmony_ci if (This->format == D3DFMT_DF16 || 524bf215546Sopenharmony_ci This->format == D3DFMT_DF24) { 525bf215546Sopenharmony_ci swizzle[1] = PIPE_SWIZZLE_0; 526bf215546Sopenharmony_ci swizzle[2] = PIPE_SWIZZLE_0; 527bf215546Sopenharmony_ci swizzle[3] = PIPE_SWIZZLE_1; 528bf215546Sopenharmony_ci } else { 529bf215546Sopenharmony_ci swizzle[1] = PIPE_SWIZZLE_X; 530bf215546Sopenharmony_ci swizzle[2] = PIPE_SWIZZLE_X; 531bf215546Sopenharmony_ci swizzle[3] = PIPE_SWIZZLE_X; 532bf215546Sopenharmony_ci } 533bf215546Sopenharmony_ci } else if (resource->format == PIPE_FORMAT_RGTC2_UNORM) { 534bf215546Sopenharmony_ci swizzle[0] = PIPE_SWIZZLE_Y; 535bf215546Sopenharmony_ci swizzle[1] = PIPE_SWIZZLE_X; 536bf215546Sopenharmony_ci swizzle[2] = PIPE_SWIZZLE_1; 537bf215546Sopenharmony_ci swizzle[3] = PIPE_SWIZZLE_1; 538bf215546Sopenharmony_ci } else if (resource->format != PIPE_FORMAT_A8_UNORM && 539bf215546Sopenharmony_ci resource->format != PIPE_FORMAT_RGTC1_UNORM) { 540bf215546Sopenharmony_ci /* exceptions: 541bf215546Sopenharmony_ci * A8 should have 0.0 as default values for RGB. 542bf215546Sopenharmony_ci * ATI1/RGTC1 should be r 0 0 1 (tested on windows). 543bf215546Sopenharmony_ci * It is already what gallium does. All the other ones 544bf215546Sopenharmony_ci * should have 1.0 for non-defined values */ 545bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 546bf215546Sopenharmony_ci if (SWIZZLE_TO_REPLACE(desc->swizzle[i])) 547bf215546Sopenharmony_ci swizzle[i] = PIPE_SWIZZLE_1; 548bf215546Sopenharmony_ci } 549bf215546Sopenharmony_ci } 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci /* if requested and supported, convert to the sRGB format */ 552bf215546Sopenharmony_ci srgb_format = util_format_srgb(resource->format); 553bf215546Sopenharmony_ci if (sRGB && srgb_format != PIPE_FORMAT_NONE && 554bf215546Sopenharmony_ci screen->is_format_supported(screen, srgb_format, 555bf215546Sopenharmony_ci resource->target, 0, 0, resource->bind)) 556bf215546Sopenharmony_ci templ.format = srgb_format; 557bf215546Sopenharmony_ci else 558bf215546Sopenharmony_ci templ.format = resource->format; 559bf215546Sopenharmony_ci templ.u.tex.first_layer = 0; 560bf215546Sopenharmony_ci templ.u.tex.last_layer = resource->target == PIPE_TEXTURE_3D ? 561bf215546Sopenharmony_ci 0 : resource->array_size - 1; 562bf215546Sopenharmony_ci templ.u.tex.first_level = 0; 563bf215546Sopenharmony_ci templ.u.tex.last_level = resource->last_level; 564bf215546Sopenharmony_ci templ.swizzle_r = swizzle[0]; 565bf215546Sopenharmony_ci templ.swizzle_g = swizzle[1]; 566bf215546Sopenharmony_ci templ.swizzle_b = swizzle[2]; 567bf215546Sopenharmony_ci templ.swizzle_a = swizzle[3]; 568bf215546Sopenharmony_ci templ.target = resource->target; 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci pipe = nine_context_get_pipe_acquire(This->base.base.device); 571bf215546Sopenharmony_ci This->view[sRGB] = pipe->create_sampler_view(pipe, resource, &templ); 572bf215546Sopenharmony_ci nine_context_get_pipe_release(This->base.base.device); 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci DBG("sampler view = %p(resource = %p)\n", This->view[sRGB], resource); 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci return This->view[sRGB] ? D3D_OK : D3DERR_DRIVERINTERNALERROR; 577bf215546Sopenharmony_ci} 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_civoid NINE_WINAPI 580bf215546Sopenharmony_ciNineBaseTexture9_PreLoad( struct NineBaseTexture9 *This ) 581bf215546Sopenharmony_ci{ 582bf215546Sopenharmony_ci DBG("This=%p\n", This); 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci if (This->base.pool == D3DPOOL_MANAGED) 585bf215546Sopenharmony_ci NineBaseTexture9_UploadSelf(This); 586bf215546Sopenharmony_ci} 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_civoid 589bf215546Sopenharmony_ciNineBaseTexture9_UnLoad( struct NineBaseTexture9 *This ) 590bf215546Sopenharmony_ci{ 591bf215546Sopenharmony_ci DBG("This=%p\n", This); 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci if (This->base.pool != D3DPOOL_MANAGED || 594bf215546Sopenharmony_ci This->managed.lod_resident == -1) 595bf215546Sopenharmony_ci return; 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci DBG("This=%p, releasing resource\n", This); 598bf215546Sopenharmony_ci pipe_resource_reference(&This->base.resource, NULL); 599bf215546Sopenharmony_ci This->managed.lod_resident = -1; 600bf215546Sopenharmony_ci This->managed.dirty = TRUE; 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci /* If the texture is bound, we have to re-upload it */ 603bf215546Sopenharmony_ci BASETEX_REGISTER_UPDATE(This); 604bf215546Sopenharmony_ci} 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci#if defined(DEBUG) || !defined(NDEBUG) 607bf215546Sopenharmony_civoid 608bf215546Sopenharmony_ciNineBaseTexture9_Dump( struct NineBaseTexture9 *This ) 609bf215546Sopenharmony_ci{ 610bf215546Sopenharmony_ci DBG("\nNineBaseTexture9(%p->NULL/%p): Pool=%s Type=%s Usage=%s\n" 611bf215546Sopenharmony_ci "Format=%s Dims=%ux%ux%u/%u LastLevel=%u Lod=%u(%u)\n", This, 612bf215546Sopenharmony_ci This->base.resource, 613bf215546Sopenharmony_ci nine_D3DPOOL_to_str(This->base.pool), 614bf215546Sopenharmony_ci nine_D3DRTYPE_to_str(This->base.type), 615bf215546Sopenharmony_ci nine_D3DUSAGE_to_str(This->base.usage), 616bf215546Sopenharmony_ci d3dformat_to_string(This->format), 617bf215546Sopenharmony_ci This->base.info.width0, This->base.info.height0, This->base.info.depth0, 618bf215546Sopenharmony_ci This->base.info.array_size, This->base.info.last_level, 619bf215546Sopenharmony_ci This->managed.lod, This->managed.lod_resident); 620bf215546Sopenharmony_ci} 621bf215546Sopenharmony_ci#endif /* DEBUG || !NDEBUG */ 622