diff --git a/src/gallium/frontends/nine/basetexture9.c b/src/gallium/frontends/nine/basetexture9.c index c509a1f4621..7c29dbeff88 100644 --- a/src/gallium/frontends/nine/basetexture9.c +++ b/src/gallium/frontends/nine/basetexture9.c @@ -66,6 +66,9 @@ NineBaseTexture9_ctor( struct NineBaseTexture9 *This, This->format = format; This->mipfilter = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; + /* In the case of D3DUSAGE_AUTOGENMIPMAP, only the first level is accessible, + * and thus needs a surface created. */ + This->level_count = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? 1 : (This->base.info.last_level+1); This->managed.lod = 0; This->managed.lod_resident = -1; /* Mark the texture as dirty to trigger first upload when we need the texture, @@ -112,15 +115,12 @@ NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, DWORD LODNew ) { DWORD old = This->managed.lod; - DWORD max_level; DBG("This=%p LODNew=%d\n", This, LODNew); user_assert(This->base.pool == D3DPOOL_MANAGED, 0); - max_level = (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? - 0 : This->base.info.last_level; - This->managed.lod = MIN2(LODNew, max_level); + This->managed.lod = MIN2(LODNew, This->level_count-1); if (This->managed.lod != old && This->bind_count && list_is_empty(&This->list)) list_add(&This->list, &This->base.base.device->update_textures); @@ -141,9 +141,7 @@ NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) { DBG("This=%p\n", This); - if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) - return 1; - return This->base.info.last_level + 1; + return This->level_count; } HRESULT NINE_WINAPI @@ -175,7 +173,6 @@ HRESULT NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) { HRESULT hr; - unsigned last_level = This->base.info.last_level; unsigned l, min_level_dirty = This->managed.lod; BOOL update_lod; @@ -184,9 +181,6 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) assert(This->base.pool == D3DPOOL_MANAGED); - if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) - last_level = 0; - update_lod = This->managed.lod_resident != This->managed.lod; if (!update_lod && !This->managed.dirty) return D3D_OK; @@ -210,7 +204,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) if (This->managed.lod_resident == -1) {/* no levels were resident */ This->managed.dirty = FALSE; /* We are going to upload everything. */ - This->managed.lod_resident = This->base.info.last_level + 1; + This->managed.lod_resident = This->level_count; } if (This->base.type == D3DRTYPE_TEXTURE) { @@ -223,14 +217,14 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) * corresponds to This->managed.lod). * Note3: We don't care about the value passed for the surfaces * before This->managed.lod, negative with this implementation. */ - for (l = 0; l <= This->base.info.last_level; ++l) + for (l = 0; l < This->level_count; ++l) NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); } else if (This->base.type == D3DRTYPE_CUBETEXTURE) { struct NineCubeTexture9 *tex = NineCubeTexture9(This); unsigned z; - for (l = 0; l <= This->base.info.last_level; ++l) { + for (l = 0; l < This->level_count; ++l) { for (z = 0; z < 6; ++z) NineSurface9_SetResource(tex->surfaces[l * 6 + z], res, l - This->managed.lod); @@ -239,7 +233,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); - for (l = 0; l <= This->base.info.last_level; ++l) + for (l = 0; l < This->level_count; ++l) NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); } else { assert(!"invalid texture type"); @@ -266,7 +260,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) * either non-existing (and thus will be entirely re-uploaded * if the lod changes) or going to have a full upload */ if (tex->dirty_rect.width) { - for (l = min_level_dirty; l <= last_level; ++l) { + for (l = min_level_dirty; l < This->level_count; ++l) { u_box_minify_2d(&box, &tex->dirty_rect, l); NineSurface9_UploadSelf(tex->surfaces[l], &box); } @@ -287,7 +281,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) tex->dirty_rect[z].width, tex->dirty_rect[z].height); if (tex->dirty_rect[z].width) { - for (l = min_level_dirty; l <= last_level; ++l) { + for (l = min_level_dirty; l < This->level_count; ++l) { u_box_minify_2d(&box, &tex->dirty_rect[z], l); NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); } @@ -305,7 +299,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); if (tex->dirty_box.width) { - for (l = min_level_dirty; l <= last_level; ++l) { + for (l = min_level_dirty; l < This->level_count; ++l) { u_box_minify_3d(&box, &tex->dirty_box, l); NineVolume9_UploadSelf(tex->volumes[l], &box); } diff --git a/src/gallium/frontends/nine/basetexture9.h b/src/gallium/frontends/nine/basetexture9.h index 70e8b934f56..e3952cf12a2 100644 --- a/src/gallium/frontends/nine/basetexture9.h +++ b/src/gallium/frontends/nine/basetexture9.h @@ -47,6 +47,8 @@ struct NineBaseTexture9 boolean dirty_mip; D3DTEXTUREFILTERTYPE mipfilter; + unsigned level_count; + /* Specific to managed textures */ struct { boolean dirty; diff --git a/src/gallium/frontends/nine/cubetexture9.c b/src/gallium/frontends/nine/cubetexture9.c index 89821682f8f..a4259dce61e 100644 --- a/src/gallium/frontends/nine/cubetexture9.c +++ b/src/gallium/frontends/nine/cubetexture9.c @@ -107,26 +107,26 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This, DBG("Application asked for Software Vertex Processing, " "but this is unimplemented\n"); - if (Pool != D3DPOOL_DEFAULT) { - level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); - face_size = nine_format_get_size_and_offsets(pf, level_offsets, - EdgeLength, EdgeLength, - info->last_level); - This->managed_buffer = align_calloc(6 * face_size, 32); - if (!This->managed_buffer) - return E_OUTOFMEMORY; - } - - This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces)); - if (!This->surfaces) - return E_OUTOFMEMORY; - hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE, Format, Pool, Usage); if (FAILED(hr)) return hr; This->base.pstype = 2; + if (Pool != D3DPOOL_DEFAULT) { + level_offsets = alloca(sizeof(unsigned) * This->base.level_count); + face_size = nine_format_get_size_and_offsets(pf, level_offsets, + EdgeLength, EdgeLength, + This->base.level_count-1); + This->managed_buffer = align_calloc(6 * face_size, 32); + if (!This->managed_buffer) + return E_OUTOFMEMORY; + } + + This->surfaces = CALLOC(6 * This->base.level_count, sizeof(*This->surfaces)); + if (!This->surfaces) + return E_OUTOFMEMORY; + /* Create all the surfaces right away. * They manage backing storage, and transfers (LockRect) are deferred * to them. @@ -143,7 +143,7 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This, */ for (f = 0; f < 6; f++) { offset = f * face_size; - for (l = 0; l <= info->last_level; l++) { + for (l = 0; l < This->base.level_count; l++) { sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l); p = This->managed_buffer ? This->managed_buffer + offset + level_offsets[l] : NULL; @@ -174,7 +174,7 @@ NineCubeTexture9_dtor( struct NineCubeTexture9 *This ) DBG("This=%p\n", This); if (This->surfaces) { - for (i = 0; i < (This->base.base.info.last_level + 1) * 6; ++i) + for (i = 0; i < This->base.level_count * 6; ++i) NineUnknown_Destroy(&This->surfaces[i]->base.base); FREE(This->surfaces); } @@ -192,9 +192,7 @@ NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, { DBG("This=%p Level=%u pDesc=%p\n", This, Level, pDesc); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); *pDesc = This->surfaces[Level * 6]->desc; @@ -212,9 +210,7 @@ NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n", This, FaceType, Level, ppCubeMapSurface); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); user_assert(FaceType < 6, D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->surfaces[s])); @@ -236,9 +232,7 @@ NineCubeTexture9_LockRect( struct NineCubeTexture9 *This, DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n", This, FaceType, Level, pLockedRect, pRect, Flags); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); user_assert(FaceType < 6, D3DERR_INVALIDCALL); return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags); @@ -253,7 +247,7 @@ NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, DBG("This=%p FaceType=%d Level=%u\n", This, FaceType, Level); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); user_assert(FaceType < 6, D3DERR_INVALIDCALL); return NineSurface9_UnlockRect(This->surfaces[s]); diff --git a/src/gallium/frontends/nine/device9.c b/src/gallium/frontends/nine/device9.c index badf65258b5..c8685588f11 100644 --- a/src/gallium/frontends/nine/device9.c +++ b/src/gallium/frontends/nine/device9.c @@ -1484,8 +1484,8 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This, * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK) */ - last_src_level = (srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : srcb->base.info.last_level; - last_dst_level = (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : dstb->base.info.last_level; + last_src_level = srcb->level_count-1; + last_dst_level = dstb->level_count-1; for (m = 0; m <= last_src_level; ++m) { unsigned w = u_minify(srcb->base.info.width0, m); diff --git a/src/gallium/frontends/nine/texture9.c b/src/gallium/frontends/nine/texture9.c index fca5e603230..ae779a0bb5b 100644 --- a/src/gallium/frontends/nine/texture9.c +++ b/src/gallium/frontends/nine/texture9.c @@ -149,37 +149,32 @@ NineTexture9_ctor( struct NineTexture9 *This, DBG("Application asked for Software Vertex Processing, " "but this is unimplemented\n"); + hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_TEXTURE, Format, Pool, Usage); + if (FAILED(hr)) + return hr; + This->base.pstype = (Height == 1) ? 1 : 0; + if (pSharedHandle && *pSharedHandle) { /* Pool == D3DPOOL_SYSTEMMEM */ user_buffer = (void *)*pSharedHandle; - level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); + level_offsets = alloca(sizeof(unsigned) * This->base.level_count); (void) nine_format_get_size_and_offsets(pf, level_offsets, Width, Height, - info->last_level); + This->base.level_count-1); } else if (Pool != D3DPOOL_DEFAULT) { - /* TODO: For D3DUSAGE_AUTOGENMIPMAP, it is likely we only have to - * allocate only for the first level, since it is the only lockable - * level. Check apps don't crash if we allocate smaller buffer (some - * apps access sublevels of texture even if they locked only first - * level) */ - level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); + level_offsets = alloca(sizeof(unsigned) * This->base.level_count); user_buffer = align_calloc( nine_format_get_size_and_offsets(pf, level_offsets, Width, Height, - info->last_level), 32); + This->base.level_count-1), 32); This->managed_buffer = user_buffer; if (!This->managed_buffer) return E_OUTOFMEMORY; } - This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces)); + This->surfaces = CALLOC(This->base.level_count, sizeof(*This->surfaces)); if (!This->surfaces) return E_OUTOFMEMORY; - hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_TEXTURE, Format, Pool, Usage); - if (FAILED(hr)) - return hr; - This->base.pstype = (Height == 1) ? 1 : 0; - /* Create all the surfaces right away. * They manage backing storage, and transfers (LockRect) are deferred * to them. @@ -191,7 +186,7 @@ NineTexture9_ctor( struct NineTexture9 *This, sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; sfdesc.MultiSampleQuality = 0; - for (l = 0; l <= info->last_level; ++l) { + for (l = 0; l < This->base.level_count; ++l) { sfdesc.Width = u_minify(Width, l); sfdesc.Height = u_minify(Height, l); /* Some apps expect the memory to be allocated in @@ -228,7 +223,7 @@ NineTexture9_dtor( struct NineTexture9 *This ) if (This->surfaces) { /* The surfaces should have 0 references and be unbound now. */ - for (l = 0; l <= This->base.base.info.last_level; ++l) + for (l = 0; l < This->base.level_count; ++l) if (This->surfaces[l]) NineUnknown_Destroy(&This->surfaces[l]->base.base); FREE(This->surfaces); @@ -247,9 +242,7 @@ NineTexture9_GetLevelDesc( struct NineTexture9 *This, { DBG("This=%p Level=%d pDesc=%p\n", This, Level, pDesc); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); *pDesc = This->surfaces[Level]->desc; @@ -263,9 +256,7 @@ NineTexture9_GetSurfaceLevel( struct NineTexture9 *This, { DBG("This=%p Level=%d ppSurfaceLevel=%p\n", This, Level, ppSurfaceLevel); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->surfaces[Level])); *ppSurfaceLevel = (IDirect3DSurface9 *)This->surfaces[Level]; @@ -283,9 +274,7 @@ NineTexture9_LockRect( struct NineTexture9 *This, DBG("This=%p Level=%u pLockedRect=%p pRect=%p Flags=%d\n", This, Level, pLockedRect, pRect, Flags); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); return NineSurface9_LockRect(This->surfaces[Level], pLockedRect, pRect, Flags); @@ -297,7 +286,7 @@ NineTexture9_UnlockRect( struct NineTexture9 *This, { DBG("This=%p Level=%u\n", This, Level); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); return NineSurface9_UnlockRect(This->surfaces[Level]); } diff --git a/src/gallium/frontends/nine/volumetexture9.c b/src/gallium/frontends/nine/volumetexture9.c index c7191bce688..4d574994599 100644 --- a/src/gallium/frontends/nine/volumetexture9.c +++ b/src/gallium/frontends/nine/volumetexture9.c @@ -100,9 +100,6 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This, DBG("Application asked for Software Vertex Processing, " "but this is unimplemented\n"); - This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes)); - if (!This->volumes) - return E_OUTOFMEMORY; This->base.pstype = 3; hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, @@ -110,11 +107,15 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This, if (FAILED(hr)) return hr; + This->volumes = CALLOC(This->base.level_count, sizeof(*This->volumes)); + if (!This->volumes) + return E_OUTOFMEMORY; + voldesc.Format = Format; voldesc.Type = D3DRTYPE_VOLUME; voldesc.Usage = Usage; voldesc.Pool = Pool; - for (l = 0; l <= info->last_level; ++l) { + for (l = 0; l < This->base.level_count; ++l) { voldesc.Width = u_minify(Width, l); voldesc.Height = u_minify(Height, l); voldesc.Depth = u_minify(Depth, l); @@ -140,7 +141,7 @@ NineVolumeTexture9_dtor( struct NineVolumeTexture9 *This ) DBG("This=%p\n", This); if (This->volumes) { - for (l = 0; l <= This->base.base.info.last_level; ++l) + for (l = 0; l < This->base.level_count; ++l) if (This->volumes[l]) NineUnknown_Destroy(&This->volumes[l]->base); FREE(This->volumes); @@ -154,7 +155,7 @@ NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, UINT Level, D3DVOLUME_DESC *pDesc ) { - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); *pDesc = This->volumes[Level]->desc; @@ -166,7 +167,7 @@ NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, UINT Level, IDirect3DVolume9 **ppVolumeLevel ) { - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->volumes[Level])); *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level]; @@ -184,7 +185,7 @@ NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, DBG("This=%p Level=%u pLockedVolume=%p pBox=%p Flags=%d\n", This, Level, pLockedVolume, pBox, Flags); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox, Flags); @@ -196,7 +197,7 @@ NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, { DBG("This=%p Level=%u\n", This, Level); - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL); return NineVolume9_UnlockBox(This->volumes[Level]); }