17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 227ec681f3Smrg 237ec681f3Smrg#include "basetexture9.h" 247ec681f3Smrg#include "device9.h" 257ec681f3Smrg 267ec681f3Smrg/* For UploadSelf: */ 277ec681f3Smrg#include "texture9.h" 287ec681f3Smrg#include "cubetexture9.h" 297ec681f3Smrg#include "volumetexture9.h" 307ec681f3Smrg#include "nine_pipe.h" 317ec681f3Smrg 327ec681f3Smrg#if defined(DEBUG) || !defined(NDEBUG) 337ec681f3Smrg#include "nine_dump.h" 347ec681f3Smrg#endif 357ec681f3Smrg 367ec681f3Smrg#include "util/format/u_format.h" 377ec681f3Smrg 387ec681f3Smrg#define DBG_CHANNEL DBG_BASETEXTURE 397ec681f3Smrg 407ec681f3SmrgHRESULT 417ec681f3SmrgNineBaseTexture9_ctor( struct NineBaseTexture9 *This, 427ec681f3Smrg struct NineUnknownParams *pParams, 437ec681f3Smrg struct pipe_resource *initResource, 447ec681f3Smrg D3DRESOURCETYPE Type, 457ec681f3Smrg D3DFORMAT format, 467ec681f3Smrg D3DPOOL Pool, 477ec681f3Smrg DWORD Usage) 487ec681f3Smrg{ 497ec681f3Smrg BOOL alloc = (Pool == D3DPOOL_DEFAULT) && !initResource && 507ec681f3Smrg (format != D3DFMT_NULL); 517ec681f3Smrg HRESULT hr; 527ec681f3Smrg 537ec681f3Smrg DBG("This=%p, pParams=%p initResource=%p Type=%d format=%d Pool=%d Usage=%d\n", 547ec681f3Smrg This, pParams, initResource, Type, format, Pool, Usage); 557ec681f3Smrg 567ec681f3Smrg user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) || 577ec681f3Smrg Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 587ec681f3Smrg user_assert(!(Usage & D3DUSAGE_DYNAMIC) || 597ec681f3Smrg !(Pool == D3DPOOL_MANAGED || 607ec681f3Smrg Pool == D3DPOOL_SCRATCH), D3DERR_INVALIDCALL); 617ec681f3Smrg 627ec681f3Smrg hr = NineResource9_ctor(&This->base, pParams, initResource, alloc, Type, Pool, Usage); 637ec681f3Smrg if (FAILED(hr)) 647ec681f3Smrg return hr; 657ec681f3Smrg 667ec681f3Smrg This->format = format; 677ec681f3Smrg This->mipfilter = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? 687ec681f3Smrg D3DTEXF_LINEAR : D3DTEXF_NONE; 697ec681f3Smrg /* In the case of D3DUSAGE_AUTOGENMIPMAP, only the first level is accessible, 707ec681f3Smrg * and thus needs a surface created. */ 717ec681f3Smrg This->level_count = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? 1 : (This->base.info.last_level+1); 727ec681f3Smrg This->managed.lod = 0; 737ec681f3Smrg This->managed.lod_resident = -1; 747ec681f3Smrg /* Mark the texture as dirty to trigger first upload when we need the texture, 757ec681f3Smrg * even if it wasn't set by the application */ 767ec681f3Smrg if (Pool == D3DPOOL_MANAGED) 777ec681f3Smrg This->managed.dirty = TRUE; 787ec681f3Smrg /* When a depth buffer is sampled, it is for shadow mapping, except for 797ec681f3Smrg * D3DFMT_INTZ, D3DFMT_DF16 and D3DFMT_DF24. 807ec681f3Smrg * In addition D3DFMT_INTZ can be used for both texturing and depth buffering 817ec681f3Smrg * if z write is disabled. This particular feature may not work for us in 827ec681f3Smrg * practice because OGL doesn't have that. However apparently it is known 837ec681f3Smrg * some cards have performance issues with this feature, so real apps 847ec681f3Smrg * shouldn't use it. */ 857ec681f3Smrg This->shadow = (This->format != D3DFMT_INTZ && This->format != D3DFMT_DF16 && 867ec681f3Smrg This->format != D3DFMT_DF24) && 877ec681f3Smrg util_format_has_depth(util_format_description(This->base.info.format)); 887ec681f3Smrg This->fetch4_compatible = fetch4_compatible_format(This->format); 897ec681f3Smrg 907ec681f3Smrg list_inithead(&This->list); 917ec681f3Smrg list_inithead(&This->list2); 927ec681f3Smrg if (Pool == D3DPOOL_MANAGED) 937ec681f3Smrg list_add(&This->list2, &This->base.base.device->managed_textures); 947ec681f3Smrg 957ec681f3Smrg return D3D_OK; 967ec681f3Smrg} 977ec681f3Smrg 987ec681f3Smrgvoid 997ec681f3SmrgNineBaseTexture9_dtor( struct NineBaseTexture9 *This ) 1007ec681f3Smrg{ 1017ec681f3Smrg DBG("This=%p\n", This); 1027ec681f3Smrg 1037ec681f3Smrg pipe_sampler_view_reference(&This->view[0], NULL); 1047ec681f3Smrg pipe_sampler_view_reference(&This->view[1], NULL); 1057ec681f3Smrg 1067ec681f3Smrg if (list_is_linked(&This->list)) 1077ec681f3Smrg list_del(&This->list); 1087ec681f3Smrg if (list_is_linked(&This->list2)) 1097ec681f3Smrg list_del(&This->list2); 1107ec681f3Smrg 1117ec681f3Smrg NineResource9_dtor(&This->base); 1127ec681f3Smrg} 1137ec681f3Smrg 1147ec681f3SmrgDWORD NINE_WINAPI 1157ec681f3SmrgNineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, 1167ec681f3Smrg DWORD LODNew ) 1177ec681f3Smrg{ 1187ec681f3Smrg DWORD old = This->managed.lod; 1197ec681f3Smrg 1207ec681f3Smrg DBG("This=%p LODNew=%d\n", This, LODNew); 1217ec681f3Smrg 1227ec681f3Smrg user_assert(This->base.pool == D3DPOOL_MANAGED, 0); 1237ec681f3Smrg 1247ec681f3Smrg This->managed.lod = MIN2(LODNew, This->level_count-1); 1257ec681f3Smrg 1267ec681f3Smrg if (This->managed.lod != old && This->bind_count && list_is_empty(&This->list)) 1277ec681f3Smrg list_add(&This->list, &This->base.base.device->update_textures); 1287ec681f3Smrg 1297ec681f3Smrg return old; 1307ec681f3Smrg} 1317ec681f3Smrg 1327ec681f3SmrgDWORD NINE_WINAPI 1337ec681f3SmrgNineBaseTexture9_GetLOD( struct NineBaseTexture9 *This ) 1347ec681f3Smrg{ 1357ec681f3Smrg DBG("This=%p\n", This); 1367ec681f3Smrg 1377ec681f3Smrg return This->managed.lod; 1387ec681f3Smrg} 1397ec681f3Smrg 1407ec681f3SmrgDWORD NINE_WINAPI 1417ec681f3SmrgNineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) 1427ec681f3Smrg{ 1437ec681f3Smrg DBG("This=%p\n", This); 1447ec681f3Smrg 1457ec681f3Smrg return This->level_count; 1467ec681f3Smrg} 1477ec681f3Smrg 1487ec681f3SmrgHRESULT NINE_WINAPI 1497ec681f3SmrgNineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, 1507ec681f3Smrg D3DTEXTUREFILTERTYPE FilterType ) 1517ec681f3Smrg{ 1527ec681f3Smrg DBG("This=%p FilterType=%d\n", This, FilterType); 1537ec681f3Smrg 1547ec681f3Smrg if (!(This->base.usage & D3DUSAGE_AUTOGENMIPMAP)) 1557ec681f3Smrg return D3D_OK; 1567ec681f3Smrg user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL); 1577ec681f3Smrg 1587ec681f3Smrg This->mipfilter = FilterType; 1597ec681f3Smrg This->dirty_mip = TRUE; 1607ec681f3Smrg NineBaseTexture9_GenerateMipSubLevels(This); 1617ec681f3Smrg 1627ec681f3Smrg return D3D_OK; 1637ec681f3Smrg} 1647ec681f3Smrg 1657ec681f3SmrgD3DTEXTUREFILTERTYPE NINE_WINAPI 1667ec681f3SmrgNineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ) 1677ec681f3Smrg{ 1687ec681f3Smrg DBG("This=%p\n", This); 1697ec681f3Smrg 1707ec681f3Smrg return This->mipfilter; 1717ec681f3Smrg} 1727ec681f3Smrg 1737ec681f3SmrgHRESULT 1747ec681f3SmrgNineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) 1757ec681f3Smrg{ 1767ec681f3Smrg HRESULT hr; 1777ec681f3Smrg unsigned l, min_level_dirty = This->managed.lod; 1787ec681f3Smrg BOOL update_lod; 1797ec681f3Smrg 1807ec681f3Smrg DBG("This=%p dirty=%i type=%s\n", This, This->managed.dirty, 1817ec681f3Smrg nine_D3DRTYPE_to_str(This->base.type)); 1827ec681f3Smrg 1837ec681f3Smrg assert(This->base.pool == D3DPOOL_MANAGED); 1847ec681f3Smrg 1857ec681f3Smrg update_lod = This->managed.lod_resident != This->managed.lod; 1867ec681f3Smrg if (!update_lod && !This->managed.dirty) 1877ec681f3Smrg return D3D_OK; 1887ec681f3Smrg 1897ec681f3Smrg /* Allocate a new resource with the correct number of levels, 1907ec681f3Smrg * Mark states for update, and tell the nine surfaces/volumes 1917ec681f3Smrg * their new resource. */ 1927ec681f3Smrg if (update_lod) { 1937ec681f3Smrg struct pipe_resource *res; 1947ec681f3Smrg 1957ec681f3Smrg DBG("updating LOD from %u to %u ...\n", This->managed.lod_resident, This->managed.lod); 1967ec681f3Smrg 1977ec681f3Smrg pipe_sampler_view_reference(&This->view[0], NULL); 1987ec681f3Smrg pipe_sampler_view_reference(&This->view[1], NULL); 1997ec681f3Smrg 2007ec681f3Smrg /* Allocate a new resource */ 2017ec681f3Smrg hr = NineBaseTexture9_CreatePipeResource(This, This->managed.lod_resident != -1); 2027ec681f3Smrg if (FAILED(hr)) 2037ec681f3Smrg return hr; 2047ec681f3Smrg res = This->base.resource; 2057ec681f3Smrg 2067ec681f3Smrg if (This->managed.lod_resident == -1) {/* no levels were resident */ 2077ec681f3Smrg This->managed.dirty = FALSE; /* We are going to upload everything. */ 2087ec681f3Smrg This->managed.lod_resident = This->level_count; 2097ec681f3Smrg } 2107ec681f3Smrg 2117ec681f3Smrg if (This->base.type == D3DRTYPE_TEXTURE) { 2127ec681f3Smrg struct NineTexture9 *tex = NineTexture9(This); 2137ec681f3Smrg 2147ec681f3Smrg /* last content (if apply) has been copied to the new resource. 2157ec681f3Smrg * Note: We cannot render to surfaces of managed textures. 2167ec681f3Smrg * Note2: the level argument passed is to get the level offset 2177ec681f3Smrg * right when the texture is uploaded (the texture first level 2187ec681f3Smrg * corresponds to This->managed.lod). 2197ec681f3Smrg * Note3: We don't care about the value passed for the surfaces 2207ec681f3Smrg * before This->managed.lod, negative with this implementation. */ 2217ec681f3Smrg for (l = 0; l < This->level_count; ++l) 2227ec681f3Smrg NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); 2237ec681f3Smrg } else 2247ec681f3Smrg if (This->base.type == D3DRTYPE_CUBETEXTURE) { 2257ec681f3Smrg struct NineCubeTexture9 *tex = NineCubeTexture9(This); 2267ec681f3Smrg unsigned z; 2277ec681f3Smrg 2287ec681f3Smrg for (l = 0; l < This->level_count; ++l) { 2297ec681f3Smrg for (z = 0; z < 6; ++z) 2307ec681f3Smrg NineSurface9_SetResource(tex->surfaces[l * 6 + z], 2317ec681f3Smrg res, l - This->managed.lod); 2327ec681f3Smrg } 2337ec681f3Smrg } else 2347ec681f3Smrg if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { 2357ec681f3Smrg struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); 2367ec681f3Smrg 2377ec681f3Smrg for (l = 0; l < This->level_count; ++l) 2387ec681f3Smrg NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); 2397ec681f3Smrg } else { 2407ec681f3Smrg assert(!"invalid texture type"); 2417ec681f3Smrg } 2427ec681f3Smrg 2437ec681f3Smrg /* We are going to fully upload the new levels, 2447ec681f3Smrg * no need to update dirty parts of the texture for these */ 2457ec681f3Smrg min_level_dirty = MAX2(This->managed.lod, This->managed.lod_resident); 2467ec681f3Smrg } 2477ec681f3Smrg 2487ec681f3Smrg /* Update dirty parts of the texture */ 2497ec681f3Smrg if (This->managed.dirty) { 2507ec681f3Smrg if (This->base.type == D3DRTYPE_TEXTURE) { 2517ec681f3Smrg struct NineTexture9 *tex = NineTexture9(This); 2527ec681f3Smrg struct pipe_box box; 2537ec681f3Smrg box.z = 0; 2547ec681f3Smrg box.depth = 1; 2557ec681f3Smrg 2567ec681f3Smrg DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n", 2577ec681f3Smrg tex->dirty_rect.x, tex->dirty_rect.y, 2587ec681f3Smrg tex->dirty_rect.width, tex->dirty_rect.height); 2597ec681f3Smrg 2607ec681f3Smrg /* Note: for l < min_level_dirty, the resource is 2617ec681f3Smrg * either non-existing (and thus will be entirely re-uploaded 2627ec681f3Smrg * if the lod changes) or going to have a full upload */ 2637ec681f3Smrg if (tex->dirty_rect.width) { 2647ec681f3Smrg for (l = min_level_dirty; l < This->level_count; ++l) { 2657ec681f3Smrg u_box_minify_2d(&box, &tex->dirty_rect, l); 2667ec681f3Smrg NineSurface9_UploadSelf(tex->surfaces[l], &box); 2677ec681f3Smrg } 2687ec681f3Smrg memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect)); 2697ec681f3Smrg tex->dirty_rect.depth = 1; 2707ec681f3Smrg } 2717ec681f3Smrg } else 2727ec681f3Smrg if (This->base.type == D3DRTYPE_CUBETEXTURE) { 2737ec681f3Smrg struct NineCubeTexture9 *tex = NineCubeTexture9(This); 2747ec681f3Smrg unsigned z; 2757ec681f3Smrg struct pipe_box box; 2767ec681f3Smrg box.z = 0; 2777ec681f3Smrg box.depth = 1; 2787ec681f3Smrg 2797ec681f3Smrg for (z = 0; z < 6; ++z) { 2807ec681f3Smrg DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z, 2817ec681f3Smrg tex->dirty_rect[z].x, tex->dirty_rect[z].y, 2827ec681f3Smrg tex->dirty_rect[z].width, tex->dirty_rect[z].height); 2837ec681f3Smrg 2847ec681f3Smrg if (tex->dirty_rect[z].width) { 2857ec681f3Smrg for (l = min_level_dirty; l < This->level_count; ++l) { 2867ec681f3Smrg u_box_minify_2d(&box, &tex->dirty_rect[z], l); 2877ec681f3Smrg NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); 2887ec681f3Smrg } 2897ec681f3Smrg memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z])); 2907ec681f3Smrg tex->dirty_rect[z].depth = 1; 2917ec681f3Smrg } 2927ec681f3Smrg } 2937ec681f3Smrg } else 2947ec681f3Smrg if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { 2957ec681f3Smrg struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); 2967ec681f3Smrg struct pipe_box box; 2977ec681f3Smrg 2987ec681f3Smrg DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n", 2997ec681f3Smrg tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y, 3007ec681f3Smrg tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); 3017ec681f3Smrg 3027ec681f3Smrg if (tex->dirty_box.width) { 3037ec681f3Smrg for (l = min_level_dirty; l < This->level_count; ++l) { 3047ec681f3Smrg u_box_minify_3d(&box, &tex->dirty_box, l); 3057ec681f3Smrg NineVolume9_UploadSelf(tex->volumes[l], &box); 3067ec681f3Smrg } 3077ec681f3Smrg memset(&tex->dirty_box, 0, sizeof(tex->dirty_box)); 3087ec681f3Smrg } 3097ec681f3Smrg } else { 3107ec681f3Smrg assert(!"invalid texture type"); 3117ec681f3Smrg } 3127ec681f3Smrg This->managed.dirty = FALSE; 3137ec681f3Smrg } 3147ec681f3Smrg 3157ec681f3Smrg /* Upload the new levels */ 3167ec681f3Smrg if (update_lod) { 3177ec681f3Smrg if (This->base.type == D3DRTYPE_TEXTURE) { 3187ec681f3Smrg struct NineTexture9 *tex = NineTexture9(This); 3197ec681f3Smrg struct pipe_box box; 3207ec681f3Smrg 3217ec681f3Smrg box.x = box.y = box.z = 0; 3227ec681f3Smrg box.depth = 1; 3237ec681f3Smrg for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { 3247ec681f3Smrg box.width = u_minify(This->base.info.width0, l); 3257ec681f3Smrg box.height = u_minify(This->base.info.height0, l); 3267ec681f3Smrg NineSurface9_UploadSelf(tex->surfaces[l], &box); 3277ec681f3Smrg } 3287ec681f3Smrg } else 3297ec681f3Smrg if (This->base.type == D3DRTYPE_CUBETEXTURE) { 3307ec681f3Smrg struct NineCubeTexture9 *tex = NineCubeTexture9(This); 3317ec681f3Smrg struct pipe_box box; 3327ec681f3Smrg unsigned z; 3337ec681f3Smrg 3347ec681f3Smrg box.x = box.y = box.z = 0; 3357ec681f3Smrg box.depth = 1; 3367ec681f3Smrg for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { 3377ec681f3Smrg box.width = u_minify(This->base.info.width0, l); 3387ec681f3Smrg box.height = u_minify(This->base.info.height0, l); 3397ec681f3Smrg for (z = 0; z < 6; ++z) 3407ec681f3Smrg NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); 3417ec681f3Smrg } 3427ec681f3Smrg } else 3437ec681f3Smrg if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { 3447ec681f3Smrg struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); 3457ec681f3Smrg struct pipe_box box; 3467ec681f3Smrg 3477ec681f3Smrg box.x = box.y = box.z = 0; 3487ec681f3Smrg for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { 3497ec681f3Smrg box.width = u_minify(This->base.info.width0, l); 3507ec681f3Smrg box.height = u_minify(This->base.info.height0, l); 3517ec681f3Smrg box.depth = u_minify(This->base.info.depth0, l); 3527ec681f3Smrg NineVolume9_UploadSelf(tex->volumes[l], &box); 3537ec681f3Smrg } 3547ec681f3Smrg } else { 3557ec681f3Smrg assert(!"invalid texture type"); 3567ec681f3Smrg } 3577ec681f3Smrg 3587ec681f3Smrg This->managed.lod_resident = This->managed.lod; 3597ec681f3Smrg } 3607ec681f3Smrg 3617ec681f3Smrg if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) 3627ec681f3Smrg This->dirty_mip = TRUE; 3637ec681f3Smrg 3647ec681f3Smrg /* Set again the textures currently bound to update the texture data */ 3657ec681f3Smrg if (This->bind_count) { 3667ec681f3Smrg struct nine_state *state = &This->base.base.device->state; 3677ec681f3Smrg unsigned s; 3687ec681f3Smrg for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 3697ec681f3Smrg /* Dirty tracking is done in device9 state, not nine_context. */ 3707ec681f3Smrg if (state->texture[s] == This) 3717ec681f3Smrg nine_context_set_texture(This->base.base.device, s, This); 3727ec681f3Smrg } 3737ec681f3Smrg 3747ec681f3Smrg DBG("DONE, generate mip maps = %i\n", This->dirty_mip); 3757ec681f3Smrg return D3D_OK; 3767ec681f3Smrg} 3777ec681f3Smrg 3787ec681f3Smrgvoid NINE_WINAPI 3797ec681f3SmrgNineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ) 3807ec681f3Smrg{ 3817ec681f3Smrg unsigned base_level = 0; 3827ec681f3Smrg unsigned last_level = This->base.info.last_level - This->managed.lod; 3837ec681f3Smrg unsigned first_layer = 0; 3847ec681f3Smrg unsigned last_layer; 3857ec681f3Smrg unsigned filter = This->mipfilter == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST 3867ec681f3Smrg : PIPE_TEX_FILTER_LINEAR; 3877ec681f3Smrg DBG("This=%p\n", This); 3887ec681f3Smrg 3897ec681f3Smrg if (This->base.pool == D3DPOOL_MANAGED) 3907ec681f3Smrg NineBaseTexture9_UploadSelf(This); 3917ec681f3Smrg if (!This->dirty_mip) 3927ec681f3Smrg return; 3937ec681f3Smrg if (This->managed.lod) { 3947ec681f3Smrg ERR("AUTOGENMIPMAP if level 0 is not resident not supported yet !\n"); 3957ec681f3Smrg return; 3967ec681f3Smrg } 3977ec681f3Smrg 3987ec681f3Smrg if (!This->view[0]) 3997ec681f3Smrg NineBaseTexture9_UpdateSamplerView(This, 0); 4007ec681f3Smrg 4017ec681f3Smrg last_layer = util_max_layer(This->view[0]->texture, base_level); 4027ec681f3Smrg 4037ec681f3Smrg nine_context_gen_mipmap(This->base.base.device, (struct NineUnknown *)This, 4047ec681f3Smrg This->base.resource, 4057ec681f3Smrg base_level, last_level, 4067ec681f3Smrg first_layer, last_layer, filter); 4077ec681f3Smrg 4087ec681f3Smrg This->dirty_mip = FALSE; 4097ec681f3Smrg} 4107ec681f3Smrg 4117ec681f3SmrgHRESULT 4127ec681f3SmrgNineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This, 4137ec681f3Smrg BOOL CopyData ) 4147ec681f3Smrg{ 4157ec681f3Smrg struct pipe_context *pipe; 4167ec681f3Smrg struct pipe_screen *screen = This->base.info.screen; 4177ec681f3Smrg struct pipe_resource templ; 4187ec681f3Smrg unsigned l, m; 4197ec681f3Smrg struct pipe_resource *res; 4207ec681f3Smrg struct pipe_resource *old = This->base.resource; 4217ec681f3Smrg 4227ec681f3Smrg DBG("This=%p lod=%u last_level=%u\n", This, 4237ec681f3Smrg This->managed.lod, This->base.info.last_level); 4247ec681f3Smrg 4257ec681f3Smrg assert(This->base.pool == D3DPOOL_MANAGED); 4267ec681f3Smrg 4277ec681f3Smrg templ = This->base.info; 4287ec681f3Smrg 4297ec681f3Smrg if (This->managed.lod) { 4307ec681f3Smrg templ.width0 = u_minify(templ.width0, This->managed.lod); 4317ec681f3Smrg templ.height0 = u_minify(templ.height0, This->managed.lod); 4327ec681f3Smrg templ.depth0 = u_minify(templ.depth0, This->managed.lod); 4337ec681f3Smrg } 4347ec681f3Smrg templ.last_level = This->base.info.last_level - This->managed.lod; 4357ec681f3Smrg 4367ec681f3Smrg if (old) { 4377ec681f3Smrg /* LOD might have changed. */ 4387ec681f3Smrg if (old->width0 == templ.width0 && 4397ec681f3Smrg old->height0 == templ.height0 && 4407ec681f3Smrg old->depth0 == templ.depth0) 4417ec681f3Smrg return D3D_OK; 4427ec681f3Smrg } 4437ec681f3Smrg 4447ec681f3Smrg res = nine_resource_create_with_retry(This->base.base.device, screen, &templ); 4457ec681f3Smrg if (!res) 4467ec681f3Smrg return D3DERR_OUTOFVIDEOMEMORY; 4477ec681f3Smrg This->base.resource = res; 4487ec681f3Smrg 4497ec681f3Smrg if (old && CopyData) { /* Don't return without releasing old ! */ 4507ec681f3Smrg struct pipe_box box; 4517ec681f3Smrg box.x = 0; 4527ec681f3Smrg box.y = 0; 4537ec681f3Smrg box.z = 0; 4547ec681f3Smrg 4557ec681f3Smrg l = (This->managed.lod < This->managed.lod_resident) ? This->managed.lod_resident - This->managed.lod : 0; 4567ec681f3Smrg m = (This->managed.lod < This->managed.lod_resident) ? 0 : This->managed.lod - This->managed.lod_resident; 4577ec681f3Smrg 4587ec681f3Smrg box.width = u_minify(templ.width0, l); 4597ec681f3Smrg box.height = u_minify(templ.height0, l); 4607ec681f3Smrg box.depth = u_minify(templ.depth0, l); 4617ec681f3Smrg 4627ec681f3Smrg pipe = nine_context_get_pipe_acquire(This->base.base.device); 4637ec681f3Smrg 4647ec681f3Smrg for (; l <= templ.last_level; ++l, ++m) { 4657ec681f3Smrg pipe->resource_copy_region(pipe, 4667ec681f3Smrg res, l, 0, 0, 0, 4677ec681f3Smrg old, m, &box); 4687ec681f3Smrg box.width = u_minify(box.width, 1); 4697ec681f3Smrg box.height = u_minify(box.height, 1); 4707ec681f3Smrg box.depth = u_minify(box.depth, 1); 4717ec681f3Smrg } 4727ec681f3Smrg 4737ec681f3Smrg nine_context_get_pipe_release(This->base.base.device); 4747ec681f3Smrg } 4757ec681f3Smrg pipe_resource_reference(&old, NULL); 4767ec681f3Smrg 4777ec681f3Smrg return D3D_OK; 4787ec681f3Smrg} 4797ec681f3Smrg 4807ec681f3Smrg#define SWIZZLE_TO_REPLACE(s) (s == PIPE_SWIZZLE_0 || \ 4817ec681f3Smrg s == PIPE_SWIZZLE_1 || \ 4827ec681f3Smrg s == PIPE_SWIZZLE_NONE) 4837ec681f3Smrg 4847ec681f3SmrgHRESULT 4857ec681f3SmrgNineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This, 4867ec681f3Smrg const int sRGB ) 4877ec681f3Smrg{ 4887ec681f3Smrg const struct util_format_description *desc; 4897ec681f3Smrg struct pipe_context *pipe; 4907ec681f3Smrg struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); 4917ec681f3Smrg struct pipe_resource *resource = This->base.resource; 4927ec681f3Smrg struct pipe_sampler_view templ; 4937ec681f3Smrg enum pipe_format srgb_format; 4947ec681f3Smrg unsigned i; 4957ec681f3Smrg uint8_t swizzle[4]; 4967ec681f3Smrg 4977ec681f3Smrg DBG("This=%p sRGB=%d\n", This, sRGB); 4987ec681f3Smrg 4997ec681f3Smrg if (unlikely(!resource)) { 5007ec681f3Smrg if (unlikely(This->format == D3DFMT_NULL)) 5017ec681f3Smrg return D3D_OK; 5027ec681f3Smrg NineBaseTexture9_Dump(This); 5037ec681f3Smrg } 5047ec681f3Smrg assert(resource); 5057ec681f3Smrg 5067ec681f3Smrg pipe_sampler_view_reference(&This->view[sRGB], NULL); 5077ec681f3Smrg 5087ec681f3Smrg swizzle[0] = PIPE_SWIZZLE_X; 5097ec681f3Smrg swizzle[1] = PIPE_SWIZZLE_Y; 5107ec681f3Smrg swizzle[2] = PIPE_SWIZZLE_Z; 5117ec681f3Smrg swizzle[3] = PIPE_SWIZZLE_W; 5127ec681f3Smrg desc = util_format_description(resource->format); 5137ec681f3Smrg if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { 5147ec681f3Smrg /* msdn doc is incomplete here and wrong. 5157ec681f3Smrg * The only formats that can be read directly here 5167ec681f3Smrg * are DF16, DF24 and INTZ. 5177ec681f3Smrg * Tested on win the swizzle is 5187ec681f3Smrg * R = depth, G = B = 0, A = 1 for DF16 and DF24 5197ec681f3Smrg * R = G = B = A = depth for INTZ 5207ec681f3Smrg * For the other ZS formats that can't be read directly 5217ec681f3Smrg * but can be used as shadow map, the result is duplicated on 5227ec681f3Smrg * all channel */ 5237ec681f3Smrg if (This->format == D3DFMT_DF16 || 5247ec681f3Smrg This->format == D3DFMT_DF24) { 5257ec681f3Smrg swizzle[1] = PIPE_SWIZZLE_0; 5267ec681f3Smrg swizzle[2] = PIPE_SWIZZLE_0; 5277ec681f3Smrg swizzle[3] = PIPE_SWIZZLE_1; 5287ec681f3Smrg } else { 5297ec681f3Smrg swizzle[1] = PIPE_SWIZZLE_X; 5307ec681f3Smrg swizzle[2] = PIPE_SWIZZLE_X; 5317ec681f3Smrg swizzle[3] = PIPE_SWIZZLE_X; 5327ec681f3Smrg } 5337ec681f3Smrg } else if (resource->format == PIPE_FORMAT_RGTC2_UNORM) { 5347ec681f3Smrg swizzle[0] = PIPE_SWIZZLE_Y; 5357ec681f3Smrg swizzle[1] = PIPE_SWIZZLE_X; 5367ec681f3Smrg swizzle[2] = PIPE_SWIZZLE_1; 5377ec681f3Smrg swizzle[3] = PIPE_SWIZZLE_1; 5387ec681f3Smrg } else if (resource->format != PIPE_FORMAT_A8_UNORM && 5397ec681f3Smrg resource->format != PIPE_FORMAT_RGTC1_UNORM) { 5407ec681f3Smrg /* exceptions: 5417ec681f3Smrg * A8 should have 0.0 as default values for RGB. 5427ec681f3Smrg * ATI1/RGTC1 should be r 0 0 1 (tested on windows). 5437ec681f3Smrg * It is already what gallium does. All the other ones 5447ec681f3Smrg * should have 1.0 for non-defined values */ 5457ec681f3Smrg for (i = 0; i < 4; i++) { 5467ec681f3Smrg if (SWIZZLE_TO_REPLACE(desc->swizzle[i])) 5477ec681f3Smrg swizzle[i] = PIPE_SWIZZLE_1; 5487ec681f3Smrg } 5497ec681f3Smrg } 5507ec681f3Smrg 5517ec681f3Smrg /* if requested and supported, convert to the sRGB format */ 5527ec681f3Smrg srgb_format = util_format_srgb(resource->format); 5537ec681f3Smrg if (sRGB && srgb_format != PIPE_FORMAT_NONE && 5547ec681f3Smrg screen->is_format_supported(screen, srgb_format, 5557ec681f3Smrg resource->target, 0, 0, resource->bind)) 5567ec681f3Smrg templ.format = srgb_format; 5577ec681f3Smrg else 5587ec681f3Smrg templ.format = resource->format; 5597ec681f3Smrg templ.u.tex.first_layer = 0; 5607ec681f3Smrg templ.u.tex.last_layer = resource->target == PIPE_TEXTURE_3D ? 5617ec681f3Smrg 0 : resource->array_size - 1; 5627ec681f3Smrg templ.u.tex.first_level = 0; 5637ec681f3Smrg templ.u.tex.last_level = resource->last_level; 5647ec681f3Smrg templ.swizzle_r = swizzle[0]; 5657ec681f3Smrg templ.swizzle_g = swizzle[1]; 5667ec681f3Smrg templ.swizzle_b = swizzle[2]; 5677ec681f3Smrg templ.swizzle_a = swizzle[3]; 5687ec681f3Smrg templ.target = resource->target; 5697ec681f3Smrg 5707ec681f3Smrg pipe = nine_context_get_pipe_acquire(This->base.base.device); 5717ec681f3Smrg This->view[sRGB] = pipe->create_sampler_view(pipe, resource, &templ); 5727ec681f3Smrg nine_context_get_pipe_release(This->base.base.device); 5737ec681f3Smrg 5747ec681f3Smrg DBG("sampler view = %p(resource = %p)\n", This->view[sRGB], resource); 5757ec681f3Smrg 5767ec681f3Smrg return This->view[sRGB] ? D3D_OK : D3DERR_DRIVERINTERNALERROR; 5777ec681f3Smrg} 5787ec681f3Smrg 5797ec681f3Smrgvoid NINE_WINAPI 5807ec681f3SmrgNineBaseTexture9_PreLoad( struct NineBaseTexture9 *This ) 5817ec681f3Smrg{ 5827ec681f3Smrg DBG("This=%p\n", This); 5837ec681f3Smrg 5847ec681f3Smrg if (This->base.pool == D3DPOOL_MANAGED) 5857ec681f3Smrg NineBaseTexture9_UploadSelf(This); 5867ec681f3Smrg} 5877ec681f3Smrg 5887ec681f3Smrgvoid 5897ec681f3SmrgNineBaseTexture9_UnLoad( struct NineBaseTexture9 *This ) 5907ec681f3Smrg{ 5917ec681f3Smrg DBG("This=%p\n", This); 5927ec681f3Smrg 5937ec681f3Smrg if (This->base.pool != D3DPOOL_MANAGED || 5947ec681f3Smrg This->managed.lod_resident == -1) 5957ec681f3Smrg return; 5967ec681f3Smrg 5977ec681f3Smrg DBG("This=%p, releasing resource\n", This); 5987ec681f3Smrg pipe_resource_reference(&This->base.resource, NULL); 5997ec681f3Smrg This->managed.lod_resident = -1; 6007ec681f3Smrg This->managed.dirty = TRUE; 6017ec681f3Smrg 6027ec681f3Smrg /* If the texture is bound, we have to re-upload it */ 6037ec681f3Smrg BASETEX_REGISTER_UPDATE(This); 6047ec681f3Smrg} 6057ec681f3Smrg 6067ec681f3Smrg#if defined(DEBUG) || !defined(NDEBUG) 6077ec681f3Smrgvoid 6087ec681f3SmrgNineBaseTexture9_Dump( struct NineBaseTexture9 *This ) 6097ec681f3Smrg{ 6107ec681f3Smrg DBG("\nNineBaseTexture9(%p->NULL/%p): Pool=%s Type=%s Usage=%s\n" 6117ec681f3Smrg "Format=%s Dims=%ux%ux%u/%u LastLevel=%u Lod=%u(%u)\n", This, 6127ec681f3Smrg This->base.resource, 6137ec681f3Smrg nine_D3DPOOL_to_str(This->base.pool), 6147ec681f3Smrg nine_D3DRTYPE_to_str(This->base.type), 6157ec681f3Smrg nine_D3DUSAGE_to_str(This->base.usage), 6167ec681f3Smrg d3dformat_to_string(This->format), 6177ec681f3Smrg This->base.info.width0, This->base.info.height0, This->base.info.depth0, 6187ec681f3Smrg This->base.info.array_size, This->base.info.last_level, 6197ec681f3Smrg This->managed.lod, This->managed.lod_resident); 6207ec681f3Smrg} 6217ec681f3Smrg#endif /* DEBUG || !NDEBUG */ 622